e766fcd95c
- Apply GTK-like color scheme (dark greys, #f76b2f accent) across cards, buttons, glows and category colors - Service cards use the official logo icons; Netbird card shows live reachability + latency instead of a separate top widget - Top widgets: Today (calendar events with in-progress highlighting), Git activity (3 rows visible, scrollable), GPU with live ROCm stats and loaded Ollama models incl. GPU/CPU split - Open WebUI card: inline prompt line with model selection - Calendar section grouping events by day below the services - data.json fetch with boot retry; GPU/Ollama poll every 5 s - Today entries wrap long titles; README documents widgets, environment variables and the .env secrets pattern
110 lines
4.4 KiB
Markdown
110 lines
4.4 KiB
Markdown
# Homelab Dashboard
|
|
|
|
A small, self-contained single-page dashboard that links all your homelab services.
|
|
Static site (HTML + CSS + JS), served by a lightweight **nginx** image. The optional
|
|
calendar widget needs the container backend to refresh Google/ICS feeds, but the
|
|
rest of the dashboard is pure static files.
|
|
|
|
## Services
|
|
|
|
Internal: Open WebUI, ComfyUI, Gitea, Jellyfin, Immich, Home Assistant,
|
|
Audio Server / Dubplate, Nextcloud, Vaultwarden, Nginx Proxy Manager, Netbird.
|
|
|
|
External: gitlab-ixsol, gem360.
|
|
|
|
## Features
|
|
|
|
- Top widgets: **Today** (calendar events for today, with in-progress highlighting),
|
|
**Netbird** status (reachability + latency), **Git activity** (recent commits from
|
|
Gitea and GitLab — 3 rows visible, scroll for more), **GPU + Ollama** (live AMD
|
|
ROCm stats: utilization, VRAM, temperature, power; plus loaded Ollama models
|
|
with their GPU/CPU split)
|
|
- Inline **Open WebUI prompt line with model selection** in the Open WebUI card
|
|
(requires `OPENWEBUI_TOKEN`)
|
|
- Responsive grid of service cards with icons, categories and a live "Online" indicator
|
|
- **Open** (new tab) + **Copy URL** per service
|
|
- Live search / filter across names, categories and URLs
|
|
- Live local clock
|
|
- Calendar section aggregating multiple ICS feeds (refreshed every 15 min in the container)
|
|
- Dark, themeable design; respects `prefers-reduced-motion`
|
|
|
|
## Run with Docker
|
|
|
|
```bash
|
|
docker compose up -d --build
|
|
```
|
|
|
|
Then open <http://localhost:8888>.
|
|
|
|
The dashboard is static, but the widgets are populated by a small Node.js updater
|
|
(`api/update-data.js`) that runs inside the container and aggregates ICS feeds,
|
|
Netbird status, git activity and Open WebUI models every 15 minutes. A second
|
|
Node process (`api/server.js`) proxies chat prompts to Open WebUI.
|
|
|
|
### Environment variables
|
|
|
|
Secrets (API keys) live in **`.env`** (gitignored) — docker compose reads it
|
|
automatically. Non-secret settings go directly in `docker-compose.yml`:
|
|
|
|
| Variable | Purpose |
|
|
| --- | --- |
|
|
| `TZ` | Timezone used for the "Today" widget (e.g. `Europe/Vienna`) |
|
|
| `OPENWEBUI_TOKEN` | Open WebUI API key — enables the prompt line + model list (**set in `.env`**) |
|
|
| `GITEA_TOKEN` | Gitea API token — private repo stats (public repos work without it) |
|
|
| `GITLAB_TOKEN` | GitLab API token — private project stats (public projects work without it) |
|
|
| `GITEA_URL` / `GITLAB_URL` / `NETBIRD_URL` / `OPENWEBUI_URL` | Override the default service URLs |
|
|
| `GPU_STATS_URL` | GPU stats upstream (default: the `gpu-stats` compose service) |
|
|
| `OLLAMA_URL` | Ollama instance for loaded-model stats (default: `http://100.103.83.12:11435`) |
|
|
|
|
### GPU stats service
|
|
|
|
The `gpu-stats` compose service runs [`gpu_stats.py`](./gpu_stats.py), a tiny HTTP
|
|
server that queries `rocm-smi`. It needs the host's ROCm install and GPU device
|
|
nodes, so the compose file mounts `/opt/rocm` and passes `/dev/kfd` + `/dev/dri`.
|
|
Set `GPU_NAME` in `docker-compose.yml` to your card's name (rocm-smi can't read it
|
|
inside the container without `libdrm_amdgpu`). The widget polls it every 5 s
|
|
through `/api/gpu-stats`.
|
|
|
|
To run it on the host instead: `python3 gpu_stats.py`, set
|
|
`GPU_STATS_URL=http://host.docker.internal:9101/stats` on the dashboard service
|
|
and add `extra_hosts: ["host.docker.internal:host-gateway"]`.
|
|
|
|
### Without Docker (quick dev)
|
|
|
|
Any static file server works for the dashboard itself, but the widgets will
|
|
show errors because the data fetcher and chat proxy run server-side:
|
|
|
|
```bash
|
|
# from this directory
|
|
python3 -m http.server 8888
|
|
# or: npx serve . -l 8888
|
|
```
|
|
|
|
## Edit services
|
|
|
|
All services live in one array at the top of [`script.js`](./script.js).
|
|
Add / remove / reorder entries there:
|
|
|
|
```js
|
|
{ section: "internal", name: "My Service", url: "http://10.0.0.5:9000", cat: "infra", icon: "⚙️" }
|
|
```
|
|
|
|
`section` is either `"internal"` or `"external"`.
|
|
`cat` is any key from the `CATEGORIES` map (or add your own).
|
|
|
|
## Build the image manually
|
|
|
|
```bash
|
|
docker build -t homelab-dashboard .
|
|
docker run -d --name homelab-dashboard -p 8888:80 --restart unless-stopped homelab-dashboard
|
|
```
|
|
|
|
## Notes
|
|
|
|
- The "Online" badge is cosmetic (a static site can't probe your services from the browser
|
|
due to CORS). If you want real health checks later, a tiny backend that pings each URL
|
|
would be the next step.
|
|
- Calendar dependencies are bundled in `api/node_modules` so the Docker build works
|
|
offline. To update them, run `npm install` in the `api/` directory.
|
|
- Port 8888 is published by the Compose file; change it there if needed.
|