Skip to content
Back to site

Kubernetes

The Helm chart runs the API, the worker and the dashboard. You supply PostgreSQL and Redis.

  • Kubernetes 1.24+ and Helm 3.8+
  • PostgreSQL 16+ and Redis 7+, managed or self-run. postgres:16-alpine and redis:7-alpine are the images the project tests against.
  1. Create the namespace and secrets

    Terminal window
    kubectl create namespace railhook
    kubectl -n railhook create secret generic railhook-secrets \
    --from-literal=encryption-key="$(openssl rand -base64 32)" \
    --from-literal=encryption-salt="$(openssl rand -base64 24)" \
    --from-literal=jwt-secret="$(openssl rand -base64 64)"
    kubectl -n railhook create secret generic railhook-postgresql-secret \
    --from-literal=password="$DB_PASSWORD"
    kubectl -n railhook create secret generic railhook-redis-secret \
    --from-literal=password="$REDIS_PASSWORD"

    All three keys in railhook-secrets are required; without them the API and worker pods crash-loop.

  2. Write a values file

    values-mycompany.yaml
    postgresql:
    external:
    host: postgres.example.com
    port: 5432
    database: railhook
    username: webhook_user
    existingSecret: railhook-postgresql-secret
    redis:
    external:
    host: redis.example.com
    port: 6379
    existingSecret: railhook-redis-secret
    ui:
    ingress:
    hosts:
    - host: hooks.example.com
    paths:
    - path: /
    pathType: Prefix

    With app.baseUrl empty, the chart takes the public URL from the first ingress host. Set it if Railhook is reached by another name.

  3. Install the chart

    The chart is on GHCR for every release; its version is the release number without the v:

    Terminal window
    helm install railhook oci://ghcr.io/vadymkykalo/charts/railhook \
    --version <version> -n railhook -f values-mycompany.yaml
  4. Check it

    Terminal window
    kubectl -n railhook get pods
    kubectl -n railhook logs -l app.kubernetes.io/component=api --tail=20

api.env.APP_ENV defaults to production. With email off, accounts are created already verified and nobody can be invited. To turn it on:

values-mycompany.yaml
email:
enabled: true
from: noreply@hooks.example.com
smtp:
host: smtp.example.com
port: 587
username: railhook@example.com
auth: true
starttls: true
existingSecret: railhook-smtp-secret # key: smtp-password

For production defaults (more replicas, autoscaling, disruption budgets, network policies, email on), clone the repository and add -f deploy/helm/railhook/values-production.yaml.

Topic Behaviour
Migrations Run inside the API pod at startup. Replicas starting together wait on a PostgreSQL advisory lock, so each migration is applied once. A worker pod from a new release waits up to 15 minutes for them before it starts, and its startup probe allows that wait
Workers Each worker claims due deliveries from PostgreSQL with FOR UPDATE SKIP LOCKED, so added worker replicas share the work without other coordination. A claim that is not finished within WEBHOOK_CLAIM_TIMEOUT_SECONDS (300 by default) can be claimed by another worker
Backups backup.enabled: true adds a CronJob that writes pg_dump files to a PVC and prunes old ones
Metrics On the named management port (8082 for the API, 8081 for the worker), never published outside the cluster
Terminal window
helm upgrade railhook oci://ghcr.io/vadymkykalo/charts/railhook --version <version> -n railhook -f values-mycompany.yaml

Take a database backup first. helm rollback returns the chart and the images, not the schema.

Terminal window
helm uninstall railhook -n railhook