How to Self-Host Homepage: Dashboard for Your Self-Hosted Services 2026
TL;DR
Homepage (Apache 2.0, ~19K GitHub stars, Next.js) is the most feature-rich self-hosted dashboard for your homelab or server — a central launcher for all your self-hosted apps with live service status, Docker container stats, and over 100 service integrations. One glance shows: is Plex running? What's the Sonarr queue? How loaded is my server? Compare: Dashy (MIT, ~17K stars) is more visual/customizable; Heimdall (MIT, ~7K stars) is simpler; Homepage is the middle ground with the best widget ecosystem.
Key Takeaways
- Homepage: Apache 2.0, ~19K stars — 100+ service widgets, Docker auto-discovery
- Live stats: Real-time data from Arr apps, Proxmox, PiHole, Grafana, and more
- Docker integration: Auto-detect containers and show CPU/RAM usage
- YAML config: All configuration in YAML files — version-controllable
- Fast: Prerendered Next.js app, loads in <200ms
- No database: Pure YAML config, nothing stored
Dashboard Alternatives Comparison
| App | License | Stars | Config | Docker Integration | Widgets |
|---|---|---|---|---|---|
| Homepage | Apache 2.0 | ~19K | YAML | Auto-discover | 100+ |
| Dashy | MIT | ~17K | YAML | Yes | 50+ |
| Heimdall | MIT | ~7K | Web UI | No | Basic |
| Organizr | UNLICENSE | ~5K | Web UI | No | Many |
| Dasherr | MIT | ~500 | YAML | Yes | Basic |
Part 1: Docker Setup
# docker-compose.yml
services:
homepage:
image: ghcr.io/gethomepage/homepage:latest
container_name: homepage
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- ./config:/app/config # YAML config files
- /var/run/docker.sock:/var/run/docker.sock:ro # For Docker integration
environment:
PUID: 1000
PGID: 1000
mkdir config
docker compose up -d
Visit http://your-server:3000.
Part 2: HTTPS with Caddy
home.yourdomain.com {
reverse_proxy localhost:3000
}
Part 3: Core Configuration Files
Homepage uses 5 YAML files in ./config/:
services.yaml — Your App Links
# config/services.yaml
- Media:
- Jellyfin:
href: https://media.yourdomain.com
description: Media Server
icon: jellyfin.png
widget:
type: jellyfin
url: http://jellyfin:8096
key: your-api-key
- Sonarr:
href: https://sonarr.yourdomain.com
icon: sonarr.png
widget:
type: sonarr
url: http://sonarr:8989
key: your-sonarr-api-key
- Infrastructure:
- Portainer:
href: https://portainer.yourdomain.com
icon: portainer.png
widget:
type: portainer
url: http://portainer:9000
env: 1
key: your-portainer-api-key
- Proxmox:
href: https://pve.yourdomain.com:8006
icon: proxmox.png
widget:
type: proxmox
url: https://pve.yourdomain.com:8006
username: api@pve!homepage
password: your-token-secret
- Pi-hole:
href: http://pihole.lan/admin
icon: pi-hole.png
widget:
type: pihole
url: http://pihole.lan
key: your-pihole-api-key
- Monitoring:
- Netdata:
href: https://metrics.yourdomain.com
icon: netdata.png
- Grafana:
href: https://grafana.yourdomain.com
icon: grafana.png
widget:
type: grafana
url: http://grafana:3000
username: admin
password: your-grafana-password
widgets.yaml — Top Bar Widgets
# config/widgets.yaml
- logo:
icon: /icons/logo.png
- greeting:
text_size: xl
text: "Good $time, $name!"
- datetime:
text_size: xl
format:
dateStyle: long
timeStyle: short
hourCycle: h23
- resources:
cpu: true
memory: true
disk: /
diskUnits: gigabytes
expanded: true
label: server
- search:
provider: duckduckgo
target: _blank
- openmeteo:
label: Home
latitude: 37.7749
longitude: -122.4194
units: imperial
cache: 5
- unifi_console:
url: https://unifi.yourdomain.com
username: readonly
password: readonly-password
bookmarks.yaml — Quick Links
# config/bookmarks.yaml
- Developer:
- GitHub:
- href: https://github.com
- Documentation:
- href: https://docs.yourdomain.com
- Social:
- Reddit:
- href: https://www.reddit.com/r/selfhosted/
- HackerNews:
- href: https://news.ycombinator.com
settings.yaml — Global Settings
# config/settings.yaml
title: My Homelab
favicon: /icons/favicon.png
theme: dark
color: slate
background:
image: /images/background.jpg
blur: sm
opacity: 50
layout:
Media:
icon: mdi-television-play
columns: 3
style: row
Infrastructure:
icon: mdi-server
columns: 4
headerStyle: boxed
statusStyle: dot
providers:
openweathermap: your-owm-api-key
docker.yaml — Docker Integration
# config/docker.yaml
my-server:
socket: /var/run/docker.sock
Part 4: Docker Auto-Discovery
Homepage can auto-discover running containers via labels:
# In any docker-compose.yml service:
services:
jellyfin:
labels:
- "homepage.group=Media"
- "homepage.name=Jellyfin"
- "homepage.icon=jellyfin.png"
- "homepage.href=https://media.yourdomain.com"
- "homepage.description=Media Server"
- "homepage.widget.type=jellyfin"
- "homepage.widget.url=http://jellyfin:8096"
- "homepage.widget.key=your-api-key"
When Homepage detects these labels, it automatically adds the service to the dashboard without modifying services.yaml.
Part 5: Available Widgets
Over 100 service widgets with live data:
| Category | Widgets |
|---|---|
| Media | Jellyfin, Plex, Emby, Sonarr, Radarr, Lidarr, Readarr, Bazarr, Overseerr, Jellyseerr |
| Download | qBittorrent, Transmission, Deluge, NZBGet, SABnzbd, Prowlarr |
| Networking | Pi-hole, AdGuard Home, Unifi, OPNsense, pfSense, Traefik |
| Infrastructure | Portainer, Proxmox, Netdata, Grafana, Uptime Kuma, Healthchecks.io |
| Home Automation | Home Assistant, Node-RED |
| System | Resources (CPU/RAM/Disk), Glances |
| Finance | Actual Budget, CoinGecko |
| Misc | Nextcloud, Gitea, Miniflux, Calibre |
Part 6: Custom Icons
Homepage has a built-in icon library (many popular self-hosted apps). For custom icons:
# Place icons in config/icons/ directory
- My App:
icon: /icons/my-app.png
# Or use Material Design Icons:
icon: mdi-server-network
# Or use Simple Icons:
icon: si-github
Part 7: Status Indicators
Each service shows a colored status dot:
- 🟢 Green: Service responding (HTTP 200)
- 🟡 Yellow: Service responding but degraded
- 🔴 Red: Service unreachable
# Enable status checking per service:
- Vaultwarden:
href: https://vault.yourdomain.com
ping: https://vault.yourdomain.com/alive # Custom health endpoint
# Or just use the href for status check
Maintenance
# Update Homepage:
docker compose pull
docker compose up -d
# Logs:
docker compose logs -f homepage
# Validate YAML:
docker exec homepage node -e "
const fs = require('fs');
const yaml = require('js-yaml');
['services','widgets','settings','bookmarks','docker'].forEach(f => {
try { yaml.load(fs.readFileSync(\`/app/config/\${f}.yaml\`,'utf8')); console.log(\`✓ \${f}.yaml\`); }
catch(e) { console.log(\`✗ \${f}.yaml: \${e.message}\`); }
});
"
# Config files are just YAML — version control them:
cd ./config && git init && git add . && git commit -m "initial homepage config"
See all open source homelab and infrastructure tools at OSSAlt.com/categories/homelab.