blob: 732b76cb56c885a0500f703c4967aba3eb11306d [file] [log] [blame]
Piotr Dobrowolskia2226912019-05-14 18:49:29 +02001# matrix.hackerspace.pl, a matrix/synapse instance
2# This needs a secret provisioned, create with:
Piotr Dobrowolskieabbe8a2019-08-11 19:49:08 +02003# kubectl -n matrix 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)
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +02004# kubectl -n matrix create secret generic oauth2-cas-proxy --from-literal=oauth2_secret=...
Piotr Dobrowolski3ea979d2019-05-23 16:11:52 +02005# kubectl -n matrix create secret generic appservice-irc-freenode-registration --from-file=registration.yaml=<(kubectl logs -n matrix $(kubectl get pods -n matrix --selector=job-name=appservice-irc-freenode-bootstrap --output=jsonpath='{.items[*].metadata.name}') | tail -n +4 | sed -r 's/(.*aliases:.*)/ group_id: "+freenode:hackerspace.pl"\n\1/')
Piotr Dobrowolskia2226912019-05-14 18:49:29 +02006
7local kube = import "../../kube/kube.libsonnet";
8local postgres = import "../../kube/postgres.libsonnet";
9
10{
11 local app = self,
12 local cfg = app.cfg,
13 cfg:: {
14 namespace: "matrix",
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020015 domain: "matrix.hackerspace.pl",
16 serverName: "hackerspace.pl",
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +020017 storageClassName: "waw-hdd-paranoid-2",
Serge Bazanskic0c037a2020-08-23 01:24:03 +000018 storageClassName3: "waw-hdd-redundant-3",
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +020019
Sergiusz Bazanskiec221a02020-07-17 12:50:18 +020020 synapseImage: "matrixdotorg/synapse:v1.17.0",
21 riotImage: "vectorim/riot-web:v1.7.1",
Sergiusz Bazanski735ac9c2020-07-17 12:10:42 +020022 casProxyImage: "registry.k0.hswaw.net/q3k/oauth2-cas-proxy:0.1.4",
23 appserviceIRCImage: "matrixdotorg/matrix-appservice-irc:release-0.17.1",
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020024 },
25
26 metadata(component):: {
Piotr Dobrowolski4b4231d2019-05-15 11:41:21 +020027 namespace: cfg.namespace,
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020028 labels: {
29 "app.kubernetes.io/name": "matrix",
30 "app.kubernetes.io/managed-by": "kubecfg",
31 "app.kubernetes.io/component": component,
32 },
33 },
34
Piotr Dobrowolski4b4231d2019-05-15 11:41:21 +020035 namespace: kube.Namespace(cfg.namespace),
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020036
Serge Bazanskic0c037a2020-08-23 01:24:03 +000037 postgres3: postgres {
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020038 cfg+: {
39 namespace: cfg.namespace,
40 appName: "synapse",
41 database: "synapse",
42 username: "synapse",
Serge Bazanskic0c037a2020-08-23 01:24:03 +000043 prefix: "waw3-",
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020044 password: { secretKeyRef: { name: "synapse", key: "postgres_password" } },
Serge Bazanskic0c037a2020-08-23 01:24:03 +000045 storageClassName: cfg.storageClassName3,
46 storageSize: "100Gi",
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020047 },
48 },
49
Serge Bazanskic0c037a2020-08-23 01:24:03 +000050 dataVolume: kube.PersistentVolumeClaim("synapse-data-waw3") {
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020051 metadata+: app.metadata("synapse-data"),
52 spec+: {
Serge Bazanskic0c037a2020-08-23 01:24:03 +000053 storageClassName: cfg.storageClassName3,
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020054 accessModes: [ "ReadWriteOnce" ],
55 resources: {
56 requests: {
57 storage: "50Gi",
58 },
59 },
60 },
61 },
Piotr Dobrowolskiffbb47c2019-05-16 12:18:39 +020062
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +020063 synapseConfig: kube.ConfigMap("synapse") {
64 metadata+: app.metadata("synapse"),
65 data: {
Piotr Dobrowolskieabbe8a2019-08-11 19:49:08 +020066 "homeserver.yaml": importstr "homeserver.yaml",
67 "log.config": importstr "log.config",
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +020068 },
69 },
70
71 casDeployment: kube.Deployment("oauth2-cas-proxy") {
72 metadata+: app.metadata("oauth2-cas-proxy"),
73 spec+: {
74 replicas: 1,
75 template+: {
76 spec+: {
77 containers_: {
78 proxy: kube.Container("oauth2-cas-proxy") {
79 image: cfg.casProxyImage,
80 ports_: {
81 http: { containerPort: 5000 },
82 },
83 env_: {
84 BASE_URL: "https://matrix.hackerspace.pl",
Piotr Dobrowolskiaa0e7552019-05-17 12:55:48 +020085 SERVICE_URL: "https://matrix.hackerspace.pl",
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +020086 OAUTH2_CLIENT: "matrix",
87 OAUTH2_SECRET: { secretKeyRef: { name: "oauth2-cas-proxy", key: "oauth2_secret" } },
88 },
89 },
90 },
91 },
92 },
93 },
94 },
95
96 casSvc: kube.Service("oauth2-cas-proxy") {
97 metadata+: app.metadata("oauth2-cas-proxy"),
98 target_pod:: app.casDeployment.spec.template,
99 },
100
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200101 synapseDeployment: kube.Deployment("synapse") {
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200102 metadata+: app.metadata("synapse"),
103 spec+: {
104 replicas: 1,
105 template+: {
106 spec+: {
107 volumes_: {
108 data: kube.PersistentVolumeClaimVolume(app.dataVolume),
Piotr Dobrowolski8ebfc1d2020-03-03 21:01:18 +0100109 config_template: kube.ConfigMapVolume(app.synapseConfig),
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200110 } + {
111 [k]: { secret: { secretName: "appservice-%s-registration" % [k] } }
112 for k in std.objectFields(app.appservices)
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200113 },
114 containers_: {
115 web: kube.Container("synapse") {
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200116 image: cfg.synapseImage,
Piotr Dobrowolski8ebfc1d2020-03-03 21:01:18 +0100117 command: ["/bin/sh", "-c", "/start.py migrate_config && exec /start.py"],
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200118 ports_: {
119 http: { containerPort: 8008 },
120 },
121 env_: {
Piotr Dobrowolski8ebfc1d2020-03-03 21:01:18 +0100122 SYNAPSE_CONFIG_DIR: "/config",
Piotr Dobrowolskieabbe8a2019-08-11 19:49:08 +0200123 SYNAPSE_CONFIG_PATH: "/config/homeserver.yaml",
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200124
Piotr Dobrowolski8ebfc1d2020-03-03 21:01:18 +0100125 # These values are not used in a template, but
126 # are required by /start.py migrate_config
127 SYNAPSE_SERVER_NAME: "hackerspace.pl",
128 SYNAPSE_REPORT_STATS: "no",
129
130 SYNAPSE_MACAROON_SECRET_KEY: { secretKeyRef: { name: "synapse", key: "macaroon_secret_key" } },
131 SYNAPSE_REGISTRATION_SHARED_SECRET: { secretKeyRef: { name: "synapse", key: "registration_shared_secret" } },
132 POSTGRES_PASSWORD: { secretKeyRef: { name: "synapse", key: "postgres_password" } },
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200133 },
134 volumeMounts_: {
135 data: { mountPath: "/data" },
Piotr Dobrowolski8ebfc1d2020-03-03 21:01:18 +0100136 config_template: {
137 mountPath: "/conf/homeserver.yaml",
138 subPath: "homeserver.yaml",
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +0200139 },
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200140 } + {
141 [k]: { mountPath: "/appservices/%s" % [k] }
142 for k in std.objectFields(app.appservices)
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200143 },
144 },
145 },
146 },
147 },
148 },
149 },
150
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200151 synapseSvc: kube.Service("synapse") {
Piotr Dobrowolskiffbb47c2019-05-16 12:18:39 +0200152 metadata+: app.metadata("synapse"),
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200153 target_pod:: app.synapseDeployment.spec.template,
Piotr Dobrowolskiffbb47c2019-05-16 12:18:39 +0200154 },
155
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200156 riotConfig: kube.ConfigMap("riot-web-config") {
157 metadata+: app.metadata("riot-web-config"),
158 data: {
159 "config.json": std.manifestJsonEx({
Piotr Dobrowolski4b4231d2019-05-15 11:41:21 +0200160 "default_hs_url": "https://%s" % [cfg.domain],
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200161 "disable_custom_urls": false,
162 "disable_guests": false,
163 "disable_login_language_selector": false,
Piotr Dobrowolski4b4231d2019-05-15 11:41:21 +0200164 "disable_3pid_login": true,
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200165 "brand": "Riot",
166 "integrations_ui_url": "https://scalar.vector.im/",
167 "integrations_rest_url": "https://scalar.vector.im/api",
168 "integrations_jitsi_widget_url": "https://scalar.vector.im/api/widgets/jitsi.html",
Piotr Dobrowolski4b4231d2019-05-15 11:41:21 +0200169
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200170 "bug_report_endpoint_url": "https://riot.im/bugreports/submit",
171 "features": {
172 "feature_groups": "labs",
173 "feature_pinning": "labs",
174 "feature_reactions": "labs"
175 },
176 "default_federate": true,
177 "default_theme": "light",
178 "roomDirectory": {
179 "servers": [
Piotr Dobrowolski4b4231d2019-05-15 11:41:21 +0200180 "hackerspace.pl"
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200181 ]
182 },
183 "welcomeUserId": "@riot-bot:matrix.org",
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200184 "enable_presence_by_hs_url": {
185 "https://matrix.org": false
186 }
187 }, ""),
188 },
189 },
190
191 riotDeployment: kube.Deployment("riot-web") {
192 metadata+: app.metadata("riot-web"),
193 spec+: {
194 replicas: 1,
195 template+: {
196 spec+: {
197 volumes_: {
198 config: kube.ConfigMapVolume(app.riotConfig),
199 },
200 containers_: {
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200201 web: kube.Container("riot-web") {
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200202 image: cfg.riotImage,
203 ports_: {
204 http: { containerPort: 80 },
205 },
206 volumeMounts_: {
207 config: {
Piotr Dobrowolskiaca7e282020-03-21 22:14:38 +0100208 mountPath: "/app/config.json",
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200209 subPath: "config.json",
210 },
211 },
212 },
213 },
214 },
215 },
216 },
217 },
218
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200219 riotSvc: kube.Service("riot-web") {
220 metadata+: app.metadata("riot-web"),
221 target_pod:: app.riotDeployment.spec.template,
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200222 },
223
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200224 appservices: {
225 "irc-freenode": app.AppServiceIrc("freenode") {
226 cfg+: {
227 metadata: app.metadata("appservice-irc-freenode"),
Sergiusz Bazanski92b48d62020-01-08 13:59:04 +0100228 // TODO(q3k): add labels to blessed nodes
229 nodeSelector: {
Serge Bazanski1b15dc42020-08-23 01:01:28 +0200230 "kubernetes.io/hostname": "bc01n03.hswaw.net",
Sergiusz Bazanski92b48d62020-01-08 13:59:04 +0100231 },
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200232 config+: {
233 homeserver+: {
234 url: "https://%s" % [cfg.domain],
235 domain: "%s" % [cfg.serverName],
236 },
Piotr Dobrowolskieabbe8a2019-08-11 19:49:08 +0200237 ircService+: {
238 servers+: {
239 "irc.freenode.net"+: {
240 ircClients+: {
241 maxClients: 150,
242 },
243 },
244 },
245 },
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200246 },
247 },
248 },
249 },
250
251 ingress: kube.Ingress("matrix") {
252 metadata+: app.metadata("matrix") {
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200253 annotations+: {
254 "kubernetes.io/tls-acme": "true",
255 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
256 "nginx.ingress.kubernetes.io/proxy-body-size": "0",
257 },
258 },
259 spec+: {
260 tls: [
261 {
262 hosts: [cfg.domain],
263 secretName: "synapse-tls",
264 },
265 ],
266 rules: [
267 {
268 host: cfg.domain,
269 http: {
270 paths: [
271 { path: "/", backend: app.riotSvc.name_port },
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200272 { path: "/_matrix", backend: app.synapseSvc.name_port },
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +0200273 { path: "/_cas", backend: app.casSvc.name_port },
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200274 ]
275 },
276 }
277 ],
278 },
279 },
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200280
281 AppServiceIrc(name):: {
282 local bridge = self,
283 local cfg = bridge.cfg,
284 cfg:: {
Sergiusz Bazanski735ac9c2020-07-17 12:10:42 +0200285 image: app.cfg.appserviceIRCImage,
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200286 metadata: {},
287 config: std.native("parseYaml")(importstr "appservice-irc.yaml")[0],
Piotr Dobrowolskib20b3662019-08-11 19:23:45 +0200288 storageClassName: app.cfg.storageClassName,
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200289 },
290
291 config: kube.ConfigMap("appservice-irc-%s" % [name]) {
292 metadata+: cfg.metadata,
293 data: {
294 "config.yaml": std.manifestJsonEx(cfg.config, ""),
295 },
296 },
297
298 dataVolume: kube.PersistentVolumeClaim("appservice-irc-%s" % [name]) {
299 metadata+: cfg.metadata,
300 spec+: {
301 storageClassName: cfg.storageClassName,
302 accessModes: [ "ReadWriteOnce" ],
303 resources: {
304 requests: {
305 storage: "10Gi",
306 },
307 },
308 },
309 },
310
311 bootstrapJob: kube.Job("appservice-irc-%s-bootstrap" % [name]) {
312 metadata+: cfg.metadata {
313 labels: {
314 "job-name": "appservice-irc-%s-bootstrap" % [name],
315 },
316 },
317 spec+: {
318 template+: {
319 spec+: {
320 volumes_: {
321 config: kube.ConfigMapVolume(bridge.config),
322 },
323 containers_: {
324 bootstrap: kube.Container("appservice-irc-%s-bootstrap" % [name]) {
325 image: cfg.image,
Piotr Dobrowolski57349d22020-03-21 22:15:18 +0100326 command: ["sh", "-c", "node app.js -r -u http://appservice-irc-%s:9999 -c /config/config.yaml -f /tmp/registration.yaml && cat /tmp/registration.yaml" % [name]],
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200327 volumeMounts_: {
328 config: { mountPath: "/config" },
329 },
330 },
331 },
332 },
333 },
334 },
335 },
336
337 deployment: kube.Deployment("appservice-irc-%s" % [name]) {
338 metadata+: cfg.metadata,
339 spec+: {
340 replicas: 1,
341 template+: {
342 spec+: {
343 volumes_: {
344 config: kube.ConfigMapVolume(bridge.config),
345 data: kube.PersistentVolumeClaimVolume(bridge.dataVolume),
346 registration: { secret: { secretName: "appservice-irc-%s-registration" % [name] } },
347 },
Sergiusz Bazanski92b48d62020-01-08 13:59:04 +0100348 nodeSelector: cfg.nodeSelector,
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200349 containers_: {
350 appserviceIrc: kube.Container("appservice-irc-%s" % [name]) {
351 image: cfg.image,
Piotr Dobrowolski57349d22020-03-21 22:15:18 +0100352 command: ["node", "app.js", "-c", "/config/config.yaml", "-f", "/registration/registration.yaml", "-p", "9999"],
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200353 ports_: {
354 http: { containerPort: 9999 },
355 },
356 volumeMounts_: {
357 registration: { mountPath: "/registration", },
358 config: { mountPath: "/config", },
359 data: { mountPath: "/data" },
360 },
361 },
362 },
363 },
364 },
365 },
366 },
367
368 svc: kube.Service("appservice-irc-%s" % [name]) {
369 metadata+: cfg.metadata,
370 target_pod:: bridge.deployment.spec.template,
371 },
372 },
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200373}