blob: 736cf873a2a9d35d5074abf537be137e64929e2d [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",
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +020018
Piotr Dobrowolskieabbe8a2019-08-11 19:49:08 +020019 synapseImage: "informatic/synapse:v1.2.1-env-conf-rev2", // https://github.com/Informatic/synapse/tree/env_config (to be upstreamed...)
20 riotImage: "bubuntux/riot-web:v1.3.2",
Sergiusz Bazanski5f3a5e02019-09-25 02:51:51 +020021 casProxyImage: "registry.k0.hswaw.net/q3k/oauth2-cas-proxy:0.1.4"
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020022 },
23
24 metadata(component):: {
Piotr Dobrowolski4b4231d2019-05-15 11:41:21 +020025 namespace: cfg.namespace,
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020026 labels: {
27 "app.kubernetes.io/name": "matrix",
28 "app.kubernetes.io/managed-by": "kubecfg",
29 "app.kubernetes.io/component": component,
30 },
31 },
32
Piotr Dobrowolski4b4231d2019-05-15 11:41:21 +020033 namespace: kube.Namespace(cfg.namespace),
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020034
35 postgres: postgres {
36 cfg+: {
37 namespace: cfg.namespace,
38 appName: "synapse",
39 database: "synapse",
40 username: "synapse",
41 password: { secretKeyRef: { name: "synapse", key: "postgres_password" } },
Piotr Dobrowolskib20b3662019-08-11 19:23:45 +020042 storageClassName: cfg.storageClassName,
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020043 },
44 },
45
46 dataVolume: kube.PersistentVolumeClaim("synapse-data") {
47 metadata+: app.metadata("synapse-data"),
48 spec+: {
49 storageClassName: cfg.storageClassName,
50 accessModes: [ "ReadWriteOnce" ],
51 resources: {
52 requests: {
53 storage: "50Gi",
54 },
55 },
56 },
57 },
Piotr Dobrowolskiffbb47c2019-05-16 12:18:39 +020058
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +020059 synapseConfig: kube.ConfigMap("synapse") {
60 metadata+: app.metadata("synapse"),
61 data: {
Piotr Dobrowolskieabbe8a2019-08-11 19:49:08 +020062 "homeserver.yaml": importstr "homeserver.yaml",
63 "log.config": importstr "log.config",
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +020064 },
65 },
66
67 casDeployment: kube.Deployment("oauth2-cas-proxy") {
68 metadata+: app.metadata("oauth2-cas-proxy"),
69 spec+: {
70 replicas: 1,
71 template+: {
72 spec+: {
73 containers_: {
74 proxy: kube.Container("oauth2-cas-proxy") {
75 image: cfg.casProxyImage,
76 ports_: {
77 http: { containerPort: 5000 },
78 },
79 env_: {
80 BASE_URL: "https://matrix.hackerspace.pl",
Piotr Dobrowolskiaa0e7552019-05-17 12:55:48 +020081 SERVICE_URL: "https://matrix.hackerspace.pl",
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +020082 OAUTH2_CLIENT: "matrix",
83 OAUTH2_SECRET: { secretKeyRef: { name: "oauth2-cas-proxy", key: "oauth2_secret" } },
84 },
85 },
86 },
87 },
88 },
89 },
90 },
91
92 casSvc: kube.Service("oauth2-cas-proxy") {
93 metadata+: app.metadata("oauth2-cas-proxy"),
94 target_pod:: app.casDeployment.spec.template,
95 },
96
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +020097 synapseDeployment: kube.Deployment("synapse") {
Piotr Dobrowolskia2226912019-05-14 18:49:29 +020098 metadata+: app.metadata("synapse"),
99 spec+: {
100 replicas: 1,
101 template+: {
102 spec+: {
103 volumes_: {
104 data: kube.PersistentVolumeClaimVolume(app.dataVolume),
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +0200105 config: kube.ConfigMapVolume(app.synapseConfig),
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200106 } + {
107 [k]: { secret: { secretName: "appservice-%s-registration" % [k] } }
108 for k in std.objectFields(app.appservices)
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200109 },
110 containers_: {
111 web: kube.Container("synapse") {
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200112 image: cfg.synapseImage,
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200113 ports_: {
114 http: { containerPort: 8008 },
115 },
116 env_: {
Piotr Dobrowolskieabbe8a2019-08-11 19:49:08 +0200117 SYNAPSE_CONFIG_PATH: "/config/homeserver.yaml",
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200118
Piotr Dobrowolskieabbe8a2019-08-11 19:49:08 +0200119 SYNAPSE_macaroon_secret_key: { secretKeyRef: { name: "synapse", key: "macaroon_secret_key" } },
120 SYNAPSE_registration_shared_secret: { secretKeyRef: { name: "synapse", key: "registration_shared_secret" } },
121 SYNAPSE_database__args__password: { secretKeyRef: { name: "synapse", key: "postgres_password" } },
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200122 },
123 volumeMounts_: {
124 data: { mountPath: "/data" },
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +0200125 config: {
Piotr Dobrowolskieabbe8a2019-08-11 19:49:08 +0200126 mountPath: "/config",
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +0200127 },
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200128 } + {
129 [k]: { mountPath: "/appservices/%s" % [k] }
130 for k in std.objectFields(app.appservices)
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200131 },
132 },
133 },
134 },
135 },
136 },
137 },
138
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200139 synapseSvc: kube.Service("synapse") {
Piotr Dobrowolskiffbb47c2019-05-16 12:18:39 +0200140 metadata+: app.metadata("synapse"),
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200141 target_pod:: app.synapseDeployment.spec.template,
Piotr Dobrowolskiffbb47c2019-05-16 12:18:39 +0200142 },
143
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200144 riotConfig: kube.ConfigMap("riot-web-config") {
145 metadata+: app.metadata("riot-web-config"),
146 data: {
147 "config.json": std.manifestJsonEx({
Piotr Dobrowolski4b4231d2019-05-15 11:41:21 +0200148 "default_hs_url": "https://%s" % [cfg.domain],
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200149 "disable_custom_urls": false,
150 "disable_guests": false,
151 "disable_login_language_selector": false,
Piotr Dobrowolski4b4231d2019-05-15 11:41:21 +0200152 "disable_3pid_login": true,
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200153 "brand": "Riot",
154 "integrations_ui_url": "https://scalar.vector.im/",
155 "integrations_rest_url": "https://scalar.vector.im/api",
156 "integrations_jitsi_widget_url": "https://scalar.vector.im/api/widgets/jitsi.html",
Piotr Dobrowolski4b4231d2019-05-15 11:41:21 +0200157
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200158 "bug_report_endpoint_url": "https://riot.im/bugreports/submit",
159 "features": {
160 "feature_groups": "labs",
161 "feature_pinning": "labs",
162 "feature_reactions": "labs"
163 },
164 "default_federate": true,
165 "default_theme": "light",
166 "roomDirectory": {
167 "servers": [
Piotr Dobrowolski4b4231d2019-05-15 11:41:21 +0200168 "hackerspace.pl"
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200169 ]
170 },
171 "welcomeUserId": "@riot-bot:matrix.org",
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200172 "enable_presence_by_hs_url": {
173 "https://matrix.org": false
174 }
175 }, ""),
176 },
177 },
178
179 riotDeployment: kube.Deployment("riot-web") {
180 metadata+: app.metadata("riot-web"),
181 spec+: {
182 replicas: 1,
183 template+: {
184 spec+: {
185 volumes_: {
186 config: kube.ConfigMapVolume(app.riotConfig),
187 },
188 containers_: {
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200189 web: kube.Container("riot-web") {
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200190 image: cfg.riotImage,
191 ports_: {
192 http: { containerPort: 80 },
193 },
194 volumeMounts_: {
195 config: {
196 mountPath: "/etc/riot-web/config.json",
197 subPath: "config.json",
198 },
199 },
200 },
201 },
202 },
203 },
204 },
205 },
206
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200207 riotSvc: kube.Service("riot-web") {
208 metadata+: app.metadata("riot-web"),
209 target_pod:: app.riotDeployment.spec.template,
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200210 },
211
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200212 appservices: {
213 "irc-freenode": app.AppServiceIrc("freenode") {
214 cfg+: {
215 metadata: app.metadata("appservice-irc-freenode"),
Sergiusz Bazanski92b48d62020-01-08 13:59:04 +0100216 // TODO(q3k): add labels to blessed nodes
217 nodeSelector: {
218 "kubernetes.io/hostname": "bc01n02.hswaw.net",
219 },
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200220 config+: {
221 homeserver+: {
222 url: "https://%s" % [cfg.domain],
223 domain: "%s" % [cfg.serverName],
224 },
Piotr Dobrowolskieabbe8a2019-08-11 19:49:08 +0200225 ircService+: {
226 servers+: {
227 "irc.freenode.net"+: {
228 ircClients+: {
229 maxClients: 150,
230 },
231 },
232 },
233 },
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200234 },
235 },
236 },
237 },
238
239 ingress: kube.Ingress("matrix") {
240 metadata+: app.metadata("matrix") {
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200241 annotations+: {
242 "kubernetes.io/tls-acme": "true",
243 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
244 "nginx.ingress.kubernetes.io/proxy-body-size": "0",
245 },
246 },
247 spec+: {
248 tls: [
249 {
250 hosts: [cfg.domain],
251 secretName: "synapse-tls",
252 },
253 ],
254 rules: [
255 {
256 host: cfg.domain,
257 http: {
258 paths: [
259 { path: "/", backend: app.riotSvc.name_port },
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200260 { path: "/_matrix", backend: app.synapseSvc.name_port },
Piotr Dobrowolskic39fb042019-05-17 09:13:56 +0200261 { path: "/_cas", backend: app.casSvc.name_port },
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200262 ]
263 },
264 }
265 ],
266 },
267 },
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200268
269 AppServiceIrc(name):: {
270 local bridge = self,
271 local cfg = bridge.cfg,
272 cfg:: {
Piotr Dobrowolskieabbe8a2019-08-11 19:49:08 +0200273 image: "registry.k0.hswaw.net/informatic/matrix-appservice-irc:0.12.0",
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200274 metadata: {},
275 config: std.native("parseYaml")(importstr "appservice-irc.yaml")[0],
Piotr Dobrowolskib20b3662019-08-11 19:23:45 +0200276 storageClassName: app.cfg.storageClassName,
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200277 },
278
279 config: kube.ConfigMap("appservice-irc-%s" % [name]) {
280 metadata+: cfg.metadata,
281 data: {
282 "config.yaml": std.manifestJsonEx(cfg.config, ""),
283 },
284 },
285
286 dataVolume: kube.PersistentVolumeClaim("appservice-irc-%s" % [name]) {
287 metadata+: cfg.metadata,
288 spec+: {
289 storageClassName: cfg.storageClassName,
290 accessModes: [ "ReadWriteOnce" ],
291 resources: {
292 requests: {
293 storage: "10Gi",
294 },
295 },
296 },
297 },
298
299 bootstrapJob: kube.Job("appservice-irc-%s-bootstrap" % [name]) {
300 metadata+: cfg.metadata {
301 labels: {
302 "job-name": "appservice-irc-%s-bootstrap" % [name],
303 },
304 },
305 spec+: {
306 template+: {
307 spec+: {
308 volumes_: {
309 config: kube.ConfigMapVolume(bridge.config),
310 },
311 containers_: {
312 bootstrap: kube.Container("appservice-irc-%s-bootstrap" % [name]) {
313 image: cfg.image,
314 command: ["sh", "-c", "matrix-appservice-irc -r -u http://appservice-irc-%s:9999 -c /config/config.yaml -f /tmp/registration.yaml && cat /tmp/registration.yaml" % [name]],
315 volumeMounts_: {
316 config: { mountPath: "/config" },
317 },
318 },
319 },
320 },
321 },
322 },
323 },
324
325 deployment: kube.Deployment("appservice-irc-%s" % [name]) {
326 metadata+: cfg.metadata,
327 spec+: {
328 replicas: 1,
329 template+: {
330 spec+: {
331 volumes_: {
332 config: kube.ConfigMapVolume(bridge.config),
333 data: kube.PersistentVolumeClaimVolume(bridge.dataVolume),
334 registration: { secret: { secretName: "appservice-irc-%s-registration" % [name] } },
335 },
Sergiusz Bazanski92b48d62020-01-08 13:59:04 +0100336 nodeSelector: cfg.nodeSelector,
Piotr Dobrowolskifef4c122019-05-16 21:05:02 +0200337 containers_: {
338 appserviceIrc: kube.Container("appservice-irc-%s" % [name]) {
339 image: cfg.image,
340 command: ["matrix-appservice-irc", "-c", "/config/config.yaml", "-f", "/registration/registration.yaml", "-p", "9999"],
341 ports_: {
342 http: { containerPort: 9999 },
343 },
344 volumeMounts_: {
345 registration: { mountPath: "/registration", },
346 config: { mountPath: "/config", },
347 data: { mountPath: "/data" },
348 },
349 },
350 },
351 },
352 },
353 },
354 },
355
356 svc: kube.Service("appservice-irc-%s" % [name]) {
357 metadata+: cfg.metadata,
358 target_pod:: bridge.deployment.spec.template,
359 },
360 },
Piotr Dobrowolskia2226912019-05-14 18:49:29 +0200361}