remove unnecessary auth, and automate slave<->master first synchronisation

This commit is contained in:
asyncnomi 2025-08-02 19:46:25 +02:00
parent a8b2476288
commit fd3c1e8537
3 changed files with 46 additions and 57 deletions

View file

@ -1,15 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 Zvjaow yrEEH8XmRgAE3GsrJLEj+31AeycI4pzJOPf3Wn/0A2A
hHL1NrHQp7Wiz0OfJocS0k5FMbNdDP6/MiE41np6Gz8
-> ssh-ed25519 ffQbjQ HuC2HMqEhyDzAoqQ8CJLlaC4MURaveqmZmgPey3oqic
7HKDbHBLKOmaE5TfCeAxlIZiL9nbXi7SLbjTE1V8X7s
-> ssh-ed25519 Ecp4NA g69mK84+q4o5FeTNgpx0mQci4YUMiopDm4deUlAGIk4
dxZ23+1xVSCj0qzb/Yk0AqFVSWQ3hq5/O7caBR/KO5I
-> ssh-ed25519 vHebMw 69vZK4gSyRFcDrOzH1K6MzIaYCcptitS5MsQZJGwWQg
svezfzc1nflR4luSz5LdKyB7qMPABwzYKeM/RMll7Jk
-> ssh-ed25519 um7xWA /e8k7zbKQA7Eh2y6k3SgqoLXiTWdmEjVNFQS0lulqT4
aNovNzQ518/AhDYRk/w2C0fjBh+vk3TRB0+ekRH0oks
-> ssh-ed25519 oRtTqQ 3T+jsCs91kDuUlOWdtDJ0mcTLnmfirsGNCX3NmJXiXk
b1anF0O9x0UGY3Swxnw2/8I/RQeN6qun0psyvbBrDLg
--- JqYMhTAVP9q3Ca8p96YVIAVSdYoc89mqx/lbRwgTgtY
쳩ñ€k_3_l¹4¯»eú•ú··!pž»ÖœúŒMÄqÌès¼ËÖp'¬¹¯jð||n¼“KàÔÃf!™ynéu×TƒÛ

View file

@ -109,8 +109,4 @@ in
"mail/dkim.age".publicKeys = system-mail ++ users; "mail/dkim.age".publicKeys = system-mail ++ users;
"mail/mbox/test.age".publicKeys = system-mail ++ users; "mail/mbox/test.age".publicKeys = system-mail ++ users;
# DB secrets
"db/repli.age".publicKeys = system-db ++ users;
} }

View file

@ -1,11 +1,3 @@
## Note: This file wont setup the replication by itself
## Once deploy follow those instruction to run the streaming replication
## Execute on each slave (replace major version an ip addr accordingly):
# 1. sudo systemctl stop postgresql.service
# 2. sudo rm -r /var/lib/postgresql/17
# 3. pg_basebackup -h 172.19.1.2 -U replication -p 5432 -D /var/lib/postgresql/17 -P -Xs
# 4. sudo systemctl restart postgresql.service
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
let let
@ -23,16 +15,6 @@ let
masterIP = "172.19.${toString masterNode.zone}.${toString masterNode.id}"; masterIP = "172.19.${toString masterNode.zone}.${toString masterNode.id}";
in in
{ {
age.secrets."repli" = {
file = ./../../secrets/db/repli.age;
owner = "postgres";
group = "postgres";
};
systemd.services.postgresql.environment = lib.mkIf (builtins.elem myName mapping.db.slaves) {
# Currently unused cause pwd is mannually set during basebackup
PGPASSFILE = "${config.age.secrets.repli.path}";
};
services.postgresql = { services.postgresql = {
enable = true; enable = true;
# Force postgres package major version # Force postgres package major version
@ -43,16 +25,19 @@ in
superuser_map root postgres superuser_map root postgres
superuser_map postgres postgres superuser_map postgres postgres
''; '';
# Replication tasks are not authenticated
# The wireguard mesh cryptographically
# ensures the sender is who we expect.
authentication = lib.mkForce (builtins.concatStringsSep "\n" (['' authentication = lib.mkForce (builtins.concatStringsSep "\n" ([''
#type database DBuser auth-method optional_ident_map #type database DBuser auth-method optional_ident_map
local all all peer map=superuser_map local all all peer map=superuser_map
''] '']
++ lib.optionals (myName == mapping.db.master) ++ lib.optionals (myName == mapping.db.master)
(map (slaveName: let slaveNode = nodes.${slaveName}; in (map (slaveName: let slaveNode = nodes.${slaveName}; in
"host replication replication 172.19.${toString slaveNode.zone}.${toString slaveNode.id}/32 md5" "host replication replication 172.19.${toString slaveNode.zone}.${toString slaveNode.id}/32 trust"
) mapping.db.slaves) ) mapping.db.slaves)
++ lib.optionals (builtins.elem myName mapping.db.slaves) [ ++ lib.optionals (builtins.elem myName mapping.db.slaves) [
"host replication replication ${masterIP}/32 md5" "host replication replication ${masterIP}/32 trust"
])); ]));
ensureUsers = lib.mkIf (myName == mapping.db.master) [{ ensureUsers = lib.mkIf (myName == mapping.db.master) [{
name = "replication"; name = "replication";
@ -65,30 +50,53 @@ in
log_statement = "none"; log_statement = "none";
logging_collector = true; logging_collector = true;
log_disconnections = true; log_disconnections = true;
} // lib.optionalAttrs (myName == mapping.db.master) {
wal_level = "logical";
wal_sender_timeout = "60s";
max_wal_senders = 16; max_wal_senders = 16;
wal_level = "logical";
} // lib.optionalAttrs (myName == mapping.db.master) {
wal_sender_timeout = "60s";
wal_keep_size = 1000; # In MB wal_keep_size = 1000; # In MB
} // lib.optionalAttrs (builtins.elem myName mapping.db.slaves) { } // lib.optionalAttrs (builtins.elem myName mapping.db.slaves) {
wal_level = "logical";
wal_receiver_timeout = "60s"; wal_receiver_timeout = "60s";
max_wal_senders = 16;
# Should be override by postgreqql.auto.conf generated by pg_basebackup
primary_conninfo = "host=${masterIP} port=5432 user=replication";
hot_standby = "on"; hot_standby = "on";
primary_conninfo = "host=${masterIP} port=5432 user=replication";
}; };
}; };
# The password looks like: "*:*:*:*:<password>" # This preStart script sync the slaves to the master
# Cf: https://www.postgresql.org/docs/current/libpq-pgpass.html # systemd.services.<name>.preStart has a mergeable type
systemd.services.postgresql.postStart = lib.mkIf (myName == mapping.db.master) '' systemd.services.postgresql.preStart = lib.mkIf (builtins.elem myName mapping.db.slaves) ''
$PSQL -tA <<'EOF' if test -e ${cfg.dataDir}/.first_startup; then
DO $$ echo "Setting up PostgreSQL slave replication..."
DECLARE password TEXT;
BEGIN # This is a sl that's defined by the default preStart script
password := trim(both from split_part(replace(pg_read_file('${config.age.secrets.repli.path}'), E'\n', '''), ':', 5)); # We need an empty dataDir for the pg_basebackup
EXECUTE format('ALTER USER replication WITH PASSWORD '''%s''';', password); # And there is no easy ways that I'm aware of
END $$; # to get the hash of that file without recomputing it
EOF PSQL_CONF_PATH="${cfg.dataDir}/postgresql.conf"
PSQL_CONF_TARGET=$(readlink "$PSQL_CONF_PATH")
# Remove data dir
if [ -d "${cfg.dataDir}" ]; then
echo "Deleting postgres data dir: ${cfg.dataDir}"
rm -rf "${cfg.dataDir}"
fi
# Perform base backup from master
echo "Starting base backup from master: ${masterIP}"
${cfg.package}/bin/pg_basebackup \
-h "${masterIP}" \
-U replication \
-p ${toString cfg.settings.port} \
-D "${cfg.dataDir}" \
-P \
-Xs \
-R
# Symlink back the psql configFile
ln -sf "$PSQL_CONF_TARGET" "$PSQL_CONF_PATH"
echo "PostgreSQL slave setup completed successfully"
else
echo "PostgreSQL standby already configured (standby.signal exists), skipping base backup"
fi
''; '';
} }