Homepage — a modern, fully static, highly customizable application dashboard with service/bookmark tiles and live widgets. Deployed as a host-networked Nomad service with a persistent Docker volume for its YAML config.
Save as values.hcl, edit, then run:
# The name of the Nomad job.
job_name = "homepage"
# The Nomad namespace to deploy into.
namespace = "default"
# The datacenters to deploy to.
datacenters = ["*"]
# The Homepage container image. Pin a tag in production.
image = "ghcr.io/gethomepage/homepage:latest"
# Host port for the dashboard. Default 3006 to avoid the panel (3000), grafana (3001), gitea (3002), metabase (3003), umami (3005).
port = 3006
# REQUIRED by recent Homepage for security: comma-separated Host header values it will serve (e.g. "home.example.com" or "<node-ip>:3006"). If wrong/unset you'll get a "host validation" error page.
allowed_hosts = ""
# Docker named volume for /app/config (settings.yaml, services.yaml, bookmarks.yaml, widgets.yaml). Homepage seeds defaults here on first run. Runs as root, so a fresh volume is writable.
data_volume = "homepage_config"
# Placement constraints — pin to one node so the local volume stays put. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true".
constraints = []
# The task resources.
resources = {
cpu = 300
memory = 256
}
| Name | Type | Default | Description |
|---|---|---|---|
| job_name | string | "homepage" | The name of the Nomad job. |
| namespace | string | "default" | The Nomad namespace to deploy into. |
| datacenters | list | ["*"] | The datacenters to deploy to. |
| image | string | "ghcr.io/gethomepage/homepage:latest" | The Homepage container image. Pin a tag in production. |
| port | number | 3006 | Host port for the dashboard. Default 3006 to avoid the panel (3000), grafana (3001), gitea (3002), metabase (3003), umami (3005). |
| allowed_hosts | string | "" | REQUIRED by recent Homepage for security: comma-separated Host header values it will serve (e.g. "home.example.com" or "<node-ip>:3006"). If wrong/unset you'll get a "host validation" error page. |
| data_volume | string | "homepage_config" | Docker named volume for /app/config (settings.yaml, services.yaml, bookmarks.yaml, widgets.yaml). Homepage seeds defaults here on first run. Runs as root, so a fresh volume is writable. |
| constraints | list | [] | Placement constraints — pin to one node so the local volume stays put. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true". |
| resources | object | {
cpu = 300
memory = 256
} | The task resources. |
No variables match.
Homepage — a modern, fully static, highly customizable application dashboard: service and bookmark tiles, plus live widgets for dozens of self-hosted apps and infra. A landing page for everything you run. Host-networked Nomad service with a persistent volume for its YAML config.
nomad-pack registry add nomploy github.com/Nomploy/nomad-packs \
--var 'allowed_hosts=<node-ip>:3006'
nomad-pack run homepage --registry nomploy --var 'allowed_hosts=<node-ip>:3006'
In nomploy: create a Compose service, type Nomad Pack, pack homepage, set
allowed_hosts, then Deploy. Open http://<node-ip>:3006.
Recent Homepage rejects any request whose Host header isn't in HOMEPAGE_ALLOWED_HOSTS
(a security default). Set allowed_hosts to how you'll reach it — "<node-ip>:3006",
or your domain "home.example.com" (comma-separate multiple). If you get a "host
validation" error page, this is why.
| Variable | Default | Notes |
|---|---|---|
image |
ghcr.io/gethomepage/homepage:latest |
Pin a tag in production. |
port |
3006 |
Dashboard host port. |
allowed_hosts |
"" |
Set this (host:port or domain) or Homepage blocks the request. |
data_volume |
homepage_config |
The YAML config. Back it up. |
constraints |
[] |
Pin to a node so the local volume stays put. |
resources |
cpu 300 / mem 256 |
Lightweight. |
count is fixed to 1 (config on a local volume). Homepage seeds default
YAML into the volume on first run; edit services.yaml / bookmarks.yaml /
widgets.yaml / settings.yaml there. Pin with constraints.services.yaml (each widget needs the
target service URL + any API key).