Merge pull request #95294 from aanderse/postgresql-rootless

nixos/postgresql: run ExecStartPost as an unprivileged user
This commit is contained in:
Aaron Andersen 2020-08-20 19:16:23 -04:00 committed by GitHub
commit b87b6abd17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 39 deletions

View file

@ -676,11 +676,19 @@ services.dokuwiki."mywiki" = {
<listitem> <listitem>
<para> <para>
The <xref linkend="opt-services.postgresql.dataDir"/> option is now set to <literal>"/var/lib/postgresql/${cfg.package.psqlSchema}"</literal> regardless of your The <xref linkend="opt-services.postgresql.dataDir"/> option is now set to <literal>"/var/lib/postgresql/${cfg.package.psqlSchema}"</literal> regardless of your
<xref linkend="opt-system.stateVersion"/>. Users with an existing postgresql install that have a <xref linkend="opt-system.stateVersion"/> of <literal>17.09</literal> or below <xref linkend="opt-system.stateVersion"/>. Users with an existing postgresql install that have a <xref linkend="opt-system.stateVersion"/> of <literal>17.03</literal> or below
should double check what the value of their <xref linkend="opt-services.postgresql.dataDir"/> option is (<literal>/var/db/postgresql</literal>) and then explicitly should double check what the value of their <xref linkend="opt-services.postgresql.dataDir"/> option is (<literal>/var/db/postgresql</literal>) and then explicitly
set this value to maintain compatibility: set this value to maintain compatibility:
<programlisting> <programlisting>
services.postgresql.dataDir = "/var/db/postgresql"; services.postgresql.dataDir = "/var/db/postgresql";
</programlisting>
</para>
<para>
The postgresql module now expects there to be a database super user account called <literal>postgres</literal> regardless of your <xref linkend="opt-system.stateVersion"/>. Users
with an existing postgresql install that have a <xref linkend="opt-system.stateVersion"/> of <literal>17.03</literal> or below should run the following SQL statements as a
database super admin user before upgrading:
<programlisting>
CREATE ROLE postgres LOGIN SUPERUSER;
</programlisting> </programlisting>
</para> </para>
</listitem> </listitem>

View file

@ -225,14 +225,15 @@ in
Contents of the <filename>recovery.conf</filename> file. Contents of the <filename>recovery.conf</filename> file.
''; '';
}; };
superUser = mkOption { superUser = mkOption {
type = types.str; type = types.str;
default= if versionAtLeast config.system.stateVersion "17.09" then "postgres" else "root"; default = "postgres";
internal = true; internal = true;
readOnly = true;
description = '' description = ''
NixOS traditionally used 'root' as superuser, most other distros use 'postgres'. PostgreSQL superuser account to use for various operations. Internal since changing
From 17.09 we also try to follow this standard. Internal since changing this value this value would lead to breakage while setting up databases.
would lead to breakage while setting up databases.
''; '';
}; };
}; };
@ -310,6 +311,35 @@ in
''} ''}
''; '';
# Wait for PostgreSQL to be ready to accept connections.
postStart =
''
PSQL="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}
'';
serviceConfig = mkMerge [ serviceConfig = mkMerge [
{ ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; { ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
User = "postgres"; User = "postgres";
@ -329,40 +359,6 @@ in
TimeoutSec = 120; TimeoutSec = 120;
ExecStart = "${postgresql}/bin/postgres"; 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}") { (mkIf (cfg.dataDir == "/var/lib/postgresql/${cfg.package.psqlSchema}") {
StateDirectory = "postgresql postgresql/${cfg.package.psqlSchema}"; StateDirectory = "postgresql postgresql/${cfg.package.psqlSchema}";