# Gitea & CI/CD Pipeline — SNS Digital

**Entity:** SNS Digital · **Status:** Active (Gitea running on 192.168.122.103)

## What it is

Self-hosted code platform (Gitea) with built-in CI/CD (Gitea Actions) and
KESTRA for complex workflow orchestration. Replaces GitHub/GitLab SaaS entirely.

## Stack

| Component | Software | FOSS | Role |
|-----------|----------|------|------|
| Code hosting | Gitea | Yes | Git repos, issues, PRs, container registry |
| CI/CD (simple) | Gitea Actions | Yes | GitHub Actions-compatible runners |
| CI/CD (complex) | KESTRA | Yes | Orchestration, data pipelines, scheduled workflows |
| Runner | Gitea Act Runner | Yes | Executes workflows (on 192.168.122.22) |
| Artifacts | Gitea Packages | Yes | Built-in package/container registry |
| Secrets | Gitea Secrets + Vaultwarden | Yes | CI secrets in Gitea, master secrets in Vaultwarden |

## Current Topology

```
┌─────────────────────────────┐
│  Gitea (192.168.122.103)    │  ← VM on Proxmox
│  - Git SSH (port 22)        │
│  - Web UI (port 3000)       │
│  - Container registry       │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│  Runner (192.168.122.22)    │  ← Dedicated VM
│  - Gitea Act Runner         │
│  - Docker executor          │
│  - Builds, tests, deploys   │
└─────────────────────────────┘
               │
               ▼
        Deploy targets:
        - Proxmox VMs (rsync/SSH)
        - Docker hosts (docker compose pull)
        - S3 (static assets)
```

## Workflow Patterns

### Simple: Build & Deploy (Gitea Actions)

```yaml
# .gitea/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build
        run: make build
      - name: Deploy
        run: rsync -avz ./dist/ sam@target:/srv/app/
        env:
          SSH_KEY: ${{ secrets.DEPLOY_KEY }}
```

### Complex: Multi-step orchestration (KESTRA)

Use KESTRA when:
- Workflow spans multiple systems (build → deploy → verify → notify)
- Needs scheduling (cron-triggered)
- Has conditional branching or retry logic
- Involves data pipelines

## Git Workflow

- **Branching:** trunk-based for solo work. Feature branches + PR when collaborating.
- **Protection:** `main` branch protected — no force push, require CI pass.
- **Naming:** `feature/`, `fix/`, `infra/` prefixes.
- **Commits:** Conventional commits (`feat:`, `fix:`, `docs:`, `infra:`).

## Build Steps (if setting up fresh)

1. **Gitea VM:**
   ```bash
   # Docker Compose (already running)
   services:
     gitea:
       image: gitea/gitea:latest
       ports: ["3000:3000", "2222:22"]
       volumes: [./gitea-data:/data]
       environment:
         GITEA__database__DB_TYPE: sqlite3
   ```

2. **Runner VM:**
   ```bash
   # Install act_runner
   wget https://gitea.com/gitea/act_runner/releases/latest/act_runner-linux-amd64
   chmod +x act_runner-linux-amd64
   ./act_runner-linux-amd64 register --instance https://gitea.internal.sns --token <TOKEN>
   ./act_runner-linux-amd64 daemon
   ```

3. **KESTRA (when needed):**
   ```yaml
   services:
     kestra:
       image: kestra/kestra:latest
       ports: ["8080:8080"]
       volumes: [./kestra-data:/app/storage]
   ```

4. **SSH access:** Add runner's SSH key to deploy targets' `authorized_keys`.

## Security Posture

- **Gitea access:** Behind Caddy + Authelia for web. SSH via ProxyJump only.
- **Runner isolation:** Dedicated VM, Docker executor (each job gets a fresh container).
- **Secrets:** Never in repos. Use Gitea Secrets for CI, Vaultwarden for everything else.
- **Container registry:** Private by default. No public pulls without explicit config.
- **Audit:** Gitea logs all repo events. Runner logs in Loki.

## Upgrade Path

- **Gitea cluster:** When you need HA or multiple runners for parallel builds.
- **Woodpecker CI:** If Gitea Actions limitations appear (it's younger than the
  alternatives). Drop-in integration with Gitea.
- **Harbor:** Enterprise container registry if Gitea's built-in registry isn't sufficient
  (vulnerability scanning, replication).

<!-- ponytail: SQLite for Gitea until performance degrades (~50 repos, ~5 users).
     Ceiling: SQLite write contention under concurrent CI. Upgrade: PostgreSQL. -->
