1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.couchdb;
7 useVersion2 = strings.versionAtLeast (strings.getVersion cfg.package) "2.0";
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 '' + (if useVersion2 then
15 ''
16 [chttpd]
17 '' else
18 ''
19 [httpd]
20 '') +
21 ''
22 port = ${toString cfg.port}
23 bind_address = ${cfg.bindAddress}
24
25 [log]
26 file = ${cfg.logFile}
27 '');
28 executable = if useVersion2 then "${cfg.package}/bin/couchdb"
29 else ''${cfg.package}/bin/couchdb -a ${configFile} -a ${pkgs.writeText "couchdb-extra.ini" cfg.extraConfig} -a ${cfg.configFile}'';
30
31in {
32
33 ###### interface
34
35 options = {
36
37 services.couchdb = {
38
39 enable = mkOption {
40 type = types.bool;
41 default = false;
42 description = ''
43 Whether to run CouchDB Server.
44 '';
45 };
46
47 package = mkOption {
48 type = types.package;
49 default = pkgs.couchdb;
50 defaultText = "pkgs.couchdb";
51 example = literalExample "pkgs.couchdb";
52 description = ''
53 CouchDB package to use.
54 '';
55 };
56
57
58 user = mkOption {
59 type = types.string;
60 default = "couchdb";
61 description = ''
62 User account under which couchdb runs.
63 '';
64 };
65
66 group = mkOption {
67 type = types.string;
68 default = "couchdb";
69 description = ''
70 Group account under which couchdb runs.
71 '';
72 };
73
74 # couchdb options: http://docs.couchdb.org/en/latest/config/index.html
75
76 databaseDir = mkOption {
77 type = types.path;
78 default = "/var/lib/couchdb";
79 description = ''
80 Specifies location of CouchDB database files (*.couch named). This
81 location should be writable and readable for the user the CouchDB
82 service runs as (couchdb by default).
83 '';
84 };
85
86 uriFile = mkOption {
87 type = types.path;
88 default = "/var/run/couchdb/couchdb.uri";
89 description = ''
90 This file contains the full URI that can be used to access this
91 instance of CouchDB. It is used to help discover the port CouchDB is
92 running on (if it was set to 0 (e.g. automatically assigned any free
93 one). This file should be writable and readable for the user that
94 runs the CouchDB service (couchdb by default).
95 '';
96 };
97
98 viewIndexDir = mkOption {
99 type = types.path;
100 default = "/var/lib/couchdb";
101 description = ''
102 Specifies location of CouchDB view index files. This location should
103 be writable and readable for the user that runs the CouchDB service
104 (couchdb by default).
105 '';
106 };
107
108 bindAddress = mkOption {
109 type = types.string;
110 default = "127.0.0.1";
111 description = ''
112 Defines the IP address by which CouchDB will be accessible.
113 '';
114 };
115
116 port = mkOption {
117 type = types.int;
118 default = 5984;
119 description = ''
120 Defined the port number to listen.
121 '';
122 };
123
124 logFile = mkOption {
125 type = types.path;
126 default = "/var/log/couchdb.log";
127 description = ''
128 Specifies the location of file for logging output.
129 '';
130 };
131
132 extraConfig = mkOption {
133 type = types.lines;
134 default = "";
135 description = ''
136 Extra configuration. Overrides any other cofiguration.
137 '';
138 };
139
140 configFile = mkOption {
141 type = types.string;
142 description = ''
143 Configuration file for persisting runtime changes. File
144 needs to be readable and writable from couchdb user/group.
145 '';
146 };
147
148 };
149
150 };
151
152 ###### implementation
153
154 config = mkIf config.services.couchdb.enable {
155
156 environment.systemPackages = [ cfg.package ];
157
158 services.couchdb.configFile = mkDefault
159 (if useVersion2 then "/var/lib/couchdb/local.ini" else "/var/lib/couchdb/couchdb.ini");
160
161 systemd.services.couchdb = {
162 description = "CouchDB Server";
163 wantedBy = [ "multi-user.target" ];
164
165 preStart =
166 ''
167 mkdir -p `dirname ${cfg.uriFile}`;
168 mkdir -p `dirname ${cfg.logFile}`;
169 mkdir -p ${cfg.databaseDir};
170 mkdir -p ${cfg.viewIndexDir};
171 touch ${cfg.configFile}
172 touch -a ${cfg.logFile}
173
174 if [ "$(id -u)" = 0 ]; then
175 chown ${cfg.user}:${cfg.group} `dirname ${cfg.uriFile}`;
176 (test -f ${cfg.uriFile} && chown ${cfg.user}:${cfg.group} ${cfg.uriFile}) || true
177 chown ${cfg.user}:${cfg.group} ${cfg.databaseDir}
178 chown ${cfg.user}:${cfg.group} ${cfg.viewIndexDir}
179 chown ${cfg.user}:${cfg.group} ${cfg.configFile}
180 chown ${cfg.user}:${cfg.group} ${cfg.logFile}
181 fi
182 '';
183
184 environment = mkIf useVersion2 {
185 # we are actually specifying 4 configuration files:
186 # 1. the preinstalled default.ini
187 # 2. the module configuration
188 # 3. the extraConfig from the module options
189 # 4. the locally writable config file, which couchdb itself writes to
190 ERL_FLAGS= ''-couch_ini ${cfg.package}/etc/default.ini ${configFile} ${pkgs.writeText "couchdb-extra.ini" cfg.extraConfig} ${cfg.configFile}'';
191 };
192
193 serviceConfig = {
194 PermissionsStartOnly = true;
195 User = cfg.user;
196 Group = cfg.group;
197 ExecStart = executable;
198 };
199 };
200
201 users.users.couchdb = {
202 description = "CouchDB Server user";
203 group = "couchdb";
204 uid = config.ids.uids.couchdb;
205 };
206
207 users.groups.couchdb.gid = config.ids.gids.couchdb;
208
209 };
210}