# Gitea K8s Migration Plan (2026-07-13)

Session where the user decided to migrate Gitea from LXC CT108 to RKE2 K8s.

## Current State (CT108)

- Host: proxmox6, LXC container
- Gitea binary (not Docker), SQLite (4.7 MB)
- 23 repos (160 MB), 5 orgs/users (dominik, clawdia, codecamp-n, pm-infra, d.schoen)
- Config: `/etc/gitea/app.ini`, data: `/var/lib/gitea/data/`
- RAM: ~142 MB RSS, Disk: 1.3 GB / 7.8 GB

## Key Decisions

### 1. Galera over CNPG (user-directed)

User instinctively preferred Galera, then asked for evaluation. After
comparison, Galera won decisively:

- HA: Galera has 3 nodes + MaxScale. CNPG plan was 1 instance = no HA.
- Resources: Galera = 0 new. CNPG = 512Mi + 10Gi.
- MySQL is Gitea's native DB — best-tested combination.
- SQLite→MySQL migration via Gitea Migration API (no schema conversion).

### 2. Gitea Migration API over manual SQLite dump

The Gitea Migration API (`POST /api/v1/repos/migrate`) eliminates the
hardest task entirely. One call per repo brings:
- Git data (clone)
- Issues + labels + milestones
- Pull requests
- Releases
- Wiki

No `pgloader`, no `sed` on SQLite dumps, no schema conversion.

### 3. External URL: git.schoen.codes

User specified `git.schoen.codes` as the new external URL (not
`git.familie-schoen.com`).

## Plan Structure (10 Tasks)

1. Create 1Password items (gitea-db, gitea-security)
2. Create database on Galera via MaxScale VIP
3. Scaffold iac-homelab directory structure + ArgoCD app manifest
4. Create ExternalSecrets (DB creds + security tokens)
5. Create Gitea Helm release values (Galera DB, PVC, Ingress)
6. Verify K8s Gitea reachable + DB connected
7. Migrate repos + metadata via Gitea Migration API
8. DNS cutover (git.schoen.codes → K8s LoadBalancer IP)
9. Update ArgoCD source URL (chicken-egg cutover)
10. Shutdown CT108 after 7-day stability window

## Resource Footprint

| Component | CPU req | RAM req | Storage |
|-----------|---------|---------|---------|
| Gitea pod | 100m | 256Mi | 10Gi (HDD) |
| Total | 100m | 256Mi | 10Gi |

Previous (CT108): 1 core, 1 GB RAM, 8 GB disk → K8s footprint smaller.

## iac-homelab Repo Structure

```
clusters/main/
├── apps/gitea.yaml          # ArgoCD Application (sync-wave 2)
├── gitea/
│   ├── namespace.yaml
│   ├── external-secrets.yaml # gitea-db + gitea-security (sync-wave 0)
│   ├── values.yaml           # HelmChart CR (sync-wave 2)
│   └── README.md
└── docs/plans/2026-07-13-gitea-k8s-migration.md
```

## Established Patterns Applied

- ArgoCD App manifest → `clusters/main/apps/{name}.yaml` with sync-waves
- ExternalSecrets → `external-secrets.io/v1`, ClusterSecretStore `onepassword-store`
- StorageClasses: `ceph-flash` (SSD) for DB, `ceph-hdd-replica` (HDD) for repo data
- Traefik ingress with TLS
- `CreateNamespace=true` in ArgoCD syncOptions
