# 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/thefurya/nuzlocke-tracker-api:latest
gitea.nerdboden.de/thefurya/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/thefurya/nuzlocke-tracker-api:latest ./backend
docker build -t gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest ./frontend

# Push
docker push gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest
docker push gitea.nerdboden.de/thefurya/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/thefurya/nuzlocke-tracker-api:latest ./backend
docker build -t gitea.nerdboden.de/thefurya/nuzlocke-tracker-frontend:latest ./frontend
docker push gitea.nerdboden.de/thefurya/nuzlocke-tracker-api:latest
docker push gitea.nerdboden.de/thefurya/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.
