Skip to main content
Platforms

Deploying to Kubernetes

Deploy your RivetKit app to any Kubernetes cluster.

Steps

Prerequisites

Package Your App

Create a Dockerfile in your project root:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
ENV PORT=8080
CMD ["node", "server.js"]

Build and Push the Image

docker build -t registry.example.com/your-team/rivetkit-app:latest .
docker push registry.example.com/your-team/rivetkit-app:latest

Replace registry.example.com/your-team with your registry path. Auth with docker login first if needed.

Set Environment Variables

After creating your project on the Rivet dashboard, select Kubernetes as your provider. You’ll be provided RIVET_ENDPOINT and RIVET_PUBLIC_ENDPOINT environment variables.

Create a rivetkit-secrets.yaml for your environment variables:

apiVersion: v1
kind: Secret
metadata:
  name: rivetkit-secrets
type: Opaque
stringData:
  RIVET_ENDPOINT: <your-rivet-endpoint>
  RIVET_PUBLIC_ENDPOINT: <your-rivet-public-endpoint>

Deploy to Kubernetes

Create a deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rivetkit-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rivetkit-app
  template:
    metadata:
      labels:
        app: rivetkit-app
    spec:
      # Allow enough time for actors to gracefully stop on SIGTERM.
      # The runner waits up to 30m for actors to finish.
      # Add buffer for runner shutdown overhead after actors stop.
      # See: /docs/actors/versions#graceful-shutdown-sigterm
      terminationGracePeriodSeconds: 2100
      containers:
        - name: rivetkit-app
          image: registry.example.com/your-team/rivetkit-app:latest
          envFrom:
            - secretRef:
                name: rivetkit-secrets

Apply both manifests:

kubectl apply -f rivetkit-secrets.yaml
kubectl apply -f deployment.yaml

Connect to Rivet

  1. Add a Service and Ingress to expose your app externally (e.g. my-app.example.com)
  2. On the Rivet dashboard, paste your domain with the /api/rivet path into the connect form (e.g. https://my-app.example.com/api/rivet)
  3. Click “Done”

Rivet envoys connect to your app over long-lived WebSockets, and your app’s clients (browsers, SDKs) do the same. Default Ingress and cloud load balancer idle timeouts (typically 30 to 60 seconds) drop these connections and cause reconnect storms.

Raise the idle / read / send timeout on every Ingress and load balancer in front of your app to at least 1 hour (3600 seconds). Examples:

  • NGINX Ingress: nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" and nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
  • AWS Load Balancer Controller (ALB): alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=3600
  • GCE Ingress (GKE): set timeoutSec: 3600 on the BackendConfig referenced by the Service.

Verify

Check that the pod is running:

kubectl get pods -l app=rivetkit-app

Your app should appear as connected on the Rivet dashboard once the pod is ready.