2023-08-20 12:15:02 +08:00
|
|
|
inputs:
|
|
|
|
{
|
2024-05-30 12:59:57 +08:00
|
|
|
options.nixos.services.postgresql = let inherit (inputs.lib) mkOption types; in
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
2024-05-30 12:59:57 +08:00
|
|
|
enable = mkOption { type = types.bool; default = inputs.config.nixos.services.postgresql.instances != {}; };
|
|
|
|
instances = mkOption
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
2024-05-30 12:59:57 +08:00
|
|
|
type = types.attrsOf (types.submodule (submoduleInputs: { options =
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
2024-05-30 12:59:57 +08:00
|
|
|
database = mkOption { type = types.nonEmptyStr; default = submoduleInputs.config._module.args.name; };
|
|
|
|
user = mkOption { type = types.nonEmptyStr; default = submoduleInputs.config._module.args.name; };
|
|
|
|
passwordFile = mkOption { type = types.nullOr types.nonEmptyStr; default = null; };
|
|
|
|
initializeFlags = mkOption { type = types.attrsOf types.nonEmptyStr; default = {}; };
|
|
|
|
};}));
|
|
|
|
default = {};
|
|
|
|
};
|
2023-09-01 21:05:26 +08:00
|
|
|
};
|
2024-05-30 12:59:57 +08:00
|
|
|
config = let inherit (inputs.config.nixos.services) postgresql; in inputs.lib.mkIf postgresql.enable
|
|
|
|
{
|
|
|
|
services =
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
2024-05-30 12:59:57 +08:00
|
|
|
postgresql =
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
2024-05-30 12:59:57 +08:00
|
|
|
enable = true;
|
|
|
|
package = inputs.pkgs.postgresql_15;
|
|
|
|
enableTCPIP = true;
|
|
|
|
authentication = "host all all 0.0.0.0/0 md5";
|
|
|
|
settings =
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
2024-05-30 12:59:57 +08:00
|
|
|
unix_socket_permissions = "0700";
|
|
|
|
shared_buffers = "8192MB";
|
|
|
|
work_mem = "512MB";
|
|
|
|
autovacuum = "on";
|
2023-09-01 21:05:26 +08:00
|
|
|
};
|
2024-05-30 12:59:57 +08:00
|
|
|
# log_timezone = 'Asia/Shanghai'
|
|
|
|
# datestyle = 'iso, mdy'
|
|
|
|
# timezone = 'Asia/Shanghai'
|
|
|
|
# lc_messages = 'en_US.utf8'
|
|
|
|
# lc_monetary = 'en_US.utf8'
|
|
|
|
# lc_numeric = 'en_US.utf8'
|
|
|
|
# lc_time = 'en_US.utf8'
|
|
|
|
# default_text_search_config = 'pg_catalog.english'
|
|
|
|
# plperl.on_init = 'use utf8; use re; package utf8; require "utf8_heavy.pl";'
|
|
|
|
# mv /path/to/dir /path/to/dir_old
|
|
|
|
# mkdir /path/to/dir
|
|
|
|
# chattr +C /path/to/dir
|
|
|
|
# cp -a --reflink=never /path/to/dir_old/. /path/to/dir
|
|
|
|
# rm -rf /path/to/dir_old
|
2024-05-30 13:48:07 +08:00
|
|
|
ensureUsers = builtins.map (db: { name = db.value.user; }) (inputs.localLib.attrsToList postgresql.instances);
|
2024-05-30 12:59:57 +08:00
|
|
|
};
|
|
|
|
postgresqlBackup =
|
|
|
|
{
|
|
|
|
enable = true;
|
|
|
|
pgdumpOptions = "-Fc";
|
|
|
|
compression = "none";
|
2024-05-30 13:48:07 +08:00
|
|
|
databases = builtins.map (db: db.value.database) (inputs.localLib.attrsToList postgresql.instances);
|
2023-09-01 21:05:26 +08:00
|
|
|
};
|
|
|
|
};
|
2024-05-30 12:59:57 +08:00
|
|
|
systemd.services.postgresql.postStart = inputs.lib.mkAfter (builtins.concatStringsSep "\n" (builtins.map
|
|
|
|
(db:
|
|
|
|
let
|
|
|
|
passwordFile =
|
|
|
|
if db.value.passwordFile or null != null then db.value.passwordFile
|
|
|
|
else inputs.config.sops.secrets."postgresql/${db.value.user}".path;
|
|
|
|
initializeFlag =
|
|
|
|
if db.value.initializeFlags != {} then
|
|
|
|
" WITH "
|
|
|
|
+ (builtins.concatStringsSep " " (map
|
|
|
|
(flag: ''${flag.name} = "${flag.value}"'')
|
2024-05-30 13:48:07 +08:00
|
|
|
(inputs.localLib.attrsToList db.value.initializeFlags)))
|
2024-05-30 12:59:57 +08:00
|
|
|
else "";
|
|
|
|
in
|
|
|
|
# create database if not exist
|
|
|
|
"$PSQL -tAc \"SELECT 1 FROM pg_database WHERE datname = '${db.value.database}'\" | grep -q 1"
|
|
|
|
+ " || $PSQL -tAc 'CREATE DATABASE \"${db.value.database}\"${initializeFlag}'"
|
|
|
|
# set user password
|
|
|
|
+ "\n"
|
|
|
|
+ "$PSQL -tAc \"ALTER USER ${db.value.user} with encrypted password '$(cat ${passwordFile})'\""
|
|
|
|
# set db owner
|
|
|
|
+ "\n"
|
|
|
|
+ "$PSQL -tAc \"select pg_catalog.pg_get_userbyid(d.datdba) FROM pg_catalog.pg_database d"
|
|
|
|
+ " WHERE d.datname = '${db.value.database}' ORDER BY 1\""
|
|
|
|
+ " | grep -E '^${db.value.user}$' -q"
|
|
|
|
+ " || $PSQL -tAc \"ALTER DATABASE ${db.value.database} OWNER TO ${db.value.user}\"")
|
2024-05-30 13:48:07 +08:00
|
|
|
(inputs.localLib.attrsToList postgresql.instances)));
|
|
|
|
sops.secrets = builtins.listToAttrs (builtins.map
|
2024-05-30 12:59:57 +08:00
|
|
|
(db: { name = "postgresql/${db.value.user}"; value.owner = inputs.config.users.users.postgres.name; })
|
2024-05-30 13:48:07 +08:00
|
|
|
(builtins.filter (db: db.value.passwordFile == null) (inputs.localLib.attrsToList postgresql.instances)));
|
2024-05-30 12:59:57 +08:00
|
|
|
environment.persistence =
|
|
|
|
let inherit (inputs.config.nixos.system) impermanence; in inputs.lib.mkIf impermanence.enable
|
|
|
|
{
|
2024-05-30 13:48:07 +08:00
|
|
|
"${impermanence.nodatacow}".directories = let user = "postgres"; in
|
|
|
|
[{ directory = "/var/lib/postgresql"; inherit user; group = user; mode = "0750"; }];
|
2024-05-30 12:59:57 +08:00
|
|
|
};
|
|
|
|
};
|
2023-08-20 12:15:02 +08:00
|
|
|
}
|