at 23.05-pre 7.3 kB view raw
1{ config, lib, pkgs, buildEnv, ... }: 2 3with lib; 4 5let 6 cfg = config.services.netbox; 7 staticDir = cfg.dataDir + "/static"; 8 configFile = pkgs.writeTextFile { 9 name = "configuration.py"; 10 text = '' 11 STATIC_ROOT = '${staticDir}' 12 ALLOWED_HOSTS = ['*'] 13 DATABASE = { 14 'NAME': 'netbox', 15 'USER': 'netbox', 16 'HOST': '/run/postgresql', 17 } 18 19 # Redis database settings. Redis is used for caching and for queuing background tasks such as webhook events. A separate 20 # configuration exists for each. Full connection details are required in both sections, and it is strongly recommended 21 # to use two separate database IDs. 22 REDIS = { 23 'tasks': { 24 'URL': 'unix://${config.services.redis.servers.netbox.unixSocket}?db=0', 25 'SSL': False, 26 }, 27 'caching': { 28 'URL': 'unix://${config.services.redis.servers.netbox.unixSocket}?db=1', 29 'SSL': False, 30 } 31 } 32 33 with open("${cfg.secretKeyFile}", "r") as file: 34 SECRET_KEY = file.readline() 35 36 ${optionalString cfg.enableLdap "REMOTE_AUTH_BACKEND = 'netbox.authentication.LDAPBackend'"} 37 38 ${cfg.extraConfig} 39 ''; 40 }; 41 pkg = (pkgs.netbox.overrideAttrs (old: { 42 installPhase = old.installPhase + '' 43 ln -s ${configFile} $out/opt/netbox/netbox/netbox/configuration.py 44 '' + optionalString cfg.enableLdap '' 45 ln -s ${ldapConfigPath} $out/opt/netbox/netbox/netbox/ldap_config.py 46 ''; 47 })).override { 48 plugins = ps: ((cfg.plugins ps) 49 ++ optionals cfg.enableLdap [ ps.django-auth-ldap ]); 50 }; 51 netboxManageScript = with pkgs; (writeScriptBin "netbox-manage" '' 52 #!${stdenv.shell} 53 export PYTHONPATH=${pkg.pythonPath} 54 sudo -u netbox ${pkg}/bin/netbox "$@" 55 ''); 56 57in { 58 options.services.netbox = { 59 enable = mkOption { 60 type = lib.types.bool; 61 default = false; 62 description = lib.mdDoc '' 63 Enable Netbox. 64 65 This module requires a reverse proxy that serves `/static` separately. 66 See this [example](https://github.com/netbox-community/netbox/blob/develop/contrib/nginx.conf/) on how to configure this. 67 ''; 68 }; 69 70 listenAddress = mkOption { 71 type = types.str; 72 default = "[::1]"; 73 description = lib.mdDoc '' 74 Address the server will listen on. 75 ''; 76 }; 77 78 port = mkOption { 79 type = types.port; 80 default = 8001; 81 description = lib.mdDoc '' 82 Port the server will listen on. 83 ''; 84 }; 85 86 plugins = mkOption { 87 type = types.functionTo (types.listOf types.package); 88 default = _: []; 89 defaultText = literalExpression '' 90 python3Packages: with python3Packages; []; 91 ''; 92 description = lib.mdDoc '' 93 List of plugin packages to install. 94 ''; 95 }; 96 97 dataDir = mkOption { 98 type = types.str; 99 default = "/var/lib/netbox"; 100 description = lib.mdDoc '' 101 Storage path of netbox. 102 ''; 103 }; 104 105 secretKeyFile = mkOption { 106 type = types.path; 107 description = lib.mdDoc '' 108 Path to a file containing the secret key. 109 ''; 110 }; 111 112 extraConfig = mkOption { 113 type = types.lines; 114 default = ""; 115 description = lib.mdDoc '' 116 Additional lines of configuration appended to the `configuration.py`. 117 See the [documentation](https://netbox.readthedocs.io/en/stable/configuration/optional-settings/) for more possible options. 118 ''; 119 }; 120 121 enableLdap = mkOption { 122 type = types.bool; 123 default = false; 124 description = lib.mdDoc '' 125 Enable LDAP-Authentication for Netbox. 126 127 This requires a configuration file being pass through `ldapConfigPath`. 128 ''; 129 }; 130 131 ldapConfigPath = mkOption { 132 type = types.path; 133 default = ""; 134 description = lib.mdDoc '' 135 Path to the Configuration-File for LDAP-Authentification, will be loaded as `ldap_config.py`. 136 See the [documentation](https://netbox.readthedocs.io/en/stable/installation/6-ldap/#configuration) for possible options. 137 ''; 138 }; 139 }; 140 141 config = mkIf cfg.enable { 142 services.redis.servers.netbox.enable = true; 143 144 services.postgresql = { 145 enable = true; 146 ensureDatabases = [ "netbox" ]; 147 ensureUsers = [ 148 { 149 name = "netbox"; 150 ensurePermissions = { 151 "DATABASE netbox" = "ALL PRIVILEGES"; 152 }; 153 } 154 ]; 155 }; 156 157 environment.systemPackages = [ netboxManageScript ]; 158 159 systemd.targets.netbox = { 160 description = "Target for all NetBox services"; 161 wantedBy = [ "multi-user.target" ]; 162 after = [ "network-online.target" "redis-netbox.service" ]; 163 }; 164 165 systemd.services = let 166 defaultServiceConfig = { 167 WorkingDirectory = "${cfg.dataDir}"; 168 User = "netbox"; 169 Group = "netbox"; 170 StateDirectory = "netbox"; 171 StateDirectoryMode = "0750"; 172 Restart = "on-failure"; 173 }; 174 in { 175 netbox-migration = { 176 description = "NetBox migrations"; 177 wantedBy = [ "netbox.target" ]; 178 179 environment = { 180 PYTHONPATH = pkg.pythonPath; 181 }; 182 183 serviceConfig = defaultServiceConfig // { 184 Type = "oneshot"; 185 ExecStart = '' 186 ${pkg}/bin/netbox migrate 187 ''; 188 }; 189 }; 190 191 netbox = { 192 description = "NetBox WSGI Service"; 193 wantedBy = [ "netbox.target" ]; 194 after = [ "netbox-migration.service" ]; 195 196 preStart = '' 197 ${pkg}/bin/netbox trace_paths --no-input 198 ${pkg}/bin/netbox collectstatic --no-input 199 ${pkg}/bin/netbox remove_stale_contenttypes --no-input 200 ''; 201 202 environment = { 203 PYTHONPATH = pkg.pythonPath; 204 }; 205 206 serviceConfig = defaultServiceConfig // { 207 ExecStart = '' 208 ${pkgs.python3Packages.gunicorn}/bin/gunicorn netbox.wsgi \ 209 --bind ${cfg.listenAddress}:${toString cfg.port} \ 210 --pythonpath ${pkg}/opt/netbox/netbox 211 ''; 212 }; 213 }; 214 215 netbox-rq = { 216 description = "NetBox Request Queue Worker"; 217 wantedBy = [ "netbox.target" ]; 218 after = [ "netbox.service" ]; 219 220 environment = { 221 PYTHONPATH = pkg.pythonPath; 222 }; 223 224 serviceConfig = defaultServiceConfig // { 225 ExecStart = '' 226 ${pkg}/bin/netbox rqworker high default low 227 ''; 228 }; 229 }; 230 231 netbox-housekeeping = { 232 description = "NetBox housekeeping job"; 233 after = [ "netbox.service" ]; 234 235 environment = { 236 PYTHONPATH = pkg.pythonPath; 237 }; 238 239 serviceConfig = defaultServiceConfig // { 240 Type = "oneshot"; 241 ExecStart = '' 242 ${pkg}/bin/netbox housekeeping 243 ''; 244 }; 245 }; 246 }; 247 248 systemd.timers.netbox-housekeeping = { 249 description = "Run NetBox housekeeping job"; 250 wantedBy = [ "timers.target" ]; 251 252 timerConfig = { 253 OnCalendar = "daily"; 254 }; 255 }; 256 257 users.users.netbox = { 258 home = "${cfg.dataDir}"; 259 isSystemUser = true; 260 group = "netbox"; 261 }; 262 users.groups.netbox = {}; 263 users.groups."${config.services.redis.servers.netbox.user}".members = [ "netbox" ]; 264 }; 265}