# Full configuration of every stack to catch potential errors in CI pipeline # Secrets etc. will be not read from file / available in Nix store. Don't do this at home :) { config, lib, pkgs, ... }: let inherit (import ./tests/dummy-values.nix pkgs) dummyClientSecretHash dummyEmail dummyId dummySecret dummySecretFile dummyUser ; in { config.nps = rec { hostIP4Address = "192.168.178.2"; hostUid = 1000; storageBaseDir = "${config.home.homeDirectory}/stacks"; externalStorageBaseDir = "/mnt/hdd"; defaultTz = "Europe/Berlin"; stacks = { adguard.enable = true; adventurelog = { enable = true; secretKeyFile = dummySecretFile; db.passwordFile = dummySecretFile; adminProvisioning = { username = "admin"; email = "admin@example.com"; passwordFile = dummySecretFile; }; oidc = { registerClient = true; clientSecretHash = dummyClientSecretHash; }; }; anchor = { enable = true; oidc.enable = true; db = { type = "postgres"; passwordFile = dummySecretFile; }; }; aiostreams = { enable = true; secretKeyFile = dummySecretFile; extraEnv = { TMDB_ACCESS_TOKEN.fromFile = dummySecretFile; }; }; audiobookshelf = { oidc = { registerClient = true; clientSecretHash = dummyClientSecretHash; }; }; authelia = { enable = true; jwtSecretFile = dummySecretFile; sessionSecretFile = dummySecretFile; storageEncryptionKeyFile = dummySecretFile; oidc = { enable = true; hmacSecretFile = dummySecretFile; jwksRsaKeyFile = dummySecretFile; clients.dummy = { public = true; authorization_policy = "two_factor"; redirect_uris = []; }; }; settings.access_control.rules = [ { domain = "private.example.com"; subject = [ "group:guest" ]; policy = "deny"; } ]; }; baikal.enable = true; bambuddy = { enable = true; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; orcaSlicer.enable = true; bambuStudio.enable = true; virtualPrinter.enable = true; }; bentopdf.enable = true; beszel = { enable = true; ed25519PrivateKeyFile = dummySecretFile; ed25519PublicKeyFile = dummySecretFile; tokenFile = dummySecretFile; adminProvisioning = { email = "admin@admin.com"; passwordFile = dummySecretFile; }; oidc = { registerClient = true; clientSecretHash = dummyClientSecretHash; }; }; blocky = { enable = true; enableGrafanaDashboard = true; enablePrometheusExport = true; containers.blocky = { dashboard.url = "${config.nps.containers.grafana.traefik.serviceUrl}/d/blocky"; gatus = { enable = true; settings = { url = "host.containers.internal"; dns = { query-name = config.nps.stacks.traefik.domain; query-type = "A"; }; conditions = [ "[DNS_RCODE] == NOERROR" ]; }; }; }; }; bookorbit = { enable = true; jwtSecretFile = dummySecretFile; podcastEncryptionKeyFile = dummySecretFile; setupBootstrapTokenFile = dummySecretFile; db.passwordFile = dummySecretFile; oidc = { registerClient = true; clientSecretHash = dummyClientSecretHash; }; tts.enable = true; }; bytestash = { enable = true; jwtSecretFile = dummySecretFile; }; calibre.enable = true; changedetection.enable = true; crowdsec = { enable = true; extraEnv = { ENROLL_INSTANCE_NAME = "dummy"; ENROLL_KEY.fromFile = dummySecretFile; }; }; davis = { adminPasswordFile = dummySecretFile; enableLdapAuth = true; db = { type = "mysql"; userPasswordFile = dummySecretFile; rootPasswordFile = dummySecretFile; }; }; dawarich = { enable = true; secretKeyFile = dummySecretFile; db.passwordFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; }; }; ddns-updater = { enable = true; settings = [ { provider = "duckdns"; domain = "example.duckdns.org"; token = "{{ file.Read `${dummySecretFile}`}}"; ip_version = "ipv4"; } ]; }; dockdns = { enable = true; extraEnv.EXAMPLE_COM_API_TOKEN.fromFile = dummySecretFile; settings.dns.purgeUnknown = true; settings.domains = let domain = config.nps.stacks.traefik.domain; in [ { name = domain; a = hostIP4Address; } { name = "*.${domain}"; a = hostIP4Address; } ]; }; donetick = { jwtSecretFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; settings.is_user_creation_disabled = true; }; dozzle = { enable = true; containers.dozzle.forwardAuth = { enable = true; rules = [ { policy = "one_factor"; } ]; }; }; dynacat = { enable = true; secretKeyFile = dummySecretFile; settings.pages.home.columns.start = { rank = 500; size = "small"; widgets = [ { type = "server-stats"; servers = [ { type = "local"; name = "Server"; } ]; } { type = "reddit"; subreddit = "selfhosted"; collapse-after = 3; } ]; }; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; excalidash = { enable = true; jwtSecretFile = dummySecretFile; csrfSecretFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; filebrowser-quantum = { enable = true; mounts = { ${config.nps.externalStorageBaseDir} = { path = "/hdd"; name = "hdd"; config = { denyByDefault = true; disableIndexing = false; }; }; }; oidc = { enable = true; clientSecretHash = dummyClientSecretHash; clientSecretFile = dummySecretFile; }; settings.auth.methods.password.enabled = false; }; flaresolverr.enable = true; fredy.enable = true; forgejo = { enable = true; lfsJwtSecretFile = dummySecretFile; secretKeyFile = dummySecretFile; internalTokenFile = dummySecretFile; jwtSecretFile = dummySecretFile; adminProvisioning = { username = "forgejo"; email = "admin@test.com"; passwordFile = dummySecretFile; }; oidc = { enable = true; clientSecretFile = dummySecretFile; }; db = { type = "postgres"; passwordFile = dummySecretFile; }; }; freshrss = { enable = true; adminProvisioning = { enable = true; username = dummyUser; email = dummyEmail; passwordFile = dummySecretFile; apiPasswordFile = dummySecretFile; }; }; frigate = { enable = true; containers.frigate.devices = lib.mkForce []; }; gatus = { enable = true; db = { type = "postgres"; passwordFile = dummySecretFile; }; settings.endpoints = [ { name = "Some website"; url = "https://example.com"; client.dns-resolver = "tcp://1.1.1.1:53"; conditions = [ "[STATUS] == 200" ]; } ]; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; glance = { enable = true; settings.pages.home = { columns.start = { rank = 500; size = "small"; widgets = [ { type = "server-stats"; servers = [ { type = "local"; name = "Server"; } ]; } { type = "reddit"; subreddit = "selfhosted"; collapse-after = 3; } ]; }; columns.end = { rank = 1500; size = "small"; widgets = [ { type = "clock"; time-format = "24h"; date-format = "d MMMM yyyy"; show-seconds = true; show-timezone = true; timezone = config.nps.defaultTz; } { type = "calendar"; first-day-of-week = "monday"; } ]; }; }; }; grimmory = { enable = true; oidc = { registerClient = true; }; db = { userPasswordFile = dummySecretFile; rootPasswordFile = dummySecretFile; }; }; guacamole = { enable = true; userMappingXml = '' ssh host.containers.internal 22 rdp 103.5.133.3 22 ''; }; healthchecks = { enable = true; secretKeyFile = dummySecretFile; superUserEmail = dummyEmail; superUserPasswordFile = dummySecretFile; }; homeassistant.enable = true; homelable = { enable = true; secretKeyFile = dummySecretFile; mcp = { enable = true; apiKeyFile = dummySecretFile; serviceKeyFile = dummySecretFile; }; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; homebox = { enable = true; apiKeyPepperFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; db = { type = "postgres"; passwordFile = dummySecretFile; }; }; homepage = { enable = true; widgets = [ { openweathermap = { units = "metric"; cache = 5; apiKey.path = dummySecretFile; }; } ]; }; hortusfox = { enable = true; db = { userPasswordFile = dummySecretFile; rootPasswordFile = dummySecretFile; }; containers.hortusfox.forwardAuth.enable = true; adminEmail = dummyEmail; extraEnv = { PROXY_ENABLE = true; PROXY_HEADER_EMAIL = "Remote-Email"; PROXY_HEADER_USERNAME = "Remote-User"; PROXY_AUTO_SIGNUP = true; PROXY_WHITELIST = config.nps.stacks.traefik.ip4; PROXY_HIDE_LOGOUT = true; }; }; immich = { enable = true; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; db.passwordFile = dummySecretFile; }; it-tools = { enable = true; containers.it-tools.sablier = { enable = true; group = "devtools"; idleReplicas = "1"; middleware = { sessionDuration = "10m"; failOpen = true; ignoreUserAgent = ["curl"]; # `displayName` is intentionally unset, `jotty` sets it and the strategy default has # to survive for containers that do not. dynamic.theme = "matrix"; }; }; }; jotty = { enable = true; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; # Second container of the "devtools" Sablier group, to exercise merging. containers.jotty.sablier = { enable = true; group = "devtools"; middleware = { sessionDuration = "20m"; ignoreUserAgent = ["(?i)uptimerobot" "curl"]; dynamic.displayName = "Jotty"; }; }; }; karakeep = { enable = true; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; nextauthSecretFile = dummySecretFile; meiliMasterKeyFile = dummySecretFile; }; kimai = { enable = true; adminEmail = dummyEmail; adminPasswordFile = dummySecretFile; db = { userPasswordFile = dummySecretFile; rootPasswordFile = dummySecretFile; }; }; kitchenowl = { enable = true; jwtSecretFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; komga = { enable = true; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; lldap = { enable = true; baseDn = "DC=example,DC=com"; jwtSecretFile = dummySecretFile; keySeedFile = dummySecretFile; adminPasswordFile = dummySecretFile; bootstrap = { cleanUp = true; users = { test = { email = dummyEmail; password_file = dummySecretFile; }; }; }; }; mazanoke.enable = true; mealie = { enable = true; oidc = { enable = true; clientSecretHash = dummyClientSecretHash; clientSecretFile = dummySecretFile; }; }; memos = { enable = true; oidc = { registerClient = true; clientSecretHash = dummyClientSecretHash; }; db = { type = "postgres"; passwordFile = dummySecretFile; }; }; microbin = { enable = true; extraEnv = { MICROBIN_ADMIN_USERNAME = dummyUser; MICROBIN_ADMIN_PASSWORD.fromFile = dummySecretFile; MICROBIN_UPLOADER_PASSWORD.fromFile = dummySecretFile; }; }; monitoring = { enable = true; prometheus.rules.groups = let cpuThresh = 90; in [ { name = "resource.usage"; rules = [ { alert = "HighCpuUsage"; expr = ''100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > ${toString cpuThresh}''; for = "20m"; labels = { severity = "warning"; }; annotations = { summary = "High CPU usage"; description = "CPU usage is above ${toString cpuThresh}% (current value: {{ $value }}%)"; }; } ]; } ]; alertmanager = { enable = true; ntfy = { enable = true; settings.ntfy.notification.topic = "monitoring"; }; }; }; netbird-client = { enable = true; setupKeyFile = dummySecretFile; }; netbird-management = { enable = true; authSecretFile = dummySecretFile; storeEncryptionKeyFile = dummySecretFile; adminProvisioning = { email = dummyEmail; passwordFile = dummySecretFile; }; oidc = { clientSecretFile = dummySecretFile; }; }; n8n.enable = true; navidrome.enable = true; networking-toolbox.enable = true; norish = { enable = true; masterKeyFile = dummySecretFile; db.passwordFile = dummySecretFile; cdpTokenFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; ntfy = { enable = true; extraEnv = { NTFY_WEB_PUSH_EMAIL_ADDRESS = dummyEmail; NTFY_WEB_PUSH_PUBLIC_KEY.fromFile = dummySecretFile; NTFY_WEB_PUSH_PRIVATE_KEY.fromFile = dummySecretFile; }; enableGrafanaDashboard = true; enablePrometheusExport = true; }; omnigent = { enable = true; db = { type = "postgres"; passwordFile = dummySecretFile; }; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; cookieSecretFile = dummySecretFile; }; }; omnitools.enable = true; outline = { enable = true; secretKeyFile = dummySecretFile; utilsSecretFile = dummySecretFile; db.passwordFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; pangolin-newt = { enable = true; enableGrafanaDashboard = true; enablePrometheusExport = true; extraEnv = { PANGOLIN_ENDPOINT.fromFile = dummySecretFile; NEWT_ID.fromFile = dummySecretFile; NEWT_SECRET.fromFile = dummySecretFile; NEWT_METRICS_PROMETHEUS_ENABLED = "true"; NEWT_ADMIN_ADDR = ":2112"; LOG_LEVEL = "INFO"; }; }; paperless = { enable = true; adminProvisioning = { username = dummyUser; email = dummyEmail; passwordFile = dummySecretFile; }; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; secretKeyFile = dummySecretFile; extraEnv = { PAPERLESS_OCR_LANGUAGES = "eng deu"; PAPERLESS_OCR_LANGUAGE = "eng+deu"; }; db = { passwordFile = dummySecretFile; }; ftp = { enable = true; passwordFile = dummySecretFile; }; }; pinepods = { enable = true; db.passwordFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; }; adminProvisioning = { enable = true; email = "admin@example.com"; passwordFile = dummySecretFile; }; }; prowlarr = { enable = true; db = { type = "postgres"; passwordFile = dummySecretFile; }; extraEnv."PROWLARR__AUTH__APIKEY".fromFile = dummySecretFile; }; qbittorrent = { enable = true; gluetun = { vpnProvider = "airvpn"; wireguardPrivateKeyFile = dummySecretFile; wireguardPresharedKeyFile = dummySecretFile; wireguardAddressesFile = dummySecretFile; extraEnv = { FIREWALL_VPN_INPUT_PORTS.fromFile = dummySecretFile; SERVER_NAMES.fromFile = dummySecretFile; HTTP_CONTROL_SERVER_LOG = "off"; }; }; extraEnv.TORRENTING_PORT.fromFile = dummySecretFile; qui = { enable = true; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; }; romm = { enable = true; authSecretKeyFile = dummySecretFile; romLibraryPath = "${config.nps.externalStorageBaseDir}/romm/library"; extraEnv = { IGDB_CLIENT_ID.fromFile = dummySecretFile; IGDB_CLIENT_SECRET.fromFile = dummySecretFile; }; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; db = { userPasswordFile = dummySecretFile; rootPasswordFile = dummySecretFile; }; }; sabnzbd = { enable = true; configIni = '' [misc] host_whitelist_entry = sabnzbd.example.com ''; }; sablier = { enable = true; settings = { sessions.default-duration = "10m"; }; }; searxng = { enable = true; secretKeyFile = dummySecretFile; settings.engines = [ { name = "dummy.online"; engine = "dummy"; } ]; }; scanopy = { enable = true; db.passwordFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; }; }; shelfmark = { enable = true; downloadDirectory = "${config.nps.storageBaseDir}/grimmory/bookdrop"; useProwlarr = true; useQbittorrent = true; extraEnv = { PROWLARR_API_KEY.fromFile = dummySecretFile; QBITTORRENT_PASSWORD.fromFile = dummySecretFile; }; }; socket-proxy.enable = true; sparky-fitness = { enable = true; betterAuthSecretFile = dummySecretFile; apiEncryptionKeyFile = dummySecretFile; db.passwordFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; }; }; spliit = { enable = true; db.passwordFile = dummySecretFile; }; sshwifty = { enable = true; settings = { SharedKey = dummySecret; Presets = [ { Title = "Host SSH"; Type = "SSH"; Host = "host.containers.internal:22"; Meta = { User = dummyId; Encoding = "utf-8"; "Private Key" = "file://${dummySecretFile}"; Authentication = "Private Key"; }; } ]; }; }; stirling-pdf.enable = true; storyteller = { enable = true; secretKeyFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; streaming = { enable = true; jellyfin = { oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; seerr.enable = true; profilarr.enable = true; useSabnzbd = true; maintainerr.enable = true; } // lib.genAttrs ["sonarr" "radarr" "bazarr"] (name: { db = { type = "postgres"; passwordFile = dummySecretFile; }; extraEnv."${lib.toUpper name}__AUTH__APIKEY".fromFile = dummySecretFile; }); super-productivity = { enable = true; enableSync = true; jwtSecretFile = dummySecretFile; db.passwordFile = dummySecretFile; smtp = { host = "localhost"; user = "test"; passwordFile = dummySecretFile; from = "test@localhost"; }; }; tandoor = { enable = true; secretKeyFile = dummySecretFile; db.passwordFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; containers.tandoor.extraEnv = { # https://docs.tandoor.dev/system/configuration/#default-permissions SOCIAL_DEFAULT_ACCESS = 1; SOCIAL_DEFAULT_GROUP = "user"; }; }; timetracker = { enable = true; secretKeyFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; db.passwordFile = dummySecretFile; }; traefik = { enable = true; domain = "example.com"; extraEnv.CF_DNS_API_TOKEN.fromFile = dummySecretFile; geoblock.allowedCountries = ["DE"]; enablePrometheusExport = true; enableGrafanaMetricsDashboard = true; enableGrafanaAccessLogDashboard = true; crowdsec.middleware.bouncerKeyFile = dummySecretFile; }; trek = { enable = true; oidc = { enable = true; clientSecretHash = dummyClientSecretHash; clientSecretFile = dummySecretFile; }; }; trip = { enable = true; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; uptime-kuma.enable = true; vaultwarden = { enable = true; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; vikunja = { enable = true; db.type = "postgres"; db.passwordFile = dummySecretFile; jwtSecretFile = dummySecretFile; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; settings = { service.enableregistration = false; auth.local.enabled = false; }; }; webtop = { enable = true; username = dummyUser; passwordFile = dummySecretFile; }; wg-easy = { enable = true; adminPasswordFile = dummySecretFile; extraEnv = { DISABLE_IPV6 = true; }; }; wg-portal = { enable = true; settings.core = { admin_user = dummyUser; admin_password = "\${ADMIN_PASSWORD}"; }; extraEnv.ADMIN_PASSWORD.fromFile = dummySecretFile; settings.advanved.use_ip_v6 = false; oidc = { enable = true; clientSecretFile = dummySecretFile; clientSecretHash = dummyClientSecretHash; }; }; yopass.enable = true; }; }; }