2024-06-24 14:45:59 +00:00
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
|
|
|
|
let
|
|
|
|
cfg = config.bagel.services.postgres;
|
|
|
|
|
|
|
|
dataDir = "/var/db/postgresql/16";
|
|
|
|
in {
|
|
|
|
options.bagel.services.postgres = with lib; {
|
|
|
|
enable = mkEnableOption "PostgreSQL server";
|
|
|
|
};
|
|
|
|
|
|
|
|
config = lib.mkIf cfg.enable {
|
2024-08-16 05:59:12 +00:00
|
|
|
age.secrets.postgresql-tls-priv.owner = "postgres";
|
2024-10-05 16:03:41 +00:00
|
|
|
age.secrets.postgresql-tls-priv.file = ../../secrets/floral/postgres-tls-priv.age;
|
2024-08-16 05:59:12 +00:00
|
|
|
|
2024-06-24 14:45:59 +00:00
|
|
|
systemd.tmpfiles.rules = [
|
|
|
|
"d /var/db 0755 root root - -"
|
2024-06-24 19:45:00 +00:00
|
|
|
"d /var/db/postgresql 0750 postgres postgres - -"
|
|
|
|
"d ${dataDir} 0750 postgres postgres - -"
|
2024-06-24 14:45:59 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
services.postgresql = {
|
|
|
|
enable = true;
|
|
|
|
package = pkgs.postgresql_16;
|
|
|
|
dataDir = dataDir;
|
|
|
|
|
2024-08-16 05:59:12 +00:00
|
|
|
enableTCPIP = true;
|
|
|
|
|
2024-06-24 14:45:59 +00:00
|
|
|
# TODO: Where to put this to properly couple things? It doesn't belong
|
|
|
|
# here, but using it in services/hydra would require running on
|
|
|
|
# localhost. Probably needs to be replaced with some different way of
|
|
|
|
# ensuring the DB/user exist.
|
|
|
|
ensureDatabases = [ "hydra" ];
|
|
|
|
ensureUsers = [
|
|
|
|
{
|
|
|
|
name = "hydra";
|
|
|
|
ensureDBOwnership = true;
|
|
|
|
}
|
|
|
|
];
|
|
|
|
identMap = ''
|
|
|
|
hydra-users hydra hydra
|
|
|
|
hydra-users hydra-queue-runner hydra
|
|
|
|
hydra-users hydra-www hydra
|
|
|
|
hydra-users root hydra
|
|
|
|
# The postgres user is used to create the pg_trgm extension for the hydra database
|
|
|
|
hydra-users postgres postgres
|
|
|
|
'';
|
|
|
|
authentication = ''
|
2024-08-16 05:59:12 +00:00
|
|
|
local hydra all peer map=hydra-users
|
|
|
|
|
|
|
|
# Allow any connection over TLS with a valid client certificate: signed
|
|
|
|
# by our CA, and with username = cert CN.
|
|
|
|
hostssl all all all cert clientcert=verify-full
|
2024-06-24 14:45:59 +00:00
|
|
|
'';
|
2024-06-24 19:00:46 +00:00
|
|
|
|
|
|
|
settings = {
|
|
|
|
max_connections = 500;
|
2024-08-16 05:59:12 +00:00
|
|
|
|
|
|
|
ssl = true;
|
|
|
|
ssl_ca_file = "${./ca.crt}";
|
|
|
|
ssl_cert_file = "${./server.crt}";
|
|
|
|
ssl_key_file = config.age.secrets.postgresql-tls-priv.path;
|
2024-06-24 19:00:46 +00:00
|
|
|
};
|
2024-06-24 14:45:59 +00:00
|
|
|
};
|
2024-08-16 05:59:12 +00:00
|
|
|
|
|
|
|
networking.firewall.allowedTCPPorts = [ config.services.postgresql.settings.port ];
|
|
|
|
|
|
|
|
# Provisioned on the server so that CA operations can be done there.
|
|
|
|
age.secrets.postgresql-ca-priv.owner = "postgres";
|
2024-10-05 16:03:41 +00:00
|
|
|
age.secrets.postgresql-ca-priv.file = ../../secrets/floral/postgres-ca-priv.age;
|
2024-08-16 05:59:12 +00:00
|
|
|
|
|
|
|
users.users.postgres.packages = [
|
|
|
|
(pkgs.writeShellScriptBin "postgres-mint-new-client" ''
|
|
|
|
#! ${pkgs.runtimeShell}
|
|
|
|
|
|
|
|
set -eo pipefail
|
|
|
|
|
|
|
|
if [ $# -eq 0 ]; then
|
|
|
|
echo "usage: $0 <pg-username>" >&2
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
user=$1
|
|
|
|
step=${pkgs.lib.getExe pkgs.step-cli}
|
|
|
|
|
|
|
|
tmpdir=$(mktemp -d)
|
|
|
|
trap "rm -rf $tmpdir" EXIT
|
|
|
|
|
|
|
|
$step certificate create "$user" "$tmpdir/client.crt" "$tmpdir/client.key" \
|
|
|
|
--profile leaf \
|
|
|
|
--ca ${./ca.crt} \
|
|
|
|
--ca-key ${config.age.secrets.postgresql-ca-priv.path} \
|
|
|
|
--not-after 87660h \
|
|
|
|
--no-password --insecure
|
|
|
|
|
|
|
|
echo "Client certificate:"
|
|
|
|
cat "$tmpdir/client.crt"
|
|
|
|
echo
|
|
|
|
|
|
|
|
echo "Client private key:"
|
|
|
|
cat "$tmpdir/client.key"
|
|
|
|
'')
|
|
|
|
];
|
2024-06-24 14:45:59 +00:00
|
|
|
};
|
|
|
|
}
|