# 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//:`: ``` 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: ```bash docker login gitea.nerdboden.de ``` Use your Gitea username and the access token as password. ### Pushing images ```bash # 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: ```bash # 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 > **TODO** — `docker-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.