LinuxcontainersTested on real hardware

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.

Distrosubuntu, debian, fedora, opensuse
Shellyaml
Updated
Compose file
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

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.