# services/comms/coturn.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: coturn
  labels:
    app: coturn
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
  selector:
    matchLabels:
      app: coturn
  template:
    metadata:
      labels:
        app: coturn
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/agent-requests-cpu: 25m
        vault.hashicorp.com/agent-requests-mem: 64Mi
        vault.hashicorp.com/agent-limits-cpu: 250m
        vault.hashicorp.com/agent-limits-mem: 128Mi
        vault.hashicorp.com/role: "comms"
        vault.hashicorp.com/agent-inject-secret-turn-secret: "kv/data/atlas/comms/turn-shared-secret"
        vault.hashicorp.com/agent-inject-template-turn-secret: |
          {{- with secret "kv/data/atlas/comms/turn-shared-secret" -}}{{ .Data.data.TURN_STATIC_AUTH_SECRET }}{{- end -}}
        vault.hashicorp.com/agent-inject-secret-livekit-primary: "kv/data/atlas/comms/livekit-api"
        vault.hashicorp.com/agent-inject-template-livekit-primary: |
          {{- with secret "kv/data/atlas/comms/livekit-api" -}}{{ .Data.data.primary }}{{- end -}}
        vault.hashicorp.com/agent-inject-secret-bot-pass: "kv/data/atlas/comms/atlasbot-credentials-runtime"
        vault.hashicorp.com/agent-inject-template-bot-pass: |
          {{- with secret "kv/data/atlas/comms/atlasbot-credentials-runtime" -}}{{ index .Data.data "bot-password" }}{{- end -}}
        vault.hashicorp.com/agent-inject-secret-seeder-pass: "kv/data/atlas/comms/atlasbot-credentials-runtime"
        vault.hashicorp.com/agent-inject-template-seeder-pass: |
          {{- with secret "kv/data/atlas/comms/atlasbot-credentials-runtime" -}}{{ index .Data.data "seeder-password" }}{{- end -}}
        vault.hashicorp.com/agent-inject-secret-chat-matrix: "kv/data/atlas/shared/chat-ai-keys-runtime"
        vault.hashicorp.com/agent-inject-template-chat-matrix: |
          {{- with secret "kv/data/atlas/shared/chat-ai-keys-runtime" -}}{{ .Data.data.matrix }}{{- end -}}
        vault.hashicorp.com/agent-inject-secret-chat-homepage: "kv/data/atlas/shared/chat-ai-keys-runtime"
        vault.hashicorp.com/agent-inject-template-chat-homepage: |
          {{- with secret "kv/data/atlas/shared/chat-ai-keys-runtime" -}}{{ .Data.data.homepage }}{{- end -}}
        vault.hashicorp.com/agent-inject-secret-mas-admin-secret: "kv/data/atlas/comms/mas-admin-client-runtime"
        vault.hashicorp.com/agent-inject-template-mas-admin-secret: |
          {{- with secret "kv/data/atlas/comms/mas-admin-client-runtime" -}}{{ .Data.data.client_secret }}{{- end -}}
        vault.hashicorp.com/agent-inject-secret-synapse-db-pass: "kv/data/atlas/comms/synapse-db"
        vault.hashicorp.com/agent-inject-template-synapse-db-pass: |
          {{- with secret "kv/data/atlas/comms/synapse-db" -}}{{ .Data.data.POSTGRES_PASSWORD }}{{- end -}}
        vault.hashicorp.com/agent-inject-secret-mas-db-pass: "kv/data/atlas/comms/mas-db"
        vault.hashicorp.com/agent-inject-template-mas-db-pass: |
          {{- with secret "kv/data/atlas/comms/mas-db" -}}{{ .Data.data.password }}{{- end -}}
        vault.hashicorp.com/agent-inject-secret-mas-matrix-shared: "kv/data/atlas/comms/mas-secrets-runtime"
        vault.hashicorp.com/agent-inject-template-mas-matrix-shared: |
          {{- with secret "kv/data/atlas/comms/mas-secrets-runtime" -}}{{ .Data.data.matrix_shared_secret }}{{- end -}}
        vault.hashicorp.com/agent-inject-secret-mas-kc-secret: "kv/data/atlas/comms/mas-secrets-runtime"
        vault.hashicorp.com/agent-inject-template-mas-kc-secret: |
          {{- with secret "kv/data/atlas/comms/mas-secrets-runtime" -}}{{ .Data.data.keycloak_client_secret }}{{- end -}}
    spec:
      serviceAccountName: comms-vault
      nodeSelector:
        hardware: rpi5
        node-role.kubernetes.io/worker: "true"
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: node-role.kubernetes.io/control-plane
                    operator: DoesNotExist
                  - key: node-role.kubernetes.io/master
                    operator: DoesNotExist
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 50
              preference:
                matchExpressions:
                  - key: hardware
                    operator: In
                    values: ["rpi5","rpi4"]
      containers:
        - name: coturn
          image: ghcr.io/coturn/coturn:4.6.2
          command:
            - /bin/sh
            - -c
            - |
              . /vault/scripts/comms_vault_env.sh
              exec /usr/bin/turnserver \
                --no-cli \
                --fingerprint \
                --lt-cred-mech \
                --listening-ip=0.0.0.0 \
                --relay-ip="${POD_IP}" \
                --external-ip="${TURN_PUBLIC_IP}/${POD_IP}" \
                --user=livekit:"${TURN_STATIC_AUTH_SECRET}" \
                --realm=live.bstein.dev \
                --listening-port=3478 \
                --tls-listening-port=5349 \
                --min-port=50000 \
                --max-port=50050 \
                --cert=/etc/coturn/tls/tls.crt \
                --pkey=/etc/coturn/tls/tls.key \
                --log-file=stdout \
                --no-software-attribute
          env:
            - name: POD_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
            - name: TURN_PUBLIC_IP
              value: "38.28.125.112"
          ports:
            - name: turn-udp
              containerPort: 3478
              protocol: UDP
            - name: turn-tcp
              containerPort: 3478
              protocol: TCP
            - name: turn-tls
              containerPort: 5349
              protocol: TCP
          volumeMounts:
            - name: tls
              mountPath: /etc/coturn/tls
              readOnly: true
            - name: vault-scripts
              mountPath: /vault/scripts
              readOnly: true
          resources:
            requests:
              cpu: 200m
              memory: 256Mi
            limits:
              cpu: "2"
              memory: 512Mi
      volumes:
        - name: tls
          secret:
            secretName: turn-live-tls
        - name: vault-scripts
          configMap:
            name: comms-vault-env
            defaultMode: 0555
---
apiVersion: v1
kind: Service
metadata:
  name: coturn
  annotations:
    metallb.universe.tf/address-pool: communication-pool
spec:
  type: LoadBalancer
  loadBalancerClass: metallb
  loadBalancerIP: 192.168.22.5
  externalTrafficPolicy: Local
  selector:
    app: coturn
  ports:
    - name: turn-udp
      port: 3478
      targetPort: 3478
      protocol: UDP
    - name: turn-tcp
      port: 3478
      targetPort: 3478
      protocol: TCP
    - name: turn-tls
      port: 5349
      targetPort: 5349
      protocol: TCP
    # Expose relay range for UDP media
    - name: relay-50000
      port: 50000
      targetPort: 50000
      protocol: UDP
    - name: relay-50001
      port: 50001
      targetPort: 50001
      protocol: UDP
    - name: relay-50002
      port: 50002
      targetPort: 50002
      protocol: UDP
    - name: relay-50003
      port: 50003
      targetPort: 50003
      protocol: UDP
    - name: relay-50004
      port: 50004
      targetPort: 50004
      protocol: UDP
    - name: relay-50005
      port: 50005
      targetPort: 50005
      protocol: UDP
    - name: relay-50006
      port: 50006
      targetPort: 50006
      protocol: UDP
    - name: relay-50007
      port: 50007
      targetPort: 50007
      protocol: UDP
    - name: relay-50008
      port: 50008
      targetPort: 50008
      protocol: UDP
    - name: relay-50009
      port: 50009
      targetPort: 50009
      protocol: UDP
    - name: relay-50010
      port: 50010
      targetPort: 50010
      protocol: UDP
    - name: relay-50011
      port: 50011
      targetPort: 50011
      protocol: UDP
    - name: relay-50012
      port: 50012
      targetPort: 50012
      protocol: UDP
    - name: relay-50013
      port: 50013
      targetPort: 50013
      protocol: UDP
    - name: relay-50014
      port: 50014
      targetPort: 50014
      protocol: UDP
    - name: relay-50015
      port: 50015
      targetPort: 50015
      protocol: UDP
    - name: relay-50016
      port: 50016
      targetPort: 50016
      protocol: UDP
    - name: relay-50017
      port: 50017
      targetPort: 50017
      protocol: UDP
    - name: relay-50018
      port: 50018
      targetPort: 50018
      protocol: UDP
    - name: relay-50019
      port: 50019
      targetPort: 50019
      protocol: UDP
    - name: relay-50020
      port: 50020
      targetPort: 50020
      protocol: UDP
    - name: relay-50021
      port: 50021
      targetPort: 50021
      protocol: UDP
    - name: relay-50022
      port: 50022
      targetPort: 50022
      protocol: UDP
    - name: relay-50023
      port: 50023
      targetPort: 50023
      protocol: UDP
    - name: relay-50024
      port: 50024
      targetPort: 50024
      protocol: UDP
    - name: relay-50025
      port: 50025
      targetPort: 50025
      protocol: UDP
    - name: relay-50026
      port: 50026
      targetPort: 50026
      protocol: UDP
    - name: relay-50027
      port: 50027
      targetPort: 50027
      protocol: UDP
    - name: relay-50028
      port: 50028
      targetPort: 50028
      protocol: UDP
    - name: relay-50029
      port: 50029
      targetPort: 50029
      protocol: UDP
    - name: relay-50030
      port: 50030
      targetPort: 50030
      protocol: UDP
    - name: relay-50031
      port: 50031
      targetPort: 50031
      protocol: UDP
    - name: relay-50032
      port: 50032
      targetPort: 50032
      protocol: UDP
    - name: relay-50033
      port: 50033
      targetPort: 50033
      protocol: UDP
    - name: relay-50034
      port: 50034
      targetPort: 50034
      protocol: UDP
    - name: relay-50035
      port: 50035
      targetPort: 50035
      protocol: UDP
    - name: relay-50036
      port: 50036
      targetPort: 50036
      protocol: UDP
    - name: relay-50037
      port: 50037
      targetPort: 50037
      protocol: UDP
    - name: relay-50038
      port: 50038
      targetPort: 50038
      protocol: UDP
    - name: relay-50039
      port: 50039
      targetPort: 50039
      protocol: UDP
    - name: relay-50040
      port: 50040
      targetPort: 50040
      protocol: UDP
    - name: relay-50041
      port: 50041
      targetPort: 50041
      protocol: UDP
    - name: relay-50042
      port: 50042
      targetPort: 50042
      protocol: UDP
    - name: relay-50043
      port: 50043
      targetPort: 50043
      protocol: UDP
    - name: relay-50044
      port: 50044
      targetPort: 50044
      protocol: UDP
    - name: relay-50045
      port: 50045
      targetPort: 50045
      protocol: UDP
    - name: relay-50046
      port: 50046
      targetPort: 50046
      protocol: UDP
    - name: relay-50047
      port: 50047
      targetPort: 50047
      protocol: UDP
    - name: relay-50048
      port: 50048
      targetPort: 50048
      protocol: UDP
    - name: relay-50049
      port: 50049
      targetPort: 50049
      protocol: UDP
    - name: relay-50050
      port: 50050
      targetPort: 50050
      protocol: UDP
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: turn-live-cert
spec:
  secretName: turn-live-tls
  issuerRef:
    name: letsencrypt
    kind: ClusterIssuer
  dnsNames:
    - turn.live.bstein.dev
