GITEA__OAUTH2__JWT_SECRET must base64url-decode to 32 bytes. The size-32 claim decoded to 24 bytes, so 1.27 rejected it and generated its own key on each boot; since app.ini lives on an emptyDir that regenerated every restart and logged out all OAuth2 clients. size 43 decodes to 32 bytes, so the rotated key is accepted and stays stable across restarts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
k-space.ee infrastructure
Kubernetes manifests, Ansible playbooks, and documentation for K-SPACE services.
- Repo is deployed with ArgoCD. For
kubectlaccess, see CLUSTER.md. - Debugging Kubernetes on Wiki
- Need help? →
#kube
Jump to docs: inventory-app / cameras / doors / list of apps // all infra / network / retro / non-infra
Tip: Search the repo for kind: xyz for examples.
Supporting services
- Build Git repositories with Woodpecker1 .
- Passmower: Authz with
kind: OIDCClient(orkind: OIDCMiddlewareClient2 ). - Traefik3 : Expose services with
kind: Service+kind: Ingress(TLS and DNS included).
Additional
- bind: Manage additional DNS records with
kind: DNSEndpoint. - Prometheus: Collect metrics with
kind: PodMonitor(alerts withkind: PrometheusRule). - Slack bots and Kubernetes CLUSTER.md itself.
Network
All nodes are in Infra VLAN 21. Routing is implemented with BGP, all nodes and the router make a full-mesh. Both Serice LB IPs and Pod IPs are advertised to the router. Router does NAT for outbound pod traffic. See the Calico installation for Kube side and Routing / BGP in the router. Static routes for 193.40.103.36/30 have been added in pve nodes to make them communicating with Passmower via Traefik more stable - otherwise packets coming back to the PVE are routed directly via VLAN 21 internal IPs by the worker nodes, breaking TCP.
Regenerate networkpolicy-base.yml
It's quite odd there is no better way to generate these.
regenerate-networkpolicy-base.sh
Databases / -stores:
- Dragonfly:
kind: Dragonfly(replaces Redis4 ) - External (hyperconverged Proxmox) Rook/Ceph:
rook-ceph/storage-classes.yaml(filesystem storage)5 - Mongo6 :
kind: MongoDBCommunity(NAS*inventory-mongodb) - Garage S37 : buckets/credentials created with CLI and usually stored in secretspace/kube #TODO: link to docs, kube claim instead?
- MariaDB*: search for
mysql,mariadb8 (replaces MySQL) - Postgres*: hardcoded to harbor/application.yml
- Seeded secrets:
kind: SecretClaim(generates random secret in templated format) - Secrets in git: https://git.k-space.ee/secretspace (members personal info, API credentials, see argocd/deploy_key.pub comment)
This page is referenced by wiki front page as the technical documentation for infra.
-
Replaces Drone CI. ↩︎
-
Applications should use OpenID Connect (
kind: OIDCClient) for authentication, whereever possible. If not possible, usekind: OIDCMiddlewareClientclient, which will provide authentication via a Traefik middleware (traefik.ingress.kubernetes.io/router.middlewares: passmower-proxmox@kubernetescrd). Sometimes you might use both for extra security. ↩︎ -
No nginx annotations! Use
kind: Ingressinstead.IngressRouteis not used as it doesn't supportexternal-dnsout of the box. ↩︎ -
Redis has been replaced as redis-operatori couldn't handle itself: didn't reconcile after reboots, master URI was empty, and clients complained about missing masters. Dragonfly replaces KeyDB. ↩︎
-
Replaces Longhorn and proxmox-csi. ↩︎
-
Mongo problems: Incompatible with rawfile csi (wiredtiger.wt corrupts), complicated resizing (PVCs from statefulset PVC template). ↩︎
-
Replaces Minio S3. ↩︎
-
As of 2024-07-30 used by auth, authelia, bitwarden, etherpad, freescout, git, grafana, nextcloud, wiki, woodpecker ↩︎