Commit Graph
616 Commits
Author SHA1 Message Date
k.rennerandClaude Opus 4.6 5ee87e8a09 fix: Make CrowdSec bouncer optional for ingress-nginx startup
- Add optional: true to secretKeyRef so ingress pods start without
  the bouncer key (CrowdSec deploys after infrastructure)
- Move ingress bouncer SealedSecret to crowdsec app (creates in
  ingress namespace when CrowdSec deploys)
- Ingress starts without CrowdSec, bouncer activates after secret appears

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 09:42:17 +02:00
k.rennerandClaude Opus 4.6 bda07b0705 fix: Move ingress bouncer SealedSecret to post-crds stage
SealedSecret CRD doesn't exist when infrastructure kustomization
first applies. Move to post-crds which depends on infrastructure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 09:35:14 +02:00
k.rennerandClaude Opus 4.6 d7587ed2a4 fix: Use SealedSecrets for CrowdSec bouncer API key
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
ci/woodpecker/cron/update-all Pipeline failed
Replace hardcoded bouncer key with SealedSecrets in both crowdsec
and ingress namespaces. CrowdSec LAPI pre-registers the bouncer
via BOUNCER_KEY_ingress env var, ingress-nginx reads the same key
from its namespace's secret.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 23:32:22 +02:00
k.rennerandClaude Opus 4.6 fe429bf60f test: Set CrowdSec bouncer API key (temporary, needs proper secret management)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 23:27:42 +02:00
k.rennerandClaude Opus 4.6 319ad82d7a fix: Move CrowdSec to dedicated privileged namespace
CrowdSec agents need hostPath volumes to read container logs, which
requires a privileged PodSecurity namespace. Move from apps to
dedicated crowdsec namespace.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 23:20:09 +02:00
k.rennerandClaude Opus 4.6 2b1897161b fix: Use Docker Hub for CrowdSec controller image
The crowdsecurity/controller image is on Docker Hub, not GHCR.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 21:27:14 +02:00
k.rennerandClaude Opus 4.6 419ba5a225 feat: Deploy CrowdSec with ingress-nginx bouncer
- Add CrowdSec Helm chart (LAPI + agent) in apps/crowdsec/
- Agent monitors ingress-nginx and app pod logs
- Collections: nginx, http-cve, appsec-virtual-patching, appsec-generic-rules
- Switch ingress-nginx to CrowdSec controller image (v1.13.2) with
  Lua bouncer plugin for request-level threat blocking
- LAPI data persisted on ceph-block

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 21:19:25 +02:00
k.rennerandClaude Opus 4.6 c3b4cc2ef0 feat: Add Cloudflare API token SealedSecret for cert-manager
Add encrypted Cloudflare DNS API token for Let's Encrypt DNS-01
challenges. Set ACME account email on ClusterIssuers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 21:03:19 +02:00
k.rennerandClaude Opus 4.6 4d01ce2718 fix: Include L2 announcements in Talos Cilium inline manifest
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
Add l2announcements.enabled and externalIPs.enabled to the Cilium
helm template used for Talos bootstrap. This ensures LoadBalancer
VIPs work immediately without needing a Cilium agent restart after
FluxCD upgrades the HelmRelease.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 20:29:54 +02:00
k.rennerandClaude Opus 4.6 b14ab6cc6c feat: Replace MetalLB with Cilium L2 announcements
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
Cilium with kubeProxyReplacement=true has native LoadBalancer support
with L2 announcements. MetalLB L2 VIPs weren't reachable because
Cilium was handling the service datapath.

- Enable l2announcements and externalIPs in Cilium HelmRelease
- Add CiliumLoadBalancerIPPool (10.2.40.64-95) and L2AnnouncementPolicy
- Remove MetalLB from infrastructure
- Remove MetalLB annotation from ingress-nginx service

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 19:53:50 +02:00
k.rennerandClaude Opus 4.6 db35c6d462 feat: Deploy Gatus status monitor to K8s
First app migration to Kubernetes. Gatus monitors all homelab services
via HTTP/TCP/DNS health checks. Deployed as a Deployment with ConfigMap
for endpoints config, 1Gi ceph-block PVC for SQLite, and Ingress on
status.renner.uno with cert-manager TLS.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 19:44:20 +02:00
k.rennerandClaude Opus 4.6 ff83cf5027 docs: Add K8s bootstrap documentation
- kubernetes/README.md: Complete bootstrap procedure, architecture,
  directory structure, known gotchas, and rebuild instructions
- CLAUDE.md: Add Kubernetes layer section, update overview to reflect
  K8s migration

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 19:41:20 +02:00
k.rennerandClaude Opus 4.6 367023e533 feat: Embed Cilium CNI in Talos bootstrap config
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
- Add cilium-cni.yaml patch that disables flannel/kube-proxy and
  includes Cilium 1.19.2 as an inline manifest
- Cilium installs during Talos bootstrap, no manual helm install needed
- Add certSANs for FQDNs to all node patches

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 19:13:10 +02:00
Flux 2470517521 Add Flux sync manifests 2026-04-04 18:58:58 +02:00
k.rennerandClaude Opus 4.6 8e8671cf70 fix: Use gitea@ SSH user for FluxCD
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 18:09:41 +02:00
Flux 60fa072381 Add Flux sync manifests 2026-04-04 18:03:20 +02:00
k.rennerandClaude Opus 4.6 fb580c616c fix: Set 32G boot disk size alongside Talos file_id
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/push/security-scan Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
The raw image is only ~8.6GB, leaving too little ephemeral storage
for Kubernetes pods. Specifying size=32G tells the provider to expand
the disk after importing the image.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 17:28:24 +02:00
k.rennerandClaude Opus 4.6 9e7f29e0f5 fix: Use gitea@ SSH user for FluxCD git source
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 16:59:12 +02:00
Flux a04782d376 Add Flux sync manifests 2026-04-04 16:52:37 +02:00
k.rennerandClaude Opus 4.6 cea5265c3d fix: Re-enable QEMU guest agent for K8s VMs
ci/woodpecker/push/security-scan Pipeline was successful
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
The custom Talos schematic includes qemu-guest-agent. The agent is
needed for Proxmox DNS to discover VM IPs via the API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 16:09:21 +02:00
k.rennerandClaude Opus 4.6 ba064c12d6 fix: Use file_id for Talos disk import via provider, remove SSH hacks
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/push/security-scan Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
Revert to using the BPG provider's native file_id disk import.
The provider SSH is configured via variable for qm importdisk.
Remove all SSH-based import steps from the CI pipeline.
Images are already downloaded to local:import/ on all nodes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 15:58:33 +02:00
k.rennerandClaude Opus 4.6 3388075a0a fix: Use function-based Talos import to avoid Woodpecker variable escaping
Woodpecker mangles parameter expansion in multi-line scripts. Use a
shell function with explicit arguments instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 15:55:42 +02:00
k.rennerandClaude Opus 4.6 f37f1f173a fix: Create K8s VMs stopped, let CI handle disk import and start
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline was successful
ci/woodpecker/push/security-scan Pipeline was successful
Tofu creates VMs with empty disks in stopped state. The CI post-apply
step imports the Talos disk image via qm importdisk over SSH and
starts the VMs. Avoids Install storage reference on VM start.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 15:53:06 +02:00
k.rennerandClaude Opus 4.6 430d4a2e5d fix: Import Talos disk via SSH instead of broken provider file_id
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline failed
The BPG provider's file_id disk import fails on this Proxmox version
with 'unable to parse volume ID' errors. Instead:
- Create VMs with empty 32G boot disks
- Post-apply CI step imports Talos image via qm importdisk over SSH
- Skips import if disk is already populated

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 15:49:02 +02:00
k.rennerandClaude Opus 4.6 d1a4996982 fix: Don't set disk size when importing from file_id
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline was successful
When a disk is imported from a file_id, the size comes from the image.
Setting both size and file_id causes the provider to fail with an
invalid volume ID error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 15:41:47 +02:00
k.rennerandClaude Opus 4.6 1e93703a1a fix: Pass SSH key as variable for BPG provider disk import
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline failed
The provider needs SSH access for qm importdisk. Pass the CI SSH key
as a tofu variable instead of reading from file (file doesn't exist
during plan step).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 15:36:49 +02:00
k.rennerandClaude Opus 4.6 2ff7e9ca2d fix: Configure SSH key for BPG Proxmox provider
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline failed
The provider needs SSH access to Proxmox nodes to import disk images
via qm importdisk. Use the CI-provisioned SSH key.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 15:34:40 +02:00
k.rennerandClaude Opus 4.6 98e1e0d9c1 fix: Add curl to apply step dependencies
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
Needed for Proxmox API calls to download Talos image.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 15:19:09 +02:00
k.rennerandClaude Opus 4.6 70a934d45a feat: Download Talos image via Proxmox API in CI pipeline
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline failed
Remove download_file resource (times out with hardcoded provider limit).
Instead, download the Talos raw image directly via the Proxmox API
download-url endpoint in the CI pipeline before tofu apply runs.
The image is stored on local storage with import content type.
Skips download if image already exists on the node.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 15:16:53 +02:00
k.rennerandClaude Opus 4.6 845d7cefbc fix: Remove unsupported timeouts block from download_file
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/cron/security-scan Pipeline was successful
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 13:38:03 +02:00
k.rennerandClaude Opus 4.6 6ac258e7a4 fix: Add 30m timeout for Talos image download
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline was successful
The 1.3GB raw image download was timing out with the default timeout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 13:32:14 +02:00
k.rennerandClaude Opus 4.6 b288afae2a fix: Download uncompressed Talos raw image
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/push/security-scan Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
Proxmox doesn't support decompression for import content type.
Use the uncompressed .raw URL from Talos factory instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 13:14:27 +02:00
k.rennerandClaude Opus 4.6 201a4e158b fix: Use .raw extension for Talos disk image filename
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline failed
Proxmox requires .raw extension for import content type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 13:10:28 +02:00
k.rennerandClaude Opus 4.6 5b34d32938 fix: Use import content type for Talos disk image on local storage
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline failed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 13:07:38 +02:00
k.rennerandClaude Opus 4.6 7427e63652 fix: Use iso content type on local storage for Talos image
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/push/security-scan Pipeline failed
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
local storage doesn't support 'import' content type. Store the raw
disk image as 'iso' content type — Proxmox accepts any file in the
ISO directory. The VM disk file_id will import from it correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 13:06:15 +02:00
k.rennerandClaude Opus 4.6 4240f20254 fix: Use local storage for Talos image download
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline failed
local-zfs is a ZFS pool (not file-based), can't upload files to it.
Use local storage with import content type instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 13:03:21 +02:00
k.rennerandClaude Opus 4.6 bef79e8bd1 fix: Use content_type 'import' for Talos disk image
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline failed
Provider only accepts 'iso', 'vztmpl', or 'import'. Raw disk images
use 'import' content type on local-zfs storage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 12:59:27 +02:00
k.rennerandClaude Opus 4.6 63ce43076f fix: Store Talos disk image on local-zfs as images content type
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline failed
Raw disk images belong on disk storage (local-zfs) with content_type
'images', not on ISO storage. Eliminates dependency on Install NFS.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 12:55:20 +02:00
k.rennerandClaude Opus 4.6 bc6e20065a fix: Use Install storage for Talos image download
ci/woodpecker/push/deploy-infrastructure Pipeline was successful
ci/woodpecker/push/security-scan Pipeline was successful
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
The local storage doesn't accept ISO content type. Use the Install NFS
storage which is configured for ISO content across all nodes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 12:47:05 +02:00
k.rennerandClaude Opus 4.6 05dfd0a467 feat: Add TOFU_STATE_RM variable to deploy pipeline
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
Allows removing orphaned resources from state before plan/apply.
Needed when VMs are destroyed outside tofu (e.g. broken storage)
and state references non-existent resources.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 12:43:52 +02:00
k.rennerandClaude Opus 4.6 7c38010d00 fix: Use zst compression for Talos image download
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline failed
BPG provider only supports gz/lzo/zst/bz2 decompression, not xz.
Switch to the .raw.zst variant from Talos factory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 12:39:21 +02:00
k.rennerandClaude Opus 4.6 36476822f5 feat: Download Talos image from factory, boot VMs from disk
ci/woodpecker/push/deploy-infrastructure Pipeline failed
ci/woodpecker/push/security-scan Pipeline failed
Replace NFS ISO dependency with proxmox_virtual_environment_download_file
that pulls the Talos nocloud image directly from factory.talos.dev to
each Proxmox node's local storage. VMs boot from the raw disk image
instead of CDROM, eliminating the Install NFS storage dependency.

- Add talos_image.tf with download_file resource per node
- Add file_id support to proxmox_vm module disk config
- Remove CDROM from K8s VM definitions
- Boot order changed to virtio0 only

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 12:36:43 +02:00
k.rennerandClaude Opus 4.6 e0629347db fix: Disable CloudNativePG PodMonitor until Prometheus CRDs exist
ci/woodpecker/manual/deploy-infrastructure Pipeline failed
PodMonitor CRD requires kube-prometheus-stack which isn't installed yet.
Disable monitoring for now, re-enable after monitoring stack is deployed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 11:54:27 +02:00
k.rennerandClaude Opus 4.6 93b1d0c171 fix: Move MetalLB IPAddressPool to post-crds stage
IPAddressPool CRD is installed by MetalLB HelmRelease, so the
IPAddressPool resource must be in the post-crds stage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 11:50:23 +02:00
k.rennerandClaude Opus 4.6 46358b722e fix: Split infrastructure into stages for CRD dependency ordering
FluxCD dry-run fails when CRD-dependent resources (ClusterIssuer,
CephCluster) are in the same Kustomization as the HelmReleases that
install those CRDs. Split into 3 stages:

1. infrastructure/ - namespaces, HelmReleases (installs CRDs)
2. post-crds/ - ClusterIssuer (needs cert-manager CRDs)
3. rook-ceph-cluster/ - CephCluster, StorageClasses (needs Rook CRDs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 11:47:55 +02:00
k.rennerandClaude Opus 4.6 400ea17c9d fix: Fix FluxCD bootstrap - SSH user and Ceph dependency ordering
- Change FluxCD git URL from git@ to gitea@ (Gitea uses 'gitea' user)
- Split Rook-Ceph into operator (infrastructure/) and cluster
  (rook-ceph-cluster/) with FluxCD dependency ordering so CRDs exist
  before CephCluster and StorageClass resources are applied

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 11:45:05 +02:00
Flux 48a3ef6c31 Add Flux sync manifests 2026-04-04 11:34:25 +02:00
Flux 32b644b843 Add Flux sync manifests 2026-04-04 11:28:45 +02:00
Flux 92e3ebb70d Add Flux sync manifests 2026-04-04 11:22:12 +02:00
Flux 2c635f5c8d Add Flux v2.8.3 component manifests 2026-04-04 11:22:10 +02:00