DockerSelf-Hosting

Homepage with Docker: One Dashboard for All Your Services (Linux, Windows, Mac)

Before you start

  • 19 min read

Boxes marked Run in terminal are what you type; plain text explains why. Check what you need first

What you get in one minute#

Homepage is a free, self-hosted start page: one fast dashboard with links, live status and widgets for all the services you run, configured with a few YAML files and shown in any browser.

Homepage official logo

Logo: the official Homepage project (github.com/gethomepage/homepage)

Instead of remembering ten ports, you open one page and see which services are up, what they are doing and where to click. Homepage has over 100 service integrations (our guides on Uptime Kuma and Beszel are two of them), proxies every API call on the server so your keys never reach the browser, and can find your Docker containers by labels. The two things that trip people up are the HOMEPAGE_ALLOWED_HOSTS variable, which is required, and the Docker socket, which is powerful. This guide handles both.

Current versionv2.7.0 (released October 2026), GitHub release page
Time neededAbout 15 minutes (our estimate: two small files and one docker compose up)
RAMNo official minimum. One user saw about 125 MB in use after a 128 MB limit made the container exit
Ports3000 (web interface)
LicenceGPL-3.0 (open source)
PlatformsDocker images for linux/amd64 and linux/arm64
Official docsgethomepage.dev and github.com/gethomepage/homepage

At a glance:

  • What it is: a Next.js application dashboard; its config is YAML files in one folder you mount into the container.
  • What it shows: your services as tiles, with optional widgets (counts, uptime, queue sizes), container status, weather, search and bookmarks.
  • Keys stay on the server: "All API requests to backend services are proxied, keeping your API keys hidden" (README). You still keep them out of your config files, see Step 3.
  • Required setting: HOMEPAGE_ALLOWED_HOSTS, since v1.0, for any address other than localhost.
  • Optional login: since v2.0 a built-in password or OIDC gate, off by default.
  • Our setup: a pinned image, a .env secrets file, and a read-only Docker socket proxy instead of the raw socket.

How it fits together#

Your browser only ever talks to Homepage; Homepage reads your config and talks to your services.

Flow diagram of Homepage: you open the dashboard, optionally through a reverse proxy for HTTPS; Homepage checks the Host against HOMEPAGE_ALLOWED_HOSTS, reads the config files and the keys in the .env file, then calls Uptime Kuma and Beszel, and optionally a read-only Docker socket proxy that talks to the Docker engine

Dashed boxes are optional. The host check comes first: a request with a Host that is not on the list never reaches your services. Drawn from the official docs, October 2026.

Before you start#

You need Docker with Compose. Any small machine works; Homepage is a light Node.js app.

SystemWhat to have
LinuxDocker Engine with the Compose plugin; the images exist for amd64 and arm64
WindowsDocker Desktop (WSL 2 backend), PowerShell
MacDocker Desktop, Terminal

Check Docker on each system (same commands):

Run in terminalbash
docker --version
docker compose version

Checklist before you install:

  • [ ] Port 3000 is free (docker ps shows nothing on it)
  • [ ] You know the address you will type in the browser, for example <server-ip>:3000 or localhost:3000
  • [ ] For widgets: the web address and, where needed, the login or API key of each service
  • [ ] Only for the HTTPS section: a domain, DNS pointing at the server, and ports 80/443 open

Tested on: not run by DIY Lab Hub for this guide. Every command comes from the official docs (v2.7.0) and the Docker image registry, read in October 2026. The Windows and Mac steps use the same Compose file as Linux; the Homepage docs only describe Linux paths.

Step 1: Create the folders and the secrets file#

Everything lives in one folder, ~/docker_volumes/homepage: config (your YAML files and logs), backups, and a .env file for settings and secrets.

Linux#

Run in terminalbash
mkdir -p ~/docker_volumes/homepage/{config,backups}
cd ~/docker_volumes/homepage
printf 'HOMEPAGE_ALLOWED_HOSTS=<server-ip>:3000\nPUID=%s\nPGID=%s\n' "$(id -u)" "$(id -g)" > .env
chmod 600 .env

PUID and PGID make the container run as you, so the files in config are yours, not root's. Replace <server-ip> with the address you type in the browser. On the same machine you can use localhost:3000.

Windows (PowerShell)#

Codepowershell
New-Item -ItemType Directory -Force "$HOME\docker_volumes\homepage\config","$HOME\docker_volumes\homepage\backups" | Out-Null
Set-Location "$HOME\docker_volumes\homepage"
Set-Content -Path .env -Value "HOMEPAGE_ALLOWED_HOSTS=localhost:3000"
icacls .env /inheritance:r /grant:r "${env:USERNAME}:(R,W)"

We leave PUID and PGID out on Windows; the image then runs as root, which is its documented default.

Mac (Terminal)#

Same commands as Linux, but leave PUID/PGID out like on Windows:

Run in terminalbash
mkdir -p ~/docker_volumes/homepage/{config,backups}
cd ~/docker_volumes/homepage
printf 'HOMEPAGE_ALLOWED_HOSTS=localhost:3000\n' > .env
chmod 600 .env

Check it worked. The folder has a config and a backups directory and a .env file only you can read (ls -la on Linux and Mac, Get-ChildItem -Force on Windows).

Tip: HOMEPAGE_ALLOWED_HOSTS is a comma-separated list with no spaces, and each entry is the host exactly as you type it in the browser, with the port when it is not 80 or 443: <server-ip>:3000,home.example.com. You do not need to add localhost:3000 or 127.0.0.1:3000, they are always included.

Step 2: Write the Compose file and start Homepage#

Save this as compose.yaml in ~/docker_volumes/homepage (any editor). It has no version: line, and the image is pinned to v2.7.0 instead of the latest tag the docs show.

File contentyaml
services:
  homepage:
    image: ghcr.io/gethomepage/homepage:v2.7.0
    container_name: homepage
    restart: unless-stopped
    ports:
      - "3000:3000"
    env_file:
      - .env
    volumes:
      - ./config:/app/config

Linux#

Run in terminalbash
cd ~/docker_volumes/homepage
nano compose.yaml
docker compose up -d
docker compose ps

Windows (PowerShell)#

Codepowershell
Set-Location "$HOME\docker_volumes\homepage"
notepad compose.yaml
docker compose up -d
docker compose ps

Mac (Terminal)#

Same commands as Linux:

Run in terminalbash
cd ~/docker_volumes/homepage
nano compose.yaml
docker compose up -d
docker compose ps

Check it worked. The image has its own health check (every 10 seconds against /api/healthcheck), so after about half a minute docker compose ps should show homepage as Up ... (healthy) (expected from the Dockerfile; we did not run it). Open http://localhost:3000 or http://<server-ip>:3000: you get the default dashboard with a resources widget and a search box.

On the first start Homepage copies its skeleton files into config. A user's v2.7.0 log shows lines like this:

File contenttext
info: kubernetes.yaml was copied to the config folder

Look in config and you find bookmarks.yaml, custom.css, custom.js, docker.yaml, kubernetes.yaml, proxmox.yaml, services.yaml, settings.yaml and widgets.yaml. These are the files you edit next.

Tip: Seeing Host validation failed. See logs for more details. in the browser? Run docker logs homepage --tail 20. The log names the exact host it refused. Copy that host into HOMEPAGE_ALLOWED_HOSTS in .env, then recreate the container with docker compose up -d --force-recreate. A plain restart does not re-read environment variables; the maintainer says so in discussions 5290 and 6094.

Step 3: Add your first services, with keys kept out of the YAML#

Open config/services.yaml (replace its content). This example adds a link plus live widget for Uptime Kuma and Beszel. If you have not installed them yet, see our Uptime Kuma guide and our Beszel guide.

File contentyaml
- Monitoring:
    - Uptime Kuma:
        icon: uptime-kuma.png
        href: http://<kuma-address>:3001
        description: Are my sites up?
        widget:
          type: uptimekuma
          url: http://<kuma-address>:3001
          slug: <status-page-slug>
    - Beszel:
        icon: beszel.png
        href: http://<beszel-address>:8090
        description: Server stats
        widget:
          type: beszel
          url: http://<beszel-address>:8090
          username: "{{HOMEPAGE_VAR_BESZEL_USER}}"
          password: "{{HOMEPAGE_VAR_BESZEL_PASSWORD}}"
          version: 2

What the widgets need, from the official widget pages:

WidgetNeedsNotes
Uptime KumaA status page and its slug (the part after /status/)No API key. url is the base address only
BeszelA Beszel superuser loginversion: 2 for Beszel 0.9.0 and newer

The secrets go in .env, not in the YAML. Any variable that starts with HOMEPAGE_VAR_ replaces {{HOMEPAGE_VAR_...}} in your config files. Add these lines to .env (edit it with nano .env on Linux and Mac, notepad .env on Windows):

File contenttext
HOMEPAGE_VAR_BESZEL_USER=<your-beszel-email>
HOMEPAGE_VAR_BESZEL_PASSWORD=<your-beszel-password>

Prefer files? HOMEPAGE_FILE_BESZEL_PASSWORD=/run/secrets/beszel makes {{HOMEPAGE_FILE_BESZEL_PASSWORD}} read the file's contents (the value must be a file path).

Linux#

Run in terminalbash
cd ~/docker_volumes/homepage
nano config/services.yaml
nano .env
docker compose up -d --force-recreate

Windows (PowerShell)#

Codepowershell
Set-Location "$HOME\docker_volumes\homepage"
notepad config\services.yaml
notepad .env
docker compose up -d --force-recreate

Mac (Terminal)#

Same commands as Linux:

Run in terminalbash
cd ~/docker_volumes/homepage
nano config/services.yaml
nano .env
docker compose up -d --force-recreate

Check it worked. Reload the dashboard. You see a Monitoring group with two tiles, each with its numbers (up/down for Uptime Kuma, systems for Beszel). After later changes to settings.yaml or services.yaml, click the refresh icon at the bottom right of the page to clear the cache. A red "API Error" button on a widget opens the error details; the cause is almost always the url.

Tip: Never type a real key into a screenshot, a forum post or a shared config. Keep keys in .env and share the YAML with the {{HOMEPAGE_VAR_...}} placeholders in it. If a key did leak, create a new one in that service.

Tip: localhost inside the Homepage container means the Homepage container itself. Use the other service's real address, or put both containers on one Docker network and use its container name. The troubleshooting page of the docs tests this with docker exec homepage ping <address>.

Step 4: Show container status (optional, with a socket proxy)#

Homepage can show a green or red dot for each container, and stats when you click it. This needs the Docker API, and that is the risky part.

The risk, in plain words. The Docker socket is the control panel of your machine. The documented easy way is to mount it into Homepage (/var/run/docker.sock:/var/run/docker.sock:ro). The authors of the Docker Socket Proxy put it bluntly: "Giving access to your Docker socket could mean giving root access to your host." The Homepage docs call mounting the socket "not the recommended method", and for the direct socket Homepage must run as root (or your user must be in the docker group). If anything in the dashboard were ever abused, the socket is what the attacker would reach for.

The documented safer option. Homepage's own Docker page recommends a docker-socket-proxy container. Only the proxy touches the socket. It answers Homepage over plain HTTP with an API that is cut down by switches; POST=0 means only GET and HEAD requests pass, so the API is read-only. Everything else gets 403 Forbidden.

Direct socketSocket proxy (our choice)
What Homepage can doEverything the socket allowsOnly what you switch on: list containers
Homepage must run asroot, or a member of the docker groupany user (PUID/PGID work)
Extra containernoneone small proxy
Documented by Homepageyes, "not recommended"yes, "more restricted and secure"

Add the proxy to compose.yaml next to Homepage (pinned tag v0.5.0; the docs example uses latest). It publishes no port: only containers on the same Compose network can reach it, which is what the proxy's authors ask for.

File contentyaml
services:
  homepage:
    image: ghcr.io/gethomepage/homepage:v2.7.0
    container_name: homepage
    restart: unless-stopped
    ports:
      - "3000:3000"
    env_file:
      - .env
    volumes:
      - ./config:/app/config

  dockerproxy:
    image: ghcr.io/tecnativa/docker-socket-proxy:v0.5.0
    container_name: dockerproxy
    restart: unless-stopped
    environment:
      - CONTAINERS=1 # allow viewing containers
      - SERVICES=1 # needed for Docker Swarm only
      - TASKS=1 # needed for Docker Swarm only
      - POST=0 # no POST requests: effectively read-only
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

Then tell Homepage where the proxy is, in config/docker.yaml:

File contentyaml
my-docker:
  host: dockerproxy
  port: 2375

And attach a container to a service tile in services.yaml with two lines (container is the container's name):

File contentyaml
    - Beszel:
        server: my-docker
        container: beszel

Linux#

Run in terminalbash
cd ~/docker_volumes/homepage
nano compose.yaml
nano config/docker.yaml
nano config/services.yaml
docker compose up -d

Windows (PowerShell)#

Codepowershell
Set-Location "$HOME\docker_volumes\homepage"
notepad compose.yaml
notepad config\docker.yaml
notepad config\services.yaml
docker compose up -d

The Homepage docs only show Linux socket paths. With Docker Desktop on Windows, the Linux containers run in WSL 2 and the same Compose lines are the normal way, but we did not test it.

Mac (Terminal)#

Same commands as Linux. If the socket mount fails, Docker's docs say the /var/run/docker.sock symlink is an optional setting in Docker Desktop (Settings, Advanced); enable it and recreate the containers.

Run in terminalbash
cd ~/docker_volumes/homepage
nano compose.yaml
nano config/docker.yaml
nano config/services.yaml
docker compose up -d

Check it worked. The Beszel tile shows a status dot; click it for CPU and memory stats of that container. docker compose ps lists homepage and dockerproxy. Homepage only reads container status; it cannot start or stop anything, which is the point of POST=0.

Tip: The :ro flag marks the mount; what limits the Docker API is the proxy's switches (POST=0 allows only GET and HEAD, per its README). Never publish the proxy's port 2375 to a network you do not control.

Put it behind HTTPS (with or without Traefik)#

This is for a server you reach by a domain name. Using Homepage only at home on localhost? You can skip this section. The docs say a public Homepage "must rely on a reverse proxy (and/or VPN) that enforces authentication, TLS, and unexpected Host headers".

Two things change when a proxy is in front: add the new host name to HOMEPAGE_ALLOWED_HOSTS in .env (for example home.example.com, without a port, because the browser uses 443), and bind Homepage's own port to the machine only ("127.0.0.1:3000:3000"). Both Traefik and Caddy pass the browser's Host header on by default, so the host Homepage sees is the one in the address bar. Check the log line if unsure.

With Traefik#

Prerequisites: a domain, DNS pointing to the server, ports 80 and 443 open, and Traefik running on the external proxy network. Create the network once if it is missing:

Run in terminalbash
docker network create proxy

Change the Homepage service like this. The labels are our example (the same pattern as in our Uptime Kuma and Beszel guides), not from the Homepage docs: check them against your Traefik setup.

File contentyaml
  homepage:
    image: ghcr.io/gethomepage/homepage:v2.7.0
    container_name: homepage
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - ./config:/app/config
    networks:
      - proxy
      - default
    labels:
      - traefik.enable=true
      - traefik.docker.network=proxy
      - traefik.http.routers.homepage.rule=Host(`home.example.com`)
      - traefik.http.routers.homepage.entrypoints=https
      - traefik.http.routers.homepage.tls=true
      - traefik.http.services.homepage.loadbalancer.server.port=3000

networks:
  proxy:
    external: true

Keep the dockerproxy service from Step 4 as it is, on the default network only: it must not join proxy.

Without Traefik: Caddy#

Choose Caddy if you have no Traefik yet and run one small server.

CaseResultYou do
Public domainAutomatic Let's Encrypt certificateDNS A record to the server, ports 80 and 443 open
Home onlytls internal (Caddy's local certificate)Trust Caddy's root certificate on each device

Caddyfile for a public domain:

File contenttext
home.example.com {
    reverse_proxy localhost:3000
}

Caddyfile for home only (point the name at the Caddy machine):

File contenttext
dashboard.home.arpa {
    tls internal
    reverse_proxy localhost:3000
}

Trust the root certificate (pki/authorities/local/root.crt in Caddy's data directory):

Run in terminalbash
# Linux: on the Caddy machine
sudo caddy trust
# other Linux devices, with root.crt copied over
sudo cp root.crt /usr/local/share/ca-certificates/caddy-root.crt && sudo update-ca-certificates
# Mac
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain root.crt
Run in terminalpowershell
# Windows (PowerShell as administrator)
certutil -addstore -f ROOT root.crt

Run Caddy. Linux: install it from the official apt repository on caddyserver.com/docs/install, then sudo systemctl reload caddy. Windows: winget install CaddyServer.Caddy, then caddy run. Mac: brew install caddy, then caddy run. Or use the official image caddy:2.11.7 (current in October 2026) on the same Docker network: drop Homepage's ports: line, use reverse_proxy homepage:3000, and keep ./caddy_data:/data under ~/docker_volumes/caddy.

Set HOMEPAGE_ALLOWED_HOSTS=home.example.com in .env, then docker compose up -d --force-recreate.

Check it worked. curl -I https://home.example.com answers HTTP/2 200.

Security and testing#

Homepage can show private data, so the dashboard needs a guard. The official warning: if it is reachable from an untrusted network, put it behind a reverse proxy or VPN that enforces authentication and TLS.

  • Do not forward port 3000 to the internet. Reach it from home, over a VPN such as WireGuard or Tailscale, or through the HTTPS proxy above.
  • Do not set HOMEPAGE_ALLOWED_HOSTS to *. It switches the host check off. The docs call that "not recommended"; and the check is only "a best-effort guard for local setups".
  • Turn on the built-in login if other people can reach the dashboard. Since v2.0, add to .env: HOMEPAGE_AUTH_ENABLED=true, HOMEPAGE_AUTH_SECRET (at least 32 characters; make one with openssl rand -base64 32), HOMEPAGE_EXTERNAL_URL (the full address, with https:// when you use TLS) and HOMEPAGE_AUTH_PASSWORD. Homepage has no rate limiting for password attempts, so the docs ask you to rate limit POST /api/auth/callback/credentials at your proxy. OIDC is supported too, via HOMEPAGE_OIDC_* variables.
  • Secrets: .env is chmod 600 (Linux/Mac) or locked with icacls (Windows); API keys only as HOMEPAGE_VAR_* or HOMEPAGE_FILE_*.
  • What leaves your machine: icons from mdi-, si- and sh- sets are loaded by your browser from CDN servers, and Homepage checks GitHub for new versions unless you set disableUpdateCheck: true in settings.yaml.
  • Status test: docker compose ps shows healthy; curl -I http://localhost:3000 returns an HTTP answer; docker logs homepage --tail 50 shows no error: lines.

Common mistakes#

MistakeWhy it happensDo this instead
Spaces after the commas in HOMEPAGE_ALLOWED_HOSTSThe value looks like a normal list. A user wrote astra.infv:4100, start.astra.home, start.astra.home:443 and still got the error (discussion 5290)Comma-separated, no spaces, each entry exactly as in the log line
Restarting the container after changing .envDocker only reads environment variables when it creates the container; the maintainer answered this twice (5290, 6094)docker compose up -d --force-recreate
Adding localhost, a scheme (https://) or a different port than the browser usesPeople copy what they think should be allowed; a TrueNAS user tried many variants (5412)Use the host as the browser shows it, with the port only when it is not 80/443
Running as a normal user (PUID/PGID) with the raw Docker socketThe docs say direct socket access needs root or the docker group; a Synology user got connect EACCES /var/run/docker.sock (7140)Use the socket proxy from Step 4, which works for any user
Putting the whole status-page URL in the Uptime Kuma widget urlThe browser address looks like the thing to paste; the widget got HTML and showed API Error: Invalid data (7279)url = base address only; the part after /status/ goes in slug
Using a public reverse-proxy domain or localhost as a widget urlThe container could not resolve the domain (ENOTFOUND, 6255)Use an address the container can reach; test with docker exec homepage ping <address>
Squeezing the container to 128 MBIt looked small enough; one Swarm user saw the container exit and blamed the Docker host, then found the memory limit (7282)Give it 512 MB while you measure with docker stats; that user then saw about 125 MB used
Trusting an AI assistant's Homepage setupAssistants copy older tutorials: the retired ghcr.io/benphelps/homepage image, no HOMEPAGE_ALLOWED_HOSTS at all (needed since v1.0), a value with http://, or ":ro makes the socket read-only"Take the image from the current docs (ghcr.io/gethomepage/homepage), the host list from the log, and limit the API with the proxy's POST=0
Keys typed straight into services.yamlThe examples in the docs show plain keysUse {{HOMEPAGE_VAR_NAME}} with the value in .env, and quote the placeholder

Tip: When a widget fails, click its "API Error Information" button first. It tells you whether the problem is reaching the host, a wrong key or a wrong path, before you change anything.

Troubleshooting#

ProblemSolution
Host validation failed. See logs for more details. in the browserRun docker logs homepage --tail 20, put the refused host in HOMEPAGE_ALLOWED_HOSTS, recreate the container
connect EACCES /var/run/docker.sockThe container user cannot read the socket. Use the socket proxy (Step 4) or run as root
Widget shows API Error: Invalid dataThe url returns a web page, not the API. Use the base address; for Uptime Kuma add slug
Widget shows ENOTFOUND or ECONNREFUSEDThe container cannot reach that address. Test docker exec homepage ping <address>; put both containers on one network
Service name missing or tiles overlapEvery service and every group needs a unique name
Icon missingCheck the icon name in the Dashboard Icons list, or use si-<name>. A local icon needs a mount at /app/public/icons and a restart
Change in services.yaml not visibleClick the refresh icon at the bottom right of the page
Container keeps exitingdocker logs homepage, check the memory limit, and remove a docker.yaml host that is switched off

Host validation failed#

File contenttext
error: Host validation failed for: <host>. Hint: Set the HOMEPAGE_ALLOWED_HOSTS environment variable to allow requests from this host / port.

This is the log line from several user reports. It means the Host header of the request is not on the list. Add exactly that host.

Known bugs#

Homepage keeps bug reports and questions in GitHub Discussions; the issues list showed one open item (a translations update) when we read it in October 2026. For a stuck widget, start from the troubleshooting page and attach its output when you ask. Diagnostic commands:

Run in terminalbash
docker logs homepage --tail 100
docker compose ps
docker exec homepage ping <address>

To add curl inside the container for a test, the docs suggest apk add curl. Set the environment variable LOG_LEVEL=debug for more detail.

Updates and backups#

Update. Homepage releases often (six releases between early September and late October 2026). Change the tag in compose.yaml, read the release notes, then:

Run in terminalbash
cd ~/docker_volumes/homepage
docker compose pull && docker compose up -d

On Windows use Set-Location "$HOME\docker_volumes\homepage" first; the Compose commands are the same.

Back up the folder that matters: config (your YAML) and .env (your secrets, so protect the archive).

Run in terminalbash
cd ~/docker_volumes/homepage
mkdir -p backups
tar -czf "backups/homepage-$(date +%F).tar.gz" config .env compose.yaml
chmod 600 backups/*.tar.gz
Codepowershell
Set-Location "$HOME\docker_volumes\homepage"
New-Item -ItemType Directory -Force backups | Out-Null
Compress-Archive -Path config,.env,compose.yaml -DestinationPath "backups\homepage-$(Get-Date -Format yyyy-MM-dd).zip" -Force

Schedule: on Linux and Mac add this cron line (crontab -e) for 03:00 every day: 0 3 * * * cd ~/docker_volumes/homepage && tar -czf "backups/homepage-$(date +\%F).tar.gz" config .env compose.yaml. On Windows, create a Task Scheduler task that runs the two PowerShell lines at 03:00.

Restore test. Unpack the archive into a new empty folder, check that config/services.yaml is there, copy it over a fresh install and start with docker compose up -d. Your dashboard should come back as it was.

Performance and resources#

  • Memory: no official minimum. One user's v2.7.0 container exited with a 128 MB limit and then sat at about 125 MB with a 512 MB limit; give yourself room and watch docker stats homepage.
  • Speed: the README promises "cached dashboard data and optimized assets"; a refresh clears the cache when you change config.
  • Many widgets: each widget makes a server-side API call; remove ones you do not read.
  • Logs: they go to config/logs, rotate at 10 MiB and keep five files; set LOG_TARGETS=stdout to log only to Docker.
Run in terminalbash
docker stats homepage --no-stream

FAQ#

Do I need Docker? No. Homepage can also be installed from source or on Kubernetes, but Docker is the simplest and best documented way.

Why does it say "Host validation failed"? Since v1.0 Homepage only answers for localhost and the hosts you list in HOMEPAGE_ALLOWED_HOSTS. Read the log, add the host, recreate the container.

Is it safe to mount the Docker socket? It gives whatever can use it broad control of your machine. Use the socket proxy with POST=0 as in Step 4, and keep the proxy off every public network.

Can I show services without widgets? Yes. A tile only needs a name and an href. Widgets, container status and ping checks are all optional.

Does it find my containers automatically? Yes, with labels such as homepage.group, homepage.name and homepage.href on the other containers. That needs the Docker integration from Step 4.

What does it cost? Nothing. It is GPL-3.0 open source.

Sources#

Checked against the official docs on 2026-10-30.