1{ config, options, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.couchdb;
7 opt = options.services.couchdb;
8 configFile = pkgs.writeText "couchdb.ini" (
9 ''
10 [couchdb]
11 database_dir = ${cfg.databaseDir}
12 uri_file = ${cfg.uriFile}
13 view_index_dir = ${cfg.viewIndexDir}
14 '' + (optionalString (cfg.adminPass != null) ''
15 [admins]
16 ${cfg.adminUser} = ${cfg.adminPass}
17 '' + ''
18 [chttpd]
19 '') +
20 ''
21 port = ${toString cfg.port}
22 bind_address = ${cfg.bindAddress}
23
24 [log]
25 file = ${cfg.logFile}
26 '');
27 executable = "${cfg.package}/bin/couchdb";
28
29in {
30
31 ###### interface
32
33 options = {
34
35 services.couchdb = {
36
37 enable = mkEnableOption (lib.mdDoc "CouchDB Server");
38
39 package = mkOption {
40 type = types.package;
41 default = pkgs.couchdb3;
42 defaultText = literalExpression "pkgs.couchdb3";
43 description = lib.mdDoc ''
44 CouchDB package to use.
45 '';
46 };
47
48 adminUser = mkOption {
49 type = types.str;
50 default = "admin";
51 description = lib.mdDoc ''
52 Couchdb (i.e. fauxton) account with permission for all dbs and
53 tasks.
54 '';
55 };
56
57 adminPass = mkOption {
58 type = types.nullOr types.str;
59 default = null;
60 description = lib.mdDoc ''
61 Couchdb (i.e. fauxton) account with permission for all dbs and
62 tasks.
63 '';
64 };
65
66 user = mkOption {
67 type = types.str;
68 default = "couchdb";
69 description = lib.mdDoc ''
70 User account under which couchdb runs.
71 '';
72 };
73
74 group = mkOption {
75 type = types.str;
76 default = "couchdb";
77 description = lib.mdDoc ''
78 Group account under which couchdb runs.
79 '';
80 };
81
82 # couchdb options: http://docs.couchdb.org/en/latest/config/index.html
83
84 databaseDir = mkOption {
85 type = types.path;
86 default = "/var/lib/couchdb";
87 description = lib.mdDoc ''
88 Specifies location of CouchDB database files (*.couch named). This
89 location should be writable and readable for the user the CouchDB
90 service runs as (couchdb by default).
91 '';
92 };
93
94 uriFile = mkOption {
95 type = types.path;
96 default = "/run/couchdb/couchdb.uri";
97 description = lib.mdDoc ''
98 This file contains the full URI that can be used to access this
99 instance of CouchDB. It is used to help discover the port CouchDB is
100 running on (if it was set to 0 (e.g. automatically assigned any free
101 one). This file should be writable and readable for the user that
102 runs the CouchDB service (couchdb by default).
103 '';
104 };
105
106 viewIndexDir = mkOption {
107 type = types.path;
108 default = "/var/lib/couchdb";
109 description = lib.mdDoc ''
110 Specifies location of CouchDB view index files. This location should
111 be writable and readable for the user that runs the CouchDB service
112 (couchdb by default).
113 '';
114 };
115
116 bindAddress = mkOption {
117 type = types.str;
118 default = "127.0.0.1";
119 description = lib.mdDoc ''
120 Defines the IP address by which CouchDB will be accessible.
121 '';
122 };
123
124 port = mkOption {
125 type = types.port;
126 default = 5984;
127 description = lib.mdDoc ''
128 Defined the port number to listen.
129 '';
130 };
131
132 logFile = mkOption {
133 type = types.path;
134 default = "/var/log/couchdb.log";
135 description = lib.mdDoc ''
136 Specifies the location of file for logging output.
137 '';
138 };
139
140 extraConfig = mkOption {
141 type = types.lines;
142 default = "";
143 description = lib.mdDoc ''
144 Extra configuration. Overrides any other configuration.
145 '';
146 };
147
148 argsFile = mkOption {
149 type = types.path;
150 default = "${cfg.package}/etc/vm.args";
151 defaultText = literalExpression ''"config.${opt.package}/etc/vm.args"'';
152 description = lib.mdDoc ''
153 vm.args configuration. Overrides Couchdb's Erlang VM parameters file.
154 '';
155 };
156
157 configFile = mkOption {
158 type = types.path;
159 description = lib.mdDoc ''
160 Configuration file for persisting runtime changes. File
161 needs to be readable and writable from couchdb user/group.
162 '';
163 };
164
165 };
166
167 };
168
169 ###### implementation
170
171 config = mkIf config.services.couchdb.enable {
172
173 environment.systemPackages = [ cfg.package ];
174
175 services.couchdb.configFile = mkDefault "/var/lib/couchdb/local.ini";
176
177 systemd.tmpfiles.rules = [
178 "d '${dirOf cfg.uriFile}' - ${cfg.user} ${cfg.group} - -"
179 "f '${cfg.logFile}' - ${cfg.user} ${cfg.group} - -"
180 "d '${cfg.databaseDir}' - ${cfg.user} ${cfg.group} - -"
181 "d '${cfg.viewIndexDir}' - ${cfg.user} ${cfg.group} - -"
182 ];
183
184 systemd.services.couchdb = {
185 description = "CouchDB Server";
186 wantedBy = [ "multi-user.target" ];
187
188 preStart = ''
189 touch ${cfg.configFile}
190 if ! test -e ${cfg.databaseDir}/.erlang.cookie; then
191 touch ${cfg.databaseDir}/.erlang.cookie
192 chmod 600 ${cfg.databaseDir}/.erlang.cookie
193 dd if=/dev/random bs=16 count=1 | base64 > ${cfg.databaseDir}/.erlang.cookie
194 fi
195 '';
196
197 environment = {
198 # we are actually specifying 5 configuration files:
199 # 1. the preinstalled default.ini
200 # 2. the module configuration
201 # 3. the extraConfig from the module options
202 # 4. the locally writable config file, which couchdb itself writes to
203 ERL_FLAGS= ''-couch_ini ${cfg.package}/etc/default.ini ${configFile} ${pkgs.writeText "couchdb-extra.ini" cfg.extraConfig} ${cfg.configFile}'';
204 # 5. the vm.args file
205 COUCHDB_ARGS_FILE=''${cfg.argsFile}'';
206 HOME =''${cfg.databaseDir}'';
207 };
208
209 serviceConfig = {
210 User = cfg.user;
211 Group = cfg.group;
212 ExecStart = executable;
213 };
214 };
215
216 users.users.couchdb = {
217 description = "CouchDB Server user";
218 group = "couchdb";
219 uid = config.ids.uids.couchdb;
220 };
221
222 users.groups.couchdb.gid = config.ids.gids.couchdb;
223
224 };
225}