Files
deploy-felhom-compose/CLAUDE.md
T
2026-02-14 08:37:13 +01:00

4.9 KiB

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).

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
  • 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.

# 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