TL;DR. Homepage ships as an 80 MB image [4] and uses ~50–150 MB RAM in practice [2][11]—lean against every other feature-rich dashboard. It has zero built-in authentication and will never add it [3]; all auth is delegated to the reverse proxy. Traefik with Docker labels is the tightest fit; Caddy needs one route block; nginx works with manual config. Since v1.0,
HOMEPAGE_ALLOWED_HOSTSis required for every non-localhost hostname [1].
Resource Footprint
Homepage ⭐ 31k is a Next.js 15 app served by Node.js. Pages pre-render statically; widget data is fetched server-side and streamed to the browser, keeping the JS bundle small but the server process persistent.
Dashboard RAM comparison (steady-state, Docker):
| Dashboard | RAM | Image | Notes |
|---|---|---|---|
| Homer ⭐ 11.4k | ~30 MB | <10 MB | Static HTML; no live API polling |
| Homepage ⭐ 31k | 50–150 MB | 80 MB | Next.js 15, server-side widget proxying |
| Dashy ⭐ 25.4k | ~150 MB | ~90 MB | Vue SPA |
| Homarr ⭐ 4k | 200–600 MB | ~250 MB | v1.0 confirmed RAM regression [12] |
[11] CPU is negligible at idle; brief spikes during widget polling (every 30 s per service by default). A Pi 4 handles it without issue.
Image size. ghcr.io/gethomepage/homepage:latest is 80.6 MB compressed (AMD64 + ARM64) with 1 M+ Docker Hub pulls [4]. One TrueNAS deployment measured 118 MiB RSS on a fully-configured instance (Next.js 15.5.x, ~450 ms startup) [2]—the high end of the observed range.
Docker socket. Auto-discovery requires access to the Docker socket. Direct bind-mount (/var/run/docker.sock:ro) forces the container to run as root. The safer path is Tecnativa/docker-socket-proxy ⭐ 2.5k, which exposes a read-only subset of the API [15][6]:
dockerproxy:
image: ghcr.io/tecnativa/docker-socket-proxy:latest
environment: { CONTAINERS: 1, SERVICES: 1, TASKS: 1, POST: 0 }
volumes: ["/var/run/docker.sock:/var/run/docker.sock:ro"]
Then in Homepage’s docker.yaml:
my-docker:
host: dockerproxy
port: 2375
Auth Model
No built-in auth—permanently. Maintainers explicitly closed this [3]:
“AuthN / AuthZ is brutally hard to securely implement … reverse-proxies have become incredibly user-friendly.”
Homepage is also a single shared view—no per-user dashboards or role-based visibility, so per-user ACLs would be moot regardless.
HOMEPAGE_ALLOWED_HOSTS. Mandatory since v1.0 for any non-localhost URL [1]. Guards the server-side API proxy against request-forgery. List every domain or IP:port used to reach the container—reverse proxies rewrite Host to the public domain, so add that domain [16]:
HOMEPAGE_ALLOWED_HOSTS=dashboard.home.example.com,192.168.1.10:3000
localhost:3000 and 127.0.0.1:3000 are always permitted without explicit listing.
Supported patterns:
| Pattern | Proxy required | Effort | Notes |
|---|---|---|---|
| VPN / Tailscale | None | Low | No public exposure; simplest security model |
| HTTP Basic Auth | nginx / Caddy | Low | Single shared password; no MFA |
| Forward Auth (Authelia) ⭐ 28k | Traefik / Caddy | Medium | TOTP/WebAuthn; lighter footprint than Authentik [14] |
| Forward Auth (Authentik) ⭐ 21.8k | Traefik / Caddy | Medium | Full OIDC + login portal; heavier baseline [7] |
| Cloudflare Access | Cloudflare Tunnel | Low | Zero open inbound ports |
⚠ Homepage does not consume forwarded user headers (X-Authentik-Username, Remote-User, etc.) for per-user customisation—whoever passes auth sees the same dashboard [3].
Reverse-Proxy Fit
Homepage listens on port 3000 and requires WebSocket/SSE passthrough (Upgrade: websocket, Connection: upgrade) for live widget updates [10]. All three major proxies handle this cleanly.
Traefik ⭐ 63.6k — best fit for Docker-native setups
Auto-discovers services via container labels; forward-auth middleware hooks in without extra routing configuration.
Minimal labels (TLS + HTTPS):
labels:
traefik.enable: "true"
traefik.http.routers.homepage.rule: "Host(`dashboard.example.com`)"
traefik.http.routers.homepage.entrypoints: "websecure"
traefik.http.routers.homepage.tls.certresolver: "myresolver"
traefik.http.services.homepage.loadbalancer.server.port: "3000"
Add Authentik forward auth (one label on Homepage; middleware defined on the Authentik outpost):
# homepage service
traefik.http.routers.homepage.middlewares: "authentik@docker"
# authentik-proxy service
traefik.http.middlewares.authentik.forwardauth.address: "http://authentik-proxy:9000/outpost.goauthentik.io/auth/traefik"
traefik.http.middlewares.authentik.forwardauth.trustForwardHeader: "true"
traefik.http.middlewares.authentik.forwardauth.authResponseHeaders: "X-authentik-username,X-authentik-groups,X-authentik-email"
For Authelia instead, swap the middleware address for http://authelia:9091/api/authz/forward-auth and adjust authResponseHeaders accordingly [14].
Caddy ⭐ 73.2k — simplest config, zero-config HTTPS
One route block handles auth and proxying in order [8][9]:
dashboard.example.com {
route {
# Authentik outpost passthrough
reverse_proxy /outpost.goauthentik.io/* http://authentik-outpost:9000
forward_auth http://authentik-outpost:9000 {
uri /outpost.goauthentik.io/auth/caddy
copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt
trusted_proxies private_ranges
}
reverse_proxy homepage:3000
}
}
For Authelia, replace the forward_auth block [9]:
forward_auth authelia:9091 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
}
⚠ copy_headers field names are case-sensitive in Caddy; wrong capitalisation produces empty headers [8].
nginx — manual, well-documented
The Upgrade and Connection headers are required; omitting them breaks real-time widget polling [10]:
server {
listen 443 ssl;
server_name dashboard.example.com;
location / {
proxy_pass http://homepage:3000/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Add auth_basic / auth_basic_user_file for htpasswd, or auth_request pointing to Authelia/Authentik for forward auth.
Quick-pick
| Feature | Traefik | Caddy | nginx |
|---|---|---|---|
| Config style | Docker labels | Caddyfile | nginx.conf |
| Auto-HTTPS | ACME cert resolver | Built-in (zero-config) | Manual / certbot |
| Forward auth | Native middleware labels | forward_auth directive |
auth_request module |
| Docker auto-discovery | ✓ native | ✗ | ✗ |
| K8s support | IngressRoute CRD | Ingress controller | Ingress controller |
| Homepage fit | ✓ Excellent | ✓ Good | ✓ Manual |