Helm Deployment¶
La Suite Meet provides an official Helm chart for Kubernetes deployments. This is the method used by DINUM in production.
Getting the Helm chart¶
The Helm chart is included in the Meet repository:
Chart structure¶
The Meet Helm chart deploys:
- Meet backend (Django) — Deployment + Service
- Celery worker — Deployment
- Static/frontend assets — served by the backend or a separate Nginx
- Ingress resources for HTTPS
- Optional: LiveKit webhook Ingress
External services (PostgreSQL, Redis, Garage) are configured via values and expected to be pre-provisioned.
Values file¶
Create a values.yaml file for your deployment. Key sections:
Image¶
image:
repository: lasuite/meet-backend
tag: "1.15.0" # pin to a specific version
pullPolicy: IfNotPresent
Backend environment¶
backend:
django:
secretKey: "your-secret-key"
allowedHosts: "meet.example.com"
csrfTrustedOrigins: "https://meet.example.com"
database:
host: "postgresql.example.com"
port: 5432
name: "meet"
user: "meet"
password: "db-password"
redis:
url: "redis://redis.example.com:6379/0"
oidc:
clientId: "meet"
clientSecret: "oidc-secret"
jwksEndpoint: "https://auth.example.com/realms/meet/protocol/openid-connect/certs"
authorizationEndpoint: "https://auth.example.com/realms/meet/protocol/openid-connect/auth"
tokenEndpoint: "https://auth.example.com/realms/meet/protocol/openid-connect/token"
userEndpoint: "https://auth.example.com/realms/meet/protocol/openid-connect/userinfo"
livekit:
apiKey: "myapikey"
apiSecret: "livekit-secret"
url: "wss://meet.example.com:7880"
apiUrl: "http://livekit-service:7880"
storage:
s3EndpointUrl: "https://s3.example.com"
s3AccessKeyId: "access-key"
s3SecretAccessKey: "secret-key"
s3BucketName: "meet-media-storage"
Ingress¶
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: meet.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: meet-tls
hosts:
- meet.example.com
Dedicated Ingress for LiveKit webhook¶
livekitWebhook:
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
host: meet.example.com
path: /api/v1.0/webhook/livekit/
tls:
secretName: meet-tls
This creates a separate Ingress for the LiveKit webhook, isolated from the main application for security.
Replicas and resources¶
replicaCount: 2
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
celery:
enabled: true
replicaCount: 1
resources:
requests:
cpu: 100m
memory: 256Mi
Security context (added in v1.14.0)¶
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containerSecurityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
Custom background image ingress (v1.11.0+)¶
Deploying¶
Install¶
Upgrade¶
Check deployment status¶
Run migrations after install/upgrade¶
kubectl -n meet exec deployment/meet-backend -- python manage.py migrate
kubectl -n meet exec deployment/meet-backend -- python manage.py collectstatic --no-input
Helmfile (multi-environment)¶
For managing multiple environments (staging, production), use helmfile:
# helmfile.yaml
releases:
- name: meet
chart: ./helm/meet
namespace: meet
values:
- values/common.yaml
- values/{{ .Environment.Name }}.yaml
environments:
staging:
production:
Deploy:
Secrets management¶
Avoid storing secrets in values.yaml in version control. Options:
- Kubernetes Secrets referenced via
valueFrom.secretKeyRef - External Secrets Operator (Vault, AWS Secrets Manager, etc.)
- SOPS encrypted values files (used by the DINUM team — see
.sops.yamlin the repo)
# Encrypt a values file with SOPS
sops --encrypt values/production-secrets.yaml > values/production-secrets.enc.yaml
Local development with Tilt¶
For local Kubernetes development mirroring production:
# Build and start a local Kind cluster
make build-k8s-cluster
# Start the application stack
make start-tilt-keycloak
# Monitor at http://localhost:10350/
# App available at https://meet.127.0.0.1.nip.io/
Tilt provides hot reloading and live log streaming for all services.