# Homepage Dashboard — Adding Machines, Tabs & Services This guide covers how to add new machines, tabs, and services to the **Homepage** dashboards on **homeserver-1** (and, by extension, any host that imports the Homepage module). ## Overview Homepage (https://gethomepage.dev) is a self-hosted dashboard. All dashboard configuration lives in Nix and is rendered to YAML files that Homepage reads at `/etc/homepage-dashboard/`. | Item | Location | |------|----------| | Homepage NixOS module (service wrapper) | `modules/services/homepage.nix` | | Dashboard definition for homeserver-1 | `hosts/homeserver-1/homepage.nix` | | Deployed config files | `/etc/homepage-dashboard/{settings,services,widgets}.yaml` | | API keys / secrets | `secrets.yaml` (SOPS) → `HOMEPAGE_VAR_*` env vars | The dashboard definition is split from the host config so it's easy to edit: - `hosts/homeserver-1/configuration.nix` enables Glances + firewall and imports: ```nix imports = [ # ... ./homepage.nix ]; ``` ## Applying Changes After editing `homepage.nix`: ```bash nixos-rebuild switch --target-host petere@homeserver-1 --flake .#homeserver-1 --use-remote-sudo ``` > **Important:** Homepage reads its config files when the service starts. After > a `nixos-rebuild`, the unit's definition usually changes, but if only the > *contents* of the config files changed (e.g. just editing `homepage.nix`), the > service may keep the old config in memory. If your changes don't appear, restart it: > > ```bash > ssh petere@homeserver-1 "sudo systemctl restart homepage-dashboard" > ``` ## Structure of the Dashboard Definition `hosts/homeserver-1/homepage.nix` has three main parts: ```nix services.homepage = { enable = true; port = 8082; allowedHosts = [ ... ]; # Host header values Homepage responds to environmentFiles = [ ... ]; # SOPS-secret env file with HOMEPAGE_VAR_* keys settings = { title = "HomeServer"; # ... layout = { ... }; # Controls grouping, tabs, and column widths }; services = [ ... ]; # The service groups and tiles (services.yaml) widgets = [ ... ]; # Header info widgets (resources, search, clock) }; ``` ## Tabs Tabs are enabled by adding a `tab` field to a group's **layout** entry. - Groups with the **same** `tab` value appear on that tab. - Groups with **no** `tab` appear on **every** tab. - Tabs are sorted by their order in the `layout` block. - Each tab is deep-linkable: `#monitoring`, `#homeserver-1`, etc. Current tabs: ``` Monitoring (default tab) ├── Homeserver-1 Monitoring → 5 Glances tiles (localhost) └── MCF Server Monitoring → 5 Glances tiles (mcf-server via tailnet) Homeserver-1 (#homeserver-1) ├── Media → Jellyfin, Immich └── System → Backrest, Pocket ID, Tailscale MCF Server (reserved; uncomment the placeholder to enable) ``` ## Adding a Service 1. **Add the service tile** to the relevant group in the `services` list: ```nix services = [ # ... { System = [ # ...existing tiles... { MyService = { icon = "sh-myservice"; href = "http://homeserver-1.gerbil-opah.ts.net:"; description = "What it does"; siteMonitor = "http://127.0.0.1:"; # green/red status widget = { # optional live stats type = "myservice"; url = "http://127.0.0.1:"; key = "{{HOMEPAGE_VAR_MYSERVICE_API_KEY}}"; # only if it needs a key }; }; } ]; } ]; ``` 2. **Set the layout** so the group renders where you want (columns = how many tiles per row; groups span the full width with `style = "row"` when they're a single top-level group): ```nix layout = { # ... MyService = { # or add to an existing group's entry tab = "Homeserver-1"; style = "row"; columns = 4; }; }; ``` 3. **API keys**: never hardcode secrets. Add the value to `secrets.yaml` under the machine section and reference it via the environment file. The secret `homeserver-1/homepage-env` already provides `HOMEPAGE_VAR_JELLYFIN_API_KEY`, `HOMEPAGE_VAR_IMMICH_API_KEY`, `HOMEPAGE_VAR_TAILSCALE_API_KEY` and `HOMEPAGE_VAR_TAILSCALE_DEVICEID`. To add another: ```bash sops --set '["homeserver-1"]["homepage-env"] "HOMEPAGE_VAR_MYSERVICE_API_KEY="' secrets.yaml ``` (This replaces the whole env file — include every existing `HOMEPAGE_VAR_*` line when setting it.) ## Adding a Tab Add a new group to `services` and give it a `tab` in the layout: ```nix # services { "My New Group" = [ { "MyService" = { href = "..."; }; } ]; } # layout "My New Group" = { tab = "My Tab"; style = "row"; columns = 4; }; ``` ## Adding a New Machine to the Dashboard To monitor another machine (e.g. `richmond-server`): ### 1. Enable Glances on the target machine Add to that host's `configuration.nix` (Glances exposes system stats to the dashboard): ```nix services.glances = { enable = true; port = 61208; extraArgs = [ "--webserver" ]; }; # Expose on Tailscale only networking.firewall.interfaces.tailscale.allowedTCPPorts = [ 61208 ]; ``` ### 2. Add the monitoring group In `hosts/homeserver-1/homepage.nix`, add a group with Glances tiles. **The group name must be unique** — Homepage's widget proxy resolves widget config by leaf group name, so duplicate group names cause one machine's stats to display on another's tiles. ```nix # services { "Richmond Server Monitoring" = [ { "System" = { widget = { type = "glances"; url = "http://richmond-server.gerbil-opah.ts.net:61208"; version = 4; metric = "info"; }; }; } { "CPU" = { widget = { type = "glances"; url = "http://richmond-server.gerbil-opah.ts.net:61208"; version = 4; metric = "cpu"; }; }; } { "Memory" = { widget = { type = "glances"; url = "http://richmond-server.gerbil-opah.ts.net:61208"; version = 4; metric = "memory"; }; }; } { "Disk" = { widget = { type = "glances"; url = "http://richmond-server.gerbil-opah.ts.net:61208"; version = 4; metric = "fs:/"; }; }; } { "Processes" = { widget = { type = "glances"; url = "http://richmond-server.gerbil-opah.ts.net:61208"; version = 4; metric = "process"; }; }; } ]; } # layout "Richmond Server Monitoring" = { tab = "Monitoring"; style = "row"; columns = 5; }; ``` ### 3. Add non-monitoring services for that machine Add a group and give it its own tab (or reuse an existing one): ```nix # services { "Richmond Server Apps" = [ { "Ntfy" = { icon = "sh-ntfy"; href = "http://richmond-server.gerbil-opah.ts.net:8080"; }; } ]; } # layout "Richmond Server Apps" = { tab = "Richmond Server"; style = "row"; columns = 4; }; ``` ### 4. (Optional) Tailscale widget for the machine Each machine's Tailscale node can be shown with its own widget, using the machine's numeric device ID (find it via the Tailscale API/admin console): ```nix { "Richmond Server" = [ { Tailscale = { icon = "sh-tailscale"; href = "https://login.tailscale.com/admin/machines"; widget = { type = "tailscale"; deviceid = ""; # NOT the ...CNTRL value key = "{{HOMEPAGE_VAR_TAILSCALE_API_KEY}}"; }; }; } ]; } ``` ## Troubleshooting | Symptom | Cause / Fix | |---------|-------------| | Changes not appearing | Service not restarted — run `sudo systemctl restart homepage-dashboard` | | `t.metric is undefined` | Glances widget missing the `metric` field — every glances tile needs `metric` (e.g. `cpu`, `memory`, `fs:/`, `process`, `info`) | | `no manageable device matching this ID found` | Tailscale widget `deviceid` is wrong — must be the **numeric** device ID, not the `...CNTRL` value | | Two machines show the same stats | Duplicate group names — every group (especially monitoring) needs a unique name | | `Host validation failed` | The `Host` header isn't in `allowedHosts` — add the hostname (with port) to `allowedHosts` | | API keys showing in config | Keys must come from the SOPS env file (`HOMEPAGE_VAR_*`), never hardcoded | ## Glances Metrics The Glances widget (`type = "glances"`) requires a `version` and `metric`: - `version = 4` for Glances v4.x (installed) - `metric`: `info` (system summary), `cpu`, `memory`, `process`, `containers`, `fs:/` (disk usage), `network:`, `sensor:`, `disk:`, `gpu:`