Files
homelab/kubernetes/apps/matrix/synapse.yaml
claude-botandClaude Opus 5.5 7ada3540b5
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
chore(paperclip): remove Paperclip and everything that only served it
Removes the Paperclip deployment (namespace paperclip, CNPG cluster
pclp-pg, ingresses, image automation, server image build) and the
infrastructure that existed only for its agents:

- agent sandbox: paperclip-renner namespace and CNPs, the
  kubernetes-sigs/agent-sandbox controller with its namespace, CNP and
  Renovate rules
- agent-runtime-{go,ops} images and the build-agent-runtime pipeline
- matrix bridge (Element <-> Paperclip agents) and synapse's appservice
  registration mount
- monitoring loki-read-gateway (only called by the paperclip Role)
- MQTT account agents-read and the controller's RBAC in ns paperclip
- the OpenBao secret-exists-check policy file
- agent admits in the wiki, lidarr, shelly-manager, mosquitto and
  hubble-relay CNPs; the paperclip-api Gitea webhook host; the wiki API
  key; the ClusterSecretStore namespace entry; the pclp-pg RECOVERY row
- the Paperclip design spec and plan

Authentik group "Paperclip Users" is switched to state: absent so the
blueprint deletes it. package-retention's EXCLUDE_PACKAGES becomes
optional, since its only value was the agent-runtime prefix.

The shelly-manager api-proxy sidecar stays: mqtt-account-controller
calls shelly-manager-api too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 07:50:12 +02:00

311 lines
9.6 KiB
YAML

# 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