From f05ce3bca5a40b8cc5e275cde7c6aa2ef676eaf7 Mon Sep 17 00:00:00 2001 From: asyncnomi Date: Sat, 2 Aug 2025 00:09:30 +0200 Subject: [PATCH] add db role --- mapping.nix | 11 ++++++ secrets/db/repli.age | 15 ++++++++ secrets/secrets.nix | 9 +++++ shared/db.nix | 7 ++++ shared/db/postgres.nix | 81 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 123 insertions(+) create mode 100644 secrets/db/repli.age create mode 100644 shared/db.nix create mode 100644 shared/db/postgres.nix diff --git a/mapping.nix b/mapping.nix index fc641cc..23654ea 100644 --- a/mapping.nix +++ b/mapping.nix @@ -36,4 +36,15 @@ ./shared/mail.nix ]; }; + + db = rec { + master = "db-mtz-lasuite-federez"; + slaves = [ + "db-ren-lasuite-federez" + ]; + hosts = [ master ] ++ slaves; + _inherit = [ + ./shared/db.nix + ]; + }; } \ No newline at end of file diff --git a/secrets/db/repli.age b/secrets/db/repli.age new file mode 100644 index 0000000..64dab05 --- /dev/null +++ b/secrets/db/repli.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-ed25519 Zvjaow Cr6SrhcqjjCORgH9MwAcYBuzy/c31XhJ+7fV90RLqgk +XisTJY3l8PzVykl3NDRRx1G0OhJaaC10fPC2V1kuPgU +-> ssh-ed25519 LcHAUw YNV4EkXmwRAEG9yAU1OeBfldS/N8tHmPoKYltrse5GM +xtklxh6Bli3xgKpBmcAlBknIMFDB8jBZtHns7wIciG4 +-> ssh-ed25519 Ecp4NA O6sIMS8SBrid2Spm9kIB4bR5Cj4MFVUEtd1L2Xmx9gI +HrtYqnPkkW4FRRCtu5XpkxLRFIRZRtUMBn7qpVSrWFg +-> ssh-ed25519 vHebMw ReeyVVo2WyrcMuA7jjvbeM3fxxbWKMf7OKsymLmtkB8 +5iYb8mnGh1w4/9pLtBn4GDzUlibhxMr4RDstqlNGUIw +-> ssh-ed25519 um7xWA fmz2nA3gqUtNjh+YWG4/Pb9mb6H1lO5GDN99SRFxdBQ +BPYb93QYS4opfngTD2MNOlXe3Dh71yPdW5e/v7/Qg04 +-> ssh-ed25519 oRtTqQ magv/dJL8COzbtaNIumlREmXx0K0meJqM0q8HyVzRXk +zP2O9Ql34YSvzbFVfNWzT1z+Q9PdvcjviuI0ncDBklk +--- Ay4fJm3FHTZZWU9P3QgfXOPtwm5PIbVjp2b9Me87Xqk +tlyn5{wѥ`jN^ `:E,of>F eB=k-W䐵ܳm \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index f8face1..b16529c 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -46,6 +46,11 @@ let "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJQ24UID4nGKru/to8wSoJ6LMcKwP3d9kZG7dlew0g9S root@mail-ren-lasuite-federez" ]; + system-db = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIJnmYY0ThWBzy7UshWY1k7ZJP+yp8z70Gtbc8QX3BY root@db-mtz-lasuite-federez" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPww9G5M8SSz8PWOJoX/C6hD12BLfGSRCnQQizOiCEGg root@db-ren-lasuite-federez" + ]; + asyncnomi = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIENo/g3BZ1bJViYE6EY4VZO96a4q8U4nWKjTprQJtjEH asyncnomi" ]; gamma = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKhuKmuBPLAtQSjy4E4UaEmf8Qj56414r+adAJ6BgmO8 gamma" ]; jeltz = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHabXDr/vrx361yaxKK58jHJB77TNVZvqhkIiaTB7ECI jeltz" ]; @@ -104,4 +109,8 @@ in "mail/dkim.age".publicKeys = system-mail ++ users; "mail/mbox/test.age".publicKeys = system-mail ++ users; + + # DB secrets + + "db/repli.age".publicKeys = system-db ++ users; } \ No newline at end of file diff --git a/shared/db.nix b/shared/db.nix new file mode 100644 index 0000000..aad3b75 --- /dev/null +++ b/shared/db.nix @@ -0,0 +1,7 @@ +{ ... }: +{ + # Import dependencies + imports = [ + ./db/postgres.nix + ]; +} \ No newline at end of file diff --git a/shared/db/postgres.nix b/shared/db/postgres.nix new file mode 100644 index 0000000..b5bf9a6 --- /dev/null +++ b/shared/db/postgres.nix @@ -0,0 +1,81 @@ +{ config, lib, ... }: + +let + # Import nodes + nodes = import ./../../nodes.nix; + myName = config.hostName; + myNode = nodes."${myName}"; + + # And mapping + mapping = import ./../../mapping.nix; + + cfg = config.services.postgresql; + + masterNode = nodes.${mapping.db.master}; + masterIP = "172.19.${toString masterNode.zone}.${toString masterNode.id}"; +in +{ + age.secrets."repli" = { + file = ./../../secrets/db/repli.age; + owner = "postgres"; + group = "postgres"; + }; + + systemd.services.postgresql.environment = mkIf builtins.elem myName mapping.db.slaves { + PGPASSFILE = "${config.age.secrets.repli.path}"; + }; + services.postgresql = { + enable = true; + # Force postgres package major version + # to avoid any unwanted upgrades + package = pkgs.postgresql_17; + identMap = '' + # ArbitraryMapName systemUser DBUser + superuser_map root postgres + superuser_map postgres postgres + ''; + authentication = lib.mkOverride 10 builtins.concatStringsSep "\n " ['' + #type database DBuser auth-method optional_ident_map + local all all peer map=superuser_map + ''] ++ lib.optionalAttrs myName == mapping.db.master [ + map (slaveName: let slaveNode = nodes.${slaveName}; in + "host replication replication 172.19.${toString slaveNode.zone}.${toString slaveNode.id}/32 md5" + ) mapping.db.slaves + ] ++ lib.optionalAttrs builtins.elem myName mapping.db.slaves ['' + host replication replication ${masterIP}/32 md5 + '']; + ensureUsers = [{ + name = "replication"; + ensureClauses.replication = true; + }]; + settings = { + listen_addresses = "localhost,172.19.${toString myNode.zone}.${toString myNode.id}"; + log_connections = true; + log_statement = "none"; + logging_collector = true; + log_disconnections = true; + } // lib.optionalAttrs myName == mapping.db.master { + wal_level = "logical"; + wal_sender_timeout = 10; + max_wal_senders = 16; + wal_keep_size = 1000; # In MB + } // lib.optionalAttrs builtins.elem myName mapping.db.slaves { + wal_level = "logical"; + wal_receiver_timeout = 10; + primary_conninfo = "host=${masterIP} port=${cfg.settings.port} user=replication"; + hot_standby = "on"; + }; + }; + # The password looks like: "*:*:*:*:" + # Cf: https://www.postgresql.org/docs/current/libpq-pgpass.html + systemd.services.postgresql.postStart = mkIf myName == mapping.db.master '' + $PSQL -tA <<'EOF' + DO $$ + DECLARE password TEXT; + BEGIN + password := trim(both from split_part(replace(pg_read_file('${config.age.secrets.repli.path}'), E'\n', '''), ':', 5)); + EXECUTE format('ALTER USER replication WITH PASSWORD '''%s''';', password); + END $$; + EOF + ''; +} \ No newline at end of file