7.5 KiB
7.5 KiB
CONTEXT.md — Project Memory
This file serves as persistent project memory across Claude Code sessions. It replaces the auto-generated "Memory" from the claude.ai Project. Update this file at the end of each working session with current state, recent decisions, and anything the next session needs to know.
Ask Claude Code: "Please update CONTEXT.md with what we did today"
Last updated: 2026-02-15
About Viktor (project owner)
- Works at Magyar Telekom (Budapest), building Felhom as a side business
- Felhom: managed home-server service for Hungarian households
- Technical but prefers pragmatic solutions over over-engineering
- Runs all infrastructure on Gitea (gitea.dooplex.hu), k3s cluster for management
- Customer deployments use Docker Compose (not Kubernetes) for simplicity
Current project state
felhom-controller (this repo)
- Version: v0.2.1
- Phase 1: ✅ COMPLETE — Stack Manager + Deploy Flow
- First app deployed: Paperless-ngx on demo-felhom.eu (2026-02-13)
- Running on: demo-felhom (N100 mini PC) at 192.168.0.162:8080
- All Phase 1 features working: deploy, start/stop/restart/update, logs, health-aware states, auth
What was just completed (2026-02-15)
- Memory validation during deployment:
- Pre-deploy memory check: compares
mem_requestsum against usable system RAM - Hard block if requests exceed usable memory (total - 384MB reserved)
- Soft warning if
mem_limitsum exceeds total RAM (overcommit OK for limits) ParseMemoryMB()supports "500M", "1G", "1.5G", "1024" formatsCommittedMemory()sums requests/limits across all deployed stacks- Memory summary bar shown on deploy page before user clicks deploy
system.reserved_memory_mbconfigurable in controller.yaml (default: 384)
- Pre-deploy memory check: compares
- Display:
~prefix on mem_request in UI badges (display-only, exact value stored) - Felhom.eu logo replaced text logos in sidebar and login page with actual SVG logo
- Logo SVG embedded as Go string constant, served at
/static/felhom-logo.svg
- Logo SVG embedded as Go string constant, served at
Previously completed (2026-02-14)
- System info bar on Vezérlőpult dashboard: RAM, SSD, and optional HDD usage
- Progress bars with color coding (green < 70%, yellow 70-85%, red > 85%)
- New
internal/systempackage reads/proc/meminfo+syscall.Statfs - Platform-specific: Linux impl + non-Linux stub (build tags)
- Hungarian labels: "Memória", "SSD tárhely", "Külső HDD"
- Docker Compose memory limits on paperless-ngx template:
- paperless-webserver: 768M, postgres: 256M, redis: 128M
- Added
mem_limitfield to.felhom.ymlResourceHints (total: 1152M)
/api/system/infoendpoint now returns live system metrics (was customer info)- Config: Added
paths.hdd_pathfor external HDD monitoring - Controller image builds via build.sh, pushes to Gitea container registry
Previously completed (2026-02-13)
- Built the entire felhom-controller from scratch (Go, no frameworks)
- Debugged and fixed 7 issues during first real deployment:
- Password validation (empty passwords accepted)
- In-memory Deployed flag not updating after deploy
- Health-aware state parsing (starting/unhealthy detection)
- Random card ordering (Go map iteration)
- "Részletek" button redirect for deployed apps
- Paperless OCR language installation (LANGUAGES vs LANGUAGE env var)
- Documentation: restart vs up -d for image updates
What's next (priorities)
- Deploy a second app (e.g., Immich, Jellyfin) to validate the template system
- Test on Raspberry Pi (pi-customer-1)
- Add
paths.hdd_pathto demo-felhom controller.yaml to enable HDD bar - Add memory limits +
mem_request/mem_limitto other app catalog templates (Immich, Jellyfin, etc.) - Phase 2 continued: CPU/temperature metrics, Healthchecks.io pings
- Phase 3: Backup system (DB dumps + restic)
Architecture decisions
| Decision | Rationale |
|---|---|
| Go stdlib for web (no Gin/Echo) | Minimal dependencies, single binary, easy to embed templates |
| Templates as Go string constants | Zero runtime file dependencies, everything in the binary |
| Docker Compose for customers (not k8s) | Simpler troubleshooting, customers don't need k8s knowledge |
| k3s for management infra only | Viktor's own services (gitea, monitoring, website) run on k3s |
| Cloudflare Tunnel for remote access | No port forwarding needed, works behind any NAT |
| app.yaml per stack | Separates deploy config from compose files, survives git pulls |
| Password fields require explicit input | Prevents accidental empty-password deployments |
| Health-aware state from Docker Status field | Docker's State says "running" even for unhealthy containers |
| Memory limits via deploy.resources.limits | Prevents runaway containers; ~50% headroom over expected usage |
| System info from /proc/meminfo + statfs | No external dependencies, cheap to read on each page load |
| mem_request vs mem_limit (K8s-inspired) | Requests = expected usage (hard block), limits = peak (overcommit OK) |
| 384MB reserved for system | Prevents deploying apps that would starve the OS/controller |
| Logo SVG embedded as Go constant | Same approach as CSS/HTML — zero external file deps |
Key file locations on demo-felhom
/opt/docker/felhom-controller/ # Controller compose + config
├── controller.yaml # Customer config (domain, auth, paths)
├── docker-compose.yml # Controller's own compose
└── .env # DOMAIN=demo-felhom.eu
/opt/docker/stacks/ # All app stacks
├── traefik/ # Reverse proxy (protected)
├── cloudflared/ # Tunnel (protected)
├── paperless-ngx/ # First deployed app ✅
│ ├── docker-compose.yml
│ ├── .felhom.yml # App metadata
│ └── app.yaml # Deploy config (env vars, locked fields)
└── whoami/ # Test stack (not deployed)
/mnt/hdd_placeholder/storage/ # HDD storage for apps
└── paperless/
├── consume/ # Drop files here for OCR
├── media/ # Processed documents
└── export/ # Backup exports
Related repositories and their state
| Repository | Status | Notes |
|---|---|---|
| deploy-felhom-compose | Active | This repo. Controller code + deploy scripts |
| app-catalog-felhom.eu | Active | 49 app templates, paperless-ngx has memory limits |
| felhom.eu | Stable | Website live, SEO indexed, email working |
| homelab-manifests | Stable | k3s cluster running (dooplex.hu services) |
| misc-scripts | Utility | collect-repo.sh, backup helpers |
Gotchas & lessons learned
docker compose restart≠docker compose up -d— restart doesn't pick up new images- Go maps have random iteration order — always sort slices before displaying
- Docker
.State="running" doesn't mean healthy — check.Statusfor "(health: starting)" / "(unhealthy)" - Paperless-ngx needs
PAPERLESS_OCR_LANGUAGES(plural) to install language packs,PAPERLESS_OCR_LANGUAGE(singular) to select - After deploying a stack, update the in-memory Deployed flag immediately — RefreshStatus() only reads docker ps
- Cloudflare Tunnel handles *.demo-felhom.eu → Traefik handles Host()-based routing to containers
- BIOS "AC Power Recovery" must be enabled on N100 for auto-restart after power outage