Personal-use NixOS configuration
1{
2 config,
3 pkgs,
4 lib ? pkgs.lib,
5 ...
6}:
7let
8 cfg = config.services.cells;
9 format = pkgs.formats.json { };
10
11 pkgs-internal = import ../packages { inherit pkgs; };
12
13 inherit (lib)
14 types
15 mkIf
16 mkOption
17 mkEnableOption
18 ;
19in
20{
21 options.services.cells = {
22 enable = mkEnableOption "Whether to enable Pydio Cells content collaboration platform.";
23
24 package = mkOption {
25 type = types.package;
26 default = pkgs-internal.cells;
27
28 description = "The Pydio Cells package to use.";
29 };
30
31 user = mkOption {
32 type = types.str;
33 default = "pydio";
34 description = "User account under which Pydio Cells runs.";
35 };
36
37 group = mkOption {
38 type = types.str;
39 default = "pydio";
40 description = "Group under which Pydio Cells runs.";
41 };
42
43 extraGroups = mkOption {
44 type = types.listOf types.str;
45 default = [ ];
46
47 description = ''
48 Additional groups for the systemd service.
49 '';
50 };
51
52 environment = mkOption {
53 type = types.attrsOf types.str;
54 default = { };
55
56 example = lib.literalExpression ''
57 {
58 CELLS_BIND_ADDRESS = "127.0.0.1";
59 CELLS_BIND = "8080";
60
61 CELLS_DAV_MULTIPART_SIZE = 100;
62 CELLS_CONFIG = "/opt/pydio.json";
63 }
64 '';
65
66 description = ''
67 Environment variables to set for the service. Secrets should be
68 specified using {option}`environmentFile`.
69
70 Refer to the [Pydio Cells documentation] for the list of available
71 configuration options. Variable name is an upper-cased coommand flag,
72 prefixed with `CELLS_`. For example, the `bind_address` entry can be
73 set using {env}`CELLS_BIND_ADDRESS`.
74
75 Pydio Cells is designed to be configured on installation, with certain
76 configuration options such as database credentials being defined
77 elsewhere. See {option}`install` for initial configuration options.
78
79 [Pydio Cells documentation]: https://pydio.com/en/docs/developer-guide/cells-start
80 '';
81 };
82
83 environmentFile = mkOption {
84 type = types.nullOr types.path;
85 default = null;
86
87 description = ''
88 File to load environment variables from. Loaded variables override
89 values set in {option}`environment`.
90 '';
91 };
92
93 database = {
94 enable =
95 mkEnableOption "The MySQL database to use with Pydio Cells. See {option}`services.mysql`"
96 // {
97 default = true;
98 };
99
100 createDB = mkEnableOption "The automatic creation of the database for Pydio Cells." // {
101 default = true;
102 };
103
104 name = mkOption {
105 type = types.str;
106 default = "cells";
107
108 description = "The name of the Pydio Cells database.";
109 };
110
111 user = mkOption {
112 type = types.str;
113 default = "cells";
114
115 description = "The database user for Pydio Cells.";
116 };
117 };
118
119 port = mkOption {
120 type = types.int;
121 default = 8080;
122
123 description = ''
124 Port used by Pydio Cells.
125
126 Note that this *will not* set the port that Pydio Cells listens on!
127 '';
128 };
129
130 openFirewall = mkEnableOption "Open ports in the firewall for the cells web interface.";
131 };
132
133 config = mkIf cfg.enable {
134 services.mysql = mkIf cfg.database.enable {
135 enable = true;
136
137 ensureDatabases = mkIf cfg.database.createDB [ cfg.database.name ];
138 ensureUsers = mkIf cfg.database.createDB [
139 {
140 name = cfg.database.user;
141 ensurePermissions = {
142 "${cfg.database.name}.*" = "ALL PRIVILEGES";
143 };
144 }
145 ];
146
147 package = lib.mkDefault pkgs.mariadb_114;
148 };
149
150 networking.firewall = mkIf cfg.openFirewall {
151 allowedTCPPorts = [ cfg.port ];
152 };
153
154 users = {
155 users = mkIf (cfg.user == "pydio") {
156 pydio = {
157 group = cfg.group;
158 isSystemUser = true;
159 };
160 };
161
162 groups = mkIf (cfg.group == "pydio") {
163 pydio = { };
164 };
165 };
166
167 systemd.services.cells = {
168 description = "Pydio Cells content collaboration platform";
169
170 wantedBy = [ "multi-user.target" ];
171 after = [
172 "network.target"
173 ]
174 ++ lib.optional cfg.database.enable "mysql.service";
175
176 environment = cfg.environment;
177
178 script = ''
179 ${lib.concatLines (
180 lib.mapAttrsToList
181 (name: value: ''
182 export ${name}="''${${name}-${value}}"
183 '')
184 {
185 CELLS_WORKING_DIR = "$STATE_DIRECTORY";
186 CELLS_LOG_DIR = "$LOGS_DIRECTORY";
187 }
188 )}
189
190 exec ${lib.getExe cfg.package} start
191 '';
192
193 serviceConfig = {
194 User = cfg.user;
195 Group = cfg.group;
196
197 SupplementaryGroups = cfg.extraGroups;
198
199 StateDirectory = "pydio";
200 StateDirectoryMode = "0700";
201 LogsDirectory = "pydio";
202 LogsDirectoryMode = "0750";
203 UMask = "0077";
204
205 EnvironmentFile = cfg.environmentFile;
206
207 AmbientCapabilities = "CAP_NET_BIND_SERVICE";
208 CapabilityBoundingSet = [ "" ];
209 DevicePolicy = "closed";
210 LockPersonality = true;
211 MemoryDenyWriteExecute = true;
212 NoNewPrivileges = true;
213 PrivateDevices = true;
214 PrivateTmp = true;
215 PrivateUsers = true;
216 ProtectClock = true;
217 ProtectControlGroups = true;
218 ProtectHome = true;
219 ProtectHostname = true;
220 ProtectKernelLogs = true;
221 ProtectKernelModules = true;
222 ProtectKernelTunables = true;
223 ProtectSystem = "strict";
224 RemoveIPC = true;
225 RestrictNamespaces = [
226 "user"
227 "mnt"
228 ];
229 RestrictRealtime = true;
230 RestrictSUIDSGID = true;
231 SystemCallArchitectures = "native";
232 SystemCallFilter = [
233 "@system-service"
234 "~@privileged"
235 "~@resources"
236 ];
237 };
238 };
239 };
240
241 meta.maintainers = [ lib.maintainers.encode42 ];
242}