diff --git a/controller/README.md b/controller/README.md index 968a5f3..0a3e209 100644 --- a/controller/README.md +++ b/controller/README.md @@ -1,31 +1,301 @@ -# App Assets +# felhom-controller -This directory contains logos and screenshots for the dashboard. -They are baked into the Docker image at build time. +**Central management container for Felhom home servers.** -## Naming convention +Replaces Portainer + scattered systemd scripts with a single, lightweight container that provides: +- Hungarian-language web dashboard for customers +- Docker Compose stack management (start/stop/update) +- Interactive first-deployment flow with auto-generated secrets +- Backup orchestration (DB dumps + restic snapshots) — Phase 3 +- System health monitoring with Healthchecks pings — Phase 2 +- Git-based stack synchronization with update management — Phase 4 +- Self-update with automatic rollback on failure — Phase 5 -Files must follow the felhom.eu website convention: +## Current Status -- `{slug}-logo.svg` — App logo (SVG preferred, displayed on dark background) -- `{slug}-logo.png` — App logo fallback (PNG, for apps without SVG) -- `{slug}-screenshot-1.webp` — First screenshot -- `{slug}-screenshot-2.webp` — Second screenshot (and so on) +**Phase 1 — Stack Manager + Deploy Flow: core features operational.** -The dashboard tries SVG first, falls back to PNG if not found. +The controller is built, deployed, and running on the N100 test node (demo-felhom.eu). +The web dashboard is accessible, stack scanning works, and the deploy UI renders correctly. + +Next milestone: end-to-end test deploying a real app (e.g., Paperless-ngx) through the dashboard. + +## Architecture -Example: ``` -paperless-ngx-logo.svg -paperless-ngx-screenshot-1.webp -adventurelog-logo.png -adventurelog-screenshot-1.webp +┌─────────────────────────────────────────────────────────────────┐ +│ Customer Hardware (N100 mini PC / Raspberry Pi) │ +│ │ +│ ┌──────────┐ ┌────────────────────────────────────────────┐ │ +│ │ Traefik │ │ felhom-controller │ │ +│ │ (reverse │──▶│ │ │ +│ │ proxy) │ │ ┌──────────┐ ┌─────────────────────────┐│ │ +│ └──────────┘ │ │ Web UI │ │ Stack Manager ││ │ +│ │ │ (HU dash │ │ (compose up/down/pull, ││ │ +│ ┌──────────┐ │ │ board) │ │ git sync, update mgmt) ││ │ +│ │cloudflared│ │ └──────────┘ └─────────────────────────┘│ │ +│ │ (tunnel) │ │ ┌──────────┐ ┌─────────────────────────┐│ │ +│ └──────────┘ │ │ Backup │ │ Monitor & Pinger ││ │ +│ │ │ (db dump │ │ (healthchecks pings, ││ │ +│ ┌──────────┐ │ │ restic) │ │ system metrics) ││ │ +│ │ App │ │ └──────────┘ └─────────────────────────┘│ │ +│ │ stacks │ │ ┌──────────┐ ┌─────────────────────────┐│ │ +│ │ (docker │ │ │Scheduler │ │ REST API ││ │ +│ │ compose) │ │ │(cron-like│ │ (for UI + remote mgmt) ││ │ +│ └──────────┘ │ │ jobs) │ └─────────────────────────┘│ │ +│ │ └──────────┘ │ │ +│ └────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + │ pings │ git pull + ▼ ▼ + status.felhom.eu gitea.dooplex.hu + (Healthchecks on k3s) (stack definitions) ``` -## Syncing from felhom.eu website +## Repository Layout -Run `make sync-assets` to copy assets from the felhom.eu website repo. -This expects the website files to be available at `../felhom.eu/website/assets/` -(relative to this repo), or set `WEBSITE_ASSETS_DIR` to override. +This is the `controller/` subfolder of the `deploy-felhom-compose` repository. -Alternatively, copy files manually from FileBrowser at https://felhom.eu. +``` +controller/ +├── cmd/controller/main.go # Entry point, wires all modules +├── internal/ +│ ├── config/config.go # YAML loader, validation, env overrides +│ ├── stacks/ +│ │ ├── manager.go # Stack scanning, compose ops, container status +│ │ ├── metadata.go # Parse .felhom.yml app metadata +│ │ └── deploy.go # First-deploy flow: secret gen, app.yaml, compose up +│ ├── api/router.go # REST API endpoints +│ └── web/ +│ ├── server.go # HTTP server, auth, page handlers, asset serving +│ └── templates.go # Embedded HTML templates + CSS (Hungarian UI) +├── configs/ +│ ├── controller.yaml.example # Full config reference (infrastructure only) +│ └── example-felhom-metadata.yml # .felhom.yml format reference +├── scripts/hashpass.go # Bcrypt password hash generator +├── assets/ # App logos + screenshots (gitignored, synced at build) +├── docs/BUILDING.md # Container image build & registry guide +├── Dockerfile # Multi-stage build (Go 1.22 + debian-slim) +├── docker-compose.yml # Controller's own compose definition +├── Makefile # Build targets + asset sync +└── go.mod +``` + +## Module Overview + +| Module | Path | Status | Responsibility | +|--------|------|--------|----------------| +| **Config** | `internal/config/` | ✅ Done | Load & validate controller.yaml, env overrides | +| **Stacks** | `internal/stacks/` | ✅ Done | Compose operations, scanning, metadata, deploy flow | +| **API** | `internal/api/` | ✅ Done | REST endpoints (stacks, deploy, system info, health) | +| **Web** | `internal/web/` | ✅ Done | Hungarian dashboard, auth, deploy pages, asset serving | +| **Backup** | `internal/backup/` | 🔲 Phase 3 | DB dumps, restic snapshots, restore | +| **Monitor** | `internal/monitor/` | 🔲 Phase 2 | Health checks, Healthchecks pings, system metrics | +| **Scheduler** | `internal/scheduler/` | 🔲 Phase 2 | Cron-like job runner for all periodic tasks | + +## Stack Management + +### How stacks get onto the machine + +1. During initial setup, `deploy-felhom-compose.sh` clones the app catalog +2. Compose files + `.felhom.yml` metadata land in `/opt/docker/stacks//` +3. The controller periodically pulls from Git to detect changes (Phase 4) + +### First deployment flow (via dashboard) + +1. Customer sees app card with "🚀 Telepítés" (Deploy) button +2. Clicks → deploy page shows: + - **Auto-filled**: DOMAIN (from controller config), read-only + - **Auto-generated**: DB passwords, secret keys (shown as "✓ Generated") + - **User input**: HDD path, admin password, language, etc. + - **"🎲 Generálás"** button next to password fields +3. Clicks "Telepítés" → controller: + - Generates all secrets + - Validates required fields (checks path exists, etc.) + - Saves `app.yaml` (env vars + locked fields list) + - Runs `docker compose up -d` with env vars injected +4. Post-deploy: locked fields (DB_PASSWORD, etc.) become read-only + +### Update strategy (Phase 4) + +Stack updates are classified in the Git repository via markers: + +| Marker | Behavior | +|--------|----------| +| No marker | Optional update — shown on dashboard, customer clicks "Update" | +| `UPDATE_REQUIRED=true` | Mandatory — auto-applied during next update window | +| `UPDATE_SECURITY=true` | Critical — applied immediately (within minutes) | + +### Protected stacks + +The following stacks cannot be stopped from the customer UI: +- `traefik` (reverse proxy) +- `cloudflared` (tunnel) +- `felhom-controller` (this container) + +## Configuration + +### Controller config (infrastructure only) + +Single YAML file per customer: `/opt/docker/felhom-controller/controller.yaml` + +Contains customer identity, infrastructure secrets, backup/monitoring settings. +Does **not** contain app-specific config (HDD paths, DB passwords, etc.). + +See `configs/controller.yaml.example` for the full reference. + +### Per-app config (created during deployment) + +Each deployed app gets an `app.yaml` in its stack directory: + +```yaml +# /opt/docker/stacks/paperless-ngx/app.yaml +# Auto-generated by felhom-controller — do not edit locked fields manually +deployed: true +deployed_at: "2026-02-13T14:30:00Z" +env: + DOMAIN: "demo-felhom.eu" + DB_PASSWORD: "a7f2b9c1e4d..." # locked + PAPERLESS_SECRET_KEY: "8b3e..." # locked + PAPERLESS_ADMIN_USER: "admin" # editable + HDD_PATH: "/mnt/hdd_1" # locked +locked_fields: + - DB_PASSWORD + - PAPERLESS_SECRET_KEY + - DOMAIN + - HDD_PATH +``` + +Fields are defined in each stack's `.felhom.yml` metadata file. See +`configs/example-felhom-metadata.yml` for the full format. + +### App assets (logos, screenshots) + +Baked into the container image at build time — no external dependencies at runtime. +Synced from the felhom.eu website repo before building. + +Served locally at `/static/assets/`. Logos try SVG first, fall back to PNG. + +| Asset | File pattern | Served at | +|-------|-------------|-----------| +| Logo (SVG) | `assets/{slug}-logo.svg` | `/static/assets/{slug}-logo.svg` | +| Logo (PNG fallback) | `assets/{slug}-logo.png` | `/static/assets/{slug}-logo.png` | +| Screenshot | `assets/{slug}-screenshot-{n}.webp` | `/static/assets/{slug}-screenshot-{n}.webp` | + +## Build & Deploy + +Source: `https://gitea.dooplex.hu/admin/deploy-felhom-compose` → `controller/` subfolder. + +Build happens outside the repo in `~/build/felhom-controller/` to keep the repo clean. +See `docs/BUILDING.md` for the full guide. + +```bash +# Quick build (current platform only) +cd ~/build/felhom-controller +./build.sh 0.1.0 + +# Build + push to Gitea registry +./build.sh 0.1.0 --push + +# Build for N100 (amd64) + Pi (arm64) and push +./build.sh 0.1.0 --multiarch +``` + +### Deploy on customer node + +```bash +# Create config first +nano /opt/docker/felhom-controller/controller.yaml + +# Create .env for compose labels +echo "DOMAIN=demo-felhom.eu" > /opt/docker/felhom-controller/.env + +# Pull and start +cd /opt/docker/felhom-controller +docker compose pull +docker compose up -d +``` + +## Test Environments + +| Node | Hardware | Domain | IP | Status | +|------|----------|--------|----|--------| +| demo-felhom | Acemagic GK3PLUS N100, 16G RAM, 512G SSD + 1TB HDD | demo-felhom.eu | 192.168.0.162 | ✅ Controller running | +| pi-customer-1 | Raspberry Pi 3B+, 1G RAM, 32G SD | pi-customer-1.local | — | 🔲 Not yet tested | + +## REST API + +| Method | Endpoint | Auth | Description | +|--------|----------|------|-------------| +| GET | `/api/health` | No | Health check (for monitoring) | +| GET | `/api/stacks` | Yes | List all stacks | +| GET | `/api/stacks/{name}` | Yes | Stack details | +| GET | `/api/stacks/{name}/deploy-fields` | Yes | Get deploy form fields | +| POST | `/api/stacks/{name}/deploy` | Yes | First-time deploy with config | +| POST | `/api/stacks/{name}/start` | Yes | Start stack | +| POST | `/api/stacks/{name}/stop` | Yes | Stop stack (not protected) | +| POST | `/api/stacks/{name}/restart` | Yes | Restart stack | +| POST | `/api/stacks/{name}/update` | Yes | Pull images + recreate | +| GET | `/api/stacks/{name}/logs` | Yes | Container logs | +| GET | `/api/system/info` | Yes | Customer/domain info | + +## Status & Roadmap + +### Phase 1 — Stack Manager + Deploy Flow ✅ +- [x] Project skeleton & config format +- [x] .felhom.yml app metadata format with deploy fields +- [x] Per-app config persistence (app.yaml) +- [x] Secret generation engine (password, hex, static) +- [x] Stack catalog (read compose files + metadata from disk) +- [x] Docker Compose operations (up/down/pull/ps/logs) +- [x] Deploy flow with interactive field input +- [x] Basic web dashboard with start/stop/deploy buttons +- [x] REST API for stack + deploy operations +- [x] Simple web authentication (bcrypt sessions) +- [x] App assets baked into container (SVG/PNG logos, webp screenshots) +- [x] Container image build pipeline (Dockerfile + build.sh) +- [x] Build + push to Gitea container registry +- [x] Deploy on N100 test node — dashboard accessible +- [x] Stack scanning + display working (whoami test stack) +- [ ] End-to-end test: deploy an app through dashboard (whoami / paperless-ngx) +- [ ] Dashboard UI redesign (align with felhom.eu dark theme) + +### Phase 2 — Monitoring & Health +- [ ] System metrics collection (CPU, RAM, disk, temperature) +- [ ] Healthchecks.io ping integration +- [ ] Dashboard system health panel +- [ ] Customer notifications (email/Telegram) +- [ ] Periodic stack status refresh (background goroutine) + +### Phase 3 — Backups +- [ ] DB dump engine (PostgreSQL, MariaDB/MySQL, SQLite) +- [ ] Restic integration (snapshot, prune, check) +- [ ] Backup status on dashboard +- [ ] Manual backup trigger from UI +- [ ] Restore workflow + +### Phase 4 — Git Sync & Updates +- [ ] Periodic git pull for stack definitions +- [ ] Update classification (optional/required/security) +- [ ] Update window enforcement +- [ ] Dashboard update notifications with "Update" button + +### Phase 5 — Self-Update & Resilience +- [ ] Self-update check & execution +- [ ] Pre-update config backup +- [ ] Health-based rollback mechanism +- [ ] Config export/import + +### Phase 6 — Central Management (future) +- [ ] API authentication for remote management +- [ ] Central dashboard on k3s querying all customer controllers +- [ ] Fleet-wide update management + +## Related Repositories + +| Repository | Purpose | +|------------|---------| +| [deploy-felhom-compose](https://gitea.dooplex.hu/admin/deploy-felhom-compose) | This repo — controller + deploy scripts | +| [app-catalog-felhom.eu](https://gitea.dooplex.hu/admin/app-catalog-felhom.eu) | Docker Compose templates + .felhom.yml metadata | +| [felhom.eu](https://gitea.dooplex.hu/admin/felhom.eu) | Website + app assets + felhom infra manifests | +| [homelab-manifests](https://gitea.dooplex.hu/admin/homelab-manifests) | k3s cluster manifests (dooplex.hu) | \ No newline at end of file