Open-source alternatives guide
How to Self-Host Homepage 2026
Self-host Homepage for a self-hosted services dashboard in 2026. Apache 2.0, ~19K stars — app launcher with live service stats, Docker integration, widgets.
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"
Why Self-Host Homepage
The pitch for a self-hosted dashboard is simple: when you're running 10, 20, or 30 self-hosted services, you need a single place to see them all. Without a dashboard, you're keeping a mental map of ports, subdomains, and service states. Homepage replaces that mental overhead with a visual interface that shows you exactly what's running, what's down, and what's queued.
Commercial dashboard alternatives don't really exist at Homepage's feature level — this is a category where open source wins comprehensively. The closest SaaS equivalent would be something like Grafana Cloud for monitoring plus a custom internal tools page, easily running $50+/month. Homepage is free and does what matters: show your services and their live status.
The widget ecosystem is where Homepage genuinely shines. Most dashboard tools show static links with a colored dot (up/down). Homepage shows you the Sonarr queue count, Radarr upcoming releases, Pi-hole query statistics, Proxmox CPU and memory usage, your Netdata system metrics, Uptime Kuma status, and your Unifi client count — all live, all on one page. This transforms the dashboard from a glorified bookmark manager into actual operational visibility.
Configuration as YAML files is an underrated feature. Every service, widget, and setting is stored in plain text files that you can version-control with git. Your entire homelab dashboard configuration lives in a git repository — you can diff changes, roll back mistakes, and recreate your exact setup on a new server in minutes. Compare this to web UI-based tools like Heimdall where your configuration is locked in a database.
When NOT to self-host Homepage: Homepage is a display tool, not a control plane — you can't manage or restart services from it. If you need active management capabilities, Portainer or a proper monitoring stack (Prometheus + Grafana) serves better. Homepage also requires maintaining YAML files, which can get complex with 30+ services. If YAML configuration feels like overhead, Heimdall's web UI approach may be preferable.
Prerequisites
Homepage is one of the least demanding self-hosted applications in the ecosystem. Its read-only nature (it only reads from Docker and service APIs) means there's very little that can go wrong.
Server specs: 256MB RAM and half a vCPU is genuinely sufficient. Homepage is a prerendered Next.js application — most of the rendering work is done at build time, and each page load is fast. Even a Raspberry Pi 3B can run Homepage without issues. It can comfortably share a VPS with other services. See our VPS comparison for self-hosters to find the right fit — Homepage is best co-located on a VPS you're already using.
Operating system: Ubuntu 22.04 LTS for Docker support. If you're running Homepage on a Raspberry Pi for a home network dashboard, Raspberry Pi OS (64-bit) also works well.
Docker socket access: For Docker integration (showing container stats and auto-discovery), Homepage mounts /var/run/docker.sock read-only. This is safe — Homepage only reads container metadata, never controls them. If you're on a managed hosting environment where Docker socket access isn't available, Homepage still works as a static bookmark launcher without the Docker features.
Service API keys: Each widget you configure needs an API key from the corresponding service. Plan ahead — you'll need to generate API keys from Sonarr, Radarr, Portainer, Grafana, etc. before Homepage can show live data. Most services generate API keys in Settings → API or similar.
Skill level: Beginner. YAML editing is the primary skill required. Start with a simple services.yaml with a few links and expand from there.
Production Security Hardening
Homepage reads from your infrastructure — Docker stats, service APIs, Proxmox credentials, Pi-hole. Its config files contain API keys and potentially passwords for your other services. Securing Homepage protects all of those credentials.
Firewall (UFW): Never expose port 3000 directly. Route everything through your reverse proxy.
sudo ufw default deny incoming
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
Add authentication to your reverse proxy: Homepage has no built-in authentication. Anyone who reaches your Homepage URL has full visibility into your infrastructure status and links. Use Caddy with basic auth or forward auth to an identity provider:
home.yourdomain.com {
basicauth {
admin JDJhJDE0JHNvbWVoYXNoZWRwYXNzd29yZA==
}
reverse_proxy localhost:3000
}
Secrets management: Homepage config files contain API keys for Sonarr, Portainer, Grafana, and other services. These files should be in a private git repository (not public GitHub) and should never be shared. Consider using Homepage's environment variable support to keep sensitive values out of YAML:
# services.yaml - reference env vars:
widget:
key: {{HOMEPAGE_VAR_SONARR_KEY}}
# .env (add to .gitignore)
HOMEPAGE_VAR_SONARR_KEY=your-sonarr-api-key
Read-only Docker socket: Mount /var/run/docker.sock:ro (read-only) as shown in the Docker Compose config. This prevents Homepage from ever accidentally modifying Docker resources even if the application were compromised.
Automatic security updates:
sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
Follow the self-hosting security checklist for the full picture. And back up your config directory — it contains your entire dashboard configuration. See automated server backups with restic for a simple automated approach.
Organizing Your Dashboard Effectively
A poorly organized Homepage dashboard is more confusing than useful. The structure you establish when you first set it up tends to stick, so it's worth thinking through the organization before you start adding services.
Group services by functional area rather than by how they're deployed. "Media" and "Monitoring" and "Infrastructure" make sense as categories. "Docker containers" and "VMs" do not — that's an implementation detail, not a mental model. Users of your dashboard shouldn't need to know the deployment topology to find what they're looking for.
Limit each group to 4-6 services. Homepage renders groups in columns, and a group with 15 services becomes a wall of icons that requires scanning. If a functional area has more than 6 services, split it. "Media" can become "Media Servers" and "Media Management" — Jellyfin and Plex in one group, Sonarr/Radarr/Lidarr in another.
Use the description field consistently. A service called "Traefik" with no description requires domain knowledge to understand — not every person who looks at your dashboard knows what Traefik is. "Traefik — reverse proxy and SSL" takes three seconds to read and eliminates confusion. Consistent descriptions also make the dashboard useful as documentation for your homelab setup.
Version-control your config directory from day one. The maintenance command at the end of Part 7 shows how to initialize a git repo in your config directory. Commit changes with meaningful messages: "add Sonarr widget" or "move Pi-hole to Networking group." When you break something with a YAML edit, git diff immediately shows what changed. When your server dies and you're rebuilding, git clone restores your entire dashboard configuration in seconds.
Use the Docker label approach (Part 4) for services you're likely to add, remove, or reconfigure frequently. This is especially useful for development or staging services that come and go. For stable production services, explicit services.yaml entries give you more control over layout and ordering.
The statusStyle: dot setting in settings.yaml shows each service's status as a colored dot rather than a text label, keeping the interface clean. Combined with a dark theme and a background image with moderate blur, Homepage creates a dashboard that's both functional and visually polished enough to leave on a second monitor.
Troubleshooting Common Issues
Dashboard loads but widgets show "Error" or no data
Widget errors mean Homepage can't reach the service API. Most common causes: the service URL in services.yaml uses localhost (wrong — use the Docker service name or actual IP/domain), the API key is incorrect or expired, or the service requires HTTPS but you specified HTTP. Click the error icon in Homepage to see the specific error message. Test the API endpoint directly with curl from the Homepage container: docker exec homepage curl http://sonarr:8989/api/v3/system/status?apiKey=YOUR_KEY.
Docker integration shows no containers
Check that /var/run/docker.sock is mounted: docker inspect homepage | grep docker.sock. If missing, it means the volume mapping in docker-compose.yml is wrong. Also verify docker.yaml is configured with the correct socket path. On some systems, the Docker socket is at a non-standard location.
YAML validation errors after editing config
Homepage is strict about YAML syntax. Use the validation command in the Maintenance section to identify which file has an error and where. Common mistakes: inconsistent indentation (tabs vs spaces — YAML requires spaces), missing quotes around values containing special characters, or incorrect list formatting. The error message from the validator usually points to the exact line.
Status dots all red even though services are running
Homepage pings the href URL to determine service status. If your services are on internal IPs or private domains that Homepage can't resolve from inside the container, all checks will fail. Make sure Homepage can reach the services — either by using Docker service names (if on the same network), internal IPs, or adding Homepage to the same Docker network as your other services.
Homepage very slow to load or widgets take a long time to populate
Homepage loads widget data in parallel on each page request. If you have many widgets pointing to slow or unreachable services, the page hangs waiting for timeouts. Identify the slow widget by removing them one by one. You can also add timeout to individual widgets: timeout: 2000 (milliseconds) to fail fast.
See the best open source developer tools for more self-hosted tooling that pairs well with a Homepage dashboard.
See all open source homelab and infrastructure tools at OSSAlt.com/categories/homelab.
The SaaS-to-Self-Hosted Migration Guide (Free PDF)
Step-by-step: infrastructure setup, data migration, backups, and security for 15+ common SaaS replacements. Used by 300+ developers.
Join 300+ self-hosters. Unsubscribe in one click.