Files
nuzlocke-tracker/DEPLOYMENT.md
Julian Tabel 349a0cb821 Add DEPLOYMENT.md as living deployment documentation
Covers architecture overview, Gitea container registry setup, branching
strategy, and deployment workflow. Sections not yet implemented are marked
with TODO to be filled in as the deployment epic progresses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 17:56:06 +01:00

5.0 KiB

Deployment

This document describes the deployment architecture and workflows for the nuzlocke-tracker. It is a living document — sections marked with TODO are planned but not yet implemented.

Architecture Overview

Component Dev (Laptop/PC) Production (Unraid)
API docker-compose.yml (hot reload) docker-compose.prod.yml (built image)
Frontend docker-compose.yml (Vite dev server) docker-compose.prod.yml (built image)
Database PostgreSQL 16 (Docker volume) PostgreSQL 16 (Docker volume)
Container Registry Gitea (user-level packages)
Container Management Portainer CE
Reverse Proxy Nginx Proxy Manager

Services

  • Gitea — self-hosted Git server, container registry, and (future) CI/CD. Accessible at gitea.nerdboden.de via SSL.
  • Portainer — Docker management UI. Accessible at portainer.nerdboden.de via SSL. Manages the production stack and provides webhook-triggered redeployments.
  • Nginx Proxy Manager — reverse proxy with SSL termination for all services on the Unraid server.

Container Registry

Docker images are hosted on Gitea's built-in container registry as user-level packages.

Image naming

Images use the format gitea.nerdboden.de/<user>/<image>:<tag>:

gitea.nerdboden.de/julian/nuzlocke-tracker-api:latest
gitea.nerdboden.de/julian/nuzlocke-tracker-frontend:latest

Authentication

  1. Create a Gitea access token at Settings > Applications with read:package and write:package scopes.
  2. Log in from the dev machine:
    docker login gitea.nerdboden.de
    
    Use your Gitea username and the access token as password.

Pushing images

# Build and tag
docker build -t gitea.nerdboden.de/julian/nuzlocke-tracker-api:latest ./backend
docker build -t gitea.nerdboden.de/julian/nuzlocke-tracker-frontend:latest ./frontend

# Push
docker push gitea.nerdboden.de/julian/nuzlocke-tracker-api:latest
docker push gitea.nerdboden.de/julian/nuzlocke-tracker-frontend:latest

Pushed images are visible under the Packages tab on your Gitea user profile.

Branching Strategy

The project uses a main / develop / feature/* branching model.

Branch Purpose
main Always production-ready. Deploy script builds from here.
develop Integration branch for day-to-day work.
feature/* Short-lived branches off develop for individual features/fixes.

Workflow

  1. Create feature/xyz from develop
  2. Work on the feature, commit, merge into develop
  3. When ready to deploy: merge develop into main
  4. Run the deploy script (see below)

Deploying

TODO — deploy script (./deploy.sh) not yet created.

The deploy script will automate:

  1. Build Docker images from main
  2. Tag and push to the Gitea container registry
  3. Trigger the Portainer webhook to pull new images and restart the stack

Manual deployment

Until the deploy script is in place, deploy manually:

# 1. Ensure you're on main with latest changes
git checkout main

# 2. Build and push images
docker build -t gitea.nerdboden.de/julian/nuzlocke-tracker-api:latest ./backend
docker build -t gitea.nerdboden.de/julian/nuzlocke-tracker-frontend:latest ./frontend
docker push gitea.nerdboden.de/julian/nuzlocke-tracker-api:latest
docker push gitea.nerdboden.de/julian/nuzlocke-tracker-frontend:latest

# 3. On Unraid (or via Portainer): pull and restart
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d

Production Compose

TODOdocker-compose.prod.yml not yet created.

The production compose file will differ from the dev compose in:

  • Uses pre-built images from the Gitea registry (no source volume mounts)
  • No hot reload / debug mode
  • Production environment variables
  • Proper restart policies
  • Frontend served as a static build (not Vite dev server)

Portainer

Portainer CE is running on Unraid at portainer.nerdboden.de.

  • Manages the production Docker stack
  • TODO: Configure a webhook for automated redeployment (pull latest images + restart on trigger)

Nginx Proxy Manager

NPM runs on Unraid and handles SSL termination and routing for:

  • gitea.nerdboden.de → Gitea
  • portainer.nerdboden.de → Portainer
  • TODO: nuzlocke.nerdboden.de (or similar) → nuzlocke-tracker frontend/API

Environment & Secrets

TODO.env.prod template not yet created.

Production environment variables to configure:

  • DATABASE_URL — PostgreSQL connection string
  • DEBUG — must be false in production
  • Additional secrets TBD

Database

PostgreSQL 16 with data stored in a named Docker volume.

  • Migrations run automatically on API container startup (Alembic)
  • TODO: Set up scheduled backups (pg_dump cron job on Unraid)

Rollback

TODO — rollback procedure to be documented once image tagging strategy is finalized.

General approach: tag images with version/commit hash in addition to latest, so rolling back means redeploying a previous tag.