Deploy Homepage as a Self-Hosted Start Page With Docker Compose

Run Homepage as a polished private start page for your own services, then add integrations carefully so convenience does not turn into unnecessary privilege.

Homepage Docker Compose Start page
Illustrated guide cover for Deploy Homepage as a Self-Hosted Start Page With Docker Compose
Homepage • Docker Compose • Start page
What you learn

How to deploy Homepage, create a first YAML-driven configuration, and decide when Docker auto-discovery is worth the extra trust boundary.

Best for

People who want one clean landing page for service links, bookmarks, and a few curated widgets without building a larger portal project.

Risk to watch

The dangerous shortcut is mounting the Docker socket into the dashboard before you actually need discovery or service widgets.

Before you begin

  • A Linux host with Docker Compose v2.
  • A short list of services you actually want on the start page.
  • A private hostname, reverse proxy, VPN, or SSH tunnel plan.
  • A willingness to start with static YAML before layering in discovery or API widgets.

Homepage's current official docs describe it as a fast, secure dashboard with configuration via YAML files or Docker label discovery. That flexibility is useful, but the safe first move is to start with files and only add discovery when you truly need it.

Expected outcome: you will finish with Homepage serving a private start page from a clean config directory and a clearer sense of when extra integrations are worth the extra risk.

Step 1: Create the Homepage stack

Create the working directory:

mkdir -p /opt/stacks/homepage/config
cd /opt/stacks/homepage

Save this as compose.yaml:

services:
  homepage:
    image: ghcr.io/gethomepage/homepage:latest
    container_name: homepage
    restart: unless-stopped
    ports:
      - 127.0.0.1:3001:3000
    volumes:
      - ./config:/app/config

This is intentionally conservative. It gets the dashboard running without giving it Docker socket access, extra host mounts, or automatic service discovery before you know whether those features are worth the tradeoff.

Step 2: Start with file-based configuration

Homepage is strongest when your first config is explicit and readable. Create three starter files.

/opt/stacks/homepage/config/settings.yaml:

title: My Start Page
theme: dark
color: slate
headerStyle: clean

/opt/stacks/homepage/config/bookmarks.yaml:

- Admin:
    - Portainer:
        - href: https://portainer.example.com
    - Beszel:
        - href: https://beszel.example.com
    - Forgejo:
        - href: https://git.example.com

/opt/stacks/homepage/config/services.yaml:

- Core:
    - Main site:
        href: https://example.com
        description: Public site
    - Status:
        href: https://status.example.com
        description: Internal checks

Start the container and verify the config is being read:

docker compose up -d
docker compose ps
docker logs homepage --tail 50

Starting with files keeps the dashboard deterministic. You can review the exact links and service groupings in Git or backups without depending on label sprawl across unrelated Compose stacks.

Step 3: Decide whether Docker discovery is worth it

Homepage supports Docker service discovery through labels. The official docs show labels like homepage.group, homepage.name, homepage.href, and widget configuration keys.

That convenience comes with a real decision:

  • If file-based links are enough, stop there and keep the dashboard less privileged.
  • If you truly need automatic service discovery, add only the minimum Docker access required and document why.

Do not normalize socket exposure because a tutorial made it look easy. A dashboard with Docker access can become much more sensitive than a page of links.

Warning: mounting /var/run/docker.sock effectively grants broad control over the Docker host. Treat it as a privileged action, not a cosmetic dashboard upgrade.

Step 4: Put Homepage behind a private access path

Homepage often becomes the doorway to many other tools. That alone is enough reason to keep it private-first. The safest access patterns are:

  • SSH port forwarding to the localhost bind.
  • A tailnet or VPN.
  • An authenticated reverse proxy such as Authelia in front of the dashboard.

Even if the page itself stores no secrets, it still advertises the shape of your stack. Treat that operational map as worth protecting.

Step 5: Operate and update the dashboard

Routine checks:

cd /opt/stacks/homepage
docker compose ps
docker logs homepage --tail 50
find config -maxdepth 1 -type f | sort

Update the service:

cd /opt/stacks/homepage
docker compose pull
docker compose up -d

Keep changes small. Add a few links, reload, and confirm behavior. Dashboards grow messy when they become a dumping ground for every service in the environment.

Rollback notes

Homepage is straightforward to roll back because its important state lives in the config files. If a change breaks rendering or layout, revert the last config edit or the last image tag rather than rebuilding the entire stack.

Troubleshooting

The page loads but changes do not appear.
Confirm you edited the files under /app/config through the mounted directory and check the container logs for parse or permission errors.

You want service widgets but do not want Docker socket risk.
Stick to file-based links or use upstream APIs selectively. Not every convenience feature is worth the trust boundary.

The dashboard is reachable publicly when it should not be.
Fix the bind or reverse-proxy access policy first. A start page that maps your stack is still sensitive.

The configuration is getting noisy.
Refactor into clear groups and remove links you never use. A dashboard should reduce clutter, not centralize it.