services: mysql: Add a default-value to the mysql-service-type.
[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>
67cadaca 5;;; Copyright © 2017 Christopher Baines <mail@cbaines.net>
5ee4cd69 6;;; Copyright © 2018 Clément Lassieur <clement@lassieur.org>
105369a4
DT
7;;;
8;;; This file is part of GNU Guix.
9;;;
10;;; GNU Guix is free software; you can redistribute it and/or modify it
11;;; under the terms of the GNU General Public License as published by
12;;; the Free Software Foundation; either version 3 of the License, or (at
13;;; your option) any later version.
14;;;
15;;; GNU Guix is distributed in the hope that it will be useful, but
16;;; WITHOUT ANY WARRANTY; without even the implied warranty of
17;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;;; GNU General Public License for more details.
19;;;
20;;; You should have received a copy of the GNU General Public License
21;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
22
23(define-module (gnu services databases)
24 #:use-module (gnu services)
0190c1c0 25 #:use-module (gnu services shepherd)
105369a4
DT
26 #:use-module (gnu system shadow)
27 #:use-module (gnu packages admin)
28 #:use-module (gnu packages databases)
119fdd0d 29 #:use-module (guix modules)
105369a4 30 #:use-module (guix records)
105369a4 31 #:use-module (guix gexp)
0adfe95a 32 #:use-module (ice-9 match)
24e96431
33 #:export (postgresql-configuration
34 postgresql-configuration?
35 postgresql-service
36 postgresql-service-type
37
119fdd0d
CB
38 memcached-service-type
39 <memcached-configuration>
40 memcached-configuration
41 memcached-configuration?
42 memcached-configuration-memecached
43 memcached-configuration-interfaces
44 memcached-configuration-tcp-port
45 memcached-configuration-udp-port
46 memcached-configuration-additional-options
47
5266ff71
CB
48 <mongodb-configuration>
49 mongodb-configuration
50 mongodb-configuration?
51 mongodb-configuration-mongodb
52 mongodb-configuration-config-file
53 mongodb-configuration-data-directory
54 mongodb-service-type
55
6575183b 56 mysql-service
24e96431
57 mysql-service-type
58 mysql-configuration
67cadaca
CB
59 mysql-configuration?
60
61 redis-configuration
62 redis-configuration?
63 redis-service-type))
105369a4
DT
64
65;;; Commentary:
66;;;
67;;; Database services.
68;;;
69;;; Code:
70
0adfe95a
LC
71(define-record-type* <postgresql-configuration>
72 postgresql-configuration make-postgresql-configuration
73 postgresql-configuration?
74 (postgresql postgresql-configuration-postgresql ;<package>
75 (default postgresql))
2d3d5cc5
CB
76 (port postgresql-configuration-port
77 (default 5432))
e05b780a
CB
78 (locale postgresql-configuration-locale
79 (default "en_US.utf8"))
1e6b9c6e
CB
80 (config-file postgresql-configuration-file
81 (default %default-postgres-config))
82 (data-directory postgresql-configuration-data-directory
83 (default "/var/lib/postgresql/data")))
0adfe95a 84
105369a4 85(define %default-postgres-hba
be1c2c54
LC
86 (plain-file "pg_hba.conf"
87 "
105369a4
DT
88local all all trust
89host all all 127.0.0.1/32 trust
90host all all ::1/128 trust"))
91
92(define %default-postgres-ident
be1c2c54 93 (plain-file "pg_ident.conf"
105369a4
DT
94 "# MAPNAME SYSTEM-USERNAME PG-USERNAME"))
95
96(define %default-postgres-config
be1c2c54 97 (mixed-text-file "postgresql.conf"
9b1cee97 98 "log_destination = 'syslog'\n"
be1c2c54 99 "hba_file = '" %default-postgres-hba "'\n"
8823ed4e 100 "ident_file = '" %default-postgres-ident "'\n"))
105369a4 101
0adfe95a
LC
102(define %postgresql-accounts
103 (list (user-group (name "postgres") (system? #t))
104 (user-account
105 (name "postgres")
106 (group "postgres")
107 (system? #t)
108 (comment "PostgreSQL server user")
109 (home-directory "/var/empty")
9e41130b 110 (shell (file-append shadow "/sbin/nologin")))))
0adfe95a
LC
111
112(define postgresql-activation
113 (match-lambda
e05b780a 114 (($ <postgresql-configuration> postgresql port locale config-file data-directory)
0adfe95a
LC
115 #~(begin
116 (use-modules (guix build utils)
117 (ice-9 match))
118
119 (let ((user (getpwnam "postgres"))
e05b780a
CB
120 (initdb (string-append #$postgresql "/bin/initdb"))
121 (initdb-args
122 (append
123 (if #$locale
124 (list (string-append "--locale=" #$locale))
125 '()))))
0adfe95a
LC
126 ;; Create db state directory.
127 (mkdir-p #$data-directory)
128 (chown #$data-directory (passwd:uid user) (passwd:gid user))
129
130 ;; Drop privileges and init state directory in a new
131 ;; process. Wait for it to finish before proceeding.
132 (match (primitive-fork)
133 (0
134 ;; Exit with a non-zero status code if an exception is thrown.
135 (dynamic-wind
136 (const #t)
137 (lambda ()
138 (setgid (passwd:gid user))
139 (setuid (passwd:uid user))
e05b780a
CB
140 (primitive-exit
141 (apply system*
142 initdb
143 "-D"
144 #$data-directory
145 initdb-args)))
0adfe95a
LC
146 (lambda ()
147 (primitive-exit 1))))
148 (pid (waitpid pid))))))))
149
d4053c71 150(define postgresql-shepherd-service
0adfe95a 151 (match-lambda
e05b780a 152 (($ <postgresql-configuration> postgresql port locale config-file data-directory)
5ee4cd69
CL
153 (let* ((pg_ctl-wrapper
154 ;; Wrapper script that switches to the 'postgres' user before
155 ;; launching daemon.
156 (program-file
157 "pg_ctl-wrapper"
158 #~(begin
159 (use-modules (ice-9 match)
160 (ice-9 format))
161 (match (command-line)
162 ((_ mode)
163 (let ((user (getpwnam "postgres"))
164 (pg_ctl #$(file-append postgresql "/bin/pg_ctl"))
165 (options (format #f "--config-file=~a -p ~d"
166 #$config-file #$port)))
167 (setgid (passwd:gid user))
168 (setuid (passwd:uid user))
169 (execl pg_ctl pg_ctl "-D" #$data-directory "-o" options
170 mode)))))))
171 (action (lambda args
172 #~(lambda _
173 (invoke #$pg_ctl-wrapper #$@args)))))
d4053c71 174 (list (shepherd-service
0adfe95a
LC
175 (provision '(postgres))
176 (documentation "Run the PostgreSQL daemon.")
9b1cee97 177 (requirement '(user-processes loopback syslogd))
5ee4cd69
CL
178 (start (action "start"))
179 (stop (action "stop"))))))))
0adfe95a
LC
180
181(define postgresql-service-type
182 (service-type (name 'postgresql)
183 (extensions
d4053c71
AK
184 (list (service-extension shepherd-root-service-type
185 postgresql-shepherd-service)
0adfe95a
LC
186 (service-extension activation-service-type
187 postgresql-activation)
188 (service-extension account-service-type
1e6b9c6e
CB
189 (const %postgresql-accounts))))
190 (default-value (postgresql-configuration))))
0adfe95a 191
105369a4 192(define* (postgresql-service #:key (postgresql postgresql)
2d3d5cc5 193 (port 5432)
e05b780a 194 (locale "en_US.utf8")
105369a4
DT
195 (config-file %default-postgres-config)
196 (data-directory "/var/lib/postgresql/data"))
197 "Return a service that runs @var{postgresql}, the PostgreSQL database server.
198
199The PostgreSQL daemon loads its runtime configuration from @var{config-file}
200and stores the database cluster in @var{data-directory}."
0adfe95a
LC
201 (service postgresql-service-type
202 (postgresql-configuration
203 (postgresql postgresql)
2d3d5cc5 204 (port port)
e05b780a 205 (locale locale)
0adfe95a
LC
206 (config-file config-file)
207 (data-directory data-directory))))
6575183b
SB
208
209\f
119fdd0d
CB
210;;;
211;;; Memcached
212;;;
213
214(define-record-type* <memcached-configuration>
215 memcached-configuration make-memcached-configuration
216 memcached-configuration?
217 (memcached memcached-configuration-memcached ;<package>
218 (default memcached))
219 (interfaces memcached-configuration-interfaces
220 (default '("0.0.0.0")))
221 (tcp-port memcached-configuration-tcp-port
222 (default 11211))
223 (udp-port memcached-configuration-udp-port
224 (default 11211))
225 (additional-options memcached-configuration-additional-options
226 (default '())))
227
228(define %memcached-accounts
229 (list (user-group (name "memcached") (system? #t))
230 (user-account
231 (name "memcached")
232 (group "memcached")
233 (system? #t)
234 (comment "Memcached server user")
235 (home-directory "/var/empty")
236 (shell (file-append shadow "/sbin/nologin")))))
237
6230e155
CB
238(define memcached-activation
239 #~(begin
240 (use-modules (guix build utils))
241 (let ((user (getpwnam "memcached")))
242 (mkdir-p "/var/run/memcached")
243 (chown "/var/run/memcached"
244 (passwd:uid user) (passwd:gid user)))))
245
119fdd0d
CB
246(define memcached-shepherd-service
247 (match-lambda
248 (($ <memcached-configuration> memcached interfaces tcp-port udp-port
249 additional-options)
250 (with-imported-modules (source-module-closure
251 '((gnu build shepherd)))
252 (list (shepherd-service
253 (provision '(memcached))
254 (documentation "Run the Memcached daemon.")
255 (requirement '(user-processes loopback))
256 (modules '((gnu build shepherd)))
257 (start #~(make-forkexec-constructor
258 `(#$(file-append memcached "/bin/memcached")
259 "-l" #$(string-join interfaces ",")
260 "-p" #$(number->string tcp-port)
261 "-U" #$(number->string udp-port)
262 "--daemon"
6230e155
CB
263 ;; Memcached changes to the memcached user prior to
264 ;; writing the pid file, so write it to a directory
265 ;; that memcached owns.
266 "-P" "/var/run/memcached/pid"
119fdd0d
CB
267 "-u" "memcached"
268 ,#$@additional-options)
269 #:log-file "/var/log/memcached"
6230e155 270 #:pid-file "/var/run/memcached/pid"))
119fdd0d
CB
271 (stop #~(make-kill-destructor))))))))
272
273(define memcached-service-type
274 (service-type (name 'memcached)
275 (extensions
276 (list (service-extension shepherd-root-service-type
277 memcached-shepherd-service)
6230e155
CB
278 (service-extension activation-service-type
279 (const memcached-activation))
119fdd0d
CB
280 (service-extension account-service-type
281 (const %memcached-accounts))))
282 (default-value (memcached-configuration))))
283
284\f
5266ff71
CB
285;;;
286;;; MongoDB
287;;;
288
289(define %default-mongodb-configuration-file
290 (plain-file
291 "mongodb.yaml"
292 "# GNU Guix: MongoDB default configuration file
293processManagement:
294 pidFilePath: /var/run/mongodb/pid
295storage:
296 dbPath: /var/lib/mongodb
297"))
298
299
300(define-record-type* <mongodb-configuration>
301 mongodb-configuration make-mongodb-configuration
302 mongodb-configuration?
303 (mongodb mongodb-configuration-mongodb
304 (default mongodb))
305 (config-file mongodb-configuration-config-file
306 (default %default-mongodb-configuration-file))
307 (data-directory mongodb-configuration-data-directory
308 (default "/var/lib/mongodb")))
309
310(define %mongodb-accounts
311 (list (user-group (name "mongodb") (system? #t))
312 (user-account
313 (name "mongodb")
314 (group "mongodb")
315 (system? #t)
316 (comment "Mongodb server user")
317 (home-directory "/var/lib/mongodb")
318 (shell (file-append shadow "/sbin/nologin")))))
319
320(define mongodb-activation
321 (match-lambda
322 (($ <mongodb-configuration> mongodb config-file data-directory)
323 #~(begin
324 (use-modules (guix build utils))
325 (let ((user (getpwnam "mongodb")))
326 (for-each
327 (lambda (directory)
328 (mkdir-p directory)
329 (chown directory
330 (passwd:uid user) (passwd:gid user)))
331 '("/var/run/mongodb" #$data-directory)))))))
332
333(define mongodb-shepherd-service
334 (match-lambda
335 (($ <mongodb-configuration> mongodb config-file data-directory)
336 (shepherd-service
337 (provision '(mongodb))
338 (documentation "Run the Mongodb daemon.")
339 (requirement '(user-processes loopback))
340 (start #~(make-forkexec-constructor
341 `(,(string-append #$mongodb "/bin/mongod")
342 "--config"
343 ,#$config-file)
344 #:user "mongodb"
345 #:group "mongodb"
346 #:pid-file "/var/run/mongodb/pid"
347 #:log-file "/var/log/mongodb.log"))
348 (stop #~(make-kill-destructor))))))
349
350(define mongodb-service-type
351 (service-type
352 (name 'mongodb)
353 (description "Run the MongoDB document database server.")
354 (extensions
355 (list (service-extension shepherd-root-service-type
356 (compose list
357 mongodb-shepherd-service))
358 (service-extension activation-service-type
359 mongodb-activation)
360 (service-extension account-service-type
361 (const %mongodb-accounts))))
362 (default-value
363 (mongodb-configuration))))
364
365\f
6575183b
SB
366;;;
367;;; MySQL.
368;;;
369
370(define-record-type* <mysql-configuration>
371 mysql-configuration make-mysql-configuration
372 mysql-configuration?
4b41febf
CB
373 (mysql mysql-configuration-mysql (default mariadb))
374 (port mysql-configuration-port (default 3306)))
6575183b
SB
375
376(define %mysql-accounts
377 (list (user-group
378 (name "mysql")
379 (system? #t))
380 (user-account
381 (name "mysql")
382 (group "mysql")
383 (system? #t)
384 (home-directory "/var/empty")
9e41130b 385 (shell (file-append shadow "/sbin/nologin")))))
6575183b
SB
386
387(define mysql-configuration-file
388 (match-lambda
4b41febf
CB
389 (($ <mysql-configuration> mysql port)
390 (mixed-text-file "my.cnf" "[mysqld]
6575183b
SB
391datadir=/var/lib/mysql
392socket=/run/mysqld/mysqld.sock
4b41febf 393port=" (number->string port) "
6575183b
SB
394"))))
395
396(define (%mysql-activation config)
397 "Return an activation gexp for the MySQL or MariaDB database server."
398 (let ((mysql (mysql-configuration-mysql config))
399 (my.cnf (mysql-configuration-file config)))
400 #~(begin
401 (use-modules (ice-9 popen)
402 (guix build utils))
403 (let* ((mysqld (string-append #$mysql "/bin/mysqld"))
404 (user (getpwnam "mysql"))
405 (uid (passwd:uid user))
406 (gid (passwd:gid user))
407 (datadir "/var/lib/mysql")
408 (rundir "/run/mysqld"))
409 (mkdir-p datadir)
410 (chown datadir uid gid)
411 (mkdir-p rundir)
412 (chown rundir uid gid)
413 ;; Initialize the database when it doesn't exist.
414 (when (not (file-exists? (string-append datadir "/mysql")))
415 (if (string-prefix? "mysql-" (strip-store-file-name #$mysql))
416 ;; For MySQL.
417 (system* mysqld
418 (string-append "--defaults-file=" #$my.cnf)
419 "--initialize"
420 "--user=mysql")
421 ;; For MariaDB.
422 ;; XXX: The 'mysql_install_db' script doesn't work directly
423 ;; due to missing 'mkdir' in PATH.
424 (let ((p (open-pipe* OPEN_WRITE mysqld
425 (string-append
426 "--defaults-file=" #$my.cnf)
427 "--bootstrap"
428 "--user=mysql")))
429 ;; Create the system database, as does by 'mysql_install_db'.
430 (display "create database mysql;\n" p)
431 (display "use mysql;\n" p)
432 (for-each
433 (lambda (sql)
434 (call-with-input-file
435 (string-append #$mysql "/share/mysql/" sql)
436 (lambda (in) (dump-port in p))))
437 '("mysql_system_tables.sql"
438 "mysql_performance_tables.sql"
439 "mysql_system_tables_data.sql"
440 "fill_help_tables.sql"))
441 ;; Remove the anonymous user and disable root access from
442 ;; remote machines, as does by 'mysql_secure_installation'.
443 (display "
444DELETE FROM user WHERE User='';
445DELETE FROM user WHERE User='root' AND
446 Host NOT IN ('localhost', '127.0.0.1', '::1');
447FLUSH PRIVILEGES;
448" p)
449 (close-pipe p))))))))
450
451(define (mysql-shepherd-service config)
452 (list (shepherd-service
453 (provision '(mysql))
454 (documentation "Run the MySQL server.")
455 (start (let ((mysql (mysql-configuration-mysql config))
456 (my.cnf (mysql-configuration-file config)))
457 #~(make-forkexec-constructor
458 (list (string-append #$mysql "/bin/mysqld")
459 (string-append "--defaults-file=" #$my.cnf))
460 #:user "mysql" #:group "mysql")))
461 (stop #~(make-kill-destructor)))))
462
463(define mysql-service-type
464 (service-type
465 (name 'mysql)
466 (extensions
467 (list (service-extension account-service-type
468 (const %mysql-accounts))
469 (service-extension activation-service-type
470 %mysql-activation)
471 (service-extension shepherd-root-service-type
e903738f
CB
472 mysql-shepherd-service)))
473 (default-value (mysql-configuration))))
6575183b
SB
474
475(define* (mysql-service #:key (config (mysql-configuration)))
476 "Return a service that runs @command{mysqld}, the MySQL or MariaDB
477database server.
478
479The optional @var{config} argument specifies the configuration for
480@command{mysqld}, which should be a @code{<mysql-configuration>} object."
481 (service mysql-service-type config))
67cadaca
CB
482
483\f
484;;;
485;;; Redis
486;;;
487
488(define-record-type* <redis-configuration>
489 redis-configuration make-redis-configuration
490 redis-configuration?
491 (redis redis-configuration-redis ;<package>
492 (default redis))
493 (bind redis-configuration-bind
494 (default "127.0.0.1"))
495 (port redis-configuration-port
496 (default 6379))
497 (working-directory redis-configuration-working-directory
498 (default "/var/lib/redis"))
499 (config-file redis-configuration-config-file
500 (default #f)))
501
502(define (default-redis.conf bind port working-directory)
503 (mixed-text-file "redis.conf"
504 "bind " bind "\n"
505 "port " (number->string port) "\n"
506 "dir " working-directory "\n"
507 "daemonize no\n"))
508
509(define %redis-accounts
510 (list (user-group (name "redis") (system? #t))
511 (user-account
512 (name "redis")
513 (group "redis")
514 (system? #t)
515 (comment "Redis server user")
516 (home-directory "/var/empty")
517 (shell (file-append shadow "/sbin/nologin")))))
518
519(define redis-activation
520 (match-lambda
521 (($ <redis-configuration> redis bind port working-directory config-file)
522 #~(begin
523 (use-modules (guix build utils)
524 (ice-9 match))
525
526 (let ((user (getpwnam "redis")))
527 (mkdir-p #$working-directory)
528 (chown #$working-directory (passwd:uid user) (passwd:gid user)))))))
529
530(define redis-shepherd-service
531 (match-lambda
532 (($ <redis-configuration> redis bind port working-directory config-file)
533 (let ((config-file
534 (or config-file
535 (default-redis.conf bind port working-directory))))
536 (list (shepherd-service
537 (provision '(redis))
538 (documentation "Run the Redis daemon.")
539 (requirement '(user-processes syslogd))
540 (start #~(make-forkexec-constructor
541 '(#$(file-append redis "/bin/redis-server")
542 #$config-file)
543 #:user "redis"
544 #:group "redis"))
545 (stop #~(make-kill-destructor))))))))
546
547(define redis-service-type
548 (service-type (name 'redis)
549 (extensions
550 (list (service-extension shepherd-root-service-type
551 redis-shepherd-service)
552 (service-extension activation-service-type
553 redis-activation)
554 (service-extension account-service-type
555 (const %redis-accounts))))))