6.5 KiB
Homepage Configuration — Netgrimoire Command Center
Overview
Homepage (ghcr.io/gethomepage/homepage) runs as a Docker Swarm service on znas, pinned to port 3056:3000 and accessible at https://homepage.netgrimoire.com.
Config files live at /DockerVol/homepage/config/. Images live at /DockerVol/homepage/images/ (mounted as /app/public/images:ro).
Tab Structure
| Tab | Groups |
|---|---|
| Glance | Glance (iframe) |
| Netgrimoire | Applications, Gremlin, Monitoring, Management, Backup, Mail Services, Remote Access, Services |
| PNCHarris | PNCHarris Apps |
| Wasted-Bandwidth | Jolly Roger, Downloaders, VPN Protected Apps, Media Management, Media Search |
| Nucking-Futz | Nucking Apps, Entertainment |
Compose File
# swarm/homepage.yaml
services:
homepage:
image: ghcr.io/gethomepage/homepage:latest
environment:
- HOMEPAGE_ALLOWED_HOSTS=homepage.netgrimoire.com,glance.netgrimoire.com
- HOMEPAGE_VAR_MAILCOW_KEY=<mailcow-api-key>
- HOMEPAGE_VAR_DNS_TOKEN=<technitium-token>
- HOMEPAGE_VAR_OPNSENSE_USER=<opnsense-api-key>
- HOMEPAGE_VAR_OPNSENSE_PASS=<opnsense-api-secret>
- HOMEPAGE_VAR_IMMICH_KEY=<immich-api-key>
ports:
- 3056:3000
volumes:
- /DockerVol/homepage/config:/app/config
- /DockerVol/homepage/images:/app/public/images:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- netgrimoire
deploy:
placement:
constraints:
- node.hostname == znas
labels:
caddy: homepage.netgrimoire.com
caddy.reverse_proxy: homepage:3000
caddy.import: crowdsec
caddy.import_1: authentik
kuma.homepage.http.name: Homepage
kuma.homepage.http.url: https://homepage.netgrimoire.com
diun.enable: "true"
Important: API keys go directly in the environment: block (not env_file:) because Docker Swarm's env_file is only read at deploy time from the deploying machine — not by the container at runtime.
API Keys
| Variable | Source | Where to Generate |
|---|---|---|
HOMEPAGE_VAR_MAILCOW_KEY |
Mailcow | Admin UI → API |
HOMEPAGE_VAR_DNS_TOKEN |
Technitium | Administration → API Tokens |
HOMEPAGE_VAR_OPNSENSE_USER |
OPNsense API key | System → Access → Users → edit user → API Keys |
HOMEPAGE_VAR_OPNSENSE_PASS |
OPNsense API secret | Same as above (one-time download) |
HOMEPAGE_VAR_IMMICH_KEY |
Immich | User Settings → API Keys |
OPNsense note: The widget uses API key/secret pairs, not admin credentials. Create a dedicated homepage user with Audit group membership and generate an API key on that user.
settings.yaml — Group Layout
All groups must be registered in settings.yaml with style: column. Any group discovered via Docker labels that is not listed here will default to full-width (stretching across all columns).
layout:
Glance:
tab: Glance
header: false
Applications:
tab: Netgrimoire
style: column
Gremlin:
tab: Netgrimoire
style: column
# ... all groups must be listed
Rule: Whenever you add a new homepage.group=Something label to a Swarm service, add a matching entry to settings.yaml.
widgets.yaml — Global Info Bar
- logo:
icon: /images/gremlin-badge.png
- greeting:
text_size: xl
text: "NetGrimoire"
- datetime:
text_size: l
format:
dateStyle: long
timeStyle: short
hour12: true
- resources:
label: ZNAS
cpu: true
memory: true
disk: /
uptime: true
refresh: 5000
- resources:
label: Hermes
cpu: true
memory: true
cputemp: true
uptime: true
refresh: 5000
- resources:
label: Docker5
cpu: true
memory: true
uptime: true
refresh: 5000
- openmeteo:
label: Pensacola
latitude: 30.42
longitude: -87.21
units: imperial
cache: 5
- search:
provider: duckduckgo
target: _blank
Note: Resource widgets currently show stats for the Homepage host only. Deploy the Homepage agent on each node for true per-node metrics.
Branding — Gremlin Images
| File | Usage |
|---|---|
/DockerVol/homepage/images/gremlin-badge.png |
Logo widget (circular badge) |
/DockerVol/homepage/images/gremlin-scene.png |
Gremlin AI service card background |
After adding new images, restart the Homepage container — Next.js static server does not pick up new files without a restart.
Service Widgets
| Service | Widget Type | URL |
|---|---|---|
| Mailcow | customapi |
http://192.168.5.16/api/v1/get/domain/all |
| Technitium | customapi |
http://192.168.5.7:5380/api/dashboard/stats/get |
| OPNsense | opnsense |
https://192.168.3.4:8443 |
| Immich | immich |
https://immich.netgrimoire.com |
| Jackett | jackett |
http://gluetun:9117 |
| Radarr | radarr |
http://radarr:7878 |
| Sonarr | sonarr |
http://sonarr:8989 |
| SABnzbd | sabnzbd |
http://sabnzbd:8080 |
Mailcow widget note: The native mailcow widget type is broken with Mailcow 2025+ (API endpoint /api/v1/get/mailboxes was removed). Use customapi pointing at /api/v1/get/domain/all instead.
custom.css — Key Sections
The CSS uses a Netgrimoire dark ops aesthetic with per-tab color theming:
| Tab | Accent Color |
|---|---|
| Netgrimoire | Teal (#00e5cc) |
| Wasted-Bandwidth | Amber (#ffaa00) |
| Nucking-Futz | Red (#ff4455) |
| PNCHarris | Teal (narrow column layout) |
Critical fix: html, body, body > div { background-color: transparent !important; } must be present or Homepage's root div paints over the body background, hiding tab background images.
Card layout: Groups use style: column in settings.yaml. The CSS does not override the grid — Homepage's own Tailwind layout handles column placement.
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| Card stretches full width | Group not in settings.yaml | Add group with style: column |
| Background image not showing | Missing transparent fix in CSS | Add html, body, body > div { background-color: transparent !important } |
| Widget shows API error | Wrong URL or missing API key | Check env vars and use internal container URLs |
| Logo not showing | Image not in /app/public/images |
Copy to /DockerVol/homepage/images/ and restart container |
| New image not loading | Next.js static cache | Restart the Homepage container after adding images |