mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-18 07:29:23 +03:00
nixos/postgres-websockets: init
This commit is contained in:
parent
b2b5f8be28
commit
d62c14f5d1
6 changed files with 313 additions and 1 deletions
221
nixos/modules/services/databases/postgres-websockets.nix
Normal file
221
nixos/modules/services/databases/postgres-websockets.nix
Normal file
|
@ -0,0 +1,221 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.postgres-websockets;
|
||||
|
||||
# Turns an attrset of libpq connection params:
|
||||
# {
|
||||
# dbname = "postgres";
|
||||
# user = "authenticator";
|
||||
# }
|
||||
# into a libpq connection string:
|
||||
# dbname=postgres user=authenticator
|
||||
PGWS_DB_URI = lib.pipe cfg.environment.PGWS_DB_URI [
|
||||
(lib.filterAttrs (_: v: v != null))
|
||||
(lib.mapAttrsToList (k: v: "${k}='${lib.escape [ "'" "\\" ] v}'"))
|
||||
(lib.concatStringsSep " ")
|
||||
];
|
||||
in
|
||||
|
||||
{
|
||||
meta = {
|
||||
maintainers = with lib.maintainers; [ wolfgangwalther ];
|
||||
};
|
||||
|
||||
options.services.postgres-websockets = {
|
||||
enable = lib.mkEnableOption "postgres-websockets";
|
||||
|
||||
pgpassFile = lib.mkOption {
|
||||
type =
|
||||
with lib.types;
|
||||
nullOr (pathWith {
|
||||
inStore = false;
|
||||
absolute = true;
|
||||
});
|
||||
default = null;
|
||||
example = "/run/keys/db_password";
|
||||
description = ''
|
||||
The password to authenticate to PostgreSQL with.
|
||||
Not needed for peer or trust based authentication.
|
||||
|
||||
The file must be a valid `.pgpass` file as described in:
|
||||
<https://www.postgresql.org/docs/current/libpq-pgpass.html>
|
||||
|
||||
In most cases, the following will be enough:
|
||||
```
|
||||
*:*:*:*:<password>
|
||||
```
|
||||
'';
|
||||
};
|
||||
|
||||
jwtSecretFile = lib.mkOption {
|
||||
type =
|
||||
with lib.types;
|
||||
nullOr (pathWith {
|
||||
inStore = false;
|
||||
absolute = true;
|
||||
});
|
||||
example = "/run/keys/jwt_secret";
|
||||
description = ''
|
||||
Secret used to sign JWT tokens used to open communications channels.
|
||||
'';
|
||||
};
|
||||
|
||||
environment = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = with lib.types; attrsOf str;
|
||||
|
||||
options = {
|
||||
PGWS_DB_URI = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = with lib.types; attrsOf str;
|
||||
|
||||
# This should not be used; use pgpassFile instead.
|
||||
options.password = lib.mkOption {
|
||||
default = null;
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
};
|
||||
# This should not be used; use pgpassFile instead.
|
||||
options.passfile = lib.mkOption {
|
||||
default = null;
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
libpq connection parameters as documented in:
|
||||
|
||||
<https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS>
|
||||
|
||||
::: {.note}
|
||||
The `environment.PGWS_DB_URI.password` and `environment.PGWS_DB_URI.passfile` options are blocked.
|
||||
Use [`pgpassFile`](#opt-services.postgres-websockets.pgpassFile) instead.
|
||||
:::
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
host = "localhost";
|
||||
dbname = "postgres";
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
# This should not be used; use jwtSecretFile instead.
|
||||
PGWS_JWT_SECRET = lib.mkOption {
|
||||
default = null;
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
};
|
||||
|
||||
PGWS_HOST = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = "127.0.0.1";
|
||||
description = ''
|
||||
Address the server will listen for websocket connections.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
postgres-websockets configuration as defined in:
|
||||
<https://github.com/diogob/postgres-websockets/blob/master/src/PostgresWebsockets/Config.hs#L71-L87>
|
||||
|
||||
`PGWS_DB_URI` is represented as an attribute set, see [`environment.PGWS_DB_URI`](#opt-services.postgres-websockets.environment.PGWS_DB_URI)
|
||||
|
||||
::: {.note}
|
||||
The `environment.PGWS_JWT_SECRET` option is blocked.
|
||||
Use [`jwtSecretFile`](#opt-services.postgres-websockets.jwtSecretFile) instead.
|
||||
:::
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
PGWS_LISTEN_CHANNEL = "my_channel";
|
||||
PGWS_DB_URI.dbname = "postgres";
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.postgres-websockets.environment.PGWS_DB_URI.application_name =
|
||||
with pkgs.postgres-websockets;
|
||||
"${pname} ${version}";
|
||||
|
||||
systemd.services.postgres-websockets = {
|
||||
description = "postgres-websockets";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
after = [
|
||||
"network-online.target"
|
||||
"postgresql.service"
|
||||
];
|
||||
|
||||
environment =
|
||||
cfg.environment
|
||||
// {
|
||||
inherit PGWS_DB_URI;
|
||||
PGWS_JWT_SECRET = "@%d/jwt_secret";
|
||||
}
|
||||
// lib.optionalAttrs (cfg.pgpassFile != null) {
|
||||
PGPASSFILE = "%C/postgres-websockets/pgpass";
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
CacheDirectory = "postgres-websockets";
|
||||
CacheDirectoryMode = "0700";
|
||||
LoadCredential = [
|
||||
"jwt_secret:${cfg.jwtSecretFile}"
|
||||
] ++ lib.optional (cfg.pgpassFile != null) "pgpass:${cfg.pgpassFile}";
|
||||
Restart = "always";
|
||||
User = "postgres-websockets";
|
||||
|
||||
# Hardening
|
||||
CapabilityBoundingSet = [ "" ];
|
||||
DevicePolicy = "closed";
|
||||
DynamicUser = true;
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateIPC = true;
|
||||
PrivateMounts = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_UNIX"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [ "" ];
|
||||
UMask = "0077";
|
||||
};
|
||||
|
||||
# Copy the pgpass file to different location, to have it report mode 0400.
|
||||
# Fixes: https://github.com/systemd/systemd/issues/29435
|
||||
script = ''
|
||||
if [ -f "$CREDENTIALS_DIRECTORY/pgpass" ]; then
|
||||
cp -f "$CREDENTIALS_DIRECTORY/pgpass" "$CACHE_DIRECTORY/pgpass"
|
||||
fi
|
||||
exec ${lib.getExe pkgs.postgres-websockets}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue