diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix index d1fd9797e4d4..84a99bcb329b 100644 --- a/nixos/modules/services/databases/postgresql.nix +++ b/nixos/modules/services/databases/postgresql.nix @@ -769,7 +769,7 @@ in systemd.targets.postgresql = { description = "PostgreSQL"; wantedBy = [ "multi-user.target" ]; - bindsTo = [ + requires = [ "postgresql.service" "postgresql-setup.service" ]; @@ -780,8 +780,13 @@ in after = [ "network.target" ]; - # To trigger the .target also on "systemctl start postgresql". - bindsTo = [ "postgresql.target" ]; + # To trigger the .target also on "systemctl start postgresql" as well as on + # restarts & stops. + # Please note that postgresql.service & postgresql.target binding to + # each other makes the Restart=always rule racy and results + # in sometimes the service not being restarted. + wants = [ "postgresql.target" ]; + partOf = [ "postgresql.target" ]; environment.PGDATA = cfg.dataDir; @@ -821,6 +826,8 @@ in ExecStart = "${cfg.finalPackage}/bin/postgres"; + Restart = "always"; + # Hardening CapabilityBoundingSet = [ "" ]; DevicePolicy = "closed"; @@ -872,7 +879,20 @@ in }) ]; - unitConfig.RequiresMountsFor = "${cfg.dataDir}"; + unitConfig = + let + inherit (config.systemd.services.postgresql.serviceConfig) TimeoutSec; + maxTries = 5; + bufferSec = 5; + in + { + RequiresMountsFor = "${cfg.dataDir}"; + + # The max. time needed to perform `maxTries` start attempts of systemd + # plus a bit of buffer time (bufferSec) on top. + StartLimitIntervalSec = TimeoutSec * maxTries + bufferSec; + StartLimitBurst = maxTries; + }; }; systemd.services.postgresql-setup = { diff --git a/nixos/tests/postgresql/postgresql.nix b/nixos/tests/postgresql/postgresql.nix index e77ec7897547..456cacb54830 100644 --- a/nixos/tests/postgresql/postgresql.nix +++ b/nixos/tests/postgresql/postgresql.nix @@ -101,6 +101,12 @@ let machine.fail(check_count("SELECT * FROM sth;", 4)) machine.succeed(check_count("SELECT xpath('/test/text()', doc) FROM xmltest;", 1)) + with subtest("killing postgres process should trigger an automatic restart"): + machine.succeed("systemctl kill -s KILL postgresql") + + machine.wait_until_succeeds("systemctl is-active postgresql.service") + machine.wait_until_succeeds("systemctl is-active postgresql.target") + with subtest("Backup service works"): machine.succeed( "systemctl start ${backupService}.service",