Commit Graph
4354 Commits
Author SHA1 Message Date
k.rennerandClaude Opus 4.6 5719e1dca2 fix: Add openssl to rebuild pipeline for talosctl install
ci/woodpecker/manual/rebuild-k8s Pipeline failed
The talosctl install script needs openssl for checksum verification.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 18:18:02 +02:00
k.rennerandClaude Opus 4.6 609d973e2a feat: Add rebuild-k8s pipeline for full cluster rebuild
ci/woodpecker/manual/rebuild-k8s Pipeline failed
Single pipeline that:
1. Replaces all 3 K8s VMs via tofu (with automatic retry for failures)
2. Runs bootstrap.sh (Talos → K8s → FluxCD → infrastructure → apps)

Requires new CI secrets: gitea_token, sops_age_key.
Trigger: woodpecker pipeline create --var "PIPELINE=rebuild-k8s"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 18:02:54 +02:00
k.rennerandClaude Opus 4.6 dcdc2ba652 feat: Deploy iCal Proxy to K8s
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
Stateless Go app from ghcr.io/konairius/ical-proxy:latest.
2 replicas, test ingress at ical-proxy.k.renner.uno.
No DB, no OIDC, no secrets needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 17:09:56 +02:00
k.rennerandClaude Opus 4.6 c1bccf3303 fix: Allow authentik namespace egress to rook-ceph for RGW access
ci/woodpecker/cron/security-scan Pipeline was successful
ci/woodpecker/manual/migrate-authentik-db Pipeline was successful
The restore Job needs to reach the Ceph RGW service in the
rook-ceph namespace to download the backup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 17:11:44 +02:00
k.rennerandClaude Opus 4.6 3e33214c7d fix: Remove empty service annotations from ObjectStore
ci/woodpecker/manual/migrate-authentik-db Pipeline was successful
Null annotations cause CRD validation failure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 17:05:13 +02:00
k.rennerandClaude Opus 4.6 1520ddbd7b fix: Use separate LoadBalancer Service for Ceph RGW
ci/woodpecker/manual/migrate-authentik-db Pipeline was successful
CephObjectStore CRD doesn't support service.type. Create a standalone
LoadBalancer Service targeting the RGW pods instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 16:59:21 +02:00
k.rennerandClaude Opus 4.6 0ea407b584 fix: Set RGW service type to LoadBalancer
ci/woodpecker/manual/migrate-authentik-db Pipeline failed
ClusterIP prevents CI runner from reaching the RGW to upload backups.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 16:47:40 +02:00
k.rennerandClaude Opus 4.6 bf20db86a8 fix: Use repo ID for Woodpecker API, rename Jobs for recreation
ci/woodpecker/manual/migrate-authentik-db Pipeline failed
Woodpecker API uses numeric repo ID (1), not full name path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 16:40:53 +02:00
k.rennerandClaude Opus 4.6 98d3036b9d fix: Improve trigger-backup Job API parsing and error handling
The sed-based JSON parsing failed silently. Use grep+cut instead
and add proper HTTP status code checking and error output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 16:11:23 +02:00
k.rennerandClaude Opus 4.6 82a8b8df40 feat: K8s Job triggers backup pipeline, no bootstrap script involvement
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
ci/woodpecker/cron/security-scan Pipeline was successful
Trigger-backup Job runs in K8s, calls Woodpecker API to start the
backup pipeline with Ceph RGW credentials from the OBC, waits for
completion. Restore Job then downloads from RGW and restores.

FluxCD orchestrates: trigger-backup → restore → Authentik HelmRelease.
Bootstrap script no longer needs woodpecker CLI or S3 credentials.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:14:35 +02:00
k.rennerandClaude Opus 4.6 e514741cc6 fix: Wait for RGW user secret and OBC ConfigMap before backup
ci/woodpecker/manual/migrate-authentik-db Pipeline failed
The CephObjectStoreUser and ObjectBucketClaim take time to
provision after the Object Store is ready. Add explicit waits.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:07:52 +02:00
k.rennerandClaude Opus 4.6 48e1104718 feat: Replace RustFS with Ceph RGW for migration S3 storage
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
RustFS has an open bug (#2505) that loses IAM users on restart.
Use Ceph Object Gateway instead — already have Rook-Ceph running.

- CephObjectStore + CephObjectStoreUser + ObjectBucketClaim
- RGW exposed via Cilium LB at 10.2.40.81
- Restore Job reads credentials from auto-generated OBC secret
- Bootstrap script triggers backup pipeline with RGW credentials
- No manual credential management needed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 21:40:21 +02:00
k.rennerandClaude Opus 4.6 613e1aee90 fix: Use stable MinIO credentials, remove broken MinIO provider
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/run-ansible Pipeline was successful
ci/woodpecker/push/security-scan Pipeline was successful
The MinIO IAM provider doesn't persist users reliably. Use manually
created credentials instead — stable across rebuilds.

Remove aminueza/minio provider, IAM resources, and credential output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 21:12:38 +02:00
k.rennerandClaude Opus 4.6 1feac3627f fix: Update migration S3 credentials after rebuild
ci/woodpecker/manual/migrate-authentik-db Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 18:04:11 +02:00
k.rennerandClaude Opus 4.6 3a862d0f4e fix: Set HOME=/tmp for mc in restore Job init container
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
ci/woodpecker/cron/security-scan Pipeline was successful
minio/mc needs a writable home dir for config. Running as non-root
user 1000 can't write to /.mc.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 12:17:18 +02:00
k.rennerandClaude Opus 4.6 621f52fe6e fix: Rename restore Job to force recreation after security fix
ci/woodpecker/cron/security-scan Pipeline was successful
Completed Jobs are immutable. Rename to v2 to trigger a new run
with the security context fixes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 06:50:28 +02:00
k.rennerandClaude Opus 4.6 bbeb447fed fix: Add security context to restore Job for PodSecurity compliance
Operation not permitted error was caused by missing securityContext.
Add runAsNonRoot, seccompProfile, and drop all capabilities.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 06:44:29 +02:00
k.rennerandClaude Opus 4.6 b8ca17b203 fix: Update migration S3 credentials after VM rebuild
ci/woodpecker/manual/migrate-authentik-db Pipeline was successful
MinIO migration user was recreated with new secret key.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 05:42:46 +02:00
k.rennerandClaude Opus 4.6 d9fa102b01 feat: Split Authentik into DB and app kustomizations
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
authentik-db deploys first: CNPG cluster, restore Job, S3 credentials.
FluxCD waits for the restore Job to complete before deploying authentik
(HelmRelease). This ensures the DB is migrated before Authentik starts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 22:25:50 +02:00
k.rennerandClaude Opus 4.6 4f32b07ef5 feat: Add restore Job to Authentik kustomization for FluxCD
The restore Job runs once via FluxCD, downloads the DB dump from S3,
and restores it into the CNPG cluster. Remove from kustomization
after migration is complete.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 22:21:20 +02:00
k.rennerandClaude Opus 4.6 47d626410e fix: Use minio/mc init container for S3 download in restore Job
Split into init container (minio/mc for S3 download) and main
container (postgres:16 for pg_restore). Shared via emptyDir volume.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 22:19:24 +02:00
k.rennerandClaude Opus 4.6 bd4bc58a2f feat: Add migration S3 credentials secret for DB restore Job
ci/woodpecker/manual/migrate-authentik-db Pipeline was successful
SOPS-encrypted secret with MinIO migration user credentials.
Used by the restore-job.yaml to download the DB dump from S3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 22:04:46 +02:00
k.rennerandClaude Opus 4.6 2e98a0b0b6 feat: Complete S3-based Authentik DB migration
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
Pipeline outputs migration S3 credentials after apply. K8s restore
Job downloads dump from s3://migration/ and pg_restores into CNPG.

Flow:
1. tofu apply creates MinIO migration user (credentials in output)
2. Backup pipeline: Ansible pg_dump → S3
3. Restore Job: S3 → pg_restore to ak-pg-rw
4. Credentials go in SOPS secret (migration-s3-credentials)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 21:57:22 +02:00
k.rennerandClaude Opus 4.6 1f5e278b62 fix: Use built-in readwrite policy for MinIO migration user
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
Custom IAM policy caused provider bug during comparison.
Use MinIO's built-in readwrite policy instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 17:01:16 +02:00
k.rennerandClaude Opus 4.6 fbf87d7028 fix: Use heredoc for MinIO IAM policy
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline failed
MinIO provider expects a JSON string, not jsonencode output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:54:19 +02:00
k.rennerandClaude Opus 4.6 5d43ce1127 fix: Reuse existing RustFS credentials for MinIO provider
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/push/security-scan Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
Use tf_rfs_access/tf_rfs_secret (already in CI secrets) instead of
adding new MinIO-specific secrets. No new env variables needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:45:39 +02:00
k.rennerandClaude Opus 4.6 33d436871a feat: Use MinIO provider for migration S3 credentials
Replace broken AWS IAM resources with aminueza/minio provider.
Creates a dedicated MinIO user with access to the migration bucket.

Requires new Gitea CI secrets: minio_server, minio_user, minio_password.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:44:00 +02:00
k.rennerandClaude Opus 4.6 9cc79c846b feat: Create dedicated S3 credentials for migration bucket
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/push/security-scan Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
IAM user with read/write access to the migration bucket only.
Credentials output as sensitive values for use in K8s secrets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:30:25 +02:00
k.rennerandClaude Opus 4.6 49db7668e1 fix: Simplify restore script using mc in PG pod
Downloads backup from RustFS S3 directly into the CNPG pod using
the MinIO client. No extra pods or complex orchestration needed.
Requires AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY env vars.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:22:51 +02:00
k.rennerandClaude Opus 4.6 1f0e3f54e3 feat: Add migration S3 bucket via OpenTofu
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/migrate-authentik-db Pipeline was successful
ci/woodpecker/push/security-scan Pipeline was successful
Create the migration bucket in RustFS via OpenTofu, not inline in
the pipeline. Remove bucket creation from the Woodpecker step.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:13:44 +02:00
k.rennerandClaude Opus 4.6 55be82fb12 feat: Add Authentik DB migration via backup pipeline + restore script
Backup pipeline (CI): runs pg_dump via Ansible on the old DB server,
uploads dump to s3://migration/ bucket in RustFS. No extra secrets needed.

Restore script (workstation): downloads from S3, copies into K8s
CNPG pod, runs pg_restore. Uses local kubectl and aws-cli.

Preserves all users, passwords, 2FA, WebAuthn, and sessions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:12:31 +02:00
k.rennerandClaude Opus 4.6 aff2f49ad0 fix: Split Authentik DB migration into backup pipeline + restore script
Backup pipeline (CI): runs pg_dump via Ansible on the old DB server,
uploads dump to RustFS S3. No kubeconfig secret needed.

Restore script (workstation): downloads from S3, copies into K8s
CNPG pod, runs pg_restore. Uses local kubectl.

Preserves all users, passwords, 2FA, WebAuthn, and sessions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:09:44 +02:00
k.rennerandClaude Opus 4.6 ba358e48dc feat: Add Authentik DB migration pipeline
Two-step pipeline:
1. Ansible playbook dumps the old Authentik PostgreSQL via pg_dump
2. kubectl restores the dump into the K8s CloudNativePG cluster

Preserves all users, passwords, 2FA devices, sessions, and config.
Requires kubeconfig_b64 secret in Gitea for K8s access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 15:56:01 +02:00
k.rennerandClaude Opus 4.6 115e23c746 revert: Remove externalTrafficPolicy Local from ingress-nginx
ci/woodpecker/cron/security-scan Pipeline was successful
Was added to try to fix ICMP on LB VIP, but that's a Cilium L2
limitation unrelated to traffic policy. Revert to default.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:50:11 +02:00
k.rennerandClaude Opus 4.6 0711edab24 fix: Enable externalTrafficPolicy Local for ICMP on LB VIP
Cilium L2 announced VIPs only forward service ports by default.
externalTrafficPolicy: Local makes the VIP a local address on the
node so the kernel responds to ICMP echo requests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:45:46 +02:00
k.rennerandClaude Opus 4.6 c93bb600c2 feat: Enable IPv6 in Cilium CNI for dual-stack L2 announcements
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
Enable IPv6 in both the Talos inline Cilium manifest and the FluxCD
HelmRelease. Required for Cilium to announce IPv6 LB VIPs via NDP.

Requires cluster rebuild to apply Talos patch changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 10:16:17 +02:00
k.rennerandClaude Opus 4.6 08c1957eaa fix: Extend IPv6 LB pool to include fd40::80
fd40::80 was outside the pool range (fd40::40-fd40::5f).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 10:11:52 +02:00
k.rennerandClaude Opus 4.6 a8bc603be6 feat: Assign dual-stack LB IPs to ingress-nginx via Cilium IPAM
Use io.cilium/lb-ipam-ips annotation to request both IPv4 (10.2.40.80)
and IPv6 ULA (fd40::80) for the ingress LoadBalancer service.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 10:09:47 +02:00
k.rennerandClaude Opus 4.6 ba63ee43ab fix: Use space-separated format for TOFU_IMPORT
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
Format: "resource id" per line (space-separated), not "resource=id".
Avoids IFS conflicts with resource addresses containing dots.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 09:34:48 +02:00
k.rennerandClaude Opus 4.6 72fb44ee05 feat: Add TOFU_IMPORT support to infrastructure pipeline
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
Allows importing existing Proxmox resources into tofu state before
plan/apply. Usage: --var "TOFU_IMPORT=resource=id" (newline-separated).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 09:31:28 +02:00
k.rennerandClaude Opus 4.6 5ad30113af feat: Enable IPv6 dual-stack for K8s cluster and ingress
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
- Add IPv6 pod/service subnets (ULA fd10:244::/48, fd10:96::/112)
- Add IPv6 ULA range to Cilium LB IP pool (fd40::40-fd40::5f)
- Enable PreferDualStack on ingress-nginx service

Requires cluster rebuild to apply Talos config changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 09:22:47 +02:00
k.rennerandClaude Opus 4.6 e13f365d54 fix: Handle empty API responses in migration script, fix bootstrap
- set_password endpoint returns empty body on success
- Remove --silent flag from flux bootstrap (unsupported)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 09:14:11 +02:00
k.rennerandClaude Opus 4.6 b09241fca2 chore: Trigger K8s VM recreation after talosctl reset
ci/woodpecker/push/security-scan Pipeline was successful
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/cron/update-all Pipeline failed
ci/woodpecker/cron/security-scan Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
VMs stuck in UEFI after disk wipe. Need to be recreated via CI
with TOFU_REPLACE for module.k8s_1, module.k8s_2, module.k8s_3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 15:53:40 +02:00
k.rennerandClaude Opus 4.6 0058b785f6 feat: Add Authentik wait step to bootstrap, add migration script
Bootstrap now waits for the authentik kustomization after apps.
Include the Authentik API migration script for post-bootstrap setup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 15:44:37 +02:00
k.rennerandClaude Opus 4.6 fc4b7be969 fix: Use internal service URL for Grafana OAuth token/userinfo
ci/woodpecker/cron/security-scan Pipeline was successful
auth_url stays external (browser redirect), but token_url and api_url
use the cluster-internal authentik-server service for server-to-server
OAuth calls from the monitoring namespace.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 12:02:50 +02:00
k.rennerandClaude Opus 4.6 38a48d13c3 fix: Allow ingress-nginx to reach monitoring namespace
Grafana in the monitoring namespace was unreachable via ingress
because the nginx egress policy didn't include that namespace.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 10:37:09 +02:00
k.rennerandClaude Opus 4.6 8191c60865 fix: Remove Recreate strategy, keep RollingUpdate for Grafana
The chart template sets rollingUpdate params that conflict with Recreate.
RollingUpdate works fine with replicas=1 since the PVC detach race
was a one-time issue during the initial config change.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 10:18:05 +02:00
k.rennerandClaude Opus 4.6 1c78f3adc4 fix: Clear rollingUpdate when using Recreate strategy for Grafana
K8s rejects Recreate strategy when rollingUpdate params are also set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 10:12:11 +02:00
k.rennerandClaude Opus 4.6 376a02c404 fix: Use test domain dash.k.renner.uno for K8s Grafana
K8s services must use *.k.renner.uno for testing before DNS cutover.
dash.renner.uno stays on the old infrastructure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 10:06:13 +02:00
k.rennerandClaude Opus 4.6 fb76be5c39 fix: Use Recreate strategy for Grafana with RWO storage
RWO PVC can't attach to two pods simultaneously, so rolling updates
get stuck waiting for the volume. Recreate terminates old pod first.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 09:59:43 +02:00