vuls: init at 0.27.0 (#348530)
[NixPkgs.git] / nixos / modules / services / web-apps / peering-manager.nix
blobacdc3937452932e42d86d17f27599363971d8715
1 { config, lib, pkgs, buildEnv, ... }:
3 let
4   cfg = config.services.peering-manager;
6   pythonFmt = pkgs.formats.pythonVars {};
7   settingsFile = pythonFmt.generate "peering-manager-settings.py" cfg.settings;
8   extraConfigFile = pkgs.writeTextFile {
9     name = "peering-manager-extraConfig.py";
10     text = cfg.extraConfig;
11   };
12   configFile = pkgs.concatText "configuration.py" [ settingsFile extraConfigFile ];
14   pkg = (pkgs.peering-manager.overrideAttrs (old: {
15     postInstall = ''
16       ln -s ${configFile} $out/opt/peering-manager/peering_manager/configuration.py
17     '' + lib.optionalString cfg.enableLdap ''
18       ln -s ${cfg.ldapConfigPath} $out/opt/peering-manager/peering_manager/ldap_config.py
19     '' + lib.optionalString cfg.enableOidc ''
20       ln -s ${cfg.oidcConfigPath} $out/opt/peering-manager/peering_manager/oidc_config.py
21     '';
22   })).override {
23     inherit (cfg) plugins;
24   };
25   peeringManagerManageScript = pkgs.writeScriptBin "peering-manager-manage" ''
26     #!${pkgs.stdenv.shell}
27     export PYTHONPATH=${pkg.pythonPath}
28     sudo -u peering-manager ${pkg}/bin/peering-manager "$@"
29   '';
31 in {
32   options.services.peering-manager = with lib; {
33     enable = mkOption {
34       type = types.bool;
35       default = false;
36       description = ''
37         Enable Peering Manager.
39         This module requires a reverse proxy that serves `/static` separately.
40         See this [example](https://github.com/peering-manager/contrib/blob/main/nginx.conf on how to configure this.
41       '';
42     };
44     enableScheduledTasks = mkOption {
45       type = types.bool;
46       default = true;
47       description = ''
48         Set up [scheduled tasks](https://peering-manager.readthedocs.io/en/stable/setup/8-scheduled-tasks/)
49       '';
50     };
52     listenAddress = mkOption {
53       type = types.str;
54       default = "[::1]";
55       description = ''
56         Address the server will listen on.
57       '';
58     };
60     port = mkOption {
61       type = types.port;
62       default = 8001;
63       description = ''
64         Port the server will listen on.
65       '';
66     };
68     plugins = mkOption {
69       type = types.functionTo (types.listOf types.package);
70       default = _: [];
71       defaultText = literalExpression ''
72         python3Packages: with python3Packages; [];
73       '';
74       description = ''
75         List of plugin packages to install.
76       '';
77     };
79     secretKeyFile = mkOption {
80       type = types.path;
81       description = ''
82         Path to a file containing the secret key.
83       '';
84     };
86     peeringdbApiKeyFile = mkOption {
87       type = with types; nullOr path;
88       default = null;
89       description = ''
90         Path to a file containing the PeeringDB API key.
91       '';
92     };
94     settings = lib.mkOption {
95       description = ''
96         Configuration options to set in `configuration.py`.
97         See the [documentation](https://peering-manager.readthedocs.io/en/stable/configuration/optional-settings/) for more possible options.
98       '';
100       default = { };
102       type = lib.types.submodule {
103         freeformType = pythonFmt.type;
105         options = {
106           ALLOWED_HOSTS = lib.mkOption {
107             type = with lib.types; listOf str;
108             default = ["*"];
109             description = ''
110               A list of valid fully-qualified domain names (FQDNs) and/or IP
111               addresses that can be used to reach the peering manager service.
112             '';
113           };
114         };
115       };
116     };
118     extraConfig = mkOption {
119       type = types.lines;
120       default = "";
121       description = ''
122         Additional lines of configuration appended to the `configuration.py`.
123         See the [documentation](https://peering-manager.readthedocs.io/en/stable/configuration/optional-settings/) for more possible options.
124       '';
125     };
127     enableLdap = mkOption {
128       type = types.bool;
129       default = false;
130       description = ''
131         Enable LDAP-Authentication for Peering Manager.
133         This requires a configuration file being pass through `ldapConfigPath`.
134       '';
135     };
137     ldapConfigPath = mkOption {
138       type = types.path;
139       description = ''
140         Path to the Configuration-File for LDAP-Authentication, will be loaded as `ldap_config.py`.
141         See the [documentation](https://peering-manager.readthedocs.io/en/stable/setup/6-ldap/#configuration) for possible options.
142       '';
143     };
145     enableOidc = mkOption {
146       type = types.bool;
147       default = false;
148       description = ''
149         Enable OIDC-Authentication for Peering Manager.
151         This requires a configuration file being pass through `oidcConfigPath`.
152       '';
153     };
155     oidcConfigPath = mkOption {
156       type = types.path;
157       description = ''
158         Path to the Configuration-File for OIDC-Authentication, will be loaded as `oidc_config.py`.
159         See the [documentation](https://peering-manager.readthedocs.io/en/stable/setup/6b-oidc/#configuration) for possible options.
160       '';
161     };
162   };
164   config = lib.mkIf cfg.enable {
165     services.peering-manager = {
166       settings = {
167         DATABASE = {
168           NAME = "peering-manager";
169           USER = "peering-manager";
170           HOST = "/run/postgresql";
171         };
173         # Redis database settings. Redis is used for caching and for queuing background tasks such as webhook events. A separate
174         # configuration exists for each. Full connection details are required in both sections, and it is strongly recommended
175         # to use two separate database IDs.
176         REDIS = {
177           tasks = {
178             UNIX_SOCKET_PATH = config.services.redis.servers.peering-manager.unixSocket;
179             DATABASE = 0;
180           };
181           caching = {
182             UNIX_SOCKET_PATH = config.services.redis.servers.peering-manager.unixSocket;
183             DATABASE = 1;
184           };
185         };
186       };
188       extraConfig = ''
189         with open("${cfg.secretKeyFile}", "r") as file:
190           SECRET_KEY = file.readline()
191       '' + lib.optionalString (cfg.peeringdbApiKeyFile != null) ''
192         with open("${cfg.peeringdbApiKeyFile}", "r") as file:
193           PEERINGDB_API_KEY = file.readline()
194       '';
196       plugins = (ps:
197         (lib.optionals cfg.enableLdap [ ps.django-auth-ldap ]) ++
198         (lib.optionals cfg.enableOidc (with ps; [ mozilla-django-oidc pyopenssl josepy ]))
199       );
200     };
202     system.build.peeringManagerPkg = pkg;
204     services.redis.servers.peering-manager.enable = true;
206     services.postgresql = {
207       enable = true;
208       ensureDatabases = [ "peering-manager" ];
209       ensureUsers = [
210         {
211           name = "peering-manager";
212           ensureDBOwnership = true;
213         }
214       ];
215     };
217     environment.systemPackages = [ peeringManagerManageScript ];
219     systemd.targets.peering-manager = {
220       description = "Target for all Peering Manager services";
221       wantedBy = [ "multi-user.target" ];
222       wants = [ "network-online.target" ];
223       after = [ "network-online.target" "redis-peering-manager.service" ];
224     };
226     systemd.services = let
227       defaults = {
228         environment = {
229           PYTHONPATH = pkg.pythonPath;
230         };
231         serviceConfig = {
232           WorkingDirectory = "/var/lib/peering-manager";
233           User = "peering-manager";
234           Group = "peering-manager";
235           StateDirectory = "peering-manager";
236           StateDirectoryMode = "0750";
237           Restart = "on-failure";
238         };
239       };
240     in {
241       peering-manager-migration = lib.recursiveUpdate defaults {
242         description = "Peering Manager migrations";
243         wantedBy = [ "peering-manager.target" ];
244         serviceConfig = {
245           Type = "oneshot";
246           ExecStart = "${pkg}/bin/peering-manager migrate";
247         };
248       };
250       peering-manager = lib.recursiveUpdate defaults {
251         description = "Peering Manager WSGI Service";
252         wantedBy = [ "peering-manager.target" ];
253         after = [ "peering-manager-migration.service" ];
255         preStart = ''
256           ${pkg}/bin/peering-manager remove_stale_contenttypes --no-input
257         '';
259         serviceConfig = {
260           ExecStart = ''
261             ${pkg.python.pkgs.gunicorn}/bin/gunicorn peering_manager.wsgi \
262               --bind ${cfg.listenAddress}:${toString cfg.port} \
263               --pythonpath ${pkg}/opt/peering-manager
264           '';
265         };
266       };
268       peering-manager-rq = lib.recursiveUpdate defaults {
269         description = "Peering Manager Request Queue Worker";
270         wantedBy = [ "peering-manager.target" ];
271         after = [ "peering-manager.service" ];
272         serviceConfig.ExecStart = "${pkg}/bin/peering-manager rqworker high default low";
273       };
275       peering-manager-housekeeping = lib.recursiveUpdate defaults {
276         description = "Peering Manager housekeeping job";
277         after = [ "peering-manager.service" ];
278         serviceConfig = {
279           Type = "oneshot";
280           ExecStart = "${pkg}/bin/peering-manager housekeeping";
281         };
282       };
284       peering-manager-peeringdb-sync = lib.recursiveUpdate defaults {
285         description = "PeeringDB sync";
286         after = [ "peering-manager.service" ];
287         serviceConfig = {
288           Type = "oneshot";
289           ExecStart = "${pkg}/bin/peering-manager peeringdb_sync";
290         };
291       };
293       peering-manager-prefix-fetch = lib.recursiveUpdate defaults {
294         description = "Fetch IRR AS-SET prefixes";
295         after = [ "peering-manager.service" ];
296         serviceConfig = {
297           Type = "oneshot";
298           ExecStart = "${pkg}/bin/peering-manager grab_prefixes";
299         };
300       };
302       peering-manager-configuration-deployment = lib.recursiveUpdate defaults {
303         description = "Push configuration to routers";
304         after = [ "peering-manager.service" ];
305         serviceConfig = {
306           Type = "oneshot";
307           ExecStart = "${pkg}/bin/peering-manager configure_routers";
308         };
309       };
311       peering-manager-session-poll = lib.recursiveUpdate defaults {
312         description = "Poll peering sessions from routers";
313         after = [ "peering-manager.service" ];
314         serviceConfig = {
315           Type = "oneshot";
316           ExecStart = "${pkg}/bin/peering-manager poll_bgp_sessions --all";
317         };
318       };
319     };
321     systemd.timers = {
322       peering-manager-housekeeping = {
323         description = "Run Peering Manager housekeeping job";
324         wantedBy = [ "timers.target" ];
325         timerConfig.OnCalendar = "daily";
326       };
328       peering-manager-peeringdb-sync = {
329         enable = lib.mkDefault cfg.enableScheduledTasks;
330         description = "Sync PeeringDB at 2:30";
331         wantedBy = [ "timers.target" ];
332         timerConfig.OnCalendar = "02:30:00";
333       };
335       peering-manager-prefix-fetch = {
336         enable = lib.mkDefault cfg.enableScheduledTasks;
337         description = "Fetch IRR AS-SET prefixes at 4:30";
338         wantedBy = [ "timers.target" ];
339         timerConfig.OnCalendar = "04:30:00";
340       };
342       peering-manager-configuration-deployment = {
343         enable = lib.mkDefault cfg.enableScheduledTasks;
344         description = "Push router configuration every hour 5 minutes before full hour";
345         wantedBy = [ "timers.target" ];
346         timerConfig.OnCalendar = "*:55:00";
347       };
349       peering-manager-session-poll = {
350         enable = lib.mkDefault cfg.enableScheduledTasks;
351         description = "Poll peering sessions from routers every hour";
352         wantedBy = [ "timers.target" ];
353         timerConfig.OnCalendar = "*:00:00";
354       };
355     };
357     users.users.peering-manager = {
358       home = "/var/lib/peering-manager";
359       isSystemUser = true;
360       group = "peering-manager";
361     };
362     users.groups.peering-manager = {};
363     users.groups."${config.services.redis.servers.peering-manager.user}".members = [ "peering-manager" ];
364   };
366   meta.maintainers = with lib.maintainers; [ yuka ];