Homepage Dashboard — Docker Compose Install
Deploy the Homepage application dashboard with Docker Compose. Creates the config directory, sets the required HOMEPAGE_ALLOWED_HOSTS variable, and starts the container on port 3000.
yaml#!/usr/bin/env bash
# Homepage dashboard — Docker Compose install.
# Docs: https://gethomepage.dev/installation/docker/
# Image: ghcr.io/gethomepage/homepage:latest
set -euo pipefail
INSTALL_DIR="/opt/homepage"
HOST_IP=$(hostname -I | awk '{print $1}')
HOST_PORT=3000
mkdir -p "${INSTALL_DIR}/config"
cd "${INSTALL_DIR}"
cat > docker-compose.yml <<EOF
services:
homepage:
image: ghcr.io/gethomepage/homepage:latest
container_name: homepage
ports:
- "${HOST_PORT}:3000"
volumes:
- ./config:/app/config
# Optional: mount the Docker socket so Homepage can auto-discover containers
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
# REQUIRED — set to every hostname/IP:port you access this on.
# Separate multiple values with commas.
- HOMEPAGE_ALLOWED_HOSTS=${HOST_IP}:${HOST_PORT}
restart: unless-stopped
EOF
docker compose up -d
echo ""
echo "Homepage is running at: http://${HOST_IP}:${HOST_PORT}"
echo "Config files are in: ${INSTALL_DIR}/config/"
echo ""
echo "Edit ${INSTALL_DIR}/config/services.yaml to add your services."
echo "Homepage reloads automatically when you save config files — no restart needed."
What this does
Writes a docker-compose.yml for Homepage and starts the container. Sets HOMEPAGE_ALLOWED_HOSTS to the host’s primary LAN IP (the most common gotcha that causes a blank page or “host validation failed” error on first run).
On first start, Homepage writes default YAML config files into the ./config directory. Edit those files to add your own service tiles and widgets.
Why this approach
A homelab with a dozen services running on different IPs and ports quickly becomes hard to navigate. Homepage gives you a single starting page: service tiles with real-time status pings, system resource widgets (CPU, RAM, disk per host), and links to every web UI in the lab. Instead of remembering that Plex is at 10.0.0.50:32400 and Grafana is at 10.0.0.55:3000, you open http://homepage.lan and click the tile.
Homepage is configured entirely through YAML files (services.yaml, widgets.yaml, bookmarks.yaml) — no database, no account setup, no admin panel. This makes it reproducible and version-controllable: the config folder is a set of text files you can back up, commit to git, and restore from scratch in seconds. The Docker auto-discovery feature (covered in the optional section below) can even populate service tiles automatically from running containers’ labels, though manual YAML gives you more control over the layout.
The HOMEPAGE_ALLOWED_HOSTS environment variable catches almost everyone on first run. Homepage validates the Host header on incoming requests and returns a blank page or an error if the hostname doesn’t match. When you access it by IP address (http://192.168.1.10:3000), the Host header is the IP. When you access it by hostname (http://homepage.lan), it’s the hostname. Both must be listed in HOMEPAGE_ALLOWED_HOSTS. Forgetting to add a second access method after the initial setup is the most common cause of “it was working and now it’s blank.”
Prerequisites
- Docker Engine + Compose plugin (docker-install-linux playbook)
- Port 3000 free on the host (or change
HOST_PORTin the script)
Add HOMEPAGE_ALLOWED_HOSTS for every access method
If you access Homepage from multiple addresses (IP, hostname, or Traefik domain), list all of them:
environment:
- HOMEPAGE_ALLOWED_HOSTS=192.168.1.50:3000,home.example.com
After changing the compose file, restart:
cd /opt/homepage && docker compose up -d
Minimal services.yaml example
- Infrastructure:
- Proxmox:
href: https://192.168.1.10:8006
description: Virtualization
icon: proxmox.png
- Pi-hole:
href: http://192.168.1.20/admin
icon: pi-hole.png
widget:
type: pihole
url: http://192.168.1.20
key: YOUR_PIHOLE_API_TOKEN
- Media:
- Jellyfin:
href: http://192.168.1.30:8096
icon: jellyfin.png
Save the file — Homepage reloads within seconds.
Minimal widgets.yaml (top bar)
- resources:
cpu: true
memory: true
disk: /
- datetime:
text_size: xl
format:
timeStyle: short
dateStyle: short
Icon packs
Homepage bundles icons for popular apps from walkxcode/dashboard-icons. Use the lowercase app name as icon: appname.png. Browse the full list at https://gethomepage.dev/widgets/services/.
Docker auto-discovery (optional)
With the Docker socket mounted, Homepage can discover running containers automatically via labels:
# In another service's docker-compose.yml:
labels:
- homepage.group=Media
- homepage.name=Jellyfin
- homepage.icon=jellyfin.png
- homepage.href=http://192.168.1.30:8096
Update Homepage
cd /opt/homepage
docker compose pull
docker compose up -d
Reach it from outside the LAN
Route it through Traefik or reach it over Tailscale. If you add a domain via Traefik, add that domain to HOMEPAGE_ALLOWED_HOSTS as well.
macOS / Windows (running Homepage locally)
Homepage is designed as a server-side app and works best self-hosted on Linux. On macOS or Windows you can run it with Docker Desktop — same compose file, same HOMEPAGE_ALLOWED_HOSTS gotcha — but most people run it on a homelab server and use it as a browser home page from any device.