# CLAUDE.md — Project Instructions for Claude Code > This file is read automatically by Claude Code at the start of every session. > It replaces the "Instructions" panel from the claude.ai Project. > Keep it updated as the project evolves. ## Project overview Creating a business (Felhom) for home-server deployment for Hungarian customers. This repository (`deploy-felhom-compose`) contains the felhom-controller — a Go application that manages Docker Compose stacks on customer hardware via a Hungarian-language web dashboard. See `controller/README.md` for full architecture and status. See `CONTEXT.md` for current project state, recent work, and decisions (update after each session). Claude in Chrome extension is available — can be used to test web UI on demo-felhom.eu or verify dashboard deployments in browser. ## Code quality rules - Always double-check generated code for bugs, logic issues, syntax errors - Handle edge cases without overcomplicating the script/program - Add debug capabilities (logging, verbose output) for easier troubleshooting - If you need more input or troubleshooting command output, ask first — don't guess ## Repository structure This repo has two main parts: ``` deploy-felhom-compose/ ├── controller/ # Go application (this is the main codebase) │ ├── cmd/controller/ # Entry point (main.go) │ ├── internal/ │ │ ├── config/ # YAML config loading │ │ ├── stacks/ # Docker Compose operations, deploy flow │ │ ├── api/ # REST API endpoints │ │ └── web/ # Dashboard UI (embedded HTML/CSS templates) │ ├── Dockerfile │ ├── Makefile │ └── go.mod ├── scripts/ # Setup scripts for customer nodes ├── CLAUDE.md # This file └── CONTEXT.md # Project memory / state ``` ## Related repositories (not in this repo) - **app-catalog-felhom.eu** — Docker Compose templates + .felhom.yml metadata per app - **felhom.eu** — Website (htmls) + k3s manifests for the web server - **homelab-manifests** — Viktor's k3s cluster manifests (dooplex.hu services) - **misc-scripts** — Helper scripts for daily tasks All hosted at `gitea.dooplex.hu/admin/` ## Test environments | Node | Hardware | Domain | IP | Notes | |------|----------|--------|----|-------| | demo-felhom | Acemagic N100, 16G RAM, 512G SSD + 1TB HDD | demo-felhom.eu | 192.168.0.162 | Primary test node, Cloudflare Tunnel | | pi-customer-1 | Raspberry Pi 3B+, 1G RAM, 32G SD | pi-customer-1.local | 192.168.0.161 | Secondary test, not yet active | - Pi-hole DNS on local network forwards `*.demo-felhom.eu` → 192.168.0.162 - External access via Cloudflare Tunnel → Traefik reverse proxy ## Build & deploy workflow Code is edited locally on Windows. Build happens on the server via SSH. ```bash # Push changes git add -A && git commit -m "..." && git push # Build + push image on server ssh kisfenyo@192.168.0.180 "cd ~/build/felhom-controller && git -C ~/git/deploy-felhom-compose pull && ./build.sh --push" # Deploy on demo node ssh kisfenyo@192.168.0.162 "cd /opt/docker/felhom-controller && docker pull gitea.dooplex.hu/admin/felhom-controller: && docker compose up -d" ``` ## Tech stack - **Language:** Go 1.22+ - **Web framework:** stdlib `net/http` + `html/template` (no frameworks) - **Templates:** Embedded as Go string constants in `templates.go` (Hungarian UI) - **CSS:** Single embedded const in `templates.go` (no external CSS files) - **Auth:** bcrypt password hash + session cookies - **Container orchestration:** Docker Compose via CLI (`docker compose up -d`) - **Reverse proxy:** Traefik (separate stack, managed by controller) - **Tunnel:** Cloudflare Tunnel (cloudflared, separate stack) ## Key patterns - All UI text is in Hungarian (Budapest timezone, Hungarian locale) - Templates use Go template functions: `stateColor`, `stateLabel`, `stateIcon`, `stateStr`, `isOperational`, `logoURL`, `logoPNGURL`, `appPageURL` - Container states: `running`, `starting`, `unhealthy`, `stopped`, `exited`, `restarting`, `paused`, `not_deployed` - Docker `.State` field is combined with `.Status` field to detect health substatus - Stacks are sorted alphabetically by DisplayName - Protected stacks (traefik, cloudflared, felhom-controller) can't be stopped from UI - `app.yaml` persists deploy config; `deployed: true` flag controls UI state - Password fields require explicit user input or generation (no silent auto-fill) ## Important lessons learned 1. `PAPERLESS_OCR_LANGUAGES` (plural, with S) **installs** tesseract packs; `PAPERLESS_OCR_LANGUAGE` (singular) **selects** which to use 2. `docker compose restart` does NOT pick up new images — always use `docker compose up -d` 3. Go map iteration order is random — always sort before displaying in UI 4. Docker's `.State` field says "running" even for unhealthy containers — must parse `.Status` for health info 5. After `DeployStack()` succeeds, update in-memory `Deployed` flag immediately — `RefreshStatus()` only reads docker ps, not app.yaml