Commit Graph

35 Commits

Author SHA1 Message Date
will.anderson 0006380c27 route runner build container clones via public URL with CF Access (#7) 2026-05-04 21:37:53 +00:00
will.anderson cbb564ccf5 revert(ci): runner public URL — CF Access blocks registration (#4) 2026-05-04 21:05:29 +00:00
will.anderson be0508037a fix(dharma): drop letsencrypt certResolver from IngressRoute 2026-05-04 20:56:29 +00:00
will.anderson 6f5d041440 fix(ci): point Gitea Actions runners at public instance URL 2026-05-04 20:56:26 +00:00
Will Anderson 4754c69e01 fix: mount /var/run/docker.sock (Docker Engine) not containerd socket 2026-05-04 14:10:25 -05:00
Will Anderson 0444d265b9 fix: gitea runner docker_host path mismatch — use /var/run/docker.sock
The containerd socket is mounted from the host at /run/k3s/containerd/containerd.sock
to /var/run/docker.sock inside the container, but act_runner config was pointing to
the host path directly. Fixes CrashLoopBackOff on all runner pods.

Also codifies both deployments (will org + neuron-technologies org) as git-managed
manifests so Argo CD owns them going forward.
2026-05-04 13:44:46 -05:00
Will Anderson 44faf74b61 fix CI runner secrets: correct Gitea URL and use Vault-backed tokens
The ExternalSecret had a stale Gitea URL (192.168.8.148:30322 — old
local IP) and runner tokens were never populated in Vault. Update the
template URL to the cluster-internal Gitea service DNS, and store the
registration tokens in Vault at secret/gitea.runner_token.
2026-05-04 11:07:43 -05:00
Will Anderson 2550786965 Revert CI to host Docker socket, remove buildkitd
BuildKit rootless failed on k3s (mount propagation), privileged mode
fixed that but buildkitd gRPC is incompatible with the Docker REST API
that forgejo-runner needs to manage job containers. Net security change
vs. the original socket approach was zero (privileged ≈ socket access).

Remove buildkitd.yaml entirely. Restore docker-sock hostPath mount on
both runners. Builds work again.
2026-04-26 02:50:27 -05:00
Will Anderson ffac2161bc Use TCP readiness probe for BuildKit — exec fails on k3s privileged containers 2026-04-26 01:23:52 -05:00
Will Anderson 6e67f62ffe Switch BuildKit to privileged mode — rootless fails on k3s mount propagation 2026-04-26 01:20:45 -05:00
Will Anderson e138c45d51 Fix BuildKit rootless: allow privilege escalation for newuidmap/newgidmap 2026-04-26 01:17:41 -05:00
Will Anderson 93358505fc Harden prod: security, autoscaling, observability, BuildKit CI
Security:
- Drop ALL capabilities, enforce non-root, RuntimeDefault seccomp on
  neuron-mcp, neuron-rest, neuron-marketing pods
- Add startup probes (150s window for JVM) so liveness doesn't fire early
- Replace docker-sock hostPath with BuildKit rootless TCP endpoint
  (moby/buildkit:v0.19.0-rootless) — removes node root access from CI
- Document full ESO AppRole migration path in cluster-secret-store.yaml

Autoscaling & availability:
- HPAs on mcp (1–6), rest (1–4), marketing (2–8) at 65–70% CPU
- PodDisruptionBudgets (minAvailable: 1) on all three services
- NetworkPolicy: default-deny-all in neuron-prod, explicit allow rules
  for Traefik ingress, intra-namespace, and egress to DNS/platform/vault

Observability:
- ServiceMonitors for mcp, rest, marketing (cross-namespace enabled in
  kube-prometheus-stack with serviceMonitorSelectorNilUsesHelmValues:false)
- PrometheusRules: high error rate, high latency, crash loops, replica
  shortage, Postgres down/connections, backup failure, backup staleness

Chart version pinning:
- kube-prometheus-stack, loki, tempo, redis, alloy, postgres — all pinned
  to major-version ranges to block silent breaking upgrades

Backup hardening:
- restic:latest → restic:0.17.3 (deterministic image)
- Weekly backup-verify CronJob: restores latest snapshot and validates
  SQL dump structure (≥5 CREATE TABLE, pg_dump header check)

ArgoCD:
- neuron-prod AppProject: scopes deploys to neuron-prod + platform ns,
  blacklists ClusterRole/ClusterRoleBinding/Namespace creation,
  automated sync window 2–6am UTC, manual always allowed
2026-04-25 22:54:18 -05:00
Will Anderson cd0cb30933 ci: add neuron-technologies runner for Gitea Actions 2026-04-23 21:19:26 -05:00
Will Anderson 43737ce5cb chore(ci-runner): restore ESO refresh interval to 1h 2026-04-23 13:32:18 -05:00
Will Anderson c8ee5e66ee fix(ci-runner): use NodePort HTTP URL to bypass Cloudflare gRPC issue 2026-04-23 13:15:16 -05:00
Will Anderson e69052d89e fix(ci-runner): use external Gitea URL now that REQUIRE_SIGNIN_VIEW is disabled 2026-04-23 12:58:51 -05:00
Will Anderson 28fb4e29f4 fix(ci-runner): use internal cluster URL for runner registration (gRPC) 2026-04-23 12:57:11 -05:00
Will Anderson b1898a7a0f fix(ci-runner): revert to external Gitea URL for git clone compatibility 2026-04-23 12:53:41 -05:00
Will Anderson 521079590b chore(ci-runner): restore ESO refresh interval to 1h 2026-04-23 12:45:34 -05:00
Will Anderson 0d9f74f68f fix(ci-runner): use internal cluster URL for Gitea to bypass Cloudflare Access 2026-04-23 12:45:00 -05:00
Will Anderson 415ee9eb68 chore(ci): restore ESO refresh interval to 1h after token sync 2026-04-23 12:33:01 -05:00
Will Anderson b31aad85a7 chore(ci): shorten ESO refresh to 10s to force runner token update 2026-04-23 12:31:11 -05:00
Will Anderson e84c586282 chore(ci): force ESO resync for gitea-runner-secret with fresh registration token 2026-04-23 12:29:58 -05:00
Will Anderson 2cb89b715f ci: copy forgejo-runner binary from correct path 2026-03-26 13:00:42 -05:00
Will Anderson 23131ef04f ci: use data.forgejo.org for runner image 2026-03-26 13:00:01 -05:00
Will Anderson e4db8bbda5 ci: switch to Forgejo runner for proper DEFAULT_ACTIONS_URL support 2026-03-26 12:58:22 -05:00
Will Anderson c9bee67e67 feat: make ci-base equivalent to ubuntu-latest
Comprehensive runner image with Python, Node.js 20, Ruby, Go 1.22,
Docker CLI, kubectl, Helm, yq, gh, make, jq, rsync, zstd, and all
standard tools. Mirrors GitHub ubuntu-24.04 hosted runner so workflows
are swappable between Gitea and GitHub with no friction.
2026-03-26 12:11:38 -05:00
Will Anderson 798cf8611d feat: make ci-base a comprehensive runner image like ubuntu-latest
Add Node.js 20 LTS (required for all Forgejo JS actions), Python 3.12,
Ruby, Go 1.22, Docker CLI, kubectl, Helm, yq, gh, zstd, and common
build/system tools. Mirrors GitHub ubuntu-24.04 hosted runner capability
so jobs work without needing container: overrides for standard tasks.
2026-03-26 12:08:16 -05:00
Will Anderson 978639601c fix: correct act_runner binary path in ci-base Dockerfile 2026-03-26 11:35:37 -05:00
Will Anderson 9595a18f3a refactor: rebase CI runner on Ubuntu 24.04, rename to ci-base
Replace Alpine-based legion-runner with a minimal Ubuntu 24.04 image.
The act_runner binary is copied from the official image via multi-stage
build. Job-specific tooling (Ruby, Node, Python, etc.) belongs in
per-job container images specified via container: in workflows, not
in the base runner image.

Rename: legion-runner → ci-base
2026-03-26 11:32:52 -05:00
Will Anderson ce45384f81 feat: add Ruby and bundler to legion-runner image
Required for Jekyll-based doc builds in CI.
2026-03-26 10:59:36 -05:00
Will Anderson f3477ac102 ci: fix gitea runner URL and set DEFAULT_ACTIONS_URL
- external-secrets.yaml: GITEA_INSTANCE_URL changed from cluster-internal
  URL to https://git.neuralplatform.ai so runner can register externally
- gitea.yaml: add GITEA__actions__DEFAULT_ACTIONS_URL=gitea so all
  actions/* references resolve from gitea.com, not github.com
- Dockerfile: track runner image (Python 3.12 + build deps) in repo
2026-03-26 10:35:13 -05:00
Will Anderson 9904bce343 gitea-runner: use internal cluster URL to avoid CF tunnel timeouts on runner long-polling 2026-03-25 20:29:23 -05:00
Will Anderson 6c073029a3 Fix gitea-runner ExternalSecret: use template for static GITEA_INSTANCE_URL 2026-03-25 10:34:11 -05:00
Will Anderson 4d0cfb1bbf Migrate k8s config from Terraform to Argo CD + ESO
Phase 1: Install External Secrets Operator via Argo CD app
- apps/external-secrets.yaml — ESO Helm chart install
- apps/external-secrets-config.yaml — ClusterSecretStore deployment
- k8s/external-secrets/cluster-secret-store.yaml — Vault backend using vault-token Secret

Phase 2: Create k8s manifests for all services
- k8s/neuron/ — PVC, ConfigMap, ExternalSecrets (neuron-secrets, cloudflared-secret), Ingress
- k8s/gitea/ — PVC, ConfigMap (custom CSS), ExternalSecret (gitea-db), Ingress
- k8s/github-runner/ — ExternalSecret (github-runner-secret)
- k8s/gitea-runner/ — ExternalSecret (gitea-runner-secret)
- k8s/monitoring/ — ExternalSecrets (grafana, slack), Alloy OTLP service+middleware, datasources ConfigMap, Ingress
- k8s/postgres/ — ExternalSecret (postgres-passwords)
- k8s/vault/ — ExternalSecret (vault-gcp-sa from Vault)
- k8s/adguard/ — PVCs, ConfigMap, Certificate, Ingress, ddclient Deployment+ExternalSecret
- k8s/ollama/ — PVC, Ingress
- k8s/headscale/ — PVC
- k8s/packages/ — PVCs, ConfigMap, Ingresses
- k8s/registry/ — PVC, Ingresses
- k8s/backup/ — CronJob, ExternalSecret (backup-credentials)

New Argo CD apps for Helm releases:
- apps/kube-prometheus-stack.yaml, loki.yaml, tempo.yaml, alloy.yaml
- apps/postgres.yaml, redis.yaml, vault.yaml

New Argo CD apps for k8s config paths:
- apps/neuron-config, gitea-config, ci-config, gitea-runner-config
- apps/monitoring-config, adguard-config, ollama-config, headscale-config
- apps/packages-config, registry-config, postgres-config, vault-config, backup

Phase 3: Strip Terraform to infrastructure-only
- All kubernetes_* and helm_release resources removed from service .tf files
- Each service .tf now contains only kubernetes_namespace (bootstrap dependency)
- variables.tf stripped to only cloudflare_api_key, cloudflare_email, gitea_api_token
- namespaces.tf gains external-secrets namespace
- ingress.tf, backup.tf, ddclient.tf emptied (resources in k8s/)
- cert-manager.tf, argocd.tf, traefik.tf unchanged (bootstrap)
2026-03-25 10:29:14 -05:00