Kubernetes Installation
Environment Requirements
Required:
- Kubernetes 1.27+
- PostgreSQL 14+
- RabbitMQ 3.11+
- Redis 7+
- Meilisearch 1.8+
- Weaviate 1.25+
- MinIO 2023-10+
- Stunner 1.0+
- SMTP server
Optional (for AI features):
- LLM on GPU cluster with OpenAI-compatible API, or OpenAI/Yandex Cloud API key — for summarization and AI functions
- Whisper on GPU cluster or Yandex Foundation Models API key — for speech-to-text
All components can be deployed inside or outside the cluster.
Tools
- ArgoCD 2.10+
Preparation
PostgreSQL
- Create database:
yuchat_db - Create schemas:
yuchatandyuchat_services - Create a service account with read/write permissions on the database and schemas
RabbitMQ
Create a service account with configure/read/write permissions on virtual host /
MinIO
-
Create a service account with bucket creation permissions
-
Configure AMQP notifications:
MINIO_NOTIFY_AMQP_ENABLE_PRIMARY: "on"
MINIO_NOTIFY_AMQP_URL_PRIMARY: "amqp://username:password@rabbitmq_host:5672"
MINIO_NOTIFY_AMQP_EXCHANGE_PRIMARY: "yuchat.aws.file.events.ex"
MINIO_NOTIFY_AMQP_EXCHANGE_TYPE_PRIMARY: "fanout"
MINIO_NOTIFY_AMQP_ROUTING_KEY_PRIMARY: "#"
MINIO_NOTIFY_AMQP_DURABLE_PRIMARY: "true"
MINIO_NOTIFY_AMQP_AUTO_DELETED_PRIMARY: "false"
MinIO must have HTTPS configured.
Redis
Create a service account (or use the default user).
SMTP Server
Configure with accessible SMTP_HOST, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD.
Public IP Address
Prepare a public IP with port 3478 for the STUN/TURN gateway.
Domain Setup
- Register your domain:
yourdomain.com - Create subdomains:
api.yourdomain.comweb.yourdomain.com
Installation
1. Create Namespace
kubectl create namespace yuchat
2. Create TLS Secret
kubectl create secret tls yuchat-tls \
--cert=/path/to/tls.crt \
--key=/path/to/tls.key \
-n yuchat
3. Create Registry Credentials
kubectl create secret docker-registry yuchat-regcred \
--docker-server=https://registry.unison.team \
--docker-username=<contact provider> \
--docker-password=<contact provider> \
-n yuchat
4. Create StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: yuchat-storage
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
5. Configure ArgoCD Repository
Create a Kubernetes secret:
apiVersion: v1
kind: Secret
metadata:
name: yuchat-charts
labels:
argocd.argoproj.io/secret-type: repository
stringData:
enableOCI: "true"
name: yuchat-charts
password: <contact provider>
type: helm
url: registry.unison.team/yuchatcharts
username: <contact provider>
6. Create Service Secrets
Redis:
kubectl create secret generic redis-creds-secret \
--from-literal=REDIS_HOST=redis.yuchat.yourdomain.com \
--from-literal=REDIS_PASSWORD=your_password \
--from-literal=REDIS_PORT=6379 \
-n yuchat
RabbitMQ:
kubectl create secret generic rabbitmq-creds-secret \
--from-literal=RABBITMQ_URI=amqp://rabbitmq.yuchat.yourdomain.com:5672 \
--from-literal=RABBITMQ_USERNAME=yuchat_user \
--from-literal=RABBITMQ_PASSWORD=your_password \
--from-literal=RABBITMQ_HOST=rabbitmq.yuchat.yourdomain.com \
--from-literal=RABBITMQ_VHOST= \
-n yuchat
RabbitMQ with Audit (optional):
kubectl create secret generic rabbitmq-creds-secret \
--from-literal=RABBITMQ_URI=amqp://rabbitmq.yuchat.yourdomain.com:5672 \
--from-literal=RABBITMQ_USERNAME=yuchat_user \
--from-literal=RABBITMQ_PASSWORD=your_password \
--from-literal=RABBITMQ_HOST=rabbitmq.yuchat.yourdomain.com \
--from-literal=RABBITMQ_VHOST= \
--from-literal=AUDIT_RABBITMQ_URI=amqp://rabbitmq.yuchat.yourdomain.com:5672 \
--from-literal=AUDIT_RABBITMQ_USERNAME=yuchat_user \
--from-literal=AUDIT_RABBITMQ_PASSWORD=your_password \
--from-literal=AUDIT_RABBITMQ_VHOST= \
-n yuchat
MinIO:
kubectl create secret generic minio-creds-secret \
--from-literal=CLOUD_ACCESS_KEY=your_access_key \
--from-literal=CLOUD_SECRET_KEY=your_secret_key \
--from-literal=S3_URL=https://minio.yuchat.yourdomain.com \
--from-literal=S3_DOMAIN=minio.yuchat.yourdomain.com \
-n yuchat
PostgreSQL:
kubectl create secret generic postgresql-creds-secret \
--from-literal=DATASOURCE_USERNAME=yuchat_user \
--from-literal=DATASOURCE_URL=jdbc:postgresql://postgres.yuchat.yourdomain.com:5432/yuchat_db \
--from-literal=DATASOURCE_PASSWORD=your_password \
--from-literal=DATASOURCE_SCHEMA=yuchat \
--from-literal=DATASOURCE_ENCRYPT_TOKEN=datasource_encrypt_token \
-n yuchat
SMTP:
kubectl create secret generic smtp-creds-secret \
--from-literal=MAIL_SMTP_HOST=smtp.yourdomain.com \
--from-literal=MAIL_SMTP_PORT=25 \
--from-literal=MAIL_SMTP_USERNAME=smtp_user \
--from-literal=MAIL_SMTP_PASSWORD=smtp_password \
-n yuchat
Set SMTP_USERNAME and SMTP_PASSWORD to empty strings if not required.
Stunner:
kubectl create secret generic stunner-creds-secret \
--from-literal=STUNNER_USERNAME=stunner_user \
--from-literal=STUNNER_PASSWORD=stunner_password \
--from-literal=STUNNER_PORT=3478 \
--from-literal=STUNNER_HOST=<public_ip> \
-n yuchat
Keycloak (for SSO):
kubectl create secret generic keycloak-creds-secret \
--from-literal=KC_CLIENT_SECRET=kc_client_secret \
--from-literal=KC_SIG_KEY_SECRET=kc_sig_key_secret \
-n yuchat
7. Create Backend Secret
kubectl create secret generic backend-secret \
--from-literal=JWT_SHARED_SECRET=random_string_256_bits \
--from-literal=MEILISEARCH_MASTER_KEY=random_string \
-n yuchat
8. Create FreeSWITCH Secret
kubectl create secret generic freeswitch-secret \
--from-literal=FS_ESL_PASS=random_string \
-n yuchat
Helm Charts Configuration
For each service, configure values.yaml with:
- Image repositories: Docker registry URL
- PullSecret: Registry credentials in
imagePullSecrets - Ingress: Domain-based access rules and annotations
- StorageClass: PVC storage class if needed
- Node placement:
nodeSelector,tolerations,topologySpreadConstraints,affinity - Secrets: Uncomment secret references in values files
Example for backend service — uncomment these secrets in values.yaml:
env:
secret:
keycloak-secret: # Optional, for SSO
- KC_CLIENT_SECRET
- KC_SIG_KEY_SECRET
postgresql-creds-secret:
- DATASOURCE_USERNAME
- DATASOURCE_URL
- DATASOURCE_PASSWORD
- DATASOURCE_SCHEMA
- DATASOURCE_ENCRYPT_TOKEN
rabbitmq-creds-secret:
- RABBITMQ_HOST
- RABBITMQ_USERNAME
- RABBITMQ_PASSWORD
- RABBITMQ_VHOST
# Remove AUDIT_ vars if audit is disabled
- AUDIT_RABBITMQ_VHOST
- AUDIT_RABBITMQ_USERNAME
- AUDIT_RABBITMQ_PASSWORD
- AUDIT_RABBITMQ_URI
redis-creds-secret:
- REDIS_HOST
- REDIS_PORT
- REDIS_PASSWORD
stunner-creds-secret:
- STUNNER_USERNAME
- STUNNER_PASSWORD
- STUNNER_PORT
- STUNNER_HOST
minio-creds-secret:
- CLOUD_ACCESS_KEY
- CLOUD_SECRET_KEY
- S3_URL
smtp-creds-secret:
- MAIL_SMTP_HOST
- MAIL_SMTP_PORT
- MAIL_SMTP_USERNAME
- MAIL_SMTP_PASSWORD
backend-secret:
- JWT_SHARED_SECRET
- MEILISEARCH_MASTER_KEY
Service Deployment Order
1. Meilisearch
Configure the master key secret:
auth:
existingMasterKeySecret: "backend-secret"
2. STUNner Gateway Operator
After deploying, create these CRDs:
Gateway:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: udp-gateway
namespace: yuchat
annotations:
stunner.l7mp.io/service-type: LoadBalancer
spec:
gatewayClassName: stunner-gatewayclass
addresses:
- type: IPAddress
value: <Your IP>
listeners:
- name: udp-listener
port: 3478
protocol: UDP
allowedRoutes:
namespaces:
from: Same
GatewayClass:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
name: stunner-gatewayclass
spec:
controllerName: "stunner.l7mp.io/gateway-operator"
parametersRef:
group: stunner.l7mp.io
kind: GatewayConfig
name: stunner-gatewayconfig
namespace: yuchat
GatewayConfig:
apiVersion: stunner.l7mp.io/v1alpha1
kind: GatewayConfig
metadata:
name: stunner-gatewayconfig
namespace: yuchat
spec:
authType: plaintext
userName: <Your username>
password: <Your password>
realm: stunner.l7mp.io
stunnerConfig: stunnerd-config
logLevel: all:TRACE
UDPRoute:
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: UDPRoute
metadata:
name: media-yuchat
namespace: yuchat
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: udp-gateway
rules:
- backendRefs:
- kind: Service
name: webrtc
namespace: yuchat
port: 8090
weight: 1
3. Web and Nginx
Deploy web service, then nginx.
In configs/prod/nginx.conf, set the correct namespace:
proxy_pass http://backend.yuchat:8080; # Adjust namespace
4. Remaining Services
Deploy in order:
- media-converter-service
- backend — optionally create a ConfigMap for
application.yaml:configurationExistingCM: "backend-configuration" - avnotes-streaming
- ws-endpoint-v2
- conference-service-discovery
- chat-message-event-service
- media-composer
- webrtc
- freeswitch
- mediahub
- admin-dashboard
5. Backend API Keys
Create a secret for iOS and Android push notifications (contact developers for keys):
apiVersion: v1
kind: Secret
metadata:
name: backend-apikeys
namespace: yuchat
data:
AuthKey_2U9QTC2B7A.p8: <base64>
AuthKey_89A2RYNYNS.p8: <base64>
electron-fcm.json: <base64>
fcm-prod.json: <base64>
6. MinIO Event Configuration
After backend starts, configure bucket events:
mc event add local/yuchat-avatars arn:minio:sqs::PRIMARY:amqp --event put
mc event add local/yuchat-file-pdf-preview arn:minio:sqs::PRIMARY:amqp --event put
mc event add local/yuchat-file-preview arn:minio:sqs::PRIMARY:amqp --event put
mc event add local/yuchat-files arn:minio:sqs::PRIMARY:amqp --event put
mc event add local/yuchat-files-presigned arn:minio:sqs::PRIMARY:amqp --event put
mc event add local/yuchat-per-track-recordings arn:minio:sqs::PRIMARY:amqp --event put
mc event add local/yuchat-records arn:minio:sqs::PRIMARY:amqp --event put
mc event add local/yuchat-transcribe arn:minio:sqs::PRIMARY:amqp --event put
7. Admin Dashboard
In values.yaml, uncomment environment variables:
env:
normal:
S3_RECORDS_BUCKET: yuchat-records
S3_REGION: ru-central