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.com or 192.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 with id $USER.
  • Docker socket mount — Optional but recommended. Mounting /var/run/docker.sock lets Homepage display container status, resource usage, and auto-discover services via Docker labels.

Start the stack:

docker compose up -d

Initial Setup

  1. Open http://your-server-ip:3000 in your browser
  2. You should see the default Homepage dashboard with sample widgets and bookmarks
  3. Homepage has no login system or setup wizard — configuration is done entirely through YAML files in the config directory

The config directory will be populated with skeleton configuration files on first start:

FilePurpose
services.yamlDefine service groups and individual services
bookmarks.yamlQuick-access bookmark groups
widgets.yamlInformation widgets (resources, weather, search, datetime)
settings.yamlGlobal settings: theme, layout, language, background
docker.yamlDocker instance connections for container monitoring
custom.cssCustom CSS overrides
custom.jsCustom 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 service
  • icon — Icon name from Dashboard Icons, or prefixed with mdi- for Material Design Icons, si- for Simple Icons
  • description — Short text displayed below the service name
  • ping — Hostname to ICMP ping for uptime status
  • siteMonitor — URL to monitor HTTP response times
  • server / container — Docker instance and container name for live stats
  • widget — 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:

FileContents
services.yamlAll service definitions and widget configs
bookmarks.yamlBookmark groups
widgets.yamlInformation widget configuration
settings.yamlTheme, layout, and display settings
docker.yamlDocker instance connections
custom.css / custom.jsCustom 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.

Comments