The main Terminus deployment uses a single Pod containing two containers:
terminus: The web application.sidekiq: The background job processor.
Both containers must share the same volume for uploads and use the Recreate deployment strategy because the PVC is ReadWriteOnce.
Key Environment Variables:
APP_SETUP: Set to true.API_URI: Your actual public domain.DATABASE_URL: Sourced from terminus-secrets.APP_SECRET: Sourced from terminus-secrets.KEYVALUE_URL: The connection string for Valkey (e.g., redis://terminus-valkey:6379).RACK_ATTACK_ALLOWED_SUBNETS: Sourced from terminus-config.
Permissions: The container runs as UID 1000, so fsGroup: 1000 must be set in the securityContext to ensure correct file permissions on the shared volume.
apiVersion: apps/v1
kind: Deployment
metadata:
name: terminus
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: terminus
template:
metadata:
labels:
app.kubernetes.io/name: terminus
spec:
securityContext:
fsGroup: 1000
containers:
- name: terminus
image: ghcr.io/usetrmnl/terminus:latest
ports:
- containerPort: 2345
name: http
volumeMounts:
- mountPath: /app/public/uploads
name: data
env:
- name: APP_SETUP
value: "true"
- name: API_URI
value: https://terminus.example.com
- name: KEYVALUE_URL
value: redis://terminus-valkey:6379
# ... other env vars from secrets/configmaps
- name: sidekiq
image: ghcr.io/usetrmnl/terminus:latest
command: ["bundle", "exec", "sidekiq", "-r", "./config/sidekiq.rb"]
volumeMounts:
- mountPath: /app/public/uploads
name: data
env:
- name: API_URI
value: https://terminus.example.com
- name: KEYVALUE_URL
value: redis://terminus-valkey:6379
# ... other env vars from secrets/configmaps
volumes:
- name: data
persistentVolumeClaim:
claimName: terminus-uploads