k8s-and-chill/CLAUDE.md
Felix Wolf c7bfd4953c feat: Wire ArgoCD to Forgejo for GitOps management
Configure myks with global repoURL pointing to Forgejo, in-cluster
destination, and disabled placeholder cluster Secret. Implement App of
Apps pattern with a root Application that syncs all child apps.

Add argocd-deploy-key-init Job that generates an ed25519 SSH keypair,
registers it as a deploy key via Forgejo API, and creates the ArgoCD
repository secret with insecure host key verification (avoids
chicken-and-egg with ArgoCD managing its own known hosts ConfigMap).

Additional changes:
- Ignore /status field diffs globally (K8s 1.32 compat)
- Add Replace=true sync option on Jobs (immutable resource compat)
- Switch job images from bitnami/kubectl to alpine/k8s
- Update CLAUDE.md with ArgoCD status and no-bitnami rule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 23:09:50 +02:00

3.6 KiB

k8s-and-chill

Project Overview

GitOps-managed Kubernetes cluster on Hetzner Cloud running Talos Linux. Uses myks for Helm chart rendering with ytt overlays, targeting ArgoCD for continuous deployment.

Cluster

  • 3 Talos control-plane nodes (CAX11 ARM64, Hetzner Cloud Nuremberg)
  • Node IPs: 195.201.219.111, 195.201.140.75, 195.201.219.17
  • allowSchedulingOnControlPlanes: true (no dedicated workers)
  • All namespaces use pod-security.kubernetes.io/enforce: privileged

Domain & DNS

  • Domain: tr1ceracop.de (registered at INWX)
  • DNS: Managed at INWX with wildcard A record *.tr1ceracop.de pointing to node IPs
  • Forgejo: https://git.tr1ceracop.de
  • ArgoCD: https://argocd.tr1ceracop.de

Deployed Applications

App Namespace Notes
traefik traefik Ingress controller, DaemonSet with hostPort 80/443
cert-manager cert-manager Let's Encrypt HTTP-01 via ClusterIssuer letsencrypt
forgejo forgejo Git server, SQLite, local-path PVC
argocd argocd GitOps controller
local-path-provisioner local-path-storage Default StorageClass, installed via upstream manifest

myks Structure

prototypes/         # Application templates (helm values + ytt overlays)
  argocd/
  traefik/
  cert-manager/
  forgejo/
envs/
  env-data.ytt.yaml           # Global ArgoCD config
  _env/                       # Shared overlays (annotations, secrets)
  production/
    env-data.ytt.yaml          # App list for production
    _apps/{app}/app-data.ytt.yaml  # Per-app overrides
rendered/
  envs/production/{app}/       # kubectl-ready manifests
  argocd/production/           # ArgoCD Application resources
talos/
  controlplane.yaml            # Talos machine config
  talosconfig                  # Talos client config
  kubeconfig                   # Cluster kubeconfig

Prototype Pattern

Each prototype follows this structure:

  • app-data.ytt.yaml — namespace declaration
  • vendir/vendir-data.ytt.yaml — chart name, version, repository URL
  • vendir/base.ytt.yaml — vendir config template (identical across all)
  • helm/{chart}.yaml — Helm values overrides
  • ytt/ns.ytt.yaml — Namespace resource + namespace overlay on all resources

Key Commands

myks render                          # Render all apps
myks render production <app>         # Render single app
kubectl apply -f rendered/envs/production/<app>/ --server-side  # Deploy

Kubeconfig & Talos

export KUBECONFIG=./talos/kubeconfig
export TALOSCONFIG=./talos/talosconfig

Known Issues / TODOs

  • Forgejo admin password: Hardcoded in rendered secrets (r8sA8CPHD9!bt6d). Move to external secret before pushing to git.
  • Namespace race condition: First kubectl apply of a new app often fails because namespace isn't ready. Re-apply once.
  • Traefik DaemonSet updates: Requires updateStrategy.rollingUpdate.maxSurge: 0 because hostPort conflicts prevent surge.
  • Forgejo Ingress API version: Chart renders extensions/v1beta1, fixed via ytt/ingress-fix.ytt.yaml overlay to networking.k8s.io/v1.
  • ArgoCD: Fully wired to Forgejo via App of Apps. Root Application in default project syncs rendered/argocd/production/. Deploy key provisioned automatically by argocd-deploy-key-init Job in forgejo namespace.

Container Images

  • Never use bitnami images. Use alpine/k8s or plain alpine for utility Jobs instead.

Secrets (not in git)

  • cert-manager/letsencrypt-account-key — ACME account key (auto-generated)
  • argocd/argocd-initial-admin-secret — ArgoCD admin password (auto-generated)