Files
deploy-felhom-compose/controller

felhom-controller

Central management container for Felhom home servers.

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

Current Status

Phase 1 — Stack Manager + Deploy Flow: core features operational.

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

┌─────────────────────────────────────────────────────────────────┐
│  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)

Repository Layout

This is the controller/ subfolder of the deploy-felhom-compose repository.

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/<app>/
  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:

# /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-composecontroller/ subfolder.

Build happens outside the repo in ~/build/felhom-controller/ to keep the repo clean. See docs/BUILDING.md for the full guide.

# 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

# 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

  • Project skeleton & config format
  • .felhom.yml app metadata format with deploy fields
  • Per-app config persistence (app.yaml)
  • Secret generation engine (password, hex, static)
  • Stack catalog (read compose files + metadata from disk)
  • Docker Compose operations (up/down/pull/ps/logs)
  • Deploy flow with interactive field input
  • Basic web dashboard with start/stop/deploy buttons
  • REST API for stack + deploy operations
  • Simple web authentication (bcrypt sessions)
  • App assets baked into container (SVG/PNG logos, webp screenshots)
  • Container image build pipeline (Dockerfile + build.sh)
  • Build + push to Gitea container registry
  • Deploy on N100 test node — dashboard accessible
  • 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
Repository Purpose
deploy-felhom-compose This repo — controller + deploy scripts
app-catalog-felhom.eu Docker Compose templates + .felhom.yml metadata
felhom.eu Website + app assets + felhom infra manifests
homelab-manifests k3s cluster manifests (dooplex.hu)