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