Store PostgreSQL data at ./data/postgres relative to the compose file so persistent data lives on the Unraid disk at /mnt/user/appdata/nuzlocke-tracker/data/postgres. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
60 lines
4.9 KiB
Markdown
60 lines
4.9 KiB
Markdown
---
|
|
# nuzlocke-tracker-ahza
|
|
title: Deployment Strategy
|
|
status: in-progress
|
|
type: epic
|
|
priority: normal
|
|
created_at: 2026-02-09T14:03:53Z
|
|
updated_at: 2026-02-10T08:16:36Z
|
|
---
|
|
|
|
Define and implement a deployment strategy for running the nuzlocke-tracker in production on a local Unraid server while keeping laptop/PC as the development environment.
|
|
|
|
## Context
|
|
|
|
- **Components:** API (Python/FastAPI), Frontend (Vite/React), PostgreSQL database
|
|
- **Dev environment:** Laptop/PC — continue using the existing `docker-compose.yml` for local development
|
|
- **Production host:** Unraid server running Docker containers
|
|
- **Networking:** LAN-only access, Nginx Proxy Manager already in place on Unraid
|
|
- **Orchestration:** Docker Compose for production (matching dev workflow). Install Portainer for container management and semi-automated deployments.
|
|
|
|
## Decided Approach
|
|
|
|
**Docker Compose + Portainer + Gitea (source hosting, container registry, CI/CD)**
|
|
|
|
1. **Gitea** runs on Unraid behind Nginx Proxy Manager with SSL (e.g., `gitea.nerdboden.de`). It serves as the self-hosted Git remote, container registry, and (optionally) CI/CD via Gitea Actions.
|
|
2. **Images are built on the dev machine** and pushed to Gitea's container registry as **user-level packages** (e.g., `gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest`, `gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest`).
|
|
3. **Production runs docker-compose** on Unraid, pulling images from the Gitea container registry instead of mounting source.
|
|
4. **Portainer** is installed on Unraid to manage stacks, provide a web UI, and enable webhook-triggered redeployments.
|
|
5. **A deploy script** on the dev machine automates the full flow: build images → push to Gitea registry → trigger Portainer webhook to redeploy.
|
|
6. **Nginx Proxy Manager** handles routing on the LAN (e.g., `nuzlocke.nerdboden.de` → frontend container, `gitea.nerdboden.de` → Gitea).
|
|
7. **Database** uses a bind mount (`./data/postgres`) for persistence on the Unraid disk; migrations run automatically on API container startup. The compose file lives at `/mnt/user/appdata/nuzlocke-tracker/`, so all persistent data is stored in subfolders there.
|
|
|
|
## Branching Strategy
|
|
|
|
**`main` + `develop` + feature branches**
|
|
|
|
- **`main`** — always production-ready. Only receives merges from `develop` when ready to deploy. The deploy script builds from `main`.
|
|
- **`develop`** — integration branch for day-to-day work. Features are merged here and tested before promoting to `main`.
|
|
- **`feature/*`** — short-lived branches off `develop` for individual features/fixes. Merged back into `develop` via PR or direct merge when complete.
|
|
|
|
**Workflow:**
|
|
1. Create `feature/xyz` from `develop`
|
|
2. Work on the feature, commit, merge into `develop`
|
|
3. When ready to deploy: merge `develop` → `main`
|
|
4. Run `./deploy.sh` (builds from `main`, pushes to Gitea registry, triggers Portainer webhook)
|
|
|
|
## Checklist
|
|
|
|
- [ ] **Set up branching structure** — create `develop` branch from `main`, establish the `main`/`develop`/`feature/*` workflow
|
|
- [ ] **Update CLAUDE.md with branching rules** — once the branching structure is in place, add instructions to CLAUDE.md that the branching strategy must be adhered to (always work on feature branches, never commit directly to `main`, merge flow is `feature/*` → `develop` → `main`)
|
|
- [ ] **Configure Gitea container registry** — create an access token with `read:package` and `write:package` scopes, verify `docker login gitea.nerdboden.de` works, test pushing and pulling an image as a user-level package
|
|
- [x] **Create production docker-compose file** (`docker-compose.prod.yml`) — uses images from the Gitea container registry, production env vars, no source volume mounts, proper restart policies
|
|
- [x] **Create production Dockerfiles (or multi-stage builds)** — ensure frontend is built and served statically (e.g., via the API or a lightweight nginx container), API runs without debug mode
|
|
- [x] **Set up Portainer on Unraid** — install Portainer CE as a Docker container, configure the stack from the production compose file
|
|
- [x] **Configure Portainer API for automated redeployment** — deploy script uses Portainer CE REST API to pull latest images and restart the stack
|
|
- [x] **Create deploy script** — `./deploy.sh` builds images, pushes to Gitea registry, triggers Portainer API redeployment
|
|
- [ ] **Configure Nginx Proxy Manager** — add proxy host entries for Gitea and the nuzlocke-tracker frontend/API on the appropriate ports
|
|
- [ ] **Environment & secrets management** — create a `.env.prod` template, document required variables, decide on secret handling (`.env` file on Unraid, Portainer env vars, etc.)
|
|
- [ ] **Database backup strategy** — set up a simple scheduled backup for the PostgreSQL volume/data (e.g., cron + `pg_dump` script on Unraid)
|
|
- [ ] **Document the deployment workflow** — README or docs covering how to deploy, redeploy, rollback, and manage the production instance |