···
9
+
cfg = config.services.cryptpad;
19
+
# The Cryptpad configuration file isn't JSON, but a JavaScript source file that assigns a JSON value
21
+
cryptpadConfigFile = builtins.toFile "cryptpad_config.js" ''
22
+
module.exports = ${builtins.toJSON cfg.settings}
25
+
# Derive domain names for Nginx configuration from Cryptpad configuration
26
+
mainDomain = strings.removePrefix "https://" cfg.settings.httpUnsafeOrigin;
28
+
if cfg.settings.httpSafeOrigin == null then
31
+
strings.removePrefix "https://" cfg.settings.httpSafeOrigin;
35
+
options.services.cryptpad = {
36
+
enable = lib.mkEnableOption "cryptpad";
38
+
package = lib.mkPackageOption pkgs "cryptpad" { };
40
+
configureNginx = mkOption {
42
+
Configure Nginx as a reverse proxy for Cryptpad.
43
+
Note that this makes some assumptions on your setup, and sets settings that will
44
+
affect other virtualHosts running on your Nginx instance, if any.
45
+
Alternatively you can configure a reverse-proxy of your choice.
51
+
settings = mkOption {
53
+
Cryptpad configuration settings.
54
+
See https://github.com/cryptpad/cryptpad/blob/main/config/config.example.js for a more extensive
55
+
reference documentation.
56
+
Test your deployed instance through `https://<domain>/checkup/`.
58
+
type = types.submodule {
59
+
freeformType = (pkgs.formats.json { }).type;
61
+
httpUnsafeOrigin = mkOption {
63
+
example = "https://cryptpad.example.com";
65
+
description = "This is the URL that users will enter to load your instance";
67
+
httpSafeOrigin = mkOption {
68
+
type = types.nullOr types.str;
69
+
example = "https://cryptpad-ui.example.com. Apparently optional but recommended.";
70
+
description = "Cryptpad sandbox URL";
72
+
httpAddress = mkOption {
74
+
default = "127.0.0.1";
75
+
description = "Address on which the Node.js server should listen";
77
+
httpPort = mkOption {
80
+
description = "Port on which the Node.js server should listen";
82
+
websocketPort = mkOption {
85
+
description = "Port for the websocket that needs to be separate";
87
+
maxWorkers = mkOption {
88
+
type = types.nullOr types.int;
90
+
description = "Number of child processes, defaults to number of cores available";
92
+
adminKeys = mkOption {
93
+
type = types.listOf types.str;
95
+
description = "List of public signing keys of users that can access the admin panel";
96
+
example = [ "[cryptpad-user1@my.awesome.website/YZgXQxKR0Rcb6r6CmxHPdAGLVludrAF2lEnkbx1vVOo=]" ];
98
+
logToStdout = mkOption {
101
+
description = "Controls whether log output should go to stdout of the systemd service";
103
+
logLevel = mkOption {
106
+
description = "Controls log level";
108
+
blockDailyCheck = mkOption {
112
+
Disable telemetry. This setting is only effective if the 'Disable server telemetry'
113
+
setting in the admin menu has been untouched, and will be ignored by cryptpad once
114
+
that option is set either way.
115
+
Note that due to the service confinement, just enabling the option in the admin
116
+
menu will not be able to resolve DNS and fail; this setting must be set as well.
119
+
installMethod = mkOption {
123
+
Install method is listed in telemetry if you agree to it through the consentToContact
124
+
setting in the admin panel.
132
+
config = mkIf cfg.enable (mkMerge [
134
+
systemd.services.cryptpad = {
135
+
description = "Cryptpad service";
136
+
wantedBy = [ "multi-user.target" ];
137
+
after = [ "networking.target" ];
139
+
BindReadOnlyPaths = [
141
+
# apparently needs proc for workers management
144
+
] ++ (if ! cfg.settings.blockDailyCheck then [
145
+
# allow DNS & TLS if telemetry is explicitly enabled
146
+
"-/etc/resolv.conf"
149
+
"/etc/ssl/certs/ca-certificates.crt"
151
+
DynamicUser = true;
153
+
"CRYPTPAD_CONFIG=${cryptpadConfigFile}"
156
+
ExecStart = lib.getExe cfg.package;
158
+
Restart = "always";
159
+
StateDirectory = "cryptpad";
160
+
WorkingDirectory = "%S/cryptpad";
165
+
mode = "chroot-only";
170
+
(mkIf cfg.configureNginx {
173
+
assertion = cfg.settings.httpUnsafeOrigin != "";
174
+
message = "services.cryptpad.settings.httpUnsafeOrigin is required";
177
+
assertion = strings.hasPrefix "https://" cfg.settings.httpUnsafeOrigin;
178
+
message = "services.cryptpad.settings.httpUnsafeOrigin must start with https://";
182
+
cfg.settings.httpSafeOrigin == null || strings.hasPrefix "https://" cfg.settings.httpSafeOrigin;
183
+
message = "services.cryptpad.settings.httpSafeOrigin must start with https:// (or be unset)";
188
+
recommendedTlsSettings = true;
189
+
recommendedProxySettings = true;
190
+
recommendedOptimisation = true;
191
+
recommendedGzipSettings = true;
193
+
virtualHosts = mkMerge [
195
+
"${mainDomain}" = {
196
+
serverAliases = lib.optionals (cfg.settings.httpSafeOrigin != null) [ sandboxDomain ];
197
+
enableACME = lib.mkDefault true;
200
+
proxyPass = "http://${cfg.settings.httpAddress}:${builtins.toString cfg.settings.httpPort}";
202
+
client_max_body_size 150m;
205
+
locations."/cryptpad_websocket" = {
206
+
proxyPass = "http://${cfg.settings.httpAddress}:${builtins.toString cfg.settings.websocketPort}";
207
+
proxyWebsockets = true;