# Vulcan CI on Kubernetes

Cloud-agnostic Kustomize base for running Vulcan CI's server components on any
Kubernetes cluster. The installer places it in `~/.vulcan/install/kubernetes`
(override the base directory with `VULCAN_HOME`):

```sh
curl -fsSL https://get.vulcan-ci.io/install.sh | sh
```

## Contents

- `namespace.yaml` — `vulcan` namespace with Pod Security Admission labels.
- `configmap.yaml` — non-secret config only.
- `forge-backend.yaml` — Forge API Deployment + ClusterIP Service.
- `automata-worker.yaml` — pull-based worker Deployment + HorizontalPodAutoscaler.
- `postgres.yaml` — self-hosted PostgreSQL StatefulSet (replace with a managed
  database for production).
- `networkpolicy.yaml` — default-deny with least-privilege allows.
- `serviceaccounts.yaml`, `kustomization.yaml`

Images default to `ghcr.io/vulcan-ci/vulcan-forge-backend:latest` and
`ghcr.io/vulcan-ci/vulcan-automata:latest`; override the registry or pin an
immutable tag with an overlay against this base.

## Prerequisites

- A Kubernetes cluster and `kubectl` (with its bundled `kustomize`).
- Three per-workload Secrets in the `vulcan` namespace before the workloads
  start. Secrets are split per workload so the Automata worker cannot read the
  backend's JWT/DB secret.

## Secret population

Secrets are never shipped in the manifests. Create the three Secrets
out-of-band:

```sh
# Backend-only: JWT + DB connection string.
kubectl -n vulcan create secret generic vulcan-backend-secrets \
  --from-literal=JWT_SECRET="$(openssl rand -hex 32)" \
  --from-literal=DATABASE_URL="postgresql://vulcan:<password>@vulcan-postgres:5432/vulcan"

# Worker-only: the token issued when enrolling a worker.
kubectl -n vulcan create secret generic vulcan-worker-secrets \
  --from-literal=FORGE_API_TOKEN="wk_<enrolled-worker-token>"

# Database (self-hosted Postgres only).
kubectl -n vulcan create secret generic vulcan-db-secrets \
  --from-literal=POSTGRES_PASSWORD="<same password used in DATABASE_URL>"
```

## Apply

```sh
kubectl create namespace vulcan   # or let the base create it
kubectl apply -k ~/.vulcan/install/kubernetes
```

## Notes

- The worker runs with Process isolation; the pod is the isolation boundary.
- In-cluster traffic is plaintext HTTP; encrypt it with a service mesh (mTLS)
  for production.
- For questions and issues, see https://docs.vulcan-ci.io or the
  [vulcan-ci GitHub organization](https://github.com/vulcan-ci).
