gnu: Add postgresql-service.
[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>
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (gnu services databases)
20 #:use-module (gnu services)
21 #:use-module (gnu system shadow)
22 #:use-module (gnu packages admin)
23 #:use-module (gnu packages databases)
24 #:use-module (guix records)
25 #:use-module (guix monads)
26 #:use-module (guix store)
27 #:use-module (guix gexp)
28 #:export (postgresql-service))
29
30;;; Commentary:
31;;;
32;;; Database services.
33;;;
34;;; Code:
35
36(define %default-postgres-hba
37 (text-file "pg_hba.conf"
38 "
39local all all trust
40host all all 127.0.0.1/32 trust
41host all all ::1/128 trust"))
42
43(define %default-postgres-ident
44 (text-file "pg_ident.conf"
45 "# MAPNAME SYSTEM-USERNAME PG-USERNAME"))
46
47(define %default-postgres-config
48 (mlet %store-monad ((hba %default-postgres-hba)
49 (ident %default-postgres-ident))
50 (text-file* "postgresql.conf"
51 ;; The daemon will not start without these.
52 "hba_file = '" hba "'\n"
53 "ident_file = '" ident "'\n")))
54
55(define* (postgresql-service #:key (postgresql postgresql)
56 (config-file %default-postgres-config)
57 (data-directory "/var/lib/postgresql/data"))
58 "Return a service that runs @var{postgresql}, the PostgreSQL database server.
59
60The PostgreSQL daemon loads its runtime configuration from @var{config-file}
61and stores the database cluster in @var{data-directory}."
62 ;; Wrapper script that switches to the 'postgres' user before launching
63 ;; daemon.
64 (define start-script
65 (mlet %store-monad ((config-file config-file))
66 (gexp->script "start-postgres"
67 #~(let ((user (getpwnam "postgres"))
68 (postgres (string-append #$postgresql
69 "/bin/postgres")))
70 (setgid (passwd:gid user))
71 (setuid (passwd:uid user))
72 (system* postgres
73 (string-append "--config-file=" #$config-file)
74 "-D" #$data-directory)))))
75
76 (define activate
77 #~(begin
78 (use-modules (guix build utils)
79 (ice-9 match))
80
81 (let ((user (getpwnam "postgres"))
82 (initdb (string-append #$postgresql "/bin/initdb")))
83 ;; Create db state directory.
84 (mkdir-p #$data-directory)
85 (chown #$data-directory (passwd:uid user) (passwd:gid user))
86
87 ;; Drop privileges and init state directory in a new
88 ;; process. Wait for it to finish before proceeding.
89 (match (primitive-fork)
90 (0
91 ;; Exit with a non-zero status code if an exception is thrown.
92 (dynamic-wind
93 (const #t)
94 (lambda ()
95 (setgid (passwd:gid user))
96 (setuid (passwd:uid user))
97 (primitive-exit (system* initdb "-D" #$data-directory)))
98 (lambda ()
99 (primitive-exit 1))))
100 (pid (waitpid pid))))))
101
102 (mlet %store-monad ((start-script start-script))
103 (return
104 (service
105 (provision '(postgres))
106 (documentation "Run the PostgreSQL daemon.")
107 (requirement '(user-processes loopback))
108 (start #~(make-forkexec-constructor #$start-script))
109 (stop #~(make-kill-destructor))
110 (activate activate)
111 (user-groups (list (user-group
112 (name "postgres")
113 (system? #t))))
114 (user-accounts (list (user-account
115 (name "postgres")
116 (group "postgres")
117 (system? #t)
118 (comment "PostgreSQL server user")
119 (home-directory "/var/empty")
120 (shell
121 #~(string-append #$shadow "/sbin/nologin")))))))))