at 18.09-beta 8.5 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.services.postgresql; 8 9 # see description of extraPlugins 10 postgresqlAndPlugins = pg: 11 if cfg.extraPlugins == [] then pg 12 else pkgs.buildEnv { 13 name = "postgresql-and-plugins-${(builtins.parseDrvName pg.name).version}"; 14 paths = [ pg pg.lib ] ++ cfg.extraPlugins; 15 buildInputs = [ pkgs.makeWrapper ]; 16 postBuild = 17 '' 18 mkdir -p $out/bin 19 rm $out/bin/{pg_config,postgres,pg_ctl} 20 cp --target-directory=$out/bin ${pg}/bin/{postgres,pg_config,pg_ctl} 21 wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib 22 ''; 23 }; 24 25 postgresql = postgresqlAndPlugins cfg.package; 26 27 # The main PostgreSQL configuration file. 28 configFile = pkgs.writeText "postgresql.conf" 29 '' 30 hba_file = '${pkgs.writeText "pg_hba.conf" cfg.authentication}' 31 ident_file = '${pkgs.writeText "pg_ident.conf" cfg.identMap}' 32 log_destination = 'stderr' 33 listen_addresses = '${if cfg.enableTCPIP then "*" else "localhost"}' 34 port = ${toString cfg.port} 35 ${cfg.extraConfig} 36 ''; 37 38in 39 40{ 41 42 ###### interface 43 44 options = { 45 46 services.postgresql = { 47 48 enable = mkOption { 49 type = types.bool; 50 default = false; 51 description = '' 52 Whether to run PostgreSQL. 53 ''; 54 }; 55 56 package = mkOption { 57 type = types.package; 58 example = literalExample "pkgs.postgresql96"; 59 description = '' 60 PostgreSQL package to use. 61 ''; 62 }; 63 64 port = mkOption { 65 type = types.int; 66 default = 5432; 67 description = '' 68 The port on which PostgreSQL listens. 69 ''; 70 }; 71 72 dataDir = mkOption { 73 type = types.path; 74 example = "/var/lib/postgresql/9.6"; 75 description = '' 76 Data directory for PostgreSQL. 77 ''; 78 }; 79 80 authentication = mkOption { 81 type = types.lines; 82 default = ""; 83 description = '' 84 Defines how users authenticate themselves to the server. By 85 default, "trust" access to local users will always be granted 86 along with any other custom options. If you do not want this, 87 set this option using "lib.mkForce" to override this 88 behaviour. 89 ''; 90 }; 91 92 identMap = mkOption { 93 type = types.lines; 94 default = ""; 95 description = '' 96 Defines the mapping from system users to database users. 97 ''; 98 }; 99 100 initialScript = mkOption { 101 type = types.nullOr types.path; 102 default = null; 103 description = '' 104 A file containing SQL statements to execute on first startup. 105 ''; 106 }; 107 108 enableTCPIP = mkOption { 109 type = types.bool; 110 default = false; 111 description = '' 112 Whether PostgreSQL should listen on all network interfaces. 113 If disabled, the database can only be accessed via its Unix 114 domain socket or via TCP connections to localhost. 115 ''; 116 }; 117 118 extraPlugins = mkOption { 119 type = types.listOf types.path; 120 default = []; 121 example = literalExample "[ (pkgs.postgis.override { postgresql = pkgs.postgresql94; }) ]"; 122 description = '' 123 When this list contains elements a new store path is created. 124 PostgreSQL and the elements are symlinked into it. Then pg_config, 125 postgres and pg_ctl are copied to make them use the new 126 $out/lib directory as pkglibdir. This makes it possible to use postgis 127 without patching the .sql files which reference $libdir/postgis-1.5. 128 ''; 129 # Note: the duplication of executables is about 4MB size. 130 # So a nicer solution was patching postgresql to allow setting the 131 # libdir explicitely. 132 }; 133 134 extraConfig = mkOption { 135 type = types.lines; 136 default = ""; 137 description = "Additional text to be appended to <filename>postgresql.conf</filename>."; 138 }; 139 140 recoveryConfig = mkOption { 141 type = types.nullOr types.lines; 142 default = null; 143 description = '' 144 Contents of the <filename>recovery.conf</filename> file. 145 ''; 146 }; 147 superUser = mkOption { 148 type = types.str; 149 default= if versionAtLeast config.system.stateVersion "17.09" then "postgres" else "root"; 150 internal = true; 151 description = '' 152 NixOS traditionally used 'root' as superuser, most other distros use 'postgres'. 153 From 17.09 we also try to follow this standard. Internal since changing this value 154 would lead to breakage while setting up databases. 155 ''; 156 }; 157 }; 158 159 }; 160 161 162 ###### implementation 163 164 config = mkIf config.services.postgresql.enable { 165 166 services.postgresql.package = 167 # Note: when changing the default, make it conditional on 168 # ‘system.stateVersion’ to maintain compatibility with existing 169 # systems! 170 mkDefault (if versionAtLeast config.system.stateVersion "17.09" then pkgs.postgresql96 171 else if versionAtLeast config.system.stateVersion "16.03" then pkgs.postgresql95 172 else pkgs.postgresql94); 173 174 services.postgresql.dataDir = 175 mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}" 176 else "/var/db/postgresql"); 177 178 services.postgresql.authentication = mkAfter 179 '' 180 # Generated file; do not edit! 181 local all all ident 182 host all all 127.0.0.1/32 md5 183 host all all ::1/128 md5 184 ''; 185 186 users.users.postgres = 187 { name = "postgres"; 188 uid = config.ids.uids.postgres; 189 group = "postgres"; 190 description = "PostgreSQL server user"; 191 }; 192 193 users.groups.postgres.gid = config.ids.gids.postgres; 194 195 environment.systemPackages = [ postgresql ]; 196 197 systemd.services.postgresql = 198 { description = "PostgreSQL Server"; 199 200 wantedBy = [ "multi-user.target" ]; 201 after = [ "network.target" ]; 202 203 environment.PGDATA = cfg.dataDir; 204 205 path = [ postgresql ]; 206 207 preStart = 208 '' 209 # Create data directory. 210 if ! test -e ${cfg.dataDir}/PG_VERSION; then 211 mkdir -m 0700 -p ${cfg.dataDir} 212 rm -f ${cfg.dataDir}/*.conf 213 chown -R postgres:postgres ${cfg.dataDir} 214 fi 215 ''; # */ 216 217 script = 218 '' 219 # Initialise the database. 220 if ! test -e ${cfg.dataDir}/PG_VERSION; then 221 initdb -U ${cfg.superUser} 222 # See postStart! 223 touch "${cfg.dataDir}/.first_startup" 224 fi 225 ln -sfn "${configFile}" "${cfg.dataDir}/postgresql.conf" 226 ${optionalString (cfg.recoveryConfig != null) '' 227 ln -sfn "${pkgs.writeText "recovery.conf" cfg.recoveryConfig}" \ 228 "${cfg.dataDir}/recovery.conf" 229 ''} 230 231 exec postgres 232 ''; 233 234 serviceConfig = 235 { ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 236 User = "postgres"; 237 Group = "postgres"; 238 PermissionsStartOnly = true; 239 240 # Shut down Postgres using SIGINT ("Fast Shutdown mode"). See 241 # http://www.postgresql.org/docs/current/static/server-shutdown.html 242 KillSignal = "SIGINT"; 243 KillMode = "mixed"; 244 245 # Give Postgres a decent amount of time to clean up after 246 # receiving systemd's SIGINT. 247 TimeoutSec = 120; 248 }; 249 250 # Wait for PostgreSQL to be ready to accept connections. 251 postStart = 252 '' 253 while ! ${pkgs.sudo}/bin/sudo -u ${cfg.superUser} psql --port=${toString cfg.port} -d postgres -c "" 2> /dev/null; do 254 if ! kill -0 "$MAINPID"; then exit 1; fi 255 sleep 0.1 256 done 257 258 if test -e "${cfg.dataDir}/.first_startup"; then 259 ${optionalString (cfg.initialScript != null) '' 260 ${pkgs.sudo}/bin/sudo -u ${cfg.superUser} psql -f "${cfg.initialScript}" --port=${toString cfg.port} -d postgres 261 ''} 262 rm -f "${cfg.dataDir}/.first_startup" 263 fi 264 ''; 265 266 unitConfig.RequiresMountsFor = "${cfg.dataDir}"; 267 }; 268 269 }; 270 271 meta.doc = ./postgresql.xml; 272 273}