diff --git a/services/matrix/matrix-deployment.yaml b/services/matrix/matrix-deployment.yaml new file mode 100644 index 0000000..7411d9f --- /dev/null +++ b/services/matrix/matrix-deployment.yaml @@ -0,0 +1,176 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: tuwunel-config + namespace: matrix +data: + tuwunel.toml: | + [global] + server_name = "starling.mynest.love" + database_path = "/var/lib/tuwunel/" + address = "0.0.0.0" + port = 6167 + allow_registration = false + + [global.well_known] + client = "https://starling.mynest.love" + livekit_url = "https://matrix-rtc.mynest.love" + + [[global.identity_provider]] + brand = "keycloak" + client_id = "matrix-tuwunel" + client_secret_file = "/etc/tuwunel/client_secret" + issuer_url = "https://sso.mynest.love/realms/nest" + callback_url = "https://starling.mynest.love/_matrix/client/unstable/login/sso/callback/matrix-tuwunel" +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tuwunel + namespace: matrix +spec: + replicas: 1 + selector: + matchLabels: + app: tuwunel + template: + metadata: + labels: + app: tuwunel + spec: + # Prevents K8s from injecting random network variables that trigger linter warnings + enableServiceLinks: false + containers: + - name: tuwunel + image: ghcr.io/matrix-construct/tuwunel:latest + ports: + - containerPort: 6167 + env: + - name: TUWUNEL_CONFIG + value: "/etc/tuwunel/tuwunel.toml" + - name: TUWUNEL_GLOBAL__IDENTITY_PROVIDER__0__CLIENT_SECRET + valueFrom: + secretKeyRef: + name: matrix-secrets + key: client-secret + volumeMounts: + - name: tuwunel-data + mountPath: /var/lib/tuwunel/ + - name: config-volume + mountPath: /etc/tuwunel/tuwunel.toml + subPath: tuwunel.toml + - name: secret-volume + mountPath: /etc/tuwunel/client_secret + subPath: client_secret + volumes: + - name: tuwunel-data + persistentVolumeClaim: + claimName: tuwunel-data + - name: config-volume + configMap: + name: tuwunel-config + - name: secret-volume + secret: + secretName: matrix-secrets + items: + - key: client-secret + path: client_secret +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: livekit-config + namespace: matrix +data: + livekit.yaml: | + port: 7880 + rtc: + tcp_port: 7881 + udp_port: 7882 + use_external_ip: true + turn: + cert_file: "" + key_file: "" + tls_port: 0 + udp_port: 3478 + external_tls: false + # Crucial for Matrix integration: Only the JWT service can create rooms + room: + auto_create: false +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: livekit + namespace: matrix +spec: + replicas: 1 + selector: + matchLabels: + app: livekit + template: + metadata: + labels: + app: livekit + spec: + containers: + - name: livekit + image: livekit/livekit-server:latest + args: ["--config", "/etc/livekit.yaml"] + ports: + - containerPort: 7880 + - containerPort: 7881 + - containerPort: 7882 + protocol: UDP + - containerPort: 3478 + protocol: UDP + env: + - name: LK_KEY + valueFrom: + secretKeyRef: + name: matrix-secrets + key: LIVEKIT_KEY + - name: LK_SECRET + valueFrom: + secretKeyRef: + name: matrix-secrets + key: LIVEKIT_SECRET + - name: LIVEKIT_KEYS + value: "$(LK_KEY): $(LK_SECRET)" + volumeMounts: + - name: config-volume + mountPath: /etc/livekit.yaml + subPath: livekit.yaml + volumes: + - name: config-volume + configMap: + name: livekit-config +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lk-jwt-service + namespace: matrix +spec: + replicas: 1 + selector: + matchLabels: + app: lk-jwt-service + template: + metadata: + labels: + app: lk-jwt-service + spec: + containers: + - name: lk-jwt-service + image: ghcr.io/element-hq/lk-jwt-service:latest + ports: + - containerPort: 8080 + envFrom: + - secretRef: + name: matrix-secrets + env: + - name: LIVEKIT_URL + value: "wss://matrix-rtc.mynest.love" + - name: LIVEKIT_FULL_ACCESS_HOMESERVERS + value: "starling.mynest.love" diff --git a/services/matrix/matrix-external-secrets.yaml b/services/matrix/matrix-external-secrets.yaml new file mode 100644 index 0000000..30f08ce --- /dev/null +++ b/services/matrix/matrix-external-secrets.yaml @@ -0,0 +1,26 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: matrix-secrets + namespace: matrix +spec: + refreshInterval: "1h" + secretStoreRef: + name: vault-external-secrets-store + kind: ClusterSecretStore + target: + name: matrix-secrets + creationPolicy: Owner + data: + - secretKey: LIVEKIT_KEY + remoteRef: + key: matrix + property: livekit-key + - secretKey: LIVEKIT_SECRET + remoteRef: + key: matrix + property: livekit-secret + - secretKey: client-secret + remoteRef: + key: matrix + property: client-secret diff --git a/services/matrix/matrix-ingress.yaml b/services/matrix/matrix-ingress.yaml new file mode 100644 index 0000000..9f038c0 --- /dev/null +++ b/services/matrix/matrix-ingress.yaml @@ -0,0 +1,67 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: matrix-ingress + namespace: matrix + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" +spec: + tls: + - hosts: + - starling.mynest.love + secretName: matrix-tls + rules: + - host: starling.mynest.love + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: tuwunel-svc + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: matrix-rtc-ingress + namespace: matrix + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" +spec: + tls: + - hosts: + - matrix-rtc.mynest.love + secretName: matrix-rtc-tls + rules: + - host: matrix-rtc.mynest.love + http: + paths: + # 1. Route token generation traffic to the lk-jwt-service + - path: /sfu/get + pathType: Prefix + backend: + service: + name: lk-jwt-svc + port: + number: 8080 + - path: /get_token + pathType: Prefix + backend: + service: + name: lk-jwt-svc + port: + number: 8080 + # 2. Route all standard traffic and WebSockets to LiveKit + - path: / + pathType: Prefix + backend: + service: + name: livekit-svc + port: + number: 7880 diff --git a/services/matrix/matrix-pvcs.yaml b/services/matrix/matrix-pvcs.yaml index 8ac41f5..a43832d 100644 --- a/services/matrix/matrix-pvcs.yaml +++ b/services/matrix/matrix-pvcs.yaml @@ -1,11 +1,15 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: conduit-data + name: tuwunel-data namespace: matrix + labels: + recurring-job.longhorn.io/source: "enabled" + recurring-job-group.longhorn.io/app-config-group: "enabled" spec: accessModes: - ReadWriteOnce + storageClassName: longhorn resources: requests: storage: 5Gi diff --git a/services/matrix/matrix-service.yaml b/services/matrix/matrix-service.yaml index 2a9a5b3..0a30694 100644 --- a/services/matrix/matrix-service.yaml +++ b/services/matrix/matrix-service.yaml @@ -1,11 +1,11 @@ apiVersion: v1 kind: Service metadata: - name: conduit-svc + name: tuwunel-svc namespace: matrix spec: selector: - app: conduit + app: tuwunel ports: - protocol: TCP port: 80 @@ -16,6 +16,9 @@ kind: Service metadata: name: livekit-svc namespace: matrix + annotations: + # Tell MetalLB to assign this specific IP from the nest-lb-pool + metallb.universe.tf/loadBalancerIPs: 192.168.1.160 spec: # Using LoadBalancer to expose the UDP WebRTC ports directly type: LoadBalancer