chore(coturn): automated TURN shared-secret rotation #46

Closed
sorb wants to merge 76 commits from turn-secret-rotation-20260801-020001 into main
8 changed files with 240 additions and 1 deletions
Showing only changes of commit f5e9fc5d2b - Show all commits
@@ -0,0 +1,23 @@
apiVersion: v1
kind: Secret
metadata:
name: authentik-backup-credentials
namespace: authentik
stringData:
borg-passphrase: ENC[AES256_GCM,data:5PApz4TqSNN2vVXeFSuomd051nl+cYk+a+STViwddG/Hj7XWQ099vvTlKSE=,iv:MFG04/66YqtOjZWsLpy236MYwR05z91ngOQ0BmLNxzA=,tag:gxD5prW8Ted3Q2ZY3sYSYQ==,type:str]
ssh-private-key: ENC[AES256_GCM,data:87PrkqAIH2xRCu3jlAK3Ts24XKRDoXNCWLomRhizCY43hwLeY5fNzfsGnMTKBt5IxL2bIljx+pbh/Y8IO38ISUUbUAczfi1KeN1gg69wKgqNAlckcmD0dkA2N2F0ZnEFX/rkad68YR8Hw1/A5h3qGUd5FwoVWzIFD/diY86s/LiQBYzwD4bYLUACHqIL7+QyJ6jEsFzA3tLwDySpUpM9OAjFQF0EazObChNYqe/qrc8i1gI8CptWOFkqiZ8Pen1E79gg/zgleOBqSmlcefgZk+JFPAfvORTHkDrHW9X/bLygaTQvskmGNzaKHpe2s/bVafWb7G60ROrpdjYIJfS7c0baRCSrd9kwdM4JQC2gSsMkI4v6oeFSvkTrb684B10zacZdiTKfySDV+Ry4hCZofF2RhAnsTbOpo0XANoOi4InoxUqGPfctVfUCVb6X+HIR5XYxpLrNwWqRpscMP2P3RJsaUZOinmQUKrHX/nMtPZ/ltpwjhQeAXZTtdyPxTCjHAh6fzouuHk66vlCdukXsMQDBdIfdA/3jjGbW,iv:yFNKkdegLLq8jq1Ya6v67urSJTdG3Ge4ZbmKizqQhmk=,tag:6l/qMb1d1oD8sfVEebW6gQ==,type:str]
sops:
age:
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWMllTL2hRcEhCT2MxcWZy
dkxndmlZRW5FZ2NiWWdFckxqYTFKS1B6SXlvCjJySXRsZThvczNnWjlyM0N2Snha
eitvWUhhdmU4U0V3OG55WjdLbU9KcUEKLS0tIEM3MStzNUJhaGg4M0hKMVF1bnBB
RWVqVDRBNmJ0b1Bwd0l3dWxPT3Q0SU0KOEoyejkH4RC0p8ka3FjI7MyzRJg+uu7h
j3wf1q+Hgg73djDBSPYJkrB6Bdl4YMwo8SzbtW8O9elDE0qAioR0bQ==
-----END AGE ENCRYPTED FILE-----
recipient: age14l0hwfqylwpemz5y2ghh2yxk0phszlnj3qlejhue0fw0kz3tmfgqdsjzdh
encrypted_regex: ^(data|stringData)$
lastmodified: "2026-07-28T18:20:58Z"
mac: ENC[AES256_GCM,data:lwwNbxSxtgDTDmaWMU1uf7TBOEw8gFBFKb982VIsGMeM0fIPHvX12Qts90MNgYIJliOWgAWrwyvAgfXWKuE37RNo+BtyfHCWi4IESKSN/RJrd/yMpRKx+02rifH3nl26ZCAQT1Pa0fjI1SfMhbVzfnD9a/AMARXZMhLRc0OqczY=,iv:SgP2iMtENRtZfw6I9EaOsmvecFNYCIZWqVj+cZ+T7EI=,tag:s4oEyxqyUx6ibqsk4g9xpw==,type:str]
version: 3.13.3
+85
View File
@@ -0,0 +1,85 @@
# Nightly Borg backup of the authentik Postgres database to a Hetzner Storage Box
# (issues #6 + #15). See apps/authentik/authentik-backup-secret.yaml for the SSH key +
# Borg repo passphrase, and apps/production/synapse-backup.yaml for the matrix-side job
# (same Storage Box, separate repo/passphrase, offset schedule).
apiVersion: v1
kind: ConfigMap
metadata:
name: authentik-backup-known-hosts
namespace: authentik
data:
known_hosts: |
[u641795.your-storagebox.de]:23 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIICf9svRenC/PLKIL9nk6K/pxQgoiFC41wTNvoIncOxs
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: authentik-backup
namespace: authentik
spec:
schedule: "15 3 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
backoffLimit: 2
template:
metadata:
labels:
app.kubernetes.io/name: authentik-backup
app.kubernetes.io/component: backup
spec:
restartPolicy: OnFailure
containers:
- name: backup
image: rohana.axion1337.de/sorb/axion-backup:v1
env:
- name: BORG_REPO
value: "ssh://u641795@u641795.your-storagebox.de:23/./authentik-backup"
- name: BORG_PASSPHRASE
valueFrom:
secretKeyRef:
name: authentik-backup-credentials
key: borg-passphrase
- name: SSH_PRIVATE_KEY_FILE
value: /secrets/ssh/ssh-private-key
- name: SSH_KNOWN_HOSTS_FILE
value: /secrets/known-hosts/known_hosts
- name: DB_HOSTS
value: "authentik:authentik-postgresql"
- name: PGUSER
value: authentik
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: authentik-credentials
key: pg-password
volumeMounts:
- name: ssh-key
mountPath: /secrets/ssh
readOnly: true
- name: known-hosts
mountPath: /secrets/known-hosts
readOnly: true
- name: scratch
mountPath: /scratch
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
memory: 256Mi
volumes:
- name: ssh-key
secret:
secretName: authentik-backup-credentials
items:
- key: ssh-private-key
path: ssh-private-key
mode: 0400
- name: known-hosts
configMap:
name: authentik-backup-known-hosts
- name: scratch
emptyDir: {}
+3
View File
@@ -9,3 +9,6 @@ resources:
- authentik.yaml - authentik.yaml
- ingress.yaml - ingress.yaml
- networkpolicy.yaml - networkpolicy.yaml
# Backup zur Hetzner Storage Box (Issues #6 + #15)
- authentik-backup-secret.yaml
- authentik-backup.yaml
+3
View File
@@ -68,6 +68,9 @@ spec:
matchLabels: matchLabels:
app.kubernetes.io/name: authentik app.kubernetes.io/name: authentik
app.kubernetes.io/component: worker app.kubernetes.io/component: worker
- podSelector:
matchLabels:
app.kubernetes.io/name: authentik-backup
ports: ports:
- protocol: TCP - protocol: TCP
port: 5432 port: 5432
+4 -1
View File
@@ -30,4 +30,7 @@ resources:
- element-server-suite.yaml - element-server-suite.yaml
# Custom Apex Ingress für Element Web + Well-Known auf axion1337.chat # Custom Apex Ingress für Element Web + Well-Known auf axion1337.chat
- apex-ingress.yaml # Custom Apex Ingress für Element Web + Well-Known auf axion1337.chat - apex-ingress.yaml # Custom Apex Ingress für Element Web + Well-Known auf axion1337.chat
- networkpolicy.yaml - networkpolicy.yaml
# Backup zur Hetzner Storage Box (Issues #6 + #15)
- synapse-backup-secret.yaml
- synapse-backup.yaml
+3
View File
@@ -258,6 +258,9 @@ spec:
- podSelector: - podSelector:
matchLabels: matchLabels:
app.kubernetes.io/name: matrix-authentication-service app.kubernetes.io/name: matrix-authentication-service
- podSelector:
matchLabels:
app.kubernetes.io/name: synapse-backup
ports: ports:
- protocol: TCP - protocol: TCP
port: 5432 port: 5432
@@ -0,0 +1,23 @@
apiVersion: v1
kind: Secret
metadata:
name: synapse-backup-credentials
namespace: matrix
stringData:
borg-passphrase: ENC[AES256_GCM,data:RRXPwr4UGX30IdozM53abN7ZYztTO3Y1/63dtTh0JSZmU8i8l/ATb4gc3lc=,iv:rIyUr+lOUjo9J53OKZ5ZDmp3d8Nrb9PP2JDK2oCutYU=,tag:MqUmoYgCA03WJQy+RQi04w==,type:str]
ssh-private-key: ENC[AES256_GCM,data:320B/lSq7DljCrXZ0BluGv8gLIzYF3KL6VQnR6CM/Vzuf/6qbbZ7lMzrS96XfoubU95OxDeJuOsuNZBQUZNyUGtt4QjQmnl8XHUJzl48xLqh83HLFPtQm2uqU072lscf5OTT7I+JzD2BGks3OIowhrg1q0MdVQdfd4Rhdz8Jphjb+WxvstzNmEX5gxQ9mnBVPmj4DS6ikdXnpe+VDvaCJaVkzD5KgwRmqPy0qbFs9WXziQSo3am5fPeHbwhV3UlRhlok9WrDI40a1T1S5DBhgNhwShq1jAxjr9onuq92REymxAV50oLzsw9ivnH0uimw+3PcplRG1v2xxJ/pimWTCjE17bO7OZ8TyzzwyZ7QA02vSpOMNUdUwVU3N6pSdYQpdTETuVBTVqVc+GKC18Z9fWh2rdwX5eUDTwp0bbDDvPEHdANNxMg3VYD3gwpCgy6/wVnjrO+pVMs8K1CqFn4/H7azhzzeEPkrz27ZBxjlnqvDODsm9tlklr6X4jZDZmTaEmiH+WXuc+1qbNxvsrqtSFfa3CfFGxM1nBOh,iv:sKGsTLsxdQYVUvw7CEARL3YNInSd9LPbFp5Ci5CTgIw=,tag:O1mjNZUsGEqV4uu+LlgD/g==,type:str]
sops:
age:
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3ZUdtN3hyNHlyMkIrbTVS
aHQ4OGNUWnA4eTFUVkx4UVp5VWlnMDgxTEU0CkU3M2dMYWgyKytlRVFOVWptZEd2
NXlIY0JCd24xcGFzaGpIeks0R2U0U3MKLS0tIHlxYVZ1ZTJsRXNaZ25sVzZtSnp0
SEhzQ0tUYzZTRXcwMVNwbG85SHpyb0UKOn3nxy6Y7yQkGargXQ9z6O36vUWW4qJZ
D/GbFGmoRi94EtVFdmTGALhjy2D4J9QXy6gHsTapvKyMxF8NEtk+FQ==
-----END AGE ENCRYPTED FILE-----
recipient: age14l0hwfqylwpemz5y2ghh2yxk0phszlnj3qlejhue0fw0kz3tmfgqdsjzdh
encrypted_regex: ^(data|stringData)$
lastmodified: "2026-07-28T18:20:58Z"
mac: ENC[AES256_GCM,data:Rur32fQdCyM3nr/X+KeSgmPYEi4nKyh8lqTuSW3TPBVDjwTWMDp1I1ZPPyy5syeW6RHbKputFUzBWVnuQmVrfbZaQ6DBBI5kP9InspUAVUjXDRk9XqiWtdg/wYaTMMJ4Nxv/zdwkh6uJQSG2JHQBWce4NZc2hoPokLR0CjcWiZk=,iv:eWTUj48EFjjtuIIuErMltEdDfabLZeolkpInMYtVP5Q=,tag:6DPxkPqLt0ihJ80WnTzHeA==,type:str]
version: 3.13.3
+96
View File
@@ -0,0 +1,96 @@
# Nightly Borg backup of the shared Postgres instance (synapse + MAS databases) and the
# Synapse media_store PVC to a Hetzner Storage Box (issues #6 + #15). See
# apps/production/synapse-backup-secret.yaml for the SSH key + Borg repo passphrase, and
# apps/authentik/authentik-backup.yaml for the equivalent authentik-side job.
apiVersion: v1
kind: ConfigMap
metadata:
name: synapse-backup-known-hosts
namespace: matrix
data:
# Pinned via `ssh-keyscan -p 23 u641795.your-storagebox.de` (2026-07-28) rather than
# trusting the host key on first connect in an unattended job.
known_hosts: |
[u641795.your-storagebox.de]:23 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIICf9svRenC/PLKIL9nk6K/pxQgoiFC41wTNvoIncOxs
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: synapse-backup
namespace: matrix
spec:
schedule: "0 3 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
backoffLimit: 2
template:
metadata:
labels:
app.kubernetes.io/name: synapse-backup
app.kubernetes.io/component: backup
spec:
restartPolicy: OnFailure
containers:
- name: backup
image: rohana.axion1337.de/sorb/axion-backup:v1
env:
- name: BORG_REPO
value: "ssh://u641795@u641795.your-storagebox.de:23/./synapse-backup"
- name: BORG_PASSPHRASE
valueFrom:
secretKeyRef:
name: synapse-backup-credentials
key: borg-passphrase
- name: SSH_PRIVATE_KEY_FILE
value: /secrets/ssh/ssh-private-key
- name: SSH_KNOWN_HOSTS_FILE
value: /secrets/known-hosts/known_hosts
- name: DB_HOSTS
value: "synapse:matrix-stack-postgres matrixauthenticationservice:matrix-stack-postgres"
- name: PGUSER
value: postgres
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: matrix-stack-generated
key: POSTGRES_ADMIN_PASSWORD
- name: MEDIA_PATH
value: /media/media_store
volumeMounts:
- name: ssh-key
mountPath: /secrets/ssh
readOnly: true
- name: known-hosts
mountPath: /secrets/known-hosts
readOnly: true
- name: media
mountPath: /media
readOnly: true
- name: scratch
mountPath: /scratch
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
memory: 256Mi
volumes:
- name: ssh-key
secret:
secretName: synapse-backup-credentials
items:
- key: ssh-private-key
path: ssh-private-key
mode: 0400
- name: known-hosts
configMap:
name: synapse-backup-known-hosts
- name: media
persistentVolumeClaim:
claimName: matrix-stack-synapse-media
readOnly: true
- name: scratch
emptyDir: {}