# Synapse homeserver for matrix.renner.uno (REN-567). # # Private: federation is off at three layers — federation_domain_whitelist # is empty, no listener serves the federation/keys resources, and the # namespace egress policy lets Synapse reach nothing outside the cluster # except the push gateway. Logins and accounts are delegated to MAS # (mas.yaml); registration is closed. # # server_name is permanent: it is part of every user and room ID, and # cannot be changed without a new, empty server. matrix.renner.uno needs no # .well-known delegation from the apex, which is the WordPress site. apiVersion: v1 kind: ConfigMap metadata: name: synapse-config namespace: matrix data: homeserver.yaml: | server_name: matrix.renner.uno public_baseurl: https://matrix.renner.uno/ # Lets Element X and other clients discover the homeserver from the # server name. No server well-known: there is no federation to point at. serve_client_wellknown: true pid_file: /tmp/homeserver.pid report_stats: false listeners: # Client API only (includes media and /.well-known). Leaving out the # `federation` and `keys` resources means this server does not answer # federation at all. - port: 8008 type: http tls: false bind_addresses: ["::"] x_forwarded: true resources: - names: [client] compress: false # The password comes from PGPASSWORD (libpq reads it), so no credential # is written into this file. database: name: psycopg2 args: host: mx-pg-rw port: 5432 dbname: synapse user: synapse cp_min: 2 cp_max: 10 # Signing key is generated on first start if missing; it lives on the # data PVC next to the media store, so Velero backs up both. signing_key_path: /data/signing.key media_store_path: /data/media_store max_upload_size: 100M # Also the macaroon key: Synapse falls back to it when # macaroon_secret_key is unset, so rotating it logs every session out. registration_shared_secret_path: /secrets/registration_shared_secret # MAS handles login, sessions and accounts. Synapse asks it to check # every access token; password login here must be off. matrix_authentication_service: enabled: true endpoint: http://mas:8080/ secret_path: /secrets/mas_matrix_secret password_config: enabled: false # Sign in with QR code (Element X): the rendezvous channel between the # new and the signed-in device. Both require MAS. `open` lets the new, # not-yet-signed-in device create the channel; the server is LAN-only. experimental_features: msc4108_enabled: true msc4388_mode: open # Federation off. federation_domain_whitelist: [] trusted_key_servers: [] allow_public_rooms_over_federation: false enable_registration: false allow_guest_access: false url_preview_enabled: false user_directory: search_all_users: true # Phones get pushes through the Element push gateway on matrix.org. # Only event and room IDs leave the cluster, never message text. push: include_content: false --- # Media store and the server signing key. Not reconstructable: lost media # is gone, and a lost signing key invalidates the server's past signatures. # Backed up by Velero (matrix-daily); the database by Barman (mx-pg). apiVersion: v1 kind: PersistentVolumeClaim metadata: name: synapse-data namespace: matrix labels: app.kubernetes.io/name: synapse spec: accessModes: - ReadWriteOnce storageClassName: ceph-block resources: requests: storage: 10Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: synapse namespace: matrix annotations: configmap.reloader.stakater.com/reload: synapse-config,mas-config secret.reloader.stakater.com/reload: synapse-secrets labels: app.kubernetes.io/name: synapse app.kubernetes.io/part-of: matrix spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app.kubernetes.io/name: synapse template: metadata: labels: app.kubernetes.io/name: synapse app.kubernetes.io/part-of: matrix spec: automountServiceAccountToken: false securityContext: runAsNonRoot: true runAsUser: 991 runAsGroup: 991 fsGroup: 991 seccompProfile: type: RuntimeDefault initContainers: # One-time move of the Synapse accounts (owner, password hash, # sessions) into the MAS database. syn2mas needs Synapse offline; # this runs before Synapse starts, and Recreate stops the old pod # first. The marker on the data PVC makes later starts skip it. # Debug image: the plain one has no shell for the marker check. - name: migrate-to-mas image: ghcr.io/element-hq/matrix-authentication-service:1.26.0-debug@sha256:46f7480f5ea4243ccb6fd2c447ea859e0230c8b3c0e676ee285d4ae6ca344ee3 command: - /busybox/sh - -ec - | if [ -f /data/.syn2mas-done ]; then echo "syn2mas already done"; exit 0 fi mas-cli syn2mas migrate \ --config /mas-config/config.yaml \ --synapse-config /config/homeserver.yaml \ --synapse-database-uri postgresql: touch /data/.syn2mas-done securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"] env: # libpq-style variables for the Synapse database; the URI above # is empty on purpose. - name: PGHOST value: mx-pg-rw - name: PGUSER value: synapse - name: PGDATABASE value: synapse - name: PGPASSWORD valueFrom: secretKeyRef: name: mx-pg-app key: password resources: requests: cpu: 10m memory: 64Mi limits: memory: 256Mi volumeMounts: - name: config mountPath: /config readOnly: true - name: mas-config mountPath: /mas-config readOnly: true - name: secrets mountPath: /secrets readOnly: true - name: pg mountPath: /pg readOnly: true - name: data mountPath: /data containers: - name: synapse image: ghcr.io/element-hq/synapse:v1.162.0@sha256:6b84a7bbac36f080b2d2e51e0289cf1b08b349598ea44a558df38d558f2c2311 # Bypass /start.py: it expects to run as root and template a config # from env. Default mode is generate-missing-and-run, which creates # the signing key on first start. command: - python - -m - synapse.app.homeserver - --config-path - /config/homeserver.yaml securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"] env: - name: PGPASSWORD valueFrom: secretKeyRef: name: mx-pg-app key: password ports: - name: http containerPort: 8008 resources: requests: cpu: 100m memory: 256Mi limits: memory: 1Gi # First start runs every schema migration against an empty # database; give it up to 10 min. startupProbe: httpGet: path: /health port: http periodSeconds: 10 failureThreshold: 60 readinessProbe: httpGet: path: /health port: http periodSeconds: 10 livenessProbe: httpGet: path: /health port: http periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 4 volumeMounts: - name: config mountPath: /config readOnly: true - name: secrets mountPath: /secrets readOnly: true - name: data mountPath: /data - name: tmp mountPath: /tmp volumes: - name: config configMap: name: synapse-config - name: secrets secret: secretName: synapse-secrets items: - key: registration_shared_secret path: registration_shared_secret - key: mas_matrix_secret path: mas_matrix_secret - key: mas_encryption path: mas_encryption - key: mas_rsa_key path: mas_rsa_key - key: mas_ec_key path: mas_ec_key - name: mas-config configMap: name: mas-config - name: pg secret: secretName: mx-pg-app items: - key: password path: password - name: data persistentVolumeClaim: claimName: synapse-data - name: tmp emptyDir: {} --- apiVersion: v1 kind: Service metadata: name: synapse namespace: matrix spec: selector: app.kubernetes.io/name: synapse ports: - name: http port: 8008 targetPort: http