From c1e75f2b19ad937ed70131caf661d05e50767fd8 Mon Sep 17 00:00:00 2001 From: Syco21 Date: Sat, 16 May 2026 16:44:45 +0200 Subject: [PATCH] Add README --- README.md | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..edf0157 --- /dev/null +++ b/README.md @@ -0,0 +1,247 @@ +# syco.me — Homelab Dashboard + +A personal homelab dashboard built with React + TypeScript on the frontend and an Express proxy server on the backend. Deployed via Woodpecker CI to a Proxmox LXC container. + +--- + +## Features + +- **Dashboard** — live widgets for all homelab services +- **Apps** — icon grid of all self-hosted apps with local icons (no CDN) +- **Home** — mobile-optimised page with weather and public transit departures +- **Responsive** — desktop defaults to Dashboard, mobile defaults to Home +- **Collapsible sections** — click any section label to fold it away +- **Header** — live clock, weather summary, and navigation tabs + +--- + +## Stack + +| Layer | Technology | +|---|---| +| Frontend | React 18, TypeScript, Vite | +| Backend | Node.js, Express | +| Routing | React Router v6 | +| Fonts | Syne, JetBrains Mono (Google Fonts) | +| CI/CD | Woodpecker CI | +| Deployment | Docker on Proxmox LXC | + +--- + +## Widgets + +### Infrastructure +| Widget | Service | API | +|---|---|---| +| Proxmox | Proxmox VE | REST API (API Token) | +| Synology NAS | DSM | Synology Web API | +| AdGuard Home | AdGuard | REST API (Basic Auth) | +| Headscale | Headscale VPN | REST API (API Key) | +| FritzBox | AVM FRITZ!Box | TR-064 SOAP API | + +### Media +| Widget | Service | API | +|---|---|---| +| Jellyfin | Jellyfin | REST API (API Key) | +| Navidrome | Navidrome | Subsonic API | +| RomM | RomM | REST API | +| Arr Calendar | Sonarr + Radarr | REST API | +| Arr Stats | Sonarr + Radarr + Lidarr | REST API | +| qBittorrent | qBittorrent | Web API | + +### Monitoring +| Widget | Service | API | +|---|---|---| +| Uptime Kuma | Kuma | REST API | +| CrowdSec | CrowdSec LAPI | REST API (Bouncer Key) | +| Grafana | Grafana | REST API | +| Prometheus | Prometheus | REST API | +| Loki | Loki | REST API | + +### Access +| Widget | Service | API | +|---|---|---| +| Authentik | Authentik | REST API (API Token) | +| Vaultwarden | Vaultwarden | Admin API | + +### Home (mobile) +| Widget | Source | +|---|---| +| Weather | [wttr.in](https://wttr.in) — no API key needed | +| Transit | [VAG PULS API](https://start.vag.de/dm/api/) — no API key needed | + +--- + +## Project Structure + +``` +├── server/ +│ ├── index.ts # Express server + route registration +│ └── routes/ # One file per service proxy +├── src/ +│ ├── components/ +│ │ ├── Header.tsx # Nav, clock, weather summary +│ │ ├── AppsSection.tsx # Icon tile grid +│ │ └── widgets/ # One component per dashboard widget +│ ├── config/ +│ │ ├── apps.ts # App links + icon paths (edit order here) +│ │ └── dashboard.ts # Dashboard sections + widget order (edit order here) +│ ├── hooks/ +│ │ └── useIsMobile.ts +│ ├── pages/ +│ │ ├── AppsPage.tsx +│ │ └── MobileHome.tsx # Weather + transit for mobile +│ └── App.tsx # Routing +├── public/ +│ └── icons/ # All icons stored locally +├── Dockerfile +└── .woodpecker.yml +``` + +> **To change widget/app order**: edit `src/config/dashboard.ts` (widgets) or `src/config/apps.ts` (app tiles) — no need to touch `App.tsx`. + +--- + +## Environment Variables + +Copy `.env.example` to `.env` and fill in your values. + +```env +# Proxmox VE +PROXMOX_HOST=https://192.168.178.x:8006 +PROXMOX_TOKEN=PVEAPIToken=user@realm!tokenid=... + +# Synology DSM +SYNOLOGY_HOST=http://192.168.178.x:5000 +SYNOLOGY_USER=... +SYNOLOGY_PASSWORD=... + +# AdGuard Home +ADGUARD_HOST=http://192.168.178.x +ADGUARD_USER=... +ADGUARD_PASSWORD=... + +# CrowdSec +CROWDSEC_HOST=http://192.168.178.x:8080 +CROWDSEC_API_KEY=... + +# Headscale +HEADSCALE_HOST=http://192.168.178.x:8085 +HEADSCALE_API_KEY=... + +# FRITZ!Box +FRITZBOX_HOST=http://192.168.178.1 + +# Uptime Kuma +KUMA_HOST=http://192.168.178.x:3001 +KUMA_USER=... +KUMA_PASSWORD=... + +# Authentik +AUTHENTIK_HOST=http://192.168.178.x:9000 +AUTHENTIK_TOKEN=... + +# Vaultwarden +VAULTWARDEN_HOST=http://192.168.178.x:8087 +VAULTWARDEN_ADMIN_TOKEN=... + +# qBittorrent +QBT_HOST=http://192.168.178.x:8080 +QBT_USER=... +QBT_PASSWORD=... + +# *arr suite +RADARR_HOST=http://192.168.178.x:7878 +RADARR_API_KEY=... +SONARR_HOST=http://192.168.178.x:8989 +SONARR_API_KEY=... +LIDARR_HOST=http://192.168.178.x:8686 +LIDARR_API_KEY=... + +# Jellyfin +JELLYFIN_HOST=http://192.168.178.x:8096 +JELLYFIN_API_KEY=... + +# Navidrome +NAVIDROME_HOST=http://192.168.178.x:4533 +NAVIDROME_USER=... +NAVIDROME_PASSWORD=... + +# RomM +ROMM_HOST=http://192.168.178.x:7998 +ROMM_USER=... +ROMM_PASSWORD=... + +# Grafana +GRAFANA_HOST=http://192.168.178.x:3000 +GRAFANA_TOKEN= + +# Prometheus +PROMETHEUS_HOST=http://192.168.178.x:9090 + +# Loki +LOKI_HOST=http://192.168.178.x:3100 + +# Weather (wttr.in — no API key needed) +WEATHER_LOCATION='90461 Nürnberg' + +# Transit (VAG PULS API — no API key needed) +TRANSIT_STOP_VAG=SCHW + +# Server port +PORT=3001 +``` + +> **Note on special characters in passwords**: The `.env` file supports shell-quoted values (`'...'` or `"..."`). The deployment script strips quotes before passing to Docker via `--env-file`. + +--- + +## Local Development + +```bash +npm install +npm run dev +``` + +Runs Vite (port 5173) and the Express server (port 3001) concurrently. + +--- + +## Deployment + +Deployment is fully automated via Woodpecker CI on every push to `main`. + +The pipeline (`.woodpecker.yml`): +1. Builds a Docker image from `Dockerfile` +2. Strips shell quotes from `.env` (Docker `--env-file` passes values literally) +3. Stops and removes the old container +4. Starts a new container with `docker run --env-file` + +The `.env` file lives at `/opt/docker/dashboard/.env` on the host and is mounted into the pipeline as a secret volume — it is never committed to the repository. + +--- + +## Adding a New App Link + +Edit `src/config/apps.ts`: + +```ts +{ name: 'My App', url: 'https://myapp.syco.me', icon: `${ICONS}/myapp.svg` } +``` + +Download the icon to `public/icons/` first. Icons are sourced from [selfh.st/icons](https://selfh.st/icons). + +## Adding a New Widget + +1. Create `src/components/widgets/MyWidget.tsx` +2. Add it to `src/config/dashboard.ts` in the appropriate section + +--- + +## Changing the Transit Stop + +Update `TRANSIT_STOP_VAG` in `.env` with a VAG stop ID. Look up stop IDs via: + +``` +https://start.vag.de/dm/api/haltestellen.json/vag?name= +```