1{
2 config,
3 options,
4 lib,
5 pkgs,
6 ...
7}:
8
9let
10 cfg = config.services.nextcloud.notify_push;
11 cfgN = config.services.nextcloud;
12in
13{
14 options.services.nextcloud.notify_push =
15 {
16 enable = lib.mkEnableOption "Notify push";
17
18 package = lib.mkOption {
19 type = lib.types.package;
20 default = pkgs.nextcloud-notify_push;
21 defaultText = lib.literalMD "pkgs.nextcloud-notify_push";
22 description = "Which package to use for notify_push";
23 };
24
25 socketPath = lib.mkOption {
26 type = lib.types.str;
27 default = "/run/nextcloud-notify_push/sock";
28 description = "Socket path to use for notify_push";
29 };
30
31 logLevel = lib.mkOption {
32 type = lib.types.enum [
33 "error"
34 "warn"
35 "info"
36 "debug"
37 "trace"
38 ];
39 default = "error";
40 description = "Log level";
41 };
42
43 nextcloudUrl = lib.mkOption {
44 type = lib.types.str;
45 default = "http${lib.optionalString cfgN.https "s"}://${cfgN.hostName}";
46 defaultText = lib.literalExpression ''"http''${lib.optionalString config.services.nextcloud.https "s"}://''${config.services.nextcloud.hostName}"'';
47 description = "Configure the nextcloud URL notify_push tries to connect to.";
48 };
49
50 bendDomainToLocalhost = lib.mkOption {
51 type = lib.types.bool;
52 default = false;
53 description = ''
54 Whether to add an entry to `/etc/hosts` for the configured nextcloud domain to point to `localhost` and add `localhost `to nextcloud's `trusted_proxies` config option.
55
56 This is useful when nextcloud's domain is not a static IP address and when the reverse proxy cannot be bypassed because the backend connection is done via unix socket.
57 '';
58 };
59 }
60 // (lib.genAttrs
61 [
62 "dbtype"
63 "dbname"
64 "dbuser"
65 "dbpassFile"
66 "dbhost"
67 "dbport"
68 "dbtableprefix"
69 ]
70 (
71 opt:
72 options.services.nextcloud.config.${opt}
73 // {
74 default = config.services.nextcloud.config.${opt};
75 defaultText = lib.literalExpression "config.services.nextcloud.config.${opt}";
76 }
77 )
78 );
79
80 config = lib.mkIf cfg.enable {
81 systemd.services = {
82 nextcloud-notify_push = {
83 description = "Push daemon for Nextcloud clients";
84 documentation = [ "https://github.com/nextcloud/notify_push" ];
85 after = [
86 "nextcloud-setup.service"
87 "phpfpm-nextcloud.service"
88 "redis-nextcloud.service"
89 ];
90 requires = [
91 "nextcloud-setup.service"
92 ];
93 wantedBy = [ "multi-user.target" ];
94 environment = {
95 NEXTCLOUD_URL = cfg.nextcloudUrl;
96 SOCKET_PATH = cfg.socketPath;
97 DATABASE_PREFIX = cfg.dbtableprefix;
98 LOG = cfg.logLevel;
99 };
100 script =
101 let
102 dbType = if cfg.dbtype == "pgsql" then "postgresql" else cfg.dbtype;
103 dbUser = lib.optionalString (cfg.dbuser != null) cfg.dbuser;
104 dbPass = lib.optionalString (cfg.dbpassFile != null) ":$DATABASE_PASSWORD";
105 dbHostHasPrefix = prefix: lib.hasPrefix prefix (toString cfg.dbhost);
106 isPostgresql = dbType == "postgresql";
107 isMysql = dbType == "mysql";
108 isSocket = (isPostgresql && dbHostHasPrefix "/") || (isMysql && dbHostHasPrefix "localhost:/");
109 dbHost = lib.optionalString (cfg.dbhost != null) (
110 if isSocket then lib.optionalString isMysql "@localhost" else "@${cfg.dbhost}"
111 );
112 dbOpts = lib.optionalString (cfg.dbhost != null && isSocket) (
113 if isPostgresql then
114 "?host=${cfg.dbhost}"
115 else if isMysql then
116 "?socket=${lib.removePrefix "localhost:" cfg.dbhost}"
117 else
118 throw "unsupported dbtype"
119 );
120 dbName = lib.optionalString (cfg.dbname != null) "/${cfg.dbname}";
121 dbUrl = "${dbType}://${dbUser}${dbPass}${dbHost}${dbName}${dbOpts}";
122 in
123 lib.optionalString (cfg.dbpassFile != null) ''
124 export DATABASE_PASSWORD="$(<"$CREDENTIALS_DIRECTORY/dbpass")"
125 ''
126 + ''
127 export DATABASE_URL="${dbUrl}"
128 exec ${cfg.package}/bin/notify_push '${cfgN.datadir}/config/config.php'
129 '';
130 serviceConfig = {
131 User = "nextcloud";
132 Group = "nextcloud";
133 RuntimeDirectory = [ "nextcloud-notify_push" ];
134 Restart = "on-failure";
135 RestartSec = "5s";
136 Type = "notify";
137 LoadCredential = lib.optional (cfg.dbpassFile != null) "dbpass:${cfg.dbpassFile}";
138 };
139 };
140
141 nextcloud-notify_push_setup = {
142 wantedBy = [ "multi-user.target" ];
143 requiredBy = [ "nextcloud-notify_push.service" ];
144 after = [ "nextcloud-notify_push.service" ];
145 serviceConfig = {
146 Type = "oneshot";
147 User = "nextcloud";
148 Group = "nextcloud";
149 ExecStart = "${lib.getExe cfgN.occ} notify_push:setup ${cfg.nextcloudUrl}/push";
150 LoadCredential = config.systemd.services.nextcloud-cron.serviceConfig.LoadCredential;
151 RestartMode = "direct";
152 Restart = "on-failure";
153 };
154 };
155 };
156
157 networking.hosts = lib.mkIf cfg.bendDomainToLocalhost {
158 "127.0.0.1" = [ cfgN.hostName ];
159 "::1" = [ cfgN.hostName ];
160 };
161
162 services = lib.mkMerge [
163 {
164 nginx.virtualHosts.${cfgN.hostName}.locations."^~ /push/" = {
165 proxyPass = "http://unix:${cfg.socketPath}";
166 proxyWebsockets = true;
167 recommendedProxySettings = true;
168 extraConfig = # nginx
169 ''
170 # disable in case it was configured on a higher level
171 keepalive_timeout 0;
172 proxy_buffering off;
173 '';
174 };
175 }
176
177 (lib.mkIf cfg.bendDomainToLocalhost {
178 nextcloud.settings.trusted_proxies = [
179 "127.0.0.1"
180 "::1"
181 ];
182 })
183 ];
184 };
185}