services: postgresql: Add port to configuration
[jackhill/guix/guix.git] / gnu / services / databases.scm
CommitLineData
105369a4
DT
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2015 David Thompson <davet@gnu.org>
9b1cee97 3;;; Copyright © 2015, 2016 Ludovic Courtès <ludo@gnu.org>
8823ed4e 4;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
105369a4
DT
5;;;
6;;; This file is part of GNU Guix.
7;;;
8;;; GNU Guix is free software; you can redistribute it and/or modify it
9;;; under the terms of the GNU General Public License as published by
10;;; the Free Software Foundation; either version 3 of the License, or (at
11;;; your option) any later version.
12;;;
13;;; GNU Guix is distributed in the hope that it will be useful, but
14;;; WITHOUT ANY WARRANTY; without even the implied warranty of
15;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;;; GNU General Public License for more details.
17;;;
18;;; You should have received a copy of the GNU General Public License
19;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
20
21(define-module (gnu services databases)
22 #:use-module (gnu services)
0190c1c0 23 #:use-module (gnu services shepherd)
105369a4
DT
24 #:use-module (gnu system shadow)
25 #:use-module (gnu packages admin)
26 #:use-module (gnu packages databases)
27 #:use-module (guix records)
105369a4 28 #:use-module (guix gexp)
0adfe95a 29 #:use-module (ice-9 match)
24e96431
30 #:export (postgresql-configuration
31 postgresql-configuration?
32 postgresql-service
33 postgresql-service-type
34
6575183b 35 mysql-service
24e96431
36 mysql-service-type
37 mysql-configuration
38 mysql-configuration?))
105369a4
DT
39
40;;; Commentary:
41;;;
42;;; Database services.
43;;;
44;;; Code:
45
0adfe95a
LC
46(define-record-type* <postgresql-configuration>
47 postgresql-configuration make-postgresql-configuration
48 postgresql-configuration?
49 (postgresql postgresql-configuration-postgresql ;<package>
50 (default postgresql))
2d3d5cc5
CB
51 (port postgresql-configuration-port
52 (default 5432))
0adfe95a
LC
53 (config-file postgresql-configuration-file)
54 (data-directory postgresql-configuration-data-directory))
55
105369a4 56(define %default-postgres-hba
be1c2c54
LC
57 (plain-file "pg_hba.conf"
58 "
105369a4
DT
59local all all trust
60host all all 127.0.0.1/32 trust
61host all all ::1/128 trust"))
62
63(define %default-postgres-ident
be1c2c54 64 (plain-file "pg_ident.conf"
105369a4
DT
65 "# MAPNAME SYSTEM-USERNAME PG-USERNAME"))
66
67(define %default-postgres-config
be1c2c54 68 (mixed-text-file "postgresql.conf"
9b1cee97 69 "log_destination = 'syslog'\n"
be1c2c54 70 "hba_file = '" %default-postgres-hba "'\n"
8823ed4e 71 "ident_file = '" %default-postgres-ident "'\n"))
105369a4 72
0adfe95a
LC
73(define %postgresql-accounts
74 (list (user-group (name "postgres") (system? #t))
75 (user-account
76 (name "postgres")
77 (group "postgres")
78 (system? #t)
79 (comment "PostgreSQL server user")
80 (home-directory "/var/empty")
9e41130b 81 (shell (file-append shadow "/sbin/nologin")))))
0adfe95a
LC
82
83(define postgresql-activation
84 (match-lambda
2d3d5cc5 85 (($ <postgresql-configuration> postgresql port config-file data-directory)
0adfe95a
LC
86 #~(begin
87 (use-modules (guix build utils)
88 (ice-9 match))
89
90 (let ((user (getpwnam "postgres"))
91 (initdb (string-append #$postgresql "/bin/initdb")))
92 ;; Create db state directory.
93 (mkdir-p #$data-directory)
94 (chown #$data-directory (passwd:uid user) (passwd:gid user))
95
96 ;; Drop privileges and init state directory in a new
97 ;; process. Wait for it to finish before proceeding.
98 (match (primitive-fork)
99 (0
100 ;; Exit with a non-zero status code if an exception is thrown.
101 (dynamic-wind
102 (const #t)
103 (lambda ()
104 (setgid (passwd:gid user))
105 (setuid (passwd:uid user))
106 (primitive-exit (system* initdb "-D" #$data-directory)))
107 (lambda ()
108 (primitive-exit 1))))
109 (pid (waitpid pid))))))))
110
d4053c71 111(define postgresql-shepherd-service
0adfe95a 112 (match-lambda
2d3d5cc5 113 (($ <postgresql-configuration> postgresql port config-file data-directory)
0adfe95a
LC
114 (let ((start-script
115 ;; Wrapper script that switches to the 'postgres' user before
116 ;; launching daemon.
117 (program-file "start-postgres"
118 #~(let ((user (getpwnam "postgres"))
119 (postgres (string-append #$postgresql
120 "/bin/postgres")))
121 (setgid (passwd:gid user))
122 (setuid (passwd:uid user))
123 (system* postgres
124 (string-append "--config-file="
125 #$config-file)
2d3d5cc5 126 "-p" (number->string #$port)
0adfe95a 127 "-D" #$data-directory)))))
d4053c71 128 (list (shepherd-service
0adfe95a
LC
129 (provision '(postgres))
130 (documentation "Run the PostgreSQL daemon.")
9b1cee97 131 (requirement '(user-processes loopback syslogd))
0adfe95a
LC
132 (start #~(make-forkexec-constructor #$start-script))
133 (stop #~(make-kill-destructor))))))))
134
135(define postgresql-service-type
136 (service-type (name 'postgresql)
137 (extensions
d4053c71
AK
138 (list (service-extension shepherd-root-service-type
139 postgresql-shepherd-service)
0adfe95a
LC
140 (service-extension activation-service-type
141 postgresql-activation)
142 (service-extension account-service-type
143 (const %postgresql-accounts))))))
144
105369a4 145(define* (postgresql-service #:key (postgresql postgresql)
2d3d5cc5 146 (port 5432)
105369a4
DT
147 (config-file %default-postgres-config)
148 (data-directory "/var/lib/postgresql/data"))
149 "Return a service that runs @var{postgresql}, the PostgreSQL database server.
150
151The PostgreSQL daemon loads its runtime configuration from @var{config-file}
152and stores the database cluster in @var{data-directory}."
0adfe95a
LC
153 (service postgresql-service-type
154 (postgresql-configuration
155 (postgresql postgresql)
2d3d5cc5 156 (port port)
0adfe95a
LC
157 (config-file config-file)
158 (data-directory data-directory))))
6575183b
SB
159
160\f
161;;;
162;;; MySQL.
163;;;
164
165(define-record-type* <mysql-configuration>
166 mysql-configuration make-mysql-configuration
167 mysql-configuration?
4b41febf
CB
168 (mysql mysql-configuration-mysql (default mariadb))
169 (port mysql-configuration-port (default 3306)))
6575183b
SB
170
171(define %mysql-accounts
172 (list (user-group
173 (name "mysql")
174 (system? #t))
175 (user-account
176 (name "mysql")
177 (group "mysql")
178 (system? #t)
179 (home-directory "/var/empty")
9e41130b 180 (shell (file-append shadow "/sbin/nologin")))))
6575183b
SB
181
182(define mysql-configuration-file
183 (match-lambda
4b41febf
CB
184 (($ <mysql-configuration> mysql port)
185 (mixed-text-file "my.cnf" "[mysqld]
6575183b
SB
186datadir=/var/lib/mysql
187socket=/run/mysqld/mysqld.sock
4b41febf 188port=" (number->string port) "
6575183b
SB
189"))))
190
191(define (%mysql-activation config)
192 "Return an activation gexp for the MySQL or MariaDB database server."
193 (let ((mysql (mysql-configuration-mysql config))
194 (my.cnf (mysql-configuration-file config)))
195 #~(begin
196 (use-modules (ice-9 popen)
197 (guix build utils))
198 (let* ((mysqld (string-append #$mysql "/bin/mysqld"))
199 (user (getpwnam "mysql"))
200 (uid (passwd:uid user))
201 (gid (passwd:gid user))
202 (datadir "/var/lib/mysql")
203 (rundir "/run/mysqld"))
204 (mkdir-p datadir)
205 (chown datadir uid gid)
206 (mkdir-p rundir)
207 (chown rundir uid gid)
208 ;; Initialize the database when it doesn't exist.
209 (when (not (file-exists? (string-append datadir "/mysql")))
210 (if (string-prefix? "mysql-" (strip-store-file-name #$mysql))
211 ;; For MySQL.
212 (system* mysqld
213 (string-append "--defaults-file=" #$my.cnf)
214 "--initialize"
215 "--user=mysql")
216 ;; For MariaDB.
217 ;; XXX: The 'mysql_install_db' script doesn't work directly
218 ;; due to missing 'mkdir' in PATH.
219 (let ((p (open-pipe* OPEN_WRITE mysqld
220 (string-append
221 "--defaults-file=" #$my.cnf)
222 "--bootstrap"
223 "--user=mysql")))
224 ;; Create the system database, as does by 'mysql_install_db'.
225 (display "create database mysql;\n" p)
226 (display "use mysql;\n" p)
227 (for-each
228 (lambda (sql)
229 (call-with-input-file
230 (string-append #$mysql "/share/mysql/" sql)
231 (lambda (in) (dump-port in p))))
232 '("mysql_system_tables.sql"
233 "mysql_performance_tables.sql"
234 "mysql_system_tables_data.sql"
235 "fill_help_tables.sql"))
236 ;; Remove the anonymous user and disable root access from
237 ;; remote machines, as does by 'mysql_secure_installation'.
238 (display "
239DELETE FROM user WHERE User='';
240DELETE FROM user WHERE User='root' AND
241 Host NOT IN ('localhost', '127.0.0.1', '::1');
242FLUSH PRIVILEGES;
243" p)
244 (close-pipe p))))))))
245
246(define (mysql-shepherd-service config)
247 (list (shepherd-service
248 (provision '(mysql))
249 (documentation "Run the MySQL server.")
250 (start (let ((mysql (mysql-configuration-mysql config))
251 (my.cnf (mysql-configuration-file config)))
252 #~(make-forkexec-constructor
253 (list (string-append #$mysql "/bin/mysqld")
254 (string-append "--defaults-file=" #$my.cnf))
255 #:user "mysql" #:group "mysql")))
256 (stop #~(make-kill-destructor)))))
257
258(define mysql-service-type
259 (service-type
260 (name 'mysql)
261 (extensions
262 (list (service-extension account-service-type
263 (const %mysql-accounts))
264 (service-extension activation-service-type
265 %mysql-activation)
266 (service-extension shepherd-root-service-type
267 mysql-shepherd-service)))))
268
269(define* (mysql-service #:key (config (mysql-configuration)))
270 "Return a service that runs @command{mysqld}, the MySQL or MariaDB
271database server.
272
273The optional @var{config} argument specifies the configuration for
274@command{mysqld}, which should be a @code{<mysql-configuration>} object."
275 (service mysql-service-type config))