services: avahi: Add #:debug? parameter.
[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)
6575183b
SB
30 #:export (postgresql-service
31 mysql-service
32 mysql-configuration))
105369a4
DT
33
34;;; Commentary:
35;;;
36;;; Database services.
37;;;
38;;; Code:
39
0adfe95a
LC
40(define-record-type* <postgresql-configuration>
41 postgresql-configuration make-postgresql-configuration
42 postgresql-configuration?
43 (postgresql postgresql-configuration-postgresql ;<package>
44 (default postgresql))
45 (config-file postgresql-configuration-file)
46 (data-directory postgresql-configuration-data-directory))
47
105369a4 48(define %default-postgres-hba
be1c2c54
LC
49 (plain-file "pg_hba.conf"
50 "
105369a4
DT
51local all all trust
52host all all 127.0.0.1/32 trust
53host all all ::1/128 trust"))
54
55(define %default-postgres-ident
be1c2c54 56 (plain-file "pg_ident.conf"
105369a4
DT
57 "# MAPNAME SYSTEM-USERNAME PG-USERNAME"))
58
59(define %default-postgres-config
be1c2c54 60 (mixed-text-file "postgresql.conf"
9b1cee97 61 "log_destination = 'syslog'\n"
be1c2c54 62 "hba_file = '" %default-postgres-hba "'\n"
8823ed4e 63 "ident_file = '" %default-postgres-ident "'\n"))
105369a4 64
0adfe95a
LC
65(define %postgresql-accounts
66 (list (user-group (name "postgres") (system? #t))
67 (user-account
68 (name "postgres")
69 (group "postgres")
70 (system? #t)
71 (comment "PostgreSQL server user")
72 (home-directory "/var/empty")
73 (shell #~(string-append #$shadow "/sbin/nologin")))))
74
75(define postgresql-activation
76 (match-lambda
77 (($ <postgresql-configuration> postgresql config-file data-directory)
78 #~(begin
79 (use-modules (guix build utils)
80 (ice-9 match))
81
82 (let ((user (getpwnam "postgres"))
83 (initdb (string-append #$postgresql "/bin/initdb")))
84 ;; Create db state directory.
85 (mkdir-p #$data-directory)
86 (chown #$data-directory (passwd:uid user) (passwd:gid user))
87
88 ;; Drop privileges and init state directory in a new
89 ;; process. Wait for it to finish before proceeding.
90 (match (primitive-fork)
91 (0
92 ;; Exit with a non-zero status code if an exception is thrown.
93 (dynamic-wind
94 (const #t)
95 (lambda ()
96 (setgid (passwd:gid user))
97 (setuid (passwd:uid user))
98 (primitive-exit (system* initdb "-D" #$data-directory)))
99 (lambda ()
100 (primitive-exit 1))))
101 (pid (waitpid pid))))))))
102
d4053c71 103(define postgresql-shepherd-service
0adfe95a
LC
104 (match-lambda
105 (($ <postgresql-configuration> postgresql config-file data-directory)
106 (let ((start-script
107 ;; Wrapper script that switches to the 'postgres' user before
108 ;; launching daemon.
109 (program-file "start-postgres"
110 #~(let ((user (getpwnam "postgres"))
111 (postgres (string-append #$postgresql
112 "/bin/postgres")))
113 (setgid (passwd:gid user))
114 (setuid (passwd:uid user))
115 (system* postgres
116 (string-append "--config-file="
117 #$config-file)
118 "-D" #$data-directory)))))
d4053c71 119 (list (shepherd-service
0adfe95a
LC
120 (provision '(postgres))
121 (documentation "Run the PostgreSQL daemon.")
9b1cee97 122 (requirement '(user-processes loopback syslogd))
0adfe95a
LC
123 (start #~(make-forkexec-constructor #$start-script))
124 (stop #~(make-kill-destructor))))))))
125
126(define postgresql-service-type
127 (service-type (name 'postgresql)
128 (extensions
d4053c71
AK
129 (list (service-extension shepherd-root-service-type
130 postgresql-shepherd-service)
0adfe95a
LC
131 (service-extension activation-service-type
132 postgresql-activation)
133 (service-extension account-service-type
134 (const %postgresql-accounts))))))
135
105369a4
DT
136(define* (postgresql-service #:key (postgresql postgresql)
137 (config-file %default-postgres-config)
138 (data-directory "/var/lib/postgresql/data"))
139 "Return a service that runs @var{postgresql}, the PostgreSQL database server.
140
141The PostgreSQL daemon loads its runtime configuration from @var{config-file}
142and stores the database cluster in @var{data-directory}."
0adfe95a
LC
143 (service postgresql-service-type
144 (postgresql-configuration
145 (postgresql postgresql)
146 (config-file config-file)
147 (data-directory data-directory))))
6575183b
SB
148
149\f
150;;;
151;;; MySQL.
152;;;
153
154(define-record-type* <mysql-configuration>
155 mysql-configuration make-mysql-configuration
156 mysql-configuration?
157 (mysql mysql-configuration-mysql (default mariadb)))
158
159(define %mysql-accounts
160 (list (user-group
161 (name "mysql")
162 (system? #t))
163 (user-account
164 (name "mysql")
165 (group "mysql")
166 (system? #t)
167 (home-directory "/var/empty")
168 (shell #~(string-append #$shadow "/sbin/nologin")))))
169
170(define mysql-configuration-file
171 (match-lambda
172 (($ <mysql-configuration> mysql)
173 (plain-file "my.cnf" "[mysqld]
174datadir=/var/lib/mysql
175socket=/run/mysqld/mysqld.sock
176"))))
177
178(define (%mysql-activation config)
179 "Return an activation gexp for the MySQL or MariaDB database server."
180 (let ((mysql (mysql-configuration-mysql config))
181 (my.cnf (mysql-configuration-file config)))
182 #~(begin
183 (use-modules (ice-9 popen)
184 (guix build utils))
185 (let* ((mysqld (string-append #$mysql "/bin/mysqld"))
186 (user (getpwnam "mysql"))
187 (uid (passwd:uid user))
188 (gid (passwd:gid user))
189 (datadir "/var/lib/mysql")
190 (rundir "/run/mysqld"))
191 (mkdir-p datadir)
192 (chown datadir uid gid)
193 (mkdir-p rundir)
194 (chown rundir uid gid)
195 ;; Initialize the database when it doesn't exist.
196 (when (not (file-exists? (string-append datadir "/mysql")))
197 (if (string-prefix? "mysql-" (strip-store-file-name #$mysql))
198 ;; For MySQL.
199 (system* mysqld
200 (string-append "--defaults-file=" #$my.cnf)
201 "--initialize"
202 "--user=mysql")
203 ;; For MariaDB.
204 ;; XXX: The 'mysql_install_db' script doesn't work directly
205 ;; due to missing 'mkdir' in PATH.
206 (let ((p (open-pipe* OPEN_WRITE mysqld
207 (string-append
208 "--defaults-file=" #$my.cnf)
209 "--bootstrap"
210 "--user=mysql")))
211 ;; Create the system database, as does by 'mysql_install_db'.
212 (display "create database mysql;\n" p)
213 (display "use mysql;\n" p)
214 (for-each
215 (lambda (sql)
216 (call-with-input-file
217 (string-append #$mysql "/share/mysql/" sql)
218 (lambda (in) (dump-port in p))))
219 '("mysql_system_tables.sql"
220 "mysql_performance_tables.sql"
221 "mysql_system_tables_data.sql"
222 "fill_help_tables.sql"))
223 ;; Remove the anonymous user and disable root access from
224 ;; remote machines, as does by 'mysql_secure_installation'.
225 (display "
226DELETE FROM user WHERE User='';
227DELETE FROM user WHERE User='root' AND
228 Host NOT IN ('localhost', '127.0.0.1', '::1');
229FLUSH PRIVILEGES;
230" p)
231 (close-pipe p))))))))
232
233(define (mysql-shepherd-service config)
234 (list (shepherd-service
235 (provision '(mysql))
236 (documentation "Run the MySQL server.")
237 (start (let ((mysql (mysql-configuration-mysql config))
238 (my.cnf (mysql-configuration-file config)))
239 #~(make-forkexec-constructor
240 (list (string-append #$mysql "/bin/mysqld")
241 (string-append "--defaults-file=" #$my.cnf))
242 #:user "mysql" #:group "mysql")))
243 (stop #~(make-kill-destructor)))))
244
245(define mysql-service-type
246 (service-type
247 (name 'mysql)
248 (extensions
249 (list (service-extension account-service-type
250 (const %mysql-accounts))
251 (service-extension activation-service-type
252 %mysql-activation)
253 (service-extension shepherd-root-service-type
254 mysql-shepherd-service)))))
255
256(define* (mysql-service #:key (config (mysql-configuration)))
257 "Return a service that runs @command{mysqld}, the MySQL or MariaDB
258database server.
259
260The optional @var{config} argument specifies the configuration for
261@command{mysqld}, which should be a @code{<mysql-configuration>} object."
262 (service mysql-service-type config))