Reference Helmfile to deploy La Suite numerique on Kubernetes.
No Kubernetes cluster? See Deploy with Docker Compose.
If you need a production-grade platform with automatic updates, security policies, and per-app isolation, check out MinBZK/mijn-bureau-infra - a more sophisticated helmfile maintained by the Dutch government. See comparison for details.
This repository serves as a reference implementation with some opinionated decisions, while still providing guidance for a somewhat advanced deployment with external infrastructure, that can be iterated upon.
Each app has its own Kubernetes installation guide. This helmfile provides:
- Unified deployment - one config for all apps instead of following N separate guides
- Standard tools - cert-manager and HAProxy instead of mkcert and nginx-specific setup
- Minimal third-party dependencies -
/etc/hostsinstead of nip.io, no external DNS service - Single command -
helmfile syncinstead of multiplehelm installcommands
See detailed comparison.
| App | Description | Status |
|---|---|---|
| Docs | Collaborative document editing (Google Docs-like) | Implemented |
| Meet | Video conferencing (Google Meet-like) | Implemented |
| Drive | File storage and sharing (Google Drive-like) | Implemented |
| People | Directory and team management | Implemented |
| Find | Cross-app search engine (requires OpenSearch) | Implemented — indexation untested (backchannel issue) |
| Conversations | AI chatbot (requires LLM backend) | Implemented |
Apps are enabled/disabled in environments/local.yaml (or your environment file):
apps:
docs:
enabled: true
meet:
enabled: false # requires LiveKit (heavy on resources)
drive:
enabled: true
people:
enabled: true
find:
enabled: false # requires OpenSearch (heavy on resources)
conversations:
enabled: false # requires LLM backend (not included)Default enables Docs, Drive, and People. Meet requires LiveKit (resource-heavy). See Known Limitations for image issues.
- Kubernetes cluster (Rancher Desktop, Docker Desktop, or other)
- Helm v3.x
- Helmfile v0.150+
kubectlconfigured for your cluster
./init.sh
# Choose option 1 (Local development)The interactive script will:
- Check prerequisites (helm, kubectl, helmfile)
- Generate a random secret seed
- Run
helmfile syncautomatically - Detect the LoadBalancer IP and show the
/etc/hostsline to add - Extract the CA certificate to
lasuite-ca.pem - Display credentials (Keycloak admin password, People Django admin if enabled)
./init.sh
# Choose option 2 (Remote deployment)The script will ask for:
- Environment name (e.g.,
production) - Domain (e.g.,
suite.example.com) - Admin email (for Let's Encrypt)
It creates the configuration files. Review them before deploying.
The People (desk) chart has a known bug that prevents the automatic superuser creation. The init.sh script handles this automatically for local deployments.
For manual creation, derive the password from the secret seed:
PASS=$(grep secretSeed environments/local.yaml | cut -d'"' -f2 | xargs -I{} sh -c 'echo -n "{}:people-superuser" | shasum -a 256 | cut -c1-50')
kubectl -n lasuite-people exec deploy/people-desk-backend -- \
python manage.py createsuperuser --username admin@suite.local --password "$PASS"This is only needed for Django admin access (https://people.suite.local/admin/). Regular users authenticate via Keycloak.
LiveKit uses hostNetwork by default to expose WebRTC ports directly on nodes. Open these ports:
- UDP 50000-60000 - WebRTC media
- TCP 7881 - WebRTC TCP fallback
To disable hostNetwork (requires cloud LoadBalancer with UDP or TURN relay), set podHostNetwork: false in values/livekit.yaml.gotmpl.
If you prefer to set things up manually instead of using init.sh:
cp environments/local.yaml.example environments/local.yamlAt the bottom of environments/local.yaml, replace the REPLACE_ME value of secretSeed with a random value (e.g. openssl rand -hex 24).
Edit environments/local.yaml to toggle apps under the apps: section.
helmfile -e local syncPoint *.suite.local domains to your LoadBalancer IP, either via local DNS or by editing /etc/hosts.
For self-signed TLS (local environment), the CA certificate is stored in the lasuite-ca-secret secret in the cert-manager namespace.
| Service | URL | Credentials |
|---|---|---|
| Docs | https://docs.suite.local | user / password |
| Meet | https://meet.suite.local | user / password |
| Drive | https://drive.suite.local | user / password |
| People | https://people.suite.local | user / password |
| Find | https://find.suite.local | user / password |
| Conversations | https://conversations.suite.local | user / password |
| Keycloak Admin | https://auth.suite.local | admin / (displayed by init.sh) |
| MinIO Console | https://minio-console.suite.local | (derived from secretSeed) |
Only apps with enabled: true in your environment file will be accessible.
The init script extracts the CA certificate to lasuite-ca.pem. To avoid browser warnings:
macOS:
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain lasuite-ca.pemLinux (Debian/Ubuntu):
sudo cp lasuite-ca.pem /usr/local/share/ca-certificates/lasuite-ca.crt
sudo update-ca-certificatesFirefox: Settings > Privacy & Security > Certificates > View Certificates > Import
grep secretSeed environments/local.yaml | cut -d'"' -f2 | xargs -I{} sh -c 'echo -n "{}:keycloak-admin" | shasum -a 256 | cut -c1-50'All infrastructure is deployed automatically. For production, replace MinIO with real S3 and consider using external PostgreSQL/Redis.
| Component | Chart | Purpose |
|---|---|---|
| PostgreSQL | bitnami/postgresql | Shared database (1 DB per app) |
| Redis | bitnami/redis | Cache and Celery broker (1 instance, DB number isolation) |
| Keycloak | codecentric/keycloakx | OIDC identity provider (1 realm, 1 client per app) |
| MinIO | minio/minio | S3-compatible storage (dev only) |
| OpenSearch | opensearch/opensearch | Search engine (for Find) |
| LiveKit | livekit/livekit-server | WebRTC server (for Meet) |
| HAProxy | haproxytech/kubernetes-ingress | Ingress controller |
| cert-manager | jetstack/cert-manager | TLS certificates |
| Reflector | emberstack/reflector | Cross-namespace secret replication |
- Deploy with Docker Compose - Run without Kubernetes using compose + Caddy
- Advanced Deployment - External PostgreSQL/Keycloak, production setup
- Architecture Decisions - Why things are the way they are
- Known Limitations - Current limitations and workarounds
- Comparison with mijn-bureau-infra - When to use which