Installation#

Junction ships as a Helm chart, published as an OCI artifact to GitHub Container Registry.

Prerequisites#

  • A Kubernetes cluster
  • Helm 3

What gets deployed#

Component Kind
API (nginx + PHP-FPM) Deployment + Service
HTTP destination worker Deployment
System worker Deployment
CLI migrations Job (runs automatically on install/upgrade)
CLI token generation Job (manual, disabled by default)
Postgres StatefulSet + Service, bundled by default
RabbitMQ StatefulSet + Service, bundled by default

Required values#

Two secrets have no default and must be set explicitly, or the install fails:

  • secrets.app.jwtSecret — the signing secret shared by the API and CLI
  • secrets.worker.token — a signed system-type token, shared by both workers

The worker token has a chicken-and-egg dependency: it’s a JWT signed with jwtSecret, but generating it requires a database this release can already reach. Bootstrap in two steps.

Step 1 — install with a placeholder worker token#

helm install junction oci://ghcr.io/junctionio/charts/junction \
  --set secrets.app.jwtSecret=$(openssl rand -hex 32) \
  --set secrets.worker.token=placeholder

The API, Postgres, and RabbitMQ come up healthy. Both workers will crash-loop until a real token is set in step 3 — expected at this point.

Step 2 — generate a real worker token#

Render and apply the CLI’s keygen Job against the running release:

helm template junction oci://ghcr.io/junctionio/charts/junction \
  --set secrets.app.jwtSecret=<same secret as step 1> \
  --set cli.keygen.enabled=true \
  --set cli.keygen.type=system \
  --set cli.keygen.id=workers \
  --show-only templates/cli-keygen-job.yaml | kubectl apply -f -

kubectl logs job/junction-keygen-<suffix>

Copy the printed token.

Step 3 — upgrade with the real token#

helm upgrade junction oci://ghcr.io/junctionio/charts/junction \
  --reuse-values \
  --set secrets.worker.token=<token from step 2>

Updating a Secret’s content via helm upgrade does not automatically restart the Deployments that consume it — restart both workers manually after this step:

kubectl rollout restart deployment/junction-http-destination-worker
kubectl rollout restart deployment/junction-system-worker

Generating additional tokens#

Calling systems need a relay token, and any management API client needs a management token — both are generated the same way as step 2, with a different --set cli.keygen.type= and --set cli.keygen.id=:

helm template junction oci://ghcr.io/junctionio/charts/junction \
  --set secrets.app.jwtSecret=<jwtSecret> \
  --set cli.keygen.enabled=true \
  --set cli.keygen.type=relay \
  --set cli.keygen.id=billing-service \
  --show-only templates/cli-keygen-job.yaml | kubectl apply -f -

See Authentication for token types and claims.

External Postgres/RabbitMQ#

Set postgres.enabled: false / rabbitmq.enabled: false and populate database.host / queue.host (and the matching credentials under secrets.app) to point at externally-managed instances instead of the bundled StatefulSets.

Verifying the install#

kubectl get pods

All pods should reach Running/Completed. Then send a test event:

curl -i -X POST https://<your-api-host>/relay \
  -H "Content-Type: application/json" \
  -H "X-Junction-Token: <relay token>" \
  -H "X-Junction-Event: test.ping" \
  -d '{"payload": {"hello": "world"}}'

A 202 Accepted with an X-Junction-Trace-ID header confirms the ingest path is working end-to-end. See Relay for the full contract.

Resource sizing#

All resources requests/limits in values.yaml are best-guess placeholders — not yet benchmarked under production load. Review and adjust before running anything beyond evaluation traffic.

Uninstalling#

helm uninstall junction

This does not remove the Postgres/RabbitMQ PersistentVolumeClaims — delete them separately if you want a clean slate:

kubectl delete pvc -l app.kubernetes.io/instance=junction