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 CLIsecrets.worker.token— a signedsystem-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=placeholderThe 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-workerGenerating 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 podsAll 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 junctionThis 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