1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8 inherit (lib)
9 literalExpression
10 mkDefault
11 mkEnableOption
12 mkIf
13 mkOption
14 mkPackageOption
15 mkRenamedOptionModule
16 types
17 ;
18
19 cfg = config.services.rss-bridge;
20
21 cfgEnv = lib.pipe cfg.config [
22 (lib.mapAttrsRecursive (
23 path: value:
24 lib.optionalAttrs (value != null) {
25 name = lib.toUpper "RSSBRIDGE_${lib.concatStringsSep "_" path}";
26 value =
27 if lib.isList value then
28 lib.concatStringsSep "," value
29 else if lib.isBool value then
30 lib.boolToString value
31 else
32 toString value;
33 }
34 ))
35 (lib.collect (x: lib.isString x.name or false && lib.isString x.value or false))
36 lib.listToAttrs
37 ];
38in
39{
40 imports = [
41 (mkRenamedOptionModule
42 [
43 "services"
44 "rss-bridge"
45 "whitelist"
46 ]
47 [
48 "services"
49 "rss-bridge"
50 "config"
51 "system"
52 "enabled_bridges"
53 ]
54 )
55 ];
56
57 options = {
58 services.rss-bridge = {
59 enable = mkEnableOption "rss-bridge";
60
61 user = mkOption {
62 type = types.str;
63 default = if cfg.webserver == null then "rss-bridge" else cfg.webserver;
64 defaultText = "{option}`config.services.rss-bridge.webserver` or \"rss-bridge\"";
65 description = ''
66 The user account under which both the service and the web application run.
67 '';
68 };
69
70 group = mkOption {
71 type = types.str;
72 default = if cfg.webserver == null then "rss-bridge" else cfg.webserver;
73 defaultText = "{option}`config.services.rss-bridge.webserver` or \"rss-bridge\"";
74 description = ''
75 The group under which the web application runs.
76 '';
77 };
78
79 package = mkPackageOption pkgs "rss-bridge" { };
80
81 pool = mkOption {
82 type = types.nullOr types.str;
83 default = "rss-bridge";
84 description = ''
85 Name of phpfpm pool that is used to run web-application.
86 If `null` specified none will be created, otherwise automatically created with default values.
87 '';
88 };
89
90 dataDir = mkOption {
91 type = types.str;
92 default = "/var/lib/rss-bridge";
93 description = ''
94 Location in which cache directory will be created.
95 You can put `config.ini.php` in here.
96 '';
97 };
98
99 virtualHost = mkOption {
100 type = types.nullOr types.str;
101 default = "rss-bridge";
102 description = ''
103 Name of the nginx or caddy virtualhost to use and setup. If null, do not setup any virtualhost.
104 '';
105 };
106
107 webserver = mkOption {
108 type = types.nullOr (
109 types.enum [
110 "nginx"
111 "caddy"
112 ]
113 );
114 default = "nginx";
115 description = ''
116 Type of virtualhost to use and setup. If null, do not setup any virtualhost.
117 '';
118 };
119
120 config = mkOption {
121 type = types.submodule {
122 freeformType = (pkgs.formats.ini { }).type;
123 options = {
124 system = {
125 enabled_bridges = mkOption {
126 type = with types; nullOr (either str (listOf str));
127 description = "Only enabled bridges are available for feed production";
128 default = null;
129 };
130 };
131 FileCache = {
132 path = mkOption {
133 type = types.str;
134 description = "Directory where to store cache files (if cache.type = \"file\").";
135 default = "${cfg.dataDir}/cache/";
136 defaultText = literalExpression "\${config.services.rss-bridge.dataDir}/cache/";
137 };
138 };
139 };
140 };
141 example = literalExpression ''
142 {
143 system.enabled_bridges = [ "*" ];
144 error = {
145 output = "http";
146 report_limit = 5;
147 };
148 FileCache = {
149 enable_purge = true;
150 };
151 }
152 '';
153 description = ''
154 Attribute set of arbitrary config options.
155 Please consult the documentation at the [wiki](https://rss-bridge.github.io/rss-bridge/For_Hosts/Custom_Configuration.html)
156 and [sample config](https://github.com/RSS-Bridge/rss-bridge/blob/master/config.default.ini.php) to see a list of available options.
157 '';
158 };
159 };
160 };
161
162 config = mkIf cfg.enable {
163 services.phpfpm.pools = mkIf (cfg.pool != null) {
164 ${cfg.pool} = {
165 user = cfg.user;
166 settings = lib.mapAttrs (name: mkDefault) {
167 "listen.owner" = cfg.user;
168 "listen.group" = cfg.group;
169 "listen.mode" = "0600";
170 "pm" = "dynamic";
171 "pm.max_children" = 75;
172 "pm.start_servers" = 10;
173 "pm.min_spare_servers" = 5;
174 "pm.max_spare_servers" = 20;
175 "pm.max_requests" = 500;
176 "catch_workers_output" = 1;
177 };
178 };
179 };
180
181 systemd.tmpfiles.settings.rss-bridge = {
182 "${cfg.config.FileCache.path}".d = {
183 mode = "0750";
184 user = cfg.user;
185 group = cfg.group;
186 };
187 };
188
189 services.nginx = mkIf (cfg.virtualHost != null && cfg.webserver == "nginx") {
190 enable = true;
191 virtualHosts = {
192 ${cfg.virtualHost} = {
193 root = "${cfg.package}";
194
195 locations."/" = {
196 tryFiles = "$uri /index.php$is_args$args";
197 };
198
199 locations."~ ^/index.php(/|$)" = {
200 extraConfig = ''
201 include ${config.services.nginx.package}/conf/fastcgi_params;
202 fastcgi_split_path_info ^(.+\.php)(/.+)$;
203 fastcgi_pass unix:${config.services.phpfpm.pools.${cfg.pool}.socket};
204 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
205 ${lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: "fastcgi_param \"${n}\" \"${v}\";") cfgEnv)}
206 '';
207 };
208 };
209 };
210 };
211
212 services.caddy = mkIf (cfg.virtualHost != null && cfg.webserver == "caddy") {
213 enable = true;
214 virtualHosts.${cfg.virtualHost} = {
215 extraConfig = ''
216 root * ${cfg.package}
217 file_server
218 php_fastcgi unix/${config.services.phpfpm.pools.${cfg.pool}.socket} {
219 ${lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: " env ${n} \"${v}\"") cfgEnv)}
220 }
221 '';
222 };
223 };
224 };
225
226 meta.maintainers = with lib.maintainers; [ quantenzitrone ];
227}