qgroundcontrol: 4.4.2 -> 4.4.3 (#360956)
[NixPkgs.git] / nixos / modules / services / web-apps / freshrss.nix
blob0e8bcc703efa957c10af74859f180efb2a3ac04e
1 { config, lib, pkgs, ... }:
3 with lib;
4 let
5   cfg = config.services.freshrss;
7   extension-env = pkgs.buildEnv {
8     name = "freshrss-extensions";
9     paths = cfg.extensions;
10   };
11   env-vars = {
12     DATA_PATH = cfg.dataDir;
13     THIRDPARTY_EXTENSIONS_PATH = "${extension-env}/share/freshrss/";
14   };
17   meta.maintainers = with maintainers; [ etu stunkymonkey mattchrist ];
19   options.services.freshrss = {
20     enable = mkEnableOption "FreshRSS RSS aggregator and reader with php-fpm backend";
22     package = mkPackageOption pkgs "freshrss" { };
24     extensions = mkOption {
25       type = types.listOf types.package;
26       default = [ ];
27       defaultText = literalExpression "[]";
28       example = literalExpression ''
29         with freshrss-extensions; [
30           youtube
31         ] ++ [
32           (freshrss-extensions.buildFreshRssExtension {
33             FreshRssExtUniqueId = "ReadingTime";
34             pname = "reading-time";
35             version = "1.5";
36             src = pkgs.fetchFromGitLab {
37               domain = "framagit.org";
38               owner = "Lapineige";
39               repo = "FreshRSS_Extension-ReadingTime";
40               rev = "fb6e9e944ef6c5299fa56ffddbe04c41e5a34ebf";
41              hash = "sha256-C5cRfaphx4Qz2xg2z+v5qRji8WVSIpvzMbethTdSqsk=";
42            };
43           })
44         ]
45       '';
46       description = "Additional extensions to be used.";
47     };
49     defaultUser = mkOption {
50       type = types.str;
51       default = "admin";
52       description = "Default username for FreshRSS.";
53       example = "eva";
54     };
56     passwordFile = mkOption {
57       type = types.nullOr types.path;
58       default = null;
59       description = "Password for the defaultUser for FreshRSS.";
60       example = "/run/secrets/freshrss";
61     };
63     baseUrl = mkOption {
64       type = types.str;
65       description = "Default URL for FreshRSS.";
66       example = "https://freshrss.example.com";
67     };
69     language = mkOption {
70       type = types.str;
71       default = "en";
72       description = "Default language for FreshRSS.";
73       example = "de";
74     };
76     database = {
77       type = mkOption {
78         type = types.enum [ "sqlite" "pgsql" "mysql" ];
79         default = "sqlite";
80         description = "Database type.";
81         example = "pgsql";
82       };
84       host = mkOption {
85         type = types.nullOr types.str;
86         default = "localhost";
87         description = "Database host for FreshRSS.";
88       };
90       port = mkOption {
91         type = types.nullOr types.port;
92         default = null;
93         description = "Database port for FreshRSS.";
94         example = 3306;
95       };
97       user = mkOption {
98         type = types.nullOr types.str;
99         default = "freshrss";
100         description = "Database user for FreshRSS.";
101       };
103       passFile = mkOption {
104         type = types.nullOr types.path;
105         default = null;
106         description = "Database password file for FreshRSS.";
107         example = "/run/secrets/freshrss";
108       };
110       name = mkOption {
111         type = types.nullOr types.str;
112         default = "freshrss";
113         description = "Database name for FreshRSS.";
114       };
116       tableprefix = mkOption {
117         type = types.nullOr types.str;
118         default = null;
119         description = "Database table prefix for FreshRSS.";
120         example = "freshrss";
121       };
122     };
124     dataDir = mkOption {
125       type = types.str;
126       default = "/var/lib/freshrss";
127       description = "Default data folder for FreshRSS.";
128       example = "/mnt/freshrss";
129     };
131     virtualHost = mkOption {
132       type = types.nullOr types.str;
133       default = "freshrss";
134       description = ''
135         Name of the nginx virtualhost to use and setup. If null, do not setup any virtualhost.
136         You may need to configure the virtualhost further through services.nginx.virtualHosts.<virtualhost>,
137         for example to enable SSL.
138       '';
139     };
141     pool = mkOption {
142       type = types.nullOr types.str;
143       default = "freshrss";
144       description = ''
145         Name of the php-fpm pool to use and setup. If not specified, a pool will be created
146         with default values.
147       '';
148     };
150     user = mkOption {
151       type = types.str;
152       default = "freshrss";
153       description = "User under which FreshRSS runs.";
154     };
156     authType = mkOption {
157       type = types.enum [ "form" "http_auth" "none" ];
158       default = "form";
159       description = "Authentication type for FreshRSS.";
160     };
161   };
163   config =
164     let
165       defaultServiceConfig = {
166         ReadWritePaths = "${cfg.dataDir}";
167         DeviceAllow = "";
168         LockPersonality = true;
169         NoNewPrivileges = true;
170         PrivateDevices = true;
171         PrivateTmp = true;
172         PrivateUsers = true;
173         ProcSubset = "pid";
174         ProtectClock = true;
175         ProtectControlGroups = true;
176         ProtectHome = true;
177         ProtectHostname = true;
178         ProtectKernelLogs = true;
179         ProtectKernelModules = true;
180         ProtectKernelTunables = true;
181         ProtectProc = "invisible";
182         ProtectSystem = "strict";
183         RemoveIPC = true;
184         RestrictNamespaces = true;
185         RestrictRealtime = true;
186         RestrictSUIDSGID = true;
187         SystemCallArchitectures = "native";
188         SystemCallFilter = [ "@system-service" "~@resources" "~@privileged" ];
189         UMask = "0007";
190         Type = "oneshot";
191         User = cfg.user;
192         Group = config.users.users.${cfg.user}.group;
193         StateDirectory = "freshrss";
194         WorkingDirectory = cfg.package;
195       };
196     in
197     mkIf cfg.enable {
198       assertions = mkIf (cfg.authType == "form") [
199         {
200           assertion = cfg.passwordFile != null;
201           message = ''
202             `passwordFile` must be supplied when using "form" authentication!
203           '';
204         }
205       ];
206       # Set up a Nginx virtual host.
207       services.nginx = mkIf (cfg.virtualHost != null) {
208         enable = true;
209         virtualHosts.${cfg.virtualHost} = {
210           root = "${cfg.package}/p";
212           # php files handling
213           # this regex is mandatory because of the API
214           locations."~ ^.+?\.php(/.*)?$".extraConfig = ''
215             fastcgi_pass unix:${config.services.phpfpm.pools.${cfg.pool}.socket};
216             fastcgi_split_path_info ^(.+\.php)(/.*)$;
217             # By default, the variable PATH_INFO is not set under PHP-FPM
218             # But FreshRSS API greader.php need it. If you have a “Bad Request” error, double check this var!
219             # NOTE: the separate $path_info variable is required. For more details, see:
220             # https://trac.nginx.org/nginx/ticket/321
221             set $path_info $fastcgi_path_info;
222             fastcgi_param PATH_INFO $path_info;
223             include ${pkgs.nginx}/conf/fastcgi_params;
224             include ${pkgs.nginx}/conf/fastcgi.conf;
225           '';
227           locations."/" = {
228             tryFiles = "$uri $uri/ index.php";
229             index = "index.php index.html index.htm";
230           };
231         };
232       };
234       # Set up phpfpm pool
235       services.phpfpm.pools = mkIf (cfg.pool != null) {
236         ${cfg.pool} = {
237           user = "freshrss";
238           settings = {
239             "listen.owner" = "nginx";
240             "listen.group" = "nginx";
241             "listen.mode" = "0600";
242             "pm" = "dynamic";
243             "pm.max_children" = 32;
244             "pm.max_requests" = 500;
245             "pm.start_servers" = 2;
246             "pm.min_spare_servers" = 2;
247             "pm.max_spare_servers" = 5;
248             "catch_workers_output" = true;
249           };
250           phpEnv = env-vars;
251         };
252       };
254       users.users."${cfg.user}" = {
255         description = "FreshRSS service user";
256         isSystemUser = true;
257         group = "${cfg.user}";
258         home = cfg.dataDir;
259       };
260       users.groups."${cfg.user}" = { };
262       systemd.tmpfiles.settings."10-freshrss".${cfg.dataDir}.d = {
263         inherit (cfg) user;
264         group = config.users.users.${cfg.user}.group;
265       };
267       systemd.services.freshrss-config =
268         let
269           settingsFlags = concatStringsSep " \\\n    "
270             (mapAttrsToList (k: v: "${k} ${toString v}") {
271               "--default-user" = ''"${cfg.defaultUser}"'';
272               "--auth-type" = ''"${cfg.authType}"'';
273               "--base-url" = ''"${cfg.baseUrl}"'';
274               "--language" = ''"${cfg.language}"'';
275               "--db-type" = ''"${cfg.database.type}"'';
276               # The following attributes are optional depending on the type of
277               # database.  Those that evaluate to null on the left hand side
278               # will be omitted.
279               ${if cfg.database.name != null then "--db-base" else null} = ''"${cfg.database.name}"'';
280               ${if cfg.database.passFile != null then "--db-password" else null} = ''"$(cat ${cfg.database.passFile})"'';
281               ${if cfg.database.user != null then "--db-user" else null} = ''"${cfg.database.user}"'';
282               ${if cfg.database.tableprefix != null then "--db-prefix" else null} = ''"${cfg.database.tableprefix}"'';
283               # hostname:port e.g. "localhost:5432"
284               ${if cfg.database.host != null && cfg.database.port != null then "--db-host" else null} = ''"${cfg.database.host}:${toString cfg.database.port}"'';
285               # socket path e.g. "/run/postgresql"
286               ${if cfg.database.host != null && cfg.database.port == null then "--db-host" else null} = ''"${cfg.database.host}"'';
287             });
288         in
289         {
290           description = "Set up the state directory for FreshRSS before use";
291           wantedBy = [ "multi-user.target" ];
292           serviceConfig = defaultServiceConfig // {
293             RemainAfterExit = true;
294           };
295           restartIfChanged = true;
296           environment = env-vars;
298           script =
299             let
300               userScriptArgs = ''--user ${cfg.defaultUser} ${optionalString (cfg.authType == "form") ''--password "$(cat ${cfg.passwordFile})"''}'';
301               updateUserScript = optionalString (cfg.authType == "form" || cfg.authType == "none") ''
302                 ./cli/update-user.php ${userScriptArgs}
303               '';
304               createUserScript = optionalString (cfg.authType == "form" || cfg.authType == "none") ''
305                 ./cli/create-user.php ${userScriptArgs}
306               '';
307             in
308             ''
309               # do installation or reconfigure
310               if test -f ${cfg.dataDir}/config.php; then
311                 # reconfigure with settings
312                 ./cli/reconfigure.php ${settingsFlags}
313                 ${updateUserScript}
314               else
315                 # check correct folders in data folder
316                 ./cli/prepare.php
317                 # install with settings
318                 ./cli/do-install.php ${settingsFlags}
319                 ${createUserScript}
320               fi
321             '';
322         };
324       systemd.services.freshrss-updater = {
325         description = "FreshRSS feed updater";
326         after = [ "freshrss-config.service" ];
327         startAt = "*:0/5";
328         environment = env-vars;
329         serviceConfig = defaultServiceConfig // {
330           ExecStart = "${cfg.package}/app/actualize_script.php";
331         };
332       };
333     };