blob: 95e92571c78c63b35ef2e2c648c94b955446c3f3 [file] [log] [blame]
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +01001# Matrix server (synapse).
2# This needs a secret provisioned, create with:
3# ns=matrix
4#
5# SIGNING_KEY="$(kubectl run -n $ns -i --quiet --restart=Never --rm synapse-generate-config --image=matrixdotorg/synapse:v1.19.2 --env SYNAPSE_SERVER_NAME=dummy --env SYNAPSE_REPORT_STATS=no -o yaml --command -- sh -c '/start.py generate >/dev/null && cat /data/*.signing.key')"
6# kubectl -n $ns create secret generic synapse --from-literal=postgres_password=$(pwgen 24 1) --from-literal=macaroon_secret_key=$(pwgen 32 1) --from-literal=registration_shared_secret=$(pwgen 32 1) --from-literal=homeserver_signing_key="$SIGNING_KEY" --from-literal=redis_password=$(pwgen 32 1) --from-literal=worker_replication_secret=$(pwgen 32 1)
7# kubectl -n $ns create secret generic oauth2-cas-proxy --from-literal=oauth2_secret=...
8#
9# When migrating from matrix.libsonnet, instance signing key, redis passwsord
10# and worker replication secret need to be added to existing synapse secret:
11#
12# echo "homeserver_signing_key: $(kubectl -n $ns exec deploy/synapse -- sh -c 'cat /data/*.signing.key' | base64 -w0)"
13# echo "redis_password: $(pwgen 32 1 | tr -d '\n' | base64 -w0)"
14# echo "worker_replication_secret: $(pwgen 32 1 | tr -d '\n' | base64 -w0)"
15# kubectl -n $ns edit secret synapse
16# # ...add homeserver_signing_key, redis_password and worker_replication_secret keys
17#
Piotr Dobrowolskib67ae482021-01-31 10:35:38 +010018# Additionally some resources need to be explicitly removed due to
19# label/annotations changes:
20# kubectl -n $ns delete deployment riot-web oauth2-cas-proxy wellknown synapse
21#
22# Some service configuration customization fields have been renamed:
23# .riotConfig → .riot.config
24# .synapseConfig → .synapse.config
25#
Piotr Dobrowolskifb119aa2021-01-31 19:07:32 +010026# When migrating from CAS to OpenID Connect authentication scheme following need
27# to be ensured:
28# * https://{homeserver}/_synapse/oidc/callback is added to allowed callback URLs list
29# * openid scope is enabled for configured client
30#
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +010031# Sequencing appservices is fun. The appservice needs to run first (for
32# instance, via a bootstrap job), and on startup it will spit out a
33# registration file. This registration file then needs to be fed to synapse -
34# this is done via specialy named secrets (appservice-X-registration, for X key
35# in the appservices object).
36#
37# For appservice-irc instances, you can use this oneliner magic to get the
38# registration YAML from logs.
39# kubectl -n matrix create secret generic appservice-irc-freenode-registration --from-file=registration.yaml=<(kubectl -n matrix logs job/appservice-irc-freenode-bootstrap | tail -n +4 | sed -r 's/(.*aliases:.*)/ group_id: "+freenode:hackerspace.pl"\n\1/')
40#
41# For appservice-telegram instances, you can use this oneliner magic:
42# kubectl -n matrix create secret generic appservice-telegram-prod-registration --from-file=registration.yaml=<(kubectl -n matrix logs job/appservice-telegram-prod-bootstrap | grep -A 100 SNIPSNIP | grep -v SNIPSNIP)
43
44local kube = import "../../../kube/kube.libsonnet";
45local postgres = import "../../../kube/postgres.libsonnet";
46local redis = import "../../../kube/redis.libsonnet";
47
Piotr Dobrowolskib67ae482021-01-31 10:35:38 +010048local riot = import "./riot.libsonnet";
49local cas = import "./cas.libsonnet";
50local wellKnown = import "./wellknown.libsonnet";
51local synapse = import "./synapse.libsonnet";
52
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +010053{
54 local app = self,
55 local cfg = app.cfg,
56 cfg:: {
57 namespace: error "cfg.namespace must be set",
58 # webDomain is the domain name at which element will run
59 webDomain: error "cfg.webDomain must be set",
60 # serverName is the server part of the MXID this homeserver will cover
61 serverName: error "cfg.serverName must be set",
62 storageClassName: "waw-hdd-redundant-3",
63
64 images: {
viqa1501ab2021-05-26 23:17:18 +020065 synapse: "matrixdotorg/synapse:v1.35.1",
Serge Bazanskiabca7902021-06-06 14:23:26 +000066 riot: "vectorim/riot-web:v1.7.29",
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +010067 casProxy: "registry.k0.hswaw.net/q3k/oauth2-cas-proxy:0.1.4",
Serge Bazanski8eae4542021-05-19 15:42:13 +000068 appserviceIRC: "matrixdotorg/matrix-appservice-irc:release-0.26.0",
69 appserviceTelegram: "dock.mau.dev/tulir/mautrix-telegram@sha256:c6e25cb57e1b67027069e8dc2627338df35d156315c004a6f2b34b6aeaa79f77",
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +010070 wellKnown: "registry.k0.hswaw.net/q3k/wellknown:1611960794-adbf560851a46ad0e58b42f0daad7ef19535687c",
71 },
72
73 # OpenID Connect provider configuration.
74 # Currently only client_secret can be provided as a secretKeyRef.
75 #
76 # https://${cfg.webDomain}/_synapse/oidc/callback needs to be set as
77 # allowed OAuth2/OpenID Connect callback URL
78 #
79 # See: https://github.com/matrix-org/synapse/blob/v1.25.0/docs/openid.md
80 oidc: {
81 enable: false,
82 config: {
83 issuer: error "oidc.config.issuer must be set",
84 client_id: error "oidc.config.client_id must be set",
85 client_secret: error "oidc.config.client_secret must be set",
86
87 # Set this to true when migrating from existing CAS deployment
88 allow_existing_users: false,
89 user_mapping_provider: {
90 config: {
91 localpart_template: '{{ user.sub }}',
92 display_name_template: '{{ user.sub }}',
93 },
94 },
95
96 # Extra configuration required when migrating from
97 # oauth2-cas-proxy bound to https://sso.hackerspace.pl
98 # user_profile_method: "userinfo_endpoint",
99 # client_auth_method: "client_secret_post",
100 },
101 },
102
103 # Central Authentication Scheme, a single-sign-on system. Note: this flow is now called 'SSO' in Matrix, we keep this name for legacy reasons.
104 # Refer to https://matrix.org/docs/spec/client_server/r0.6.1#sso-client-login
105 cas: {
106 # whether to enable the CAS proxy (ie. connect to hswaw sso via OAuth)
107 enable: false,
108 # generate client ID and secret in with your OAuth2 provider, refer to https://www.oauth.com/oauth2-servers/client-registration/client-id-secret/
109 oauth2: {
110 clientID: error "cas.oauth2.clientID must be set",
111 clientSecret: error "cas.oauth2.clientSecret must be set",
112 scope: error "cas.oauth2.scope must be set",
113 authorizeURL: error "cas.oauth2.authorizeURL must be set",
114 tokenURL: error "cas.oauth2.tokenURL must be set",
115 userinfoURL: error "cas.oauth2.userinfoURL must be set",
116 },
117 },
118
119 # Serve /.well-known/matrix configuration endpoints required when using
120 # cfg.webDomain directly as mxid.
121 wellKnown: false,
122 },
123
Piotr Dobrowolskifb119aa2021-01-31 19:07:32 +0100124 # DEPRECATED: this needs to be removed in favor of namespace.Contain() in
125 # modules that depend on this (appservices/instance defintions)
126 metadata(component):: {
127 namespace: cfg.namespace,
128 labels: {
129 "app.kubernetes.io/name": "matrix",
130 "app.kubernetes.io/managed-by": "kubecfg",
131 "app.kubernetes.io/component": component,
132 },
133 },
134
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +0100135 namespace: kube.Namespace(cfg.namespace),
136
137 postgres3: postgres {
138 cfg+: {
139 namespace: cfg.namespace,
140 appName: "synapse",
141 database: "synapse",
142 username: "synapse",
143 prefix: "waw3-",
144 password: { secretKeyRef: { name: "synapse", key: "postgres_password" } },
145 storageClassName: cfg.storageClassName,
146 storageSize: "100Gi",
147 initdbArgs: "--encoding='UTF8' --lc-collate='C' --lc-ctype='C'",
148 },
149 },
150
151 redis: redis {
152 cfg+: {
153 namespace: cfg.namespace,
154 appName: "synapse",
155 storageClassName: cfg.storageClassName,
156 password: { secretKeyRef: { name: "synapse", key: "redis_password" } },
157 },
158 },
159
Piotr Dobrowolskib67ae482021-01-31 10:35:38 +0100160 riot: riot {
161 ns: app.namespace,
162 cfg+: {
163 webDomain: cfg.webDomain,
164 serverName: cfg.serverName,
165 image: cfg.images.riot,
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +0100166 },
167 },
168
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +0100169 cas: if cfg.cas.enable && cfg.oidc.enable then error "cfg.cas.enable and cfg.oidc.enable options are exclusive"
Piotr Dobrowolskib67ae482021-01-31 10:35:38 +0100170 else if cfg.cas.enable then cas {
171 ns: app.namespace,
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +0100172 cfg+: {
Piotr Dobrowolskib67ae482021-01-31 10:35:38 +0100173 image: cfg.images.casProxy,
174 webDomain: cfg.webDomain,
175 oauth2: cfg.cas.oauth2,
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +0100176 },
177 },
178
Piotr Dobrowolskib67ae482021-01-31 10:35:38 +0100179 wellKnown: if cfg.wellKnown then wellKnown {
180 ns: app.namespace,
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +0100181 cfg+: {
Piotr Dobrowolskib67ae482021-01-31 10:35:38 +0100182 image: cfg.images.wellKnown,
183 webDomain: cfg.webDomain,
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +0100184 },
185 } else {},
186
Piotr Dobrowolskib67ae482021-01-31 10:35:38 +0100187 synapse: synapse {
188 ns: app.namespace,
189 postgres: app.postgres3,
190 redis: app.redis,
191 appservices: app.appservices,
192 cfg+: app.cfg {
193 image: app.cfg.images.synapse,
194
195 macaroonSecretKey: { secretKeyRef: { name: "synapse", key: "macaroon_secret_key" } },
196 registrationSharedSecret: { secretKeyRef: { name: "synapse", key: "registration_shared_secret" } },
197 workerReplicationSecret: { secretKeyRef: { name: "synapse", key: "worker_replication_secret" } },
198 },
199 },
200
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +0100201 // Any appservice you add here will require an appservice-X-registration
202 // secret containing a registration.yaml file. Adding something to this
203 // dictionary will cause Synapse to not start until that secret is
204 // available - so change things carefully!
205 // If bootstrapping a new appservice, just keep it out of this dictionary
206 // until it spits you a registration YAML and you feed that to a secret.
207 appservices: {},
208
Piotr Dobrowolskib67ae482021-01-31 10:35:38 +0100209 ingress: app.namespace.Contain(kube.Ingress("matrix")) {
210 metadata+: {
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +0100211 annotations+: {
212 "kubernetes.io/tls-acme": "true",
213 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
214 "nginx.ingress.kubernetes.io/proxy-body-size": "0",
215 "nginx.ingress.kubernetes.io/use-regex": "true",
216 },
217 },
218 spec+: {
219 tls: [
220 {
221 hosts: [cfg.webDomain],
222 secretName: "synapse-tls",
223 },
224 ],
225 rules: [
226 {
227 host: cfg.webDomain,
228 http: {
229 paths: [
Piotr Dobrowolskib67ae482021-01-31 10:35:38 +0100230 { path: path, backend: app.synapse.genericWorker.svc.name_port }
231 for path in app.synapse.genericWorker.paths
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +0100232 ] + [
Piotr Dobrowolskib67ae482021-01-31 10:35:38 +0100233 { path: "/", backend: app.riot.svc.name_port },
234 { path: "/_matrix/media/", backend: app.synapse.mediaWorker.svc.name_port },
235 { path: "/_matrix/", backend: app.synapse.main.svc.name_port },
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +0100236
237 # Used by OpenID Connect login flow
Piotr Dobrowolskib67ae482021-01-31 10:35:38 +0100238 { path: "/_synapse/", backend: app.synapse.main.svc.name_port },
Piotr Dobrowolski8ec86572021-01-30 13:06:07 +0100239 ] + (if cfg.cas.enable then [
240 { path: "/_cas", backend: app.cas.svc.name_port },
241 ] else []) + (if cfg.wellKnown then [
242 { path: "/.well-known/matrix", backend: app.wellKnown.svc.name_port },
243 ] else [])
244 },
245 }
246 ],
247 },
248 },
249}