From dbd49febb5c56d77450ab03bd4b990afc9ffbcb3 Mon Sep 17 00:00:00 2001 From: Ember 'n0emis' Keske Date: Sat, 5 Mar 2022 19:25:21 +0100 Subject: [PATCH] netbox: init module --- .../from_md/release-notes/rl-2205.section.xml | 7 + .../manual/release-notes/rl-2205.section.md | 2 + nixos/modules/module-list.nix | 1 + nixos/modules/services/web-apps/netbox.nix | 265 ++++++++++++++++++ 4 files changed, 275 insertions(+) create mode 100644 nixos/modules/services/web-apps/netbox.nix diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml index 6c8d881b15f..797cb1f1693 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml @@ -229,6 +229,13 @@ services.prometheus.exporters.pve. + + + netbox, + infrastructure resource modeling (IRM) tool. Available as + services.netbox. + + tetrd, share your diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md index 9aba688cb9b..351ef644828 100644 --- a/nixos/doc/manual/release-notes/rl-2205.section.md +++ b/nixos/doc/manual/release-notes/rl-2205.section.md @@ -67,6 +67,8 @@ In addition to numerous new and upgraded packages, this release has the followin - [prometheus-pve-exporter](https://github.com/prometheus-pve/prometheus-pve-exporter), a tool that exposes information from the Proxmox VE API for use by Prometheus. Available as [services.prometheus.exporters.pve](options.html#opt-services.prometheus.exporters.pve). +- [netbox](https://github.com/netbox-community/netbox), infrastructure resource modeling (IRM) tool. Available as [services.netbox](options.html#opt-services.netbox.enable). + - [tetrd](https://tetrd.app), share your internet connection from your device to your PC and vice versa through a USB cable. Available at [services.tetrd](#opt-services.tetrd.enable). - [agate](https://github.com/mbrubeck/agate), a very simple server for the Gemini hypertext protocol. Available as [services.agate](options.html#opt-services.agate.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index adeddbf139a..a9ed8f25128 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1048,6 +1048,7 @@ ./services/web-apps/mediawiki.nix ./services/web-apps/miniflux.nix ./services/web-apps/moodle.nix + ./services/web-apps/netbox.nix ./services/web-apps/nextcloud.nix ./services/web-apps/nexus.nix ./services/web-apps/node-red.nix diff --git a/nixos/modules/services/web-apps/netbox.nix b/nixos/modules/services/web-apps/netbox.nix new file mode 100644 index 00000000000..a7d8bede74b --- /dev/null +++ b/nixos/modules/services/web-apps/netbox.nix @@ -0,0 +1,265 @@ +{ config, lib, pkgs, buildEnv, ... }: + +with lib; + +let + cfg = config.services.netbox; + staticDir = cfg.dataDir + "/static"; + configFile = pkgs.writeTextFile { + name = "configuration.py"; + text = '' + STATIC_ROOT = '${staticDir}' + ALLOWED_HOSTS = ['*'] + DATABASE = { + 'NAME': 'netbox', + 'USER': 'netbox', + 'HOST': '/run/postgresql', + } + + # Redis database settings. Redis is used for caching and for queuing background tasks such as webhook events. A separate + # configuration exists for each. Full connection details are required in both sections, and it is strongly recommended + # to use two separate database IDs. + REDIS = { + 'tasks': { + 'URL': 'unix://${config.services.redis.servers.netbox.unixSocket}?db=0', + 'SSL': False, + }, + 'caching': { + 'URL': 'unix://${config.services.redis.servers.netbox.unixSocket}?db=1', + 'SSL': False, + } + } + + with open("${cfg.secretKeyFile}", "r") as file: + SECRET_KEY = file.readline() + + ${optionalString cfg.enableLdap "REMOTE_AUTH_BACKEND = 'netbox.authentication.LDAPBackend'"} + + ${cfg.extraConfig} + ''; + }; + pkg = (pkgs.netbox.overrideAttrs (old: { + installPhase = old.installPhase + '' + ln -s ${configFile} $out/opt/netbox/netbox/netbox/configuration.py + '' + optionalString cfg.enableLdap '' + ln -s ${ldapConfigPath} $out/opt/netbox/netbox/netbox/ldap_config.py + ''; + })).override { + plugins = ps: ((cfg.plugins ps) + ++ optional cfg.enableLdap [ ps.django-auth-ldap ]); + }; + netboxManageScript = with pkgs; (writeScriptBin "netbox-manage" '' + #!${stdenv.shell} + export PYTHONPATH=${pkg.pythonPath} + sudo -u netbox ${pkg}/bin/netbox "$@" + ''); + +in { + options.services.netbox = { + enable = mkOption { + type = lib.types.bool; + default = false; + description = '' + Enable Netbox. + + This module requires a reverse proxy that serves /static separately. + See this example on how to configure this. + ''; + }; + + listenAddress = mkOption { + type = types.str; + default = "[::1]"; + description = '' + Address the server will listen on. + ''; + }; + + port = mkOption { + type = types.port; + default = 8001; + description = '' + Port the server will listen on. + ''; + }; + + plugins = mkOption { + type = types.functionTo (types.listOf types.package); + default = _: []; + defaultText = literalExpression '' + python3Packages: with python3Packages; []; + ''; + description = '' + List of plugin packages to install. + ''; + }; + + dataDir = mkOption { + type = types.str; + default = "/var/lib/netbox"; + description = '' + Storage path of netbox. + ''; + }; + + secretKeyFile = mkOption { + type = types.path; + description = '' + Path to a file containing the secret key. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional lines of configuration appended to the configuration.py. + See the documentation for more possible options. + ''; + }; + + enableLdap = mkOption { + type = types.bool; + default = false; + description = '' + Enable LDAP-Authentication for Netbox. + + This requires a configuration file being pass through ldapConfigPath. + ''; + }; + + ldapConfigPath = mkOption { + type = types.path; + default = ""; + description = '' + Path to the Configuration-File for LDAP-Authentification, will be loaded as ldap_config.py. + See the documentation for possible options. + ''; + }; + }; + + config = mkIf cfg.enable { + services.redis.servers.netbox.enable = true; + + services.postgresql = { + enable = true; + ensureDatabases = [ "netbox" ]; + ensureUsers = [ + { + name = "netbox"; + ensurePermissions = { + "DATABASE netbox" = "ALL PRIVILEGES"; + }; + } + ]; + }; + + environment.systemPackages = [ netboxManageScript ]; + + systemd.targets.netbox = { + description = "Target for all NetBox services"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" "redis-netbox.service" ]; + }; + + systemd.services = let + defaultServiceConfig = { + WorkingDirectory = "${cfg.dataDir}"; + User = "netbox"; + Group = "netbox"; + StateDirectory = "netbox"; + StateDirectoryMode = "0750"; + Restart = "on-failure"; + }; + in { + netbox-migration = { + description = "NetBox migrations"; + wantedBy = [ "netbox.target" ]; + + environment = { + PYTHONPATH = pkg.pythonPath; + }; + + serviceConfig = defaultServiceConfig // { + Type = "oneshot"; + ExecStart = '' + ${pkg}/bin/netbox migrate + ''; + }; + }; + + netbox = { + description = "NetBox WSGI Service"; + wantedBy = [ "netbox.target" ]; + after = [ "netbox-migration.service" ]; + + preStart = '' + ${pkg}/bin/netbox trace_paths --no-input + ${pkg}/bin/netbox collectstatic --no-input + ${pkg}/bin/netbox remove_stale_contenttypes --no-input + ''; + + environment = { + PYTHONPATH = pkg.pythonPath; + }; + + serviceConfig = defaultServiceConfig // { + ExecStart = '' + ${pkgs.python3Packages.gunicorn}/bin/gunicorn netbox.wsgi \ + --bind ${cfg.listenAddress}:${toString cfg.port} \ + --pythonpath ${pkg}/opt/netbox/netbox + ''; + }; + }; + + netbox-rq = { + description = "NetBox Request Queue Worker"; + wantedBy = [ "netbox.target" ]; + after = [ "netbox.service" ]; + + environment = { + PYTHONPATH = pkg.pythonPath; + }; + + serviceConfig = defaultServiceConfig // { + ExecStart = '' + ${pkg}/bin/netbox rqworker high default low + ''; + }; + }; + + netbox-housekeeping = { + description = "NetBox housekeeping job"; + after = [ "netbox.service" ]; + + environment = { + PYTHONPATH = pkg.pythonPath; + }; + + serviceConfig = defaultServiceConfig // { + Type = "oneshot"; + ExecStart = '' + ${pkg}/bin/netbox housekeeping + ''; + }; + }; + }; + + systemd.timers.netbox-housekeeping = { + description = "Run NetBox housekeeping job"; + wantedBy = [ "timers.target" ]; + + timerConfig = { + OnCalendar = "daily"; + }; + }; + + users.users.netbox = { + home = "${cfg.dataDir}"; + isSystemUser = true; + group = "netbox"; + }; + users.groups.netbox = {}; + users.groups."${config.services.redis.servers.netbox.user}".members = [ "netbox" ]; + }; +}