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.
How to deploy Homepage, create a first YAML-driven configuration, and decide when Docker auto-discovery is worth the extra trust boundary.
People who want one clean landing page for service links, bookmarks, and a few curated widgets without building a larger portal project.
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.
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.
/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.