Building a Home Dashboard with Homepage
Prerequisites
- Docker and Docker Compose (the real ones, not just the word “Docker” tattooed on your forearm)
- At least one self-hosted service to display, otherwise this is just a very pretty empty page
- A working network where your services are reachable (thoughts and prayers dont count as DNS)
- A mild obsession with knowing whether your services are up at 3am
- One of those massive ultrawide monitors so you can admire your dashboard in full cinematic glory (optional but encouraged)
What We’re Building
Every homelabber hits the same wall eventually. You’ve got Proxmox running VMs, TrueNAS hoarding your Linux ISOs, Plex serving media to the household, and about fifteen other services scattered across your network. You open a new tab, squint at your bookmarks bar, and think “which port was Jellyfin on again?”
Homepage fixes that. Its a single, clean dashboard that pulls in live status from all your services, shows widgets for things like CPU and weather, and auto-discovers Docker containers. One page, everything at a glance.
The plan is straightforward:
- Deploy Homepage with Docker
- Configure services
- Add widgets and bookmarks
- Customise the layout
Lets get into it.
Step 1: Deploy Homepage
The compose file is minimal, which is always a good sign.
services:
homepage:
image: ghcr.io/gethomepage/homepage:latest
ports:
- "3000:3000"
volumes:
- ./config:/app/config
- /var/run/docker.sock:/var/run/docker.sock:ro
We’re mounting the Docker socket read-only so Homepage can peek at your running containers without being able to do anything reckless with them. Sensible defaults.
Create the config/ directory and fire it up:
mkdir config
docker compose up -d
Hit http://localhost:3000 and you should see a mostly empty dashboard staring back at you, full of potential and absolutely no data. Time to fix that.

Step 2: Configure Services
This is where it gets satisfying. Create config/services.yaml and start telling Homepage about the things running on your network:
- Infrastructure:
- Proxmox:
href: https://proxmox.home.local
icon: proxmox.png
description: Virtualisation
widget:
type: proxmox
url: https://proxmox.home.local
username: api@pam!homepage
password: {{HOMEPAGE_VAR_PROXMOX_TOKEN}}
- TrueNAS:
href: https://truenas.home.local
icon: truenas.png
description: Network storage
widget:
type: truenas
url: https://truenas.home.local
key: {{HOMEPAGE_VAR_TRUENAS_KEY}}
- Media:
- Plex:
href: https://plex.home.local
icon: plex.png
widget:
type: plex
url: https://plex.home.local
key: {{HOMEPAGE_VAR_PLEX_TOKEN}}
- Jellyfin:
href: https://jellyfin.home.local
icon: jellyfin.png
widget:
type: jellyfin
url: https://jellyfin.home.local
key: {{HOMEPAGE_VAR_JELLYFIN_KEY}}
The widget blocks are the magic here. Homepage doesn’t just link to your services, it actually queries their APIs and pulls back live data. Proxmox shows VM status, TrueNAS shows pool health, Plex shows active streams. You get real information instead of just a grid of fancy bookmarks.
Notice those {{HOMEPAGE_VAR_...}} placeholders? Homepage has its own templating for secrets so you isnt hardcoding API keys into config files like an animal.
Step 3: Add Secrets
Create a .env file to hold all your API tokens:
HOMEPAGE_VAR_PROXMOX_TOKEN=your-token
HOMEPAGE_VAR_TRUENAS_KEY=your-key
HOMEPAGE_VAR_PLEX_TOKEN=your-token
HOMEPAGE_VAR_JELLYFIN_KEY=your-key
Then tell your compose file about it:
services:
homepage:
env_file: .env
Keep this .env out of version control. Add it to your .gitignore and move on with a clean conscience.

Step 4: Configure Bookmarks
Not everything needs a widget. Sometimes you just want quick links to things you visit constantly. Create config/bookmarks.yaml:
- Developer:
- GitHub:
- abbr: GH
href: https://github.com
- GitLab:
- abbr: GL
href: https://gitlab.com
- Social:
- Twitter:
- abbr: TW
href: https://twitter.com
- Reddit:
- abbr: RD
href: https://reddit.com
These show up as compact little pill buttons on the dashboard. Nothing clever, just useful. I ended up adding way more of these than I expected because once you have a dashboard open as your new tab page, you start routing everything through it.
Step 5: Customise Widgets
The top bar of Homepage can show system resources, weather, time, and a bunch of other glanceable info. Create config/widgets.yaml:
- resources:
cpu: true
memory: true
disk: /
- openweathermap:
label: Weather
latitude: 51.5074
longitude: -0.1278
units: metric
apiKey: {{HOMEPAGE_VAR_WEATHER_KEY}}
- datetime:
text_size: xl
format:
dateStyle: short
timeStyle: short
hour12: false
The resource widget pulls from the host machine, so if Homepage is running in Docker you’ll see the host’s actual CPU and memory usage, not the container’s. The weather widget needs an OpenWeatherMap API key (free tier is fine, they give you a generous number of calls). And yes, hour12: false because we’re not savages.

Step 6: Docker Integration
This is the bit that made me properly grin the first time I set it up. Homepage can auto-discover your Docker containers using labels. Add these to any service in your compose files:
services:
myapp:
image: myapp:latest
labels:
- homepage.group=Apps
- homepage.name=My App
- homepage.icon=myapp.png
- homepage.href=http://myapp.home.local
- homepage.description=My custom app
Then create config/docker.yaml to point Homepage at your Docker socket:
my-docker:
socket: /var/run/docker.sock
Now whenever you spin up a new container with the right labels, it just appears on the dashboard. No editing services.yaml, no restarting Homepage. It just shows up. Genuinely brilliant for a homelab where you’re constantly deploying and tearing down containers.

The Result
Once everything is wired up you get:
- A single page showing every service on your network with live status
- Widgets pulling real data from Proxmox, TrueNAS, Plex, and anything else with an API
- Automatic discovery of new Docker containers
- A clean, customisable interface that actually looks good enough to leave on a wall monitor
What I’d Do Differently
Plan your service categories before you start adding things. I went with a loose “Infrastructure / Media / Apps” split and it worked well enough, but reorganising later means editing every single service entry. Fifteen minutes of planning saves you an hour of YAML shuffling.
Homepage replaced my old Heimdall setup and a janky custom monitoring page I’d cobbled together. Fewer moving parts, better features, and I stopped having to fix my own dashboard every time I updated something else. Sometimes the best tool is the one someone else maintains.