From 1ffb260e8852a4197691d5fa5d6b2097e5c511e9 Mon Sep 17 00:00:00 2001 From: Stefan Kempinger Date: Sun, 25 Jan 2026 23:42:34 +0100 Subject: [PATCH] Enable Scrutiny, InfluxDB2 and homepage dashboard Open firewall ports for Scrutiny (8185) and homepage (8080). Add binutils to systemPackages and enable services.influxdb2. Configure Scrutiny to use InfluxDB. Enable homepage-dashboard with widgets, bookmarks and an environmentFile for secrets. Fix docker pull string formatting and minor whitespace cleanup. --- heimserver/configuration.nix | 289 ++++++++++++++++++++++++++++++++++- 1 file changed, 281 insertions(+), 8 deletions(-) diff --git a/heimserver/configuration.nix b/heimserver/configuration.nix index 215b331..4861e51 100644 --- a/heimserver/configuration.nix +++ b/heimserver/configuration.nix @@ -80,6 +80,8 @@ 2055 # ntopng sink 8182 # ntopng frontend 8183 # adguardhome frontend + 8185 # scrutiny frontend + 8080 # homepage ]; firewall.allowedUDPPorts = [ 53 @@ -118,6 +120,8 @@ parted borgbackup lshw + binutils + influxdb2 nil ]; @@ -142,7 +146,6 @@ #services.resolved.enable = true; - services.nginx = { enable = true; recommendedTlsSettings = true; @@ -264,7 +267,6 @@ }; }; - services.fail2ban = { enable = true; @@ -301,7 +303,7 @@ }; }; }; - + environment.etc."fail2ban/filter.d/immich.local".text = '' [Definition] # Matches: ... Failed login attempt for user ... from ip address @@ -310,7 +312,7 @@ ignoreregex = ''; - + environment.etc."fail2ban/filter.d/forgejo.local".text = '' [Definition] # Matches: ... Failed login attempt for user ... from ip address @@ -319,15 +321,15 @@ ignoreregex = ''; - + environment.etc."magic-update-script.sh".text = '' #!/usr/bin/env bash set -euo pipefail echo "Pulling latest container images..." - ${lib.concatMapStringsSep "\n" (name: - "docker pull ${config.virtualisation.oci-containers.containers.${name}.image}" + ${lib.concatMapStringsSep "\n" ( + name: "docker pull ${config.virtualisation.oci-containers.containers.${name}.image}" ) (builtins.attrNames config.virtualisation.oci-containers.containers)} echo "All images updated successfully!" @@ -440,7 +442,19 @@ --local-networks "185.27.122.0/24=WAN,192.168.69.0/24=LAN,192.168.42.0/24=Wireguard"''; }; - services.influxdb.enable = true; + services.influxdb2 = { + enable = true; + + # provision = { + # enable = true; + # initialSetup = { + # organization = "default"; + # bucket = "default"; + # passwordFile = pkgs.writeText "admin-pw" "ExAmPl3PA55W0rD"; + # tokenFile = pkgs.writeText "admin-token" "verysecureadmintoken"; + # }; + # }; + }; services.geoipupdate = { enable = true; @@ -458,6 +472,18 @@ }; }; + services.scrutiny = { + enable = true; + settings.web.listen.port = 8185; + influxdb.enable = true; + collector.schedule = "hourly"; + settings.web.influxdb = { + bucket = "default"; + org = "default"; + token = "verysecureadmintoken"; + }; + }; + services.adguardhome = { enable = true; # You can select any ip and port, just make sure to open firewalls where needed @@ -465,6 +491,253 @@ port = 8183; }; + services.homepage-dashboard = { + enable = true; + listenPort = 8080; + allowedHosts = "192.168.69.69:8080"; + + settings = { + title = "Heimserver"; + theme = "dark"; + color = "slate"; + layout = { + "Home Automation" = { + style = "row"; + columns = 3; + }; + "Media & Storage" = { + style = "row"; + columns = 2; + }; + "Development" = { + style = "row"; + columns = 2; + }; + "Network & Monitoring" = { + style = "row"; + columns = 3; + }; + }; + }; + + services = [ + { + "Home Automation" = [ + { + "Home Assistant" = { + href = "http://192.168.69.69:8123"; + description = "Home automation platform"; + icon = "home-assistant.png"; + widget = { + type = "homeassistant"; + url = "http://192.168.69.69:8123"; + key = "{{HOMEPAGE_VAR_HASS_TOKEN}}"; # Create long-lived token in HA + # Shows: entities count, automations, sensors + custom = [ + { + state = "sensor.indoor_outdoor_meter_5109_temperature"; + label = "Außentemperatur"; + } + { + state = "weather.forecast_home"; + label = "Windgeschwindigkeit"; + value = "{attributes.wind_speed} {attributes.wind_speed_unit}"; + } + { + state = "sensor.load_power"; + label = "Stromverbrauch"; + } + ]; + }; + }; + } + { + "Frigate" = { + href = "https://192.168.69.69:8971"; + description = "NVR with AI detection"; + icon = "frigate.png"; + widget = { + type = "frigate"; + url = "http://127.0.0.1:5000"; + # Shows: camera status, detection counts, storage usage + }; + }; + } + ]; + } + { + "Media & Storage" = [ + { + "Immich" = { + href = "https://bilder.kempinger.at"; + description = "Photo & video management"; + icon = "immich.png"; + widget = { + type = "immich"; + url = "https://bilder.kempinger.at"; + key = "{{HOMEPAGE_VAR_IMMICH_API_KEY}}"; # Generate in Immich settings + version = 2; + # Shows: photo count, video count, storage usage, user count + }; + }; + } + ]; + } + { + "Development" = [ + { + "Forgejo" = { + href = "https://git.kempinger.at"; + description = "Git repository hosting"; + icon = "forgejo.png"; + widget = { + type = "gitea"; # Forgejo uses Gitea API + url = "http://192.168.69.69:8184"; + key = "{{HOMEPAGE_VAR_FORGEJO_TOKEN}}"; # Create in Forgejo settings + # Shows: repository count, issue count, pull requests + }; + }; + } + { + "Github" = { + href = "https://github.com/CrazyChaoz"; + description = "Github"; + icon = "github.png"; + }; + } + ]; + } + { + "Network & Monitoring" = [ + { + "AdGuard Home" = { + href = "http://192.168.69.69:8183"; + description = "DNS filtering & ad blocking"; + icon = "adguard-home.png"; + widget = { + type = "adguard"; + url = "http://192.168.69.69:8183"; + username = "{{HOMEPAGE_VAR_ADGUARD_USER}}"; + password = "{{HOMEPAGE_VAR_ADGUARD_PASS}}"; + # Shows: queries blocked, % blocked, queries processed + }; + }; + } + { + "Mikrotik" = { + href = "https://192.168.69.1"; + description = "My Router"; + icon = "mikrotik.png"; + widget = { + type = "mikrotik"; + url = "https://192.168.69.1:443"; + username = "{{HOMEPAGE_VAR_USER}}"; + password = "{{HOMEPAGE_VAR_PASS}}"; + }; + }; + } + { + "Scrutiny" = { + href = "http://192.168.69.69:8185"; + description = "S.M.A.R.T Monitoring"; + icon = "scrutiny.png"; + widget = { + type = "scrutiny"; + url = "http://192.168.69.69:8185"; + }; + }; + } + { + "ntopng" = { + href = "http://192.168.69.69:8182"; + description = "Network traffic analysis"; + icon = "ntopng.png"; + # No official widget, but could use iframe or custom API + }; + } + ]; + } + ]; + + widgets = [ + { + resources = { + info = true; + cpu = true; + memory = true; + "gpu:0" = true; + disk = "/"; + uptime = true; + units = "metric"; + refresh = 3000; # Refresh every 3 seconds + }; + } + { + search = { + provider = "duckduckgo"; + target = "_blank"; + }; + } + # Optional: Add datetime widget + { + datetime = { + text_size = "xl"; + format = { + dateStyle = "long"; + timeStyle = "short"; + hour12 = false; + }; + }; + } + ]; + + bookmarks = [ + { + "Services" = [ + { + "Website" = [ + { + abbr = "WEB"; + href = "https://kempinger.at"; + } + ]; + } + ]; + } + { + "Documentation" = [ + { + "NixOS" = [ + { + abbr = "NX"; + href = "https://nixos.org/manual/nixos/stable/"; + } + ]; + } + { + "Home Assistant" = [ + { + abbr = "HA"; + href = "https://www.home-assistant.io/docs/"; + } + ]; + } + { + "Frigate" = [ + { + abbr = "FR"; + href = "https://docs.frigate.video/"; + } + ]; + } + ]; + } + ]; + + # Environment variables for API keys (more secure than hardcoding) + environmentFile = "/var/lib/homepage-dashboard/secrets.env"; + }; + nixpkgs.config.allowUnfree = true; nixpkgs.overlays = [