Self-Host Homepage Dashboard with Docker Compose
What Is Homepage?
Homepage is a self-hosted application dashboard that organizes your services, bookmarks, and system information into a single, fast-loading page. It supports over 100 service integrations (Sonarr, Radarr, Plex, Jellyfin, and many more), Docker container status monitoring, and information widgets for weather, system resources, and search. Unlike most dashboards that use a web UI for configuration, Homepage uses YAML files — making your entire setup version-controllable and reproducible.
Updated March 2026: Verified with latest Docker images and configurations.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 256 MB of free RAM (minimum)
- 200 MB of free disk space
- A domain name (optional, for remote access)
Docker Compose Configuration
Create a directory for Homepage and its configuration files:
mkdir -p ~/homepage/config
Create a docker-compose.yml file in ~/homepage/:
services:
homepage:
image: ghcr.io/gethomepage/homepage:v1.11.0
container_name: homepage
restart: unless-stopped
ports:
- "3000:3000" # Web UI
volumes:
- ./config:/app/config # YAML configuration files
- /var/run/docker.sock:/var/run/docker.sock:ro # Optional: enables Docker integration
environment:
PUID: 1000 # Run as non-root user (match your user ID)
PGID: 1000 # Run as non-root group (match your group ID)
HOMEPAGE_ALLOWED_HOSTS: homepage.local # CHANGE THIS — comma-separated list of allowed hostnames
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000"]
interval: 30s
timeout: 10s
retries: 3
Key configuration notes:
HOMEPAGE_ALLOWED_HOSTS— Required. Set this to the hostname or domain you use to access Homepage (e.g.,homepage.example.comor192.168.1.50). Multiple hosts can be comma-separated. Without this, Homepage will reject requests from unrecognized hostnames.PUID/PGID— Run the container as a non-root user. Find your values withid $USER.- Docker socket mount — Optional but recommended. Mounting
/var/run/docker.socklets Homepage display container status, resource usage, and auto-discover services via Docker labels.
Start the stack:
docker compose up -d
Initial Setup
- Open
http://your-server-ip:3000in your browser - You should see the default Homepage dashboard with sample widgets and bookmarks
- Homepage has no login system or setup wizard — configuration is done entirely through YAML files in the
configdirectory
The config directory will be populated with skeleton configuration files on first start:
| File | Purpose |
|---|---|
services.yaml | Define service groups and individual services |
bookmarks.yaml | Quick-access bookmark groups |
widgets.yaml | Information widgets (resources, weather, search, datetime) |
settings.yaml | Global settings: theme, layout, language, background |
docker.yaml | Docker instance connections for container monitoring |
custom.css | Custom CSS overrides |
custom.js | Custom JavaScript |
Edit these files directly, then reload the page. Homepage picks up YAML changes without restarting the container.
Configuration
Services
Services are the core of your dashboard. Edit config/services.yaml to define groups and services:
- Infrastructure:
- Proxmox:
icon: proxmox.png
href: https://proxmox.home.lan:8006
description: Hypervisor
ping: proxmox.home.lan
- Portainer:
icon: portainer.png
href: https://portainer.home.lan:9443
description: Docker management
server: my-docker
container: portainer
- Media:
- Jellyfin:
icon: jellyfin.png
href: https://jellyfin.home.lan
description: Media server
widget:
type: jellyfin
url: http://jellyfin:8096
key: YOUR_JELLYFIN_API_KEY
- Sonarr:
icon: sonarr.png
href: https://sonarr.home.lan
description: Series management
widget:
type: sonarr
url: http://sonarr:8989
key: YOUR_SONARR_API_KEY
- Self-Hosted:
- Vaultwarden:
icon: vaultwarden.png
href: https://vault.home.lan
description: Password manager
- Immich:
icon: immich.png
href: https://photos.home.lan
description: Photo management
widget:
type: immich
url: http://immich-server:2283
key: YOUR_IMMICH_API_KEY
Each service supports these properties:
href— URL to the serviceicon— Icon name from Dashboard Icons, or prefixed withmdi-for Material Design Icons,si-for Simple Iconsdescription— Short text displayed below the service nameping— Hostname to ICMP ping for uptime statussiteMonitor— URL to monitor HTTP response timesserver/container— Docker instance and container name for live statswidget— Service widget for deep integration (API key required)
Bookmarks
Edit config/bookmarks.yaml for quick-access links that don’t need widgets:
- Developer:
- GitHub:
- abbr: GH
href: https://github.com
- Stack Overflow:
- abbr: SO
href: https://stackoverflow.com
- Social:
- Reddit:
- icon: reddit.png
href: https://reddit.com
- Hacker News:
- abbr: HN
href: https://news.ycombinator.com
Information Widgets
Edit config/widgets.yaml to configure the top bar:
- resources:
cpu: true
memory: true
disk: /
cputemp: true
uptime: true
refresh: 3000 # Update interval in milliseconds
- search:
provider: google # google, duckduckgo, bing, baidu, brave
target: _blank
- datetime:
text_size: xl
format:
dateStyle: long
timeStyle: short
hour12: true
- openmeteo:
label: Weather
latitude: 40.71
longitude: -74.01
units: metric
cache: 5
Note: For the resources widget to monitor disk usage, the disk path must be mounted as a volume in the container. Add a read-only mount to your docker-compose.yml:
volumes:
- ./config:/app/config
- /var/run/docker.sock:/var/run/docker.sock:ro
- /:/host:ro # Mount root filesystem for disk monitoring
Settings
Edit config/settings.yaml to control the dashboard appearance:
title: My Homelab
theme: dark # dark or light (omit to allow toggling)
color: slate # slate, gray, zinc, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose
background:
image: https://images.unsplash.com/photo-example
blur: sm
opacity: 50
cardBlur: md
layout:
Infrastructure:
style: row
columns: 4
Media:
style: row
columns: 3
headerStyle: clean
statusStyle: dot
target: _blank # Open service links in new tab
Docker Integration
Edit config/docker.yaml to connect to Docker instances:
my-docker:
socket: /var/run/docker.sock
For remote Docker hosts:
remote-docker:
host: 192.168.1.100
port: 2375
Once configured, you can reference server: my-docker and container: container-name in your services to display live CPU, memory, and network stats for individual containers.
Automatic Service Discovery
Instead of manually editing services.yaml, you can add Docker labels to your containers and Homepage will auto-discover them:
# Example: adding Homepage labels to a Jellyfin container
services:
jellyfin:
image: jellyfin/jellyfin:10.11.6
labels:
- homepage.group=Media
- homepage.name=Jellyfin
- homepage.icon=jellyfin.png
- homepage.href=http://jellyfin.home.lan
- homepage.description=Media server
- homepage.widget.type=jellyfin
- homepage.widget.url=http://jellyfin:8096
- homepage.widget.key=${JELLYFIN_API_KEY}
This is particularly useful if you manage many containers — services appear on the dashboard automatically when you deploy them with the right labels.
Advanced Configuration
Protecting Sensitive Values
Avoid putting API keys directly in YAML files. Homepage supports environment variable substitution:
In your docker-compose.yml, define variables with the HOMEPAGE_VAR_ prefix:
environment:
PUID: 1000
PGID: 1000
HOMEPAGE_ALLOWED_HOSTS: homepage.example.com
HOMEPAGE_VAR_JELLYFIN_KEY: your-actual-api-key
HOMEPAGE_VAR_SONARR_KEY: your-actual-api-key
Then reference them in services.yaml:
- Media:
- Jellyfin:
widget:
type: jellyfin
url: http://jellyfin:8096
key: {{HOMEPAGE_VAR_JELLYFIN_KEY}}
For file-based secrets, use HOMEPAGE_FILE_ variables pointing to secret files — useful with Docker Swarm or external secret managers.
Custom CSS
Edit config/custom.css to override any element. You can also assign id properties to services and bookmarks for targeted styling:
/* Dark background override */
:root {
--color-bg: #0a0a0a;
}
/* Custom card styling */
.service-card {
border-radius: 12px;
backdrop-filter: blur(10px);
}
/* Target a specific service by ID */
#myservice {
border-left: 3px solid #3b82f6;
}
Assign the ID in services.yaml:
- Jellyfin:
id: myservice
icon: jellyfin.png
href: https://jellyfin.home.lan
Tabs
Organize services into tabs for large dashboards:
# settings.yaml
layout:
Infrastructure:
tab: Systems
Media:
tab: Entertainment
Self-Hosted:
tab: Apps
Authentication Proxy Integration
Homepage has no built-in authentication. For access control, place it behind an authentication proxy like Authelia or Authentik. Configure your reverse proxy to require authentication before forwarding requests to Homepage.
Reverse Proxy
Nginx Proxy Manager
Create a proxy host pointing to your server’s IP on port 3000. Enable SSL with Let’s Encrypt. Make sure the hostname you configure matches HOMEPAGE_ALLOWED_HOSTS in your Docker Compose environment.
Caddy
homepage.example.com {
reverse_proxy localhost:3000
}
Traefik
Add labels to the Homepage container:
labels:
- "traefik.enable=true"
- "traefik.http.routers.homepage.rule=Host(`homepage.example.com`)"
- "traefik.http.routers.homepage.entrypoints=websecure"
- "traefik.http.routers.homepage.tls.certresolver=letsencrypt"
- "traefik.http.services.homepage.loadbalancer.server.port=3000"
For detailed reverse proxy setup, see the Reverse Proxy guide.
Backup
Homepage stores all configuration in the config directory. Back up this single directory to preserve your entire dashboard setup:
tar czf homepage-backup-$(date +%Y%m%d).tar.gz ~/homepage/config/
What to back up:
| File | Contents |
|---|---|
services.yaml | All service definitions and widget configs |
bookmarks.yaml | Bookmark groups |
widgets.yaml | Information widget configuration |
settings.yaml | Theme, layout, and display settings |
docker.yaml | Docker instance connections |
custom.css / custom.js | Custom styling and scripts |
Since all configuration is plain YAML text, you can also version-control the entire config directory with Git — a major advantage over dashboards that store config in a database.
For a comprehensive backup strategy, see the Backup Strategy guide.
Troubleshooting
Homepage Rejects Requests with “Host Not Allowed”
Symptom: Browser shows an error or blank page. Container logs show a host validation error.
Fix: Set HOMEPAGE_ALLOWED_HOSTS in your docker-compose.yml to match the exact hostname you use in the browser. If you access the dashboard at http://192.168.1.50:3000, set it to 192.168.1.50. For multiple hostnames, comma-separate them: homepage.local,192.168.1.50,homepage.example.com. Recreate the container after changing this value.
YAML Syntax Errors Break the Dashboard
Symptom: After editing a config file, the dashboard shows an error or reverts to defaults. Fix: YAML is whitespace-sensitive. Validate your config files with a YAML linter before saving. Common mistakes: using tabs instead of spaces, incorrect indentation (Homepage expects 4-space indent for nested items), or missing colons. Check container logs for the specific parsing error:
docker logs homepage
Docker Container Stats Not Showing
Symptom: Services show as configured but container CPU/memory/network stats are missing.
Fix: Ensure /var/run/docker.sock is mounted in the container (read-only is fine). Verify docker.yaml references the correct socket path. The container needs to run as root or the PUID user must be in the Docker group. If using Docker Socket Proxy, verify the proxy allows the required API endpoints.
Service Widgets Show “Error” or No Data
Symptom: A service widget displays an error badge instead of live data.
Fix: Verify the widget url is reachable from inside the Homepage container (use the internal Docker network hostname, not the external URL). Confirm the API key is correct. Test connectivity:
docker exec homepage wget -qO- http://jellyfin:8096/System/Info
If the service is on a different Docker network, ensure both containers share a network or use the host IP.
Resource Widget Shows No Disk Information
Symptom: CPU and memory display correctly but disk usage is missing.
Fix: The disk path specified in widgets.yaml must be mounted as a volume in the container. Add a read-only mount for the path you want to monitor (e.g., - /:/host:ro) and reference it as /host in the widget config.
Resource Requirements
- RAM: ~50 MB idle, ~100 MB with many widgets actively polling
- CPU: Very low — Homepage is statically generated and serves pre-rendered pages
- Disk: ~150 MB for the container image, negligible for configuration files
- Network: Minimal unless you have many service widgets polling APIs frequently
Homepage is one of the lightest dashboards available. It runs comfortably on a Raspberry Pi or any low-power device.
Frequently Asked Questions
Does Homepage have user authentication?
No. Homepage has no built-in authentication or login system. If you need to restrict access, place it behind an authentication proxy like Authelia or Authentik. For basic protection, your reverse proxy can also add HTTP basic auth.
How do I add a new service widget?
Edit config/services.yaml and add a new entry under a service group. Include the widget block with the type, url, and key fields for that service. Homepage supports 100+ widget types — check the widget documentation for the specific configuration for each service. Changes take effect on page reload without restarting the container.
Can Homepage show Docker container status?
Yes. Mount the Docker socket (/var/run/docker.sock:/var/run/docker.sock:ro) and configure docker.yaml. Homepage shows CPU usage, memory, and network stats for individual containers. You can also use Docker labels on your containers for automatic service discovery.
What’s the difference between Homepage and Homarr?
Homepage uses YAML configuration files, is faster and lighter (~50 MB RAM), and has 100+ service widget integrations. Homarr has a visual drag-and-drop editor and doesn’t require editing config files. Choose Homepage if you’re comfortable with YAML and want the most service integrations. Choose Homarr if you prefer a GUI for dashboard layout.
Can I use Homepage on a Raspberry Pi?
Yes. Homepage is one of the lightest dashboards — it uses about 50 MB of RAM idle. It runs perfectly on a Raspberry Pi 3 or newer.
Does Homepage support multiple pages or tabs?
Yes. You can organize services into tabs using the tab property in settings.yaml. Each service group can be assigned to a tab, creating a multi-page dashboard experience without separate instances.
Verdict
Homepage is the best self-hosted dashboard for users who want speed, deep service integrations, and version-controllable configuration. Its YAML-based setup is a clear advantage over GUI-only dashboards — you can back up, diff, and template your entire dashboard layout with Git.
Compared to Homarr, Homepage trades the drag-and-drop visual editor for a faster, lighter experience with more service widget integrations (100+ vs Homarr’s still-growing list). If you want a GUI for building your dashboard and don’t mind the extra resource overhead, Homarr is the better choice. If you prefer editing config files and want the fastest possible load times, Homepage wins.
Compared to Dashy, Homepage is more actively maintained, has better service widget support, and is simpler to configure. Dashy offers more visual customization options and a built-in config editor, but its development pace has slowed significantly.
Pick Homepage if: You manage a homelab with many services, you want live widget data from your *arr stack and media servers, and you’re comfortable editing YAML. It is the strongest all-around choice for most self-hosters.
Pick Homarr if: You want a visual drag-and-drop editor and don’t want to touch config files.
Pick Dashy if: You want maximum visual customization and don’t need deep service integrations.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments