From 4f5fc729c7333c45eedf65b972ca8dd651fac985 Mon Sep 17 00:00:00 2001 From: Aaron Andersen Date: Sat, 1 Aug 2020 10:44:17 -0400 Subject: [PATCH 1/3] nixos/postgresql: use a standard default value for dataDir --- nixos/doc/manual/release-notes/rl-2009.xml | 11 +++++++++++ nixos/modules/services/databases/postgresql.nix | 8 +++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/nixos/doc/manual/release-notes/rl-2009.xml b/nixos/doc/manual/release-notes/rl-2009.xml index a3d9c11e520..35ffadc17c5 100644 --- a/nixos/doc/manual/release-notes/rl-2009.xml +++ b/nixos/doc/manual/release-notes/rl-2009.xml @@ -615,6 +615,17 @@ services.dokuwiki."mywiki" = { }; ... }; + + + + + + The option is now set to "/var/lib/postgresql/${cfg.package.psqlSchema}" regardless of your + . Users with an existing postgresql install that have a of 17.09 or below + should double check what the value of their option is (/var/db/postgresql) and then explicitly + set this value to maintain compatibility: + +services.postgresql.dataDir = "/var/db/postgresql"; diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix index 579b6a4d9c6..b883134e7dc 100644 --- a/nixos/modules/services/databases/postgresql.nix +++ b/nixos/modules/services/databases/postgresql.nix @@ -21,7 +21,7 @@ let listen_addresses = '${if cfg.enableTCPIP then "*" else "localhost"}' port = ${toString cfg.port} ${cfg.extraConfig} - ''; + ''; groupAccessAvailable = versionAtLeast postgresql.version "11.0"; @@ -55,6 +55,7 @@ in dataDir = mkOption { type = types.path; + defaultText = "/var/lib/postgresql/\${config.services.postgresql.package.psqlSchema}"; example = "/var/lib/postgresql/11"; description = '' Data directory for PostgreSQL. @@ -249,10 +250,7 @@ in else if versionAtLeast config.system.stateVersion "16.03" then pkgs.postgresql_9_5 else throw "postgresql_9_4 was removed, please upgrade your postgresql version."); - services.postgresql.dataDir = - mkDefault (if versionAtLeast config.system.stateVersion "17.09" - then "/var/lib/postgresql/${cfg.package.psqlSchema}" - else "/var/db/postgresql"); + services.postgresql.dataDir = mkDefault "/var/lib/postgresql/${cfg.package.psqlSchema}"; services.postgresql.authentication = mkAfter '' From e50e89e1a854c4b78929a322b60fe236476141f3 Mon Sep 17 00:00:00 2001 From: Aaron Andersen Date: Sat, 1 Aug 2020 11:23:28 -0400 Subject: [PATCH 2/3] nixos/postgresql: conditionally provision data directory with StateDirectory --- .../modules/services/databases/postgresql.nix | 24 ++++++++++--------- nixos/tests/postgresql-wal-receiver.nix | 4 ++++ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix index b883134e7dc..29f8eb8b735 100644 --- a/nixos/modules/services/databases/postgresql.nix +++ b/nixos/modules/services/databases/postgresql.nix @@ -58,7 +58,10 @@ in defaultText = "/var/lib/postgresql/\${config.services.postgresql.package.psqlSchema}"; example = "/var/lib/postgresql/11"; description = '' - Data directory for PostgreSQL. + The data directory for PostgreSQL. If left as the default value + this directory will automatically be created before the PostgreSQL server starts, otherwise + the sysadmin is responsible for ensuring the directory exists with appropriate ownership + and permissions. ''; }; @@ -289,13 +292,11 @@ in preStart = '' - # Create data directory. + # Cleanup the data directory. if ! test -e ${cfg.dataDir}/PG_VERSION; then - mkdir -m 0700 -p ${cfg.dataDir} rm -f ${cfg.dataDir}/*.conf - chown -R postgres:postgres ${cfg.dataDir} fi - ''; # */ + ''; script = '' @@ -310,15 +311,11 @@ in ln -sfn "${pkgs.writeText "recovery.conf" cfg.recoveryConfig}" \ "${cfg.dataDir}/recovery.conf" ''} - ${optionalString (!groupAccessAvailable) '' - # postgresql pre 11.0 doesn't start if state directory mode is group accessible - chmod 0700 "${cfg.dataDir}" - ''} exec postgres ''; - serviceConfig = + serviceConfig = mkMerge [ { ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; User = "postgres"; Group = "postgres"; @@ -336,7 +333,12 @@ in # Give Postgres a decent amount of time to clean up after # receiving systemd's SIGINT. TimeoutSec = 120; - }; + } + (mkIf (cfg.dataDir == "/var/lib/postgresql/${cfg.package.psqlSchema}") { + StateDirectory = "postgresql postgresql/${cfg.package.psqlSchema}"; + StateDirectoryMode = if groupAccessAvailable then "0750" else "0700"; + }) + ]; # Wait for PostgreSQL to be ready to accept connections. postStart = diff --git a/nixos/tests/postgresql-wal-receiver.nix b/nixos/tests/postgresql-wal-receiver.nix index 372dd9d8c1c..c50746aa838 100644 --- a/nixos/tests/postgresql-wal-receiver.nix +++ b/nixos/tests/postgresql-wal-receiver.nix @@ -28,6 +28,10 @@ let meta.maintainers = with maintainers; [ pacien ]; machine = { ... }: { + # Needed because this test uses a non-default 'services.postgresql.dataDir'. + systemd.tmpfiles.rules = [ + "d /var/db/postgresql 0700 postgres postgres" + ]; services.postgresql = { package = postgresqlPackage; enable = true; From f42f8a6d3c59b483a649bf1e5910733396a45eb2 Mon Sep 17 00:00:00 2001 From: Aaron Andersen Date: Sat, 1 Aug 2020 11:39:18 -0400 Subject: [PATCH 3/3] nixos/postgresql: replace deprecated usage of PermissionsStartOnly --- .../modules/services/databases/postgresql.nix | 79 ++++++++++--------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix index 29f8eb8b735..59c9325ca90 100644 --- a/nixos/modules/services/databases/postgresql.nix +++ b/nixos/modules/services/databases/postgresql.nix @@ -292,34 +292,28 @@ in preStart = '' - # Cleanup the data directory. if ! test -e ${cfg.dataDir}/PG_VERSION; then + # Cleanup the data directory. rm -f ${cfg.dataDir}/*.conf - fi - ''; - script = - '' - # Initialise the database. - if ! test -e ${cfg.dataDir}/PG_VERSION; then + # Initialise the database. initdb -U ${cfg.superUser} ${concatStringsSep " " cfg.initdbArgs} + # See postStart! touch "${cfg.dataDir}/.first_startup" fi + ln -sfn "${configFile}" "${cfg.dataDir}/postgresql.conf" ${optionalString (cfg.recoveryConfig != null) '' ln -sfn "${pkgs.writeText "recovery.conf" cfg.recoveryConfig}" \ "${cfg.dataDir}/recovery.conf" ''} - - exec postgres ''; serviceConfig = mkMerge [ { ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; User = "postgres"; Group = "postgres"; - PermissionsStartOnly = true; RuntimeDirectory = "postgresql"; Type = if versionAtLeast cfg.package.version "9.6" then "notify" @@ -333,6 +327,42 @@ in # Give Postgres a decent amount of time to clean up after # receiving systemd's SIGINT. TimeoutSec = 120; + + ExecStart = "${postgresql}/bin/postgres"; + + # Wait for PostgreSQL to be ready to accept connections. + ExecStartPost = + let + setupScript = pkgs.writeScript "postgresql-setup" '' + #!${pkgs.runtimeShell} -e + + PSQL="${pkgs.utillinux}/bin/runuser -u ${cfg.superUser} -- psql --port=${toString cfg.port}" + + while ! $PSQL -d postgres -c "" 2> /dev/null; do + if ! kill -0 "$MAINPID"; then exit 1; fi + sleep 0.1 + done + + if test -e "${cfg.dataDir}/.first_startup"; then + ${optionalString (cfg.initialScript != null) '' + $PSQL -f "${cfg.initialScript}" -d postgres + ''} + rm -f "${cfg.dataDir}/.first_startup" + fi + '' + optionalString (cfg.ensureDatabases != []) '' + ${concatMapStrings (database: '' + $PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '${database}'" | grep -q 1 || $PSQL -tAc 'CREATE DATABASE "${database}"' + '') cfg.ensureDatabases} + '' + '' + ${concatMapStrings (user: '' + $PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname='${user.name}'" | grep -q 1 || $PSQL -tAc 'CREATE USER "${user.name}"' + ${concatStringsSep "\n" (mapAttrsToList (database: permission: '' + $PSQL -tAc 'GRANT ${permission} ON ${database} TO "${user.name}"' + '') user.ensurePermissions)} + '') cfg.ensureUsers} + ''; + in + "+${setupScript}"; } (mkIf (cfg.dataDir == "/var/lib/postgresql/${cfg.package.psqlSchema}") { StateDirectory = "postgresql postgresql/${cfg.package.psqlSchema}"; @@ -340,35 +370,6 @@ in }) ]; - # Wait for PostgreSQL to be ready to accept connections. - postStart = - '' - PSQL="${pkgs.utillinux}/bin/runuser -u ${cfg.superUser} -- psql --port=${toString cfg.port}" - - while ! $PSQL -d postgres -c "" 2> /dev/null; do - if ! kill -0 "$MAINPID"; then exit 1; fi - sleep 0.1 - done - - if test -e "${cfg.dataDir}/.first_startup"; then - ${optionalString (cfg.initialScript != null) '' - $PSQL -f "${cfg.initialScript}" -d postgres - ''} - rm -f "${cfg.dataDir}/.first_startup" - fi - '' + optionalString (cfg.ensureDatabases != []) '' - ${concatMapStrings (database: '' - $PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '${database}'" | grep -q 1 || $PSQL -tAc 'CREATE DATABASE "${database}"' - '') cfg.ensureDatabases} - '' + '' - ${concatMapStrings (user: '' - $PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname='${user.name}'" | grep -q 1 || $PSQL -tAc 'CREATE USER "${user.name}"' - ${concatStringsSep "\n" (mapAttrsToList (database: permission: '' - $PSQL -tAc 'GRANT ${permission} ON ${database} TO "${user.name}"' - '') user.ensurePermissions)} - '') cfg.ensureUsers} - ''; - unitConfig.RequiresMountsFor = "${cfg.dataDir}"; };