# Building & Publishing felhom-controller ## Prerequisites - Docker installed on your build machine - Docker Buildx plugin (for multi-arch builds — included with Docker Desktop, may need install on Linux) - Access to Gitea at gitea.dooplex.hu ## Step 1: Enable Gitea Container Registry Gitea has a built-in container registry. Check if it's enabled: ```bash # SSH into your k3s node or wherever Gitea runs # Check Gitea config (app.ini) kubectl exec -it -n deploy/gitea -- cat /data/gitea/conf/app.ini | grep -A5 '\[packages\]' ``` If the `[packages]` section is missing or `ENABLED=false`, add/update: ```ini [packages] ENABLED = true ``` Then restart Gitea: ```bash kubectl rollout restart deploy/gitea -n ``` **Verify it works:** ```bash # Login to the registry (use your Gitea username + password or access token) docker login gitea.dooplex.hu # Username: admin # Password: ``` If login succeeds, the registry is working. The image URL pattern is: `gitea.dooplex.hu//:` ## Step 2: Sync app assets before building The container image includes app logos and screenshots. Sync them from the felhom.eu website repo before building: ```bash # If the website repo is checked out alongside this repo: make sync-assets # Or specify the path explicitly: make sync-assets WEBSITE_ASSETS_DIR=/home/admin/repos/felhom.eu/website/assets # Verify ls assets/*.webp ``` If you skip this step, the dashboard will work but show no app logos/screenshots (the `onerror` handler hides broken images gracefully). ## Step 3: Build for single architecture (quick test) ```bash cd ~/repos/deploy-felhom-compose # Build for your current architecture docker build \ --build-arg VERSION=$(git describe --tags --always 2>/dev/null || echo "0.1.0") \ --build-arg GIT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") \ -t gitea.dooplex.hu/admin/felhom-controller:latest \ -t gitea.dooplex.hu/admin/felhom-controller:0.1.0 \ . # Push docker push gitea.dooplex.hu/admin/felhom-controller:latest docker push gitea.dooplex.hu/admin/felhom-controller:0.1.0 ``` ## Step 4: Build for both architectures (production) You need both amd64 (N100 mini PCs) and arm64 (Raspberry Pi). Use Docker Buildx: ```bash # One-time: Create a buildx builder that supports multi-arch docker buildx create --name felhom-builder --use --bootstrap # Verify it supports the architectures we need docker buildx inspect felhom-builder # Should show: linux/amd64, linux/arm64 in Platforms # Build + push multi-arch image in one step docker buildx build \ --platform linux/amd64,linux/arm64 \ --build-arg VERSION=0.1.0 \ --build-arg GIT_COMMIT=$(git rev-parse --short HEAD) \ -t gitea.dooplex.hu/admin/felhom-controller:latest \ -t gitea.dooplex.hu/admin/felhom-controller:0.1.0 \ --push \ . ``` **Note:** `--push` is required with multi-arch builds because buildx doesn't store multi-platform images in the local Docker cache. It pushes directly to the registry. ### If buildx multi-arch doesn't work (missing QEMU) On Linux you might need QEMU for cross-compilation: ```bash # Install QEMU user-mode emulation sudo apt-get install -y qemu-user-static binfmt-support # Register QEMU with Docker docker run --rm --privileged multiarch/qemu-user-static --reset -p yes # Verify docker buildx ls ``` ### Alternative: Build natively on each architecture If you don't want to cross-compile, build on each machine: ```bash # On the N100 (amd64): docker build -t gitea.dooplex.hu/admin/felhom-controller:latest-amd64 . docker push gitea.dooplex.hu/admin/felhom-controller:latest-amd64 # On the Pi (arm64): docker build -t gitea.dooplex.hu/admin/felhom-controller:latest-arm64 . docker push gitea.dooplex.hu/admin/felhom-controller:latest-arm64 # Then create a manifest list to combine them: docker manifest create gitea.dooplex.hu/admin/felhom-controller:latest \ gitea.dooplex.hu/admin/felhom-controller:latest-amd64 \ gitea.dooplex.hu/admin/felhom-controller:latest-arm64 docker manifest push gitea.dooplex.hu/admin/felhom-controller:latest ``` ## Step 5: Deploy on a customer node On the customer's machine, the docker-compose.yml for the controller references the image from the registry: ```yaml services: felhom-controller: image: gitea.dooplex.hu/admin/felhom-controller:latest # ... ``` Pull and start: ```bash # Login to registry on the customer node (one-time) docker login gitea.dooplex.hu # Start the controller cd /opt/docker/felhom-controller docker compose pull docker compose up -d # Verify docker compose logs -f curl -s http://localhost:8080/api/health ``` ## Step 6: Updating the controller When you release a new version: ```bash # On your build machine: docker buildx build \ --platform linux/amd64,linux/arm64 \ --build-arg VERSION=0.2.0 \ -t gitea.dooplex.hu/admin/felhom-controller:latest \ -t gitea.dooplex.hu/admin/felhom-controller:0.2.0 \ --push . # On the customer node (manually for now; auto-update comes in Phase 5): cd /opt/docker/felhom-controller docker compose pull docker compose up -d ``` ## Makefile shortcuts The Makefile has convenience targets: ```bash make docker-build # Build for current platform make docker-buildx # Build multi-arch + push make docker-push # Push current platform image ``` ## Troubleshooting ### "unauthorized" when pushing ```bash docker logout gitea.dooplex.hu docker login gitea.dooplex.hu ``` ### Gitea registry not accessible Check if Gitea's HTTPS is working and the domain resolves: ```bash curl -v https://gitea.dooplex.hu/v2/ # Should return: {"errors":[{"code":"UNAUTHORIZED",...}]} ``` ### Build fails on arm64 via QEMU (too slow or errors) Cross-compiling Go via QEMU can be slow. Since the Go binary itself is cross-compiled (CGO_ENABLED=0), only the Debian packages in the runtime stage need QEMU. Alternative: build the Go binary natively, then build only the runtime Docker layer via buildx. ### Image too large Expected sizes: - Go binary: ~15-20 MB - Runtime image (debian-slim + docker-cli + restic + pg_dump): ~250-350 MB To reduce: consider Alpine instead of Debian slim, but test pg_dump/mysqldump compatibility first.