Tech Digest

Dashboards

Homepage

YAML-configured start page that pulls live status from a hundred-plus self-hosted services

DashboardsGPL-3.0Stablearm64 buildsNative OIDC
Last reviewed Profile maintained against the project's own documentation
Operational load
2 / 5
Light
Idle memory
110 MB
typical use ~220 MB
Moving parts
1
containers in a normal deployment
Backup shape
File copy
live file copy safe

A static start page whose entire configuration is a folder of YAML files, with service widgets that proxy API calls to Sonarr, Proxmox, Pi-hole, your UPS and about a hundred other things. It replaces a browser bookmarks bar and a hand-written HTML index page.

Our verdict on Homepage#

Homepage is the dashboard for people who want their start page in version control. Everything lives in YAML under /app/config: services.yaml, widgets.yaml, bookmarks.yaml, settings.yaml, docker.yaml, kubernetes.yaml, proxmox.yaml. There is no admin UI and no database, which is both the pitch and the bill. The bill is API keys. Every service widget wants a token for the thing it watches, so a 30 tile page ends up holding read credentials for your *arr stack, Proxmox, your router and your UPS in plaintext on one host, plus a Docker socket if you enabled discovery. v2.0.0 (August 2026) finally shipped a built-in auth gate, password or OIDC; before that the only honest answer was a VPN. Pick Homepage if editing YAML is a feature. Pick Homarr if you want to drag tiles with a mouse.

Who Homepage is for#

Choose it if

  • Someone who already runs their homelab from a git repo and wants the dashboard config to live in it next to the compose files
  • An *arr-stack operator who wants queue counts, disk free and download speed on one page without clicking into six web UIs
  • Kubernetes users, since discovery reads pod annotations the same way it reads Docker labels
  • Anyone who has been burned by a dashboard whose layout lived in a database they could not diff

Look elsewhere if

  • You want to rearrange tiles by dragging them; the layout is column and group definitions in a text file, full stop
  • You are handing the dashboard to non-technical household members who will want to add their own links
  • You are unwilling to manage a pile of long-lived read-only API keys, because that is most of what configuring Homepage is

What running it actually looks like#

One container, one bind mount. Create the config directory on the host before you start, or the container writes a skeleton as root and you spend the next ten minutes on chown. Set HOMEPAGE_ALLOWED_HOSTS to the hostname and port you actually browse to, or every API proxy call is rejected and the tiles show errors while the page itself loads fine. First run gives you a demo layout; you delete it and write services.yaml by hand. Docker discovery needs either /var/run/docker.sock mounted read-only, which means running as root or in the docker group, or a socket proxy. Upgrades are a pull and a restart. The v1 to v2 jump does not migrate config, but it does add the auth environment variables, and 2.1.1 shipped a YAML parsing bug fixed the same day in 2.1.2.

Resource profile#

Memory
110 MB idle, around 220 MB in ordinary use. One Next.js server process. Memory tracks how many service widgets are polling on a timer, not how many tiles you drew. The project publishes no figure, so treat these as observed estimates.
CPU and acceleration
Idles at nothing. Each service widget issues its own outbound API call on its own interval, so a 40 widget page is a steady trickle of requests rather than a spike; no GPU, no transcoding, no indexing.
Storage growth
The config folder is a few kilobytes of YAML plus whatever custom icons you drop in. Nothing grows on its own.
Operational load
2 of 5, Light. One container, no database, and backup is copying a folder of text files. The ongoing cost is that upstream APIs change and individual widgets break, so you read release notes and occasionally fix a widget block by hand.

Figures describe a small single-household install and are the working assumptions behind our stack planner. Your numbers will differ with library size, user count and hardware. See methodology.

Data and backup surface#

Back up the config directory and nothing else. It is settings.yaml, services.yaml, widgets.yaml, bookmarks.yaml, docker.yaml, kubernetes.yaml, proxmox.yaml, custom.css and custom.js, all plain text, all safe to copy live with the container running. There is no database, no cache worth keeping and no upload directory except any icons you added yourself. Treat the whole thing as source: commit it, but scrub it first, because those files hold cleartext API keys for every integrated service. Restore is copying the folder back and starting the container. The logs/ subdirectory is disposable.

Derived backup shape

File copy. Copy the config and data directories. Safe while running for anything that writes atomically.

Traps and surprises#

Docker socket mount is full API access

Mounting /var/run/docker.sock gives Homepage, and anything that compromises it, the ability to start privileged containers on the host. The docs say direct socket use is not the recommended method. Run ghcr.io/tecnativa/docker-socket-proxy with CONTAINERS=1, SERVICES=1 and POST=0, point docker.yaml at it over TCP, and Homepage gets the container list without gaining the ability to change anything.

HOMEPAGE_ALLOWED_HOSTS breaks widgets silently

Since v1.0 the API proxy validates the Host header. Get it wrong and the page renders but every widget shows an error, which reads like a broken API key. The logs print the exact host string it saw; paste that into the comma-separated list. Setting it to * disables the check and is explicitly discouraged. Auth routes under /api/auth/* are exempt so logins keep working.

OIDC login has no group or claim filtering

Homepage grants access to any identity the configured provider authorizes for the client. There is no allowlist, no group claim check, no role mapping. If your IdP hands out tokens for that client broadly, everyone gets in. Do the authorization at the provider with client assignments or access policies.

No rate limiting on password login

The docs state plainly that Homepage applies no application-level rate limiting to password attempts. If it is reachable from outside a trusted network, rate limit POST /api/auth/callback/credentials at the proxy. Each failure logs at warn level as <nextauth> Failed password sign-in attempt, which works as a fail2ban or CrowdSec filter.

Widget API keys are cleartext YAML

Service widget credentials sit in services.yaml in plain text, readable by anyone with the file or a shell in the container. Mint scoped read-only keys where the upstream supports them (Proxmox API tokens, *arr read keys), never reuse an admin token, and keep the config directory out of any repo you push without filtering.

Specifications#

Category
Dashboards and automation glue
Licence
GPL-3.0 (Copyleft)
Written in
JavaScript / Next.js
First release
2022
Maturity
Stable
Datastore
None (YAML files on disk)
Default ports
3000
Ships as
docker, kubernetes helm chart, node from source
arm64 builds
Yes
Identity
Native OIDC. v2.0 added a built-in gate (`HOMEPAGE_AUTH_ENABLED`) with either a single shared password or OIDC, but it grants access to any identity your provider authorizes for the client and applies no claim or group checks of its own.
Replaces
Start.me, Netvibes, Protopage, igHome
Project site
gethomepage.dev
Source
github.com/gethomepage/homepage
Documentation
gethomepage.dev/installation

Alternatives to Homepage#

Everything else in dashboards and automation glue, closest in operational weight first.

ToolOps loadIdle RAMLicence
Homarr2, Light500 MBApache-2.0
Glance1, Set and forget25 MBAGPL-3.0
n8n4, Heavy400 MBSustainable Use License 1.0 (plus n8n Enterprise License for .ee files)

Where Homepage comes up elsewhere#

Sources#

Published . Last reviewed . Found something out of date? Tell us and we will fix it and log the change.