What it is
gethomepage is a YAML-configured dashboard for self-hosted services. Tiles with icons, live widgets that pull metrics from each service's API, a few utility widgets up top (datetime, system resources, search). It's the internal start page my browser opens to.
Why I run it
Without an internal dashboard I'd have a Notion page or a bookmark folder, and I'd never look at it. With Homepage as my browser start page, it's the natural starting point for everything I do in the homelab. Click a tile to land in the service; glance at the widget on the tile to know if something needs attention.
The widget API integrations are the actual value, not the icons. Uptime Kuma's status page, PBS datastore usage, Plex active streams, AdGuard query counts, Proxmox VM/CT counts — all surfaced as small live numbers on the tiles. The dashboard answers "is anything obviously wrong right now" in two seconds.
How I use it
Sections are ordered operations-first, not alphabetically. What might be broken goes near the top:
- Infrastructure — Home Assistant, Portainer, Grafana, Proxmox. The "is the cluster healthy" row.
- Hosts & Services — quick links to second-node UIs, the router, the LLM machine.
- Network — Uptime Kuma + two AdGuards + NPM.
- Backups — PBS gets a full-width row because its widget has four stat blocks.
- Security & Access — Vaultwarden, Tailscale, icon-only (no widgets).
- Personal Cloud, Media, Media Tools, Sandbox — the day-to-day apps.
A few widgets aren't enabled deliberately. Vaultwarden's widget requires the master password, which is an unacceptable secret to put into a compose env var even on a homelab. Stirling PDF doesn't have an upstream widget. Nextcloud needs a user-driven app-password setup I haven't done.
Setup notes
- Host: a Docker container on the edge LXC, alongside NPM and AdGuard.
- Config: YAML files in a config directory bind-mounted into the container.
services.yamldefines tiles;settings.yamlcontrols layout, theme, and global behavior. YAML auto-reloads on file change — no container restart needed for layout edits. - Background image: in Homepage 1.x, custom images need a second bind mount under
/app/public/imagesbecause the base image only serves/public/...paths. Took a while to figure out. HOMEPAGE_ALLOWED_HOSTS: when accessed via a proxied hostname, Homepage validates theHostheader against this list. Missing values return an HTML "Host validation failed" page served as HTTP 200 — easy to miss when health-checking viacurl.- Secrets: widget API keys live in runtime-only environment variables outside git.
services.yamlreferences them by name. - Backups: config is in the LXC rootfs, captured by PBS.
Runbook
- Healthy looks like: tiles load, every widget shows live numbers, the Uptime Kuma widget shows real status-page values (not zeros).
- Background image returns 404: the
/app/public/imagesbind mount is missing. Add it to the compose volumes and restart. - Widget shows literal
{{HOMEPAGE_VAR_X}}: the env var isn't reaching the container. Confirm it's in the composeenvironment:block. - Uptime Kuma widget shows zeros: status-page slug in
services.yamldoesn't match an actual status page in Uptime Kuma. Both ends need to use the same slug. - AdGuard widget shows nothing: using port
3030(the setup wizard port) instead of8089(the admin API port). Same trap I hit twice. - Service tile dot is red but the service works: Homepage is using
ping:against a host that blocks ICMP (Windows default). Switch tositeMonitor:(HTTP GET) instead — it tests the actual web service, not the network layer. - Where logs live:
docker logs homepageon the host.