nixos-config/config/fudo/postgres.nix

236 lines
6.3 KiB
Nix
Raw Normal View History

2020-01-15 09:24:11 -08:00
{ config, lib, pkgs, environment, ... }:
with lib;
let
cfg = config.fudo.postgresql;
userOpts = { username, ... }: {
options = {
password = mkOption {
2020-02-03 17:07:46 -08:00
type = with types; nullOr str;
2020-01-15 09:24:11 -08:00
description = "The user's (plaintext) password.";
2020-02-03 17:07:46 -08:00
default = null;
2020-01-15 09:24:11 -08:00
};
databases = mkOption {
2020-02-03 17:07:46 -08:00
type = with types; loaOf str;
description = "Map of databases to which this user has access, to the required perms.";
default = {};
example = {
my_database = "ALL PRIVILEGES";
};
2020-01-15 09:24:11 -08:00
};
};
};
databaseOpts = { dbname, ... }: {
options = {
users = mkOption {
type = with types; listOf str;
2020-02-03 17:07:46 -08:00
description = "A list of users who should have full access to this database.";
2020-01-15 09:24:11 -08:00
default = [];
};
};
};
userDatabaseAccess = user: databases:
2020-02-03 17:07:46 -08:00
mapAttrs' (database: perms:
nameValuePair "DATABASE ${database}" perms)
databases;
2020-01-15 09:24:11 -08:00
stringJoin = joiner: els:
if (length els) == 0 then
""
else
foldr(lel: rel: "${lel}${joiner}${rel}") (last els) (init els);
makeEntry = nw:
"host all all ${nw} gss include_realm=0 krb_realm=FUDO.ORG";
makeNetworksEntry = networks:
stringJoin "\n" (map makeEntry networks);
setPasswordSql = username: attrs:
"ALTER USER ${username} ENCRYPTED PASSWORD '${attrs.password}';";
setPasswordsSql = users:
2020-02-03 17:07:46 -08:00
(stringJoin "\n"
2020-01-15 09:24:11 -08:00
(mapAttrsToList (username: attrs: setPasswordSql username attrs)
2020-02-03 17:07:46 -08:00
(filterAttrs (user: attrs: attrs.password != null) users))) + "\n";
2020-01-15 09:24:11 -08:00
makeLocalUserPasswordEntries = users:
stringJoin "\n"
(mapAttrsToList
(username: attrs:
stringJoin "\n"
(map (db: ''
2020-06-06 18:58:13 -07:00
local ${db} ${username} md5
host ${db} ${username} 127.0.0.1/16 md5
host ${db} ${username} ::1/128 md5
2020-02-03 17:07:46 -08:00
'') (attrNames attrs.databases)))
2020-01-15 09:24:11 -08:00
users);
in {
options.fudo.postgresql = {
enable = mkEnableOption "Fudo PostgreSQL Server";
ssl-private-key = mkOption {
type = types.str;
description = "Location of the server SSL private key.";
};
ssl-certificate = mkOption {
type = types.str;
description = "Location of the server SSL certificate.";
};
keytab = mkOption {
type = types.str;
description = "Location of the server Kerberos keytab.";
};
local-networks = mkOption {
type = with types; listOf str;
description = "A list of networks from which to accept connections.";
example = [
"10.0.0.1/16"
];
default = [];
};
2020-02-03 17:07:46 -08:00
users = mkOption {
2020-01-15 09:24:11 -08:00
type = with types; loaOf (submodule userOpts);
description = "A map of users to user attributes.";
example = {
sampleUser = {
password = "some-password";
databases = [ "sample_user_db" ];
};
};
default = {};
};
databases = mkOption {
type = with types; loaOf (submodule databaseOpts);
description = "A map of databases to database options.";
default = {};
};
2020-06-06 18:58:13 -07:00
socket-directory = mkOption {
type = types.str;
description = "Directory in which to place unix sockets.";
default = "/run/postgresql";
};
socket-group = mkOption {
type = types.str;
description = "Group for accessing sockets.";
default = "postgres_local";
};
local-users = mkOption {
type = with types; listOf str;
description = "Users able to access the server via local socket.";
default = [];
};
2020-01-15 09:24:11 -08:00
};
config = mkIf cfg.enable {
environment = {
systemPackages = with pkgs; [
postgresql_11_gssapi
];
etc = {
"postgresql/private/privkey.pem" = {
mode = "0400";
user = "postgres";
group = "postgres";
source = cfg.ssl-private-key;
};
"postgresql/cert.pem" = {
mode = "0444";
user = "postgres";
group = "postgres";
source = cfg.ssl-certificate;
};
"postgresql/private/postgres.keytab" = {
mode = "0400";
user = "postgres";
group = "postgres";
source = cfg.keytab;
};
2020-02-03 17:07:46 -08:00
"postgresql/private/user-script.sql" = {
mode = "0400";
user = "postgres";
group = "postgres";
text = setPasswordsSql cfg.users;
};
2020-01-15 09:24:11 -08:00
};
};
2020-06-06 18:58:13 -07:00
users.groups = {
${cfg.socket-group} = {
members = ["postgres"] ++ cfg.local-users;
};
};
2020-01-15 09:24:11 -08:00
services.postgresql = {
enable = true;
package = pkgs.postgresql_11_gssapi;
enableTCPIP = true;
ensureDatabases = mapAttrsToList (name: value: name) cfg.databases;
ensureUsers = mapAttrsToList
(username: attrs:
{
name = username;
ensurePermissions =
#{ "DATABASE ${username}" = "ALL PRIVILEGES"; };
(userDatabaseAccess username attrs.databases);
})
2020-02-03 17:07:46 -08:00
cfg.users;
2020-01-15 09:24:11 -08:00
2020-06-06 18:58:13 -07:00
extraConfig = ''
2020-01-15 09:24:11 -08:00
krb_server_keyfile = '/etc/postgresql/private/postgres.keytab'
ssl = true
ssl_cert_file = '/etc/postgresql/cert.pem'
ssl_key_file = '/etc/postgresql/private/privkey.pem'
2020-06-06 18:58:13 -07:00
unix_socket_directories = '${cfg.socket-directory}'
unix_socket_group = '${cfg.socket-group}'
unix_socket_permissions = 0777
2020-01-15 09:24:11 -08:00
'';
2020-06-06 18:58:13 -07:00
authentication = lib.mkForce ''
2020-02-03 17:07:46 -08:00
${makeLocalUserPasswordEntries cfg.users}
2020-01-15 09:24:11 -08:00
2020-06-06 18:58:13 -07:00
local all all ident
2020-01-15 09:24:11 -08:00
# host-local
host all all 127.0.0.1/32 gss include_realm=0 krb_realm=FUDO.ORG
host all all ::1/128 gss include_realm=0 krb_realm=FUDO.ORG
# local networks
${makeNetworksEntry cfg.local-networks}
'';
2020-02-03 17:07:46 -08:00
# initialScript = pkgs.writeText "database-init.sql" ''
# ${setPasswordsSql cfg.users}
# '';
2020-01-15 09:24:11 -08:00
};
2020-02-03 17:07:46 -08:00
systemd.services.postgresql.postStart = ''
${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} ${pkgs.postgresql}/bin/psql --port ${toString config.services.postgresql.port} -f /etc/postgresql/private/user-script.sql -d postgres
2020-06-06 18:58:13 -07:00
${pkgs.coreutils}/bin/chgrp ${cfg.socket-group} ${cfg.socket-directory}/.s.PGSQL*
2020-02-03 17:07:46 -08:00
'';
2020-01-15 09:24:11 -08:00
};
}