Pierre Bourdon
0dd333c573
New client certs can be minted via the provided script, which is meant to be run on the postgres server (where the CA private key is conveniently deployed).
106 lines
3 KiB
Nix
106 lines
3 KiB
Nix
{ 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 {
|
|
age.secrets.postgresql-tls-priv.owner = "postgres";
|
|
age.secrets.postgresql-tls-priv.file = ../../secrets/postgres-tls-priv.age;
|
|
|
|
systemd.tmpfiles.rules = [
|
|
"d /var/db 0755 root root - -"
|
|
"d /var/db/postgresql 0750 postgres postgres - -"
|
|
"d ${dataDir} 0750 postgres postgres - -"
|
|
];
|
|
|
|
services.postgresql = {
|
|
enable = true;
|
|
package = pkgs.postgresql_16;
|
|
dataDir = dataDir;
|
|
|
|
enableTCPIP = true;
|
|
|
|
# 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 = ''
|
|
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
|
|
'';
|
|
|
|
settings = {
|
|
max_connections = 500;
|
|
|
|
ssl = true;
|
|
ssl_ca_file = "${./ca.crt}";
|
|
ssl_cert_file = "${./server.crt}";
|
|
ssl_key_file = config.age.secrets.postgresql-tls-priv.path;
|
|
};
|
|
};
|
|
|
|
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";
|
|
age.secrets.postgresql-ca-priv.file = ../../secrets/postgres-ca-priv.age;
|
|
|
|
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"
|
|
'')
|
|
];
|
|
};
|
|
}
|