From d20774f507e884c7218502df31752ac8ba996631 Mon Sep 17 00:00:00 2001 From: Daniel Berteaud Date: Thu, 21 Dec 2023 11:48:16 +0100 Subject: [PATCH] More work on Synapse + Element + Synapse admin --- consul/config/service-intentions/matrix.hcl | 6 ++ images/matrix-element/Dockerfile | 10 ++- .../nginx/conf.d/default.conf.template | 0 .../root/entrypoint.d/50-synapse-conf.sh | 2 + .../root/usr/local/bin/matrix-synapse | 6 +- matrix.nomad.hcl | 63 ++++++++++--------- templates/element.json.tpl | 39 ++++++++++++ templates/homeserver.yml.tpl | 28 ++++----- templates/logging.conf.tpl | 27 ++++++++ templates/nginx.conf.tpl | 50 ++++++++++++--- variables.yml | 61 +++++++++++++++--- 11 files changed, 225 insertions(+), 67 deletions(-) rename images/matrix-element/root/{ => etc}/nginx/conf.d/default.conf.template (100%) create mode 100644 templates/element.json.tpl create mode 100644 templates/logging.conf.tpl diff --git a/consul/config/service-intentions/matrix.hcl b/consul/config/service-intentions/matrix.hcl index e61a81a..422a79b 100644 --- a/consul/config/service-intentions/matrix.hcl +++ b/consul/config/service-intentions/matrix.hcl @@ -10,6 +10,12 @@ Sources = [ PathRegex = "^/_(matrix|synapse)/.*" Methods = ["GET", "HEAD", "POST", "OPTIONS", "PUT", "DELETE"] } + }, + { + Action = "allow" + HTTP { + Methods = ["GET", "HEAD"] + } } ] } diff --git a/images/matrix-element/Dockerfile b/images/matrix-element/Dockerfile index 7729e5f..b09f0b6 100644 --- a/images/matrix-element/Dockerfile +++ b/images/matrix-element/Dockerfile @@ -1,7 +1,8 @@ FROM nginxinc/nginx-unprivileged:alpine MAINTAINER [[ .docker.maintainer ]] -ARG ELEMENT_VERSION=1.11.51 +ARG ELEMENT_VERSION=1.11.52 \ + SYNAPSE_ADMIN_VERSION=0.8.7 ENV ELEMENT_NGINX_BIND_ADDR=0.0.0.0 \ ELEMENT_NGINX_BIND_PORT=8710 @@ -10,8 +11,13 @@ USER root RUN set -eux &&\ mkdir -p /opt/element &&\ + mkdir -p /opt/synapse-admin &&\ curl -sSL https://github.com/element-hq/element-web/releases/download/v${ELEMENT_VERSION}/element-v${ELEMENT_VERSION}.tar.gz |\ - tar xvz -C /opt/element/ --strip-components 1 + tar xvz -C /opt/element/ --strip-components 1 &&\ + curl -sSL https://github.com/Awesome-Technologies/synapse-admin/releases/download/${SYNAPSE_ADMIN_VERSION}/synapse-admin-${SYNAPSE_ADMIN_VERSION}-dirty.tar.gz |\ + tar xvz -C /opt/synapse-admin --strip-components 1 &&\ + rm -rf /opt/synapse-admin/data/* &&\ + chown -R root: /opt/element /opt/synapse-admin USER nginx EXPOSE ${ELEMENT_BIND_PORT} diff --git a/images/matrix-element/root/nginx/conf.d/default.conf.template b/images/matrix-element/root/etc/nginx/conf.d/default.conf.template similarity index 100% rename from images/matrix-element/root/nginx/conf.d/default.conf.template rename to images/matrix-element/root/etc/nginx/conf.d/default.conf.template diff --git a/images/matrix-synapse/root/entrypoint.d/50-synapse-conf.sh b/images/matrix-synapse/root/entrypoint.d/50-synapse-conf.sh index 0b13891..7b25be2 100755 --- a/images/matrix-synapse/root/entrypoint.d/50-synapse-conf.sh +++ b/images/matrix-synapse/root/entrypoint.d/50-synapse-conf.sh @@ -4,6 +4,8 @@ set -euo pipefail source /opt/synapse/venv/bin/activate +umask 007 + if [ ! -e "${SYNAPSE_CONFIG}" ]; then echo "Generating a default ${SYNAPSE_CONFIG}" if [ -z "${SYNAPSE_SERVER_NAME}" ]; then diff --git a/images/matrix-synapse/root/usr/local/bin/matrix-synapse b/images/matrix-synapse/root/usr/local/bin/matrix-synapse index 576251f..8e65718 100755 --- a/images/matrix-synapse/root/usr/local/bin/matrix-synapse +++ b/images/matrix-synapse/root/usr/local/bin/matrix-synapse @@ -3,4 +3,8 @@ set -euo pipefail source /opt/synapse/venv/bin/activate -exec python3 -m synapse.app.homeserver -c ${SYNAPSE_CONFIG} +exec python3 -m synapse.app.homeserver \ + --config-path ${SYNAPSE_CONFIG} \ + --config-directory=/data/conf \ + --keys-directory=/data/conf \ + --data-directory=/data diff --git a/matrix.nomad.hcl b/matrix.nomad.hcl index 72f033d..d89d82d 100644 --- a/matrix.nomad.hcl +++ b/matrix.nomad.hcl @@ -29,6 +29,21 @@ job [[ .instance | toJSON ]] { } } + tags = [ +[[- $w := merge .matrix.nginx . ]] + "[[ $w.traefik.instance ]].enable=[[ $w.traefik.enabled ]]", + + "[[ $c.traefik.instance ]].http.middlewares.[[ .instance ]]-headers[[ .consul.suffix ]].headers.contentsecuritypolicy=[[ range $k, $v := $w.traefik.csp ]][[ $k ]] [[ $v ]];[[ end ]]", + + "[[ $w.traefik.instance ]].http.routers.[[ .instance ]]-admin[[ .consul.suffix ]].rule=Host(`[[ (urlParse .matrix.public_url).Hostname ]]`) && (PathPrefix(`/_admin/`) || PathPrefix(`/_synapse/admin`))", + "[[ $w.traefik.instance ]].http.routers.[[ .instance ]]-admin[[ .consul.suffix ]].entrypoints=[[ join $w.traefik.entrypoints "," ]]", + "[[ $w.traefik.instance ]].http.routers.[[ .instance ]]-admin[[ .consul.suffix ]].middlewares=[[ template "common/traefik_middlewares" $w.traefik.admin ]]", + + "[[ $w.traefik.instance ]].http.routers.[[ .instance ]][[ .consul.suffix ]].rule=Host(`[[ (urlParse .matrix.public_url).Hostname ]]`) || (Host(`[[ .matrix.server_name ]]`) && PathRegexp(`^/(_(synapse|matrix)|\\.well-known/matrix)/.*`))", + "[[ $w.traefik.instance ]].http.routers.[[ .instance ]][[ .consul.suffix ]].entrypoints=[[ join $w.traefik.entrypoints "," ]]", + "[[ $w.traefik.instance ]].http.routers.[[ .instance ]][[ .consul.suffix ]].middlewares=[[ template "common/traefik_middlewares" $w.traefik ]]", + ] + [[ template "common/connect" merge .matrix . ]] } @@ -67,6 +82,13 @@ _EOT perms = 0640 } + template { + data =<<_EOT +[[ template "matrix/logging.conf.tpl" . ]] +_EOT + destination = "secrets/logging.conf" + } + volume_mount { volume = "data" destination = "/data" @@ -75,55 +97,34 @@ _EOT [[ template "common/resources" $c.resources ]] } -[[ $c = merge .matrix.element . ]] - task "element" { - driver = [[ $c.nomad.driver | toJSON ]] - - lifecycle { - hook = "prestart" - sidecar = true - } - - config { - image = [[ $c.image | toJSON ]] - readonly_rootfs = true - pids_limit = 100 - [[ template "common/tmpfs" dict "size" "5000000" "target" "/tmp" ]] - } - - env { - ELEMENT_BIND_ADDR = "127.0.0.1" - ELEMENT_NGINX_BIND_PORT = "8710" - } - -[[ template "common/resources" $c.resources ]] - } - [[ $c = merge .matrix.nginx . ]] task "nginx" { driver = [[ $c.nomad.driver | toJSON ]] - lifecycle { - hook = "prestart" - sidecar = true - } - config { image = [[ $c.image | toJSON ]] readonly_rootfs = true pids_limit = 100 volumes = [ - "local/nginx.conf:/etc/nginx/conf.d/default.conf" + "local/nginx.conf:/etc/nginx/conf.d/default.conf:ro", ] [[ template "common/tmpfs" dict "size" "5000000" "target" "/tmp" ]] } template { data =<<_EOT -[[ template "matrix/nginx.conf.tpl" ]] +[[ template "matrix/nginx.conf.tpl" . ]] _EOT destination = "local/nginx.conf" } + + template { + data =<<_EOT +[[ template "matrix/element.json.tpl" . ]] +_EOT + destination = "local/element.json" + } + [[ template "common/resources" $c.resources ]] } } diff --git a/templates/element.json.tpl b/templates/element.json.tpl new file mode 100644 index 0000000..187b391 --- /dev/null +++ b/templates/element.json.tpl @@ -0,0 +1,39 @@ +{ + "default_server_config": { + "m.homeserver": { + "base_url": "[[ .matrix.public_url ]]", + "server_name": "[[ .matrix.server_name ]]" + }, + "m.identity_server": { + "base_url": "https://vector.im" + } + }, + "brand": "Element", + "integrations_ui_url": "https://scalar.vector.im/", + "integrations_rest_url": "https://scalar.vector.im/api", + "integrations_widgets_urls": [ + "https://scalar.vector.im/_matrix/integrations/v1", + "https://scalar.vector.im/api", + "https://scalar-staging.vector.im/_matrix/integrations/v1", + "https://scalar-staging.vector.im/api", + "https://scalar-staging.element.im/scalar/api" + ], + "show_labs_settings": true, + "roomDirectory": { + "servers": [ + "matrix.org" + ] + }, + "disable_guests": [[ .matrix.allow_guests | ternary "false" "true" ]], +[[ if and (has .matrix "jitsi") (has .matrix.jitsi "domain") ]] + "jitsi": { + "preferredDomain": "[[ .matrix.jitsi.domain ]]" + }, +[[ end ]] + "settingDefaults": { + "UIFeature.feedback": false, + "UIFeature.thirdPartyId": false + }, + "map_style_url": "[[ .matrix.element.map_style_url ]]", + "happyJson": true +} diff --git a/templates/homeserver.yml.tpl b/templates/homeserver.yml.tpl index 3b32b56..7b027ba 100644 --- a/templates/homeserver.yml.tpl +++ b/templates/homeserver.yml.tpl @@ -2,7 +2,6 @@ server_name: [[ .matrix.server_name ]] public_baseurl: [[ .matrix.public_url ]] -serve_server_wellknown: true report_stats: false web_client: false @@ -52,27 +51,22 @@ media_retention: local_media_lifetime: 730d remote_media_lifetime: 14d +[[ if .matrix.synapse.url_preview.enabled ]] url_preview_enabled: true url_preview_ip_range_blacklist: - - '127.0.0.0/8' - - '10.0.0.0/8' - - '172.16.0.0/12' - - '192.168.0.0/16' - - '100.64.0.0/10' - - '192.0.0.0/24' - - '169.254.0.0/16' - - '192.88.99.0/24' - - '198.18.0.0/15' - - '192.0.2.0/24' - - '198.51.100.0/24' - - '203.0.113.0/24' - - '224.0.0.0/4' + [[- range $idx, $black := .matrix.synapse.url_preview.ip_range_blacklist ]] + - [[ $black ]] + [[- end ]] url_preview_url_blacklist: - - username: '*' - - netloc: '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' + [[- range $idx, $black := .matrix.synapse.url_preview.url_blacklist ]] + - [[ $black | toYAML ]] + [[- end ]] +[[- end ]] default_identity_server: https://matrix.org +allow_guest_access: [[ .matrix.allow_guests ]] + macaroon_secret_key: '[[ .matrix.synapse.macaroon_secret_key ]]' form_secret: '[[ .matrix.synapse.form_secret ]]' @@ -96,3 +90,5 @@ alias_creation_rules: alias: '*' action: allow +log_config: /secrets/logging.conf +signing_key_path: /data/conf/[[ .matrix.server_name ]].signing.key diff --git a/templates/logging.conf.tpl b/templates/logging.conf.tpl new file mode 100644 index 0000000..907e09a --- /dev/null +++ b/templates/logging.conf.tpl @@ -0,0 +1,27 @@ +version: 1 + +formatters: + precise: + format: '%(name)s - %(lineno)d - %(levelname)s - %(request)s- %(message)s' + +filters: + context: + (): synapse.util.logcontext.LoggingContextFilter + request: "" + +handlers: + console: + class: logging.StreamHandler + formatter: precise + filters: [context] + +loggers: + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: INFO + +root: + level: INFO + handlers: [console] + diff --git a/templates/nginx.conf.tpl b/templates/nginx.conf.tpl index 0b929dd..166dc90 100644 --- a/templates/nginx.conf.tpl +++ b/templates/nginx.conf.tpl @@ -2,10 +2,6 @@ upstream synapse { server unix:/alloc/tmp/synapse.sock; } -upstream element { - server 127.0.0.1:8710; -} - map $http_upgrade $connection_upgrade { default upgrade; '' close; @@ -14,13 +10,18 @@ map $http_upgrade $connection_upgrade { server { listen 127.0.0.1:8008 default_server; server_tokens off; - root /usr/share/html; + root /opt/element; + index index.html; + include /etc/nginx/mime.types; + default_type application/octet-stream; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; proxy_socket_keepalive on; + proxy_buffering off; + proxy_request_buffering off; client_max_body_size 100m; set_real_ip_from 127.0.0.1; real_ip_header X-Forwarded-For; @@ -30,14 +31,49 @@ server { proxy_pass http://synapse; proxy_read_timeout 600; } + location /_synapse { proxy_pass http://synapse; proxy_read_timeout 600; } - location /health { + + location = /health { proxy_pass http://synapse; } + + location /index.html { + add_header Cache-Control "no-cache"; + } + + location /version { + add_header Cache-Control "no-cache"; + } + + location /config.json { + add_header Cache-Control "no-cache"; + alias /local/element.json; + } + + location /.well-known/matrix/server { + add_header Access-Control-Allow-Origin *; + default_type application/json; + expires 6h; + return 200 '{"m.server": "[[ (urlParse .matrix.public_url).Hostname ]]:[[ if eq (urlParse .matrix.public_url).Port "" ]]443[[ else ]][[ (urlParse .matrix.public_url).Port ]][[ end ]]"}'; + } + location /.well-known/matrix/client { + add_header Access-Control-Allow-Origin *; + default_type application/json; + expires 6h; + return 200 '{"m.homeserver": {"base_url": "[[ .matrix.public_url ]]"}}'; + } + + # Expose synapse admin + location /_admin/ { + alias /opt/synapse-admin/; + expires 30d; + } + # default files location / { - proxy_pass http://element; + expires 30d; } } diff --git a/variables.yml b/variables.yml index a6e3037..0aa5d6b 100644 --- a/variables.yml +++ b/variables.yml @@ -6,6 +6,7 @@ matrix: server_name: matrix.[[ .consul.domain ]] public_url: https://matrix.[[ .consul.domain ]] + allow_guests: false consul: connect: @@ -15,7 +16,7 @@ matrix: synapse: - image: '[[ .docker.repo ]]matrix-synapse:latest' + image: '[[ .docker.repo ]]matrix-synapse:1.98.0-1' env: {} @@ -23,6 +24,26 @@ matrix: macaroon_secret_key: '{{ with secret "[[ .vault.prefix ]]kv/service/[[ .instance ]]" }}{{ .Data.data.macaroon_secret_key }}{{ end }}' form_secret: '{{ with secret "[[ .vault.prefix ]]kv/service/[[ .instance ]]" }}{{ .Data.data.form_secret }}{{ end }}' + + url_preview: + enabled: true + ip_range_blacklist: + - 127.0.0.0/8 + - 10.0.0.0/8 + - 172.16.0.0/12 + - 192.168.0.0/16 + - 100.64.0.0/10 + - 192.0.0.0/24 + - 169.254.0.0/16 + - 192.88.99.0/24 + - 198.18.0.0/15 + - 192.0.2.0/24 + - 198.51.100.0/24 + - 203.0.113.0/24 + - 224.0.0.0/4 + url_blacklist: + - username: '*' + - netloc: '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' db: host: 127.0.0.1 @@ -37,23 +58,43 @@ matrix: resources: cpu: 500 memory: 384 - + element: - image: '[[ .docker.repo ]]matrix-element:latest' + map_style_url: https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx - env: {} - - resources: - cpu: 20 - memory: 16 - nginx: - image: nginxinc/nginx-unprivileged:alpine + image: '[[ .docker.repo ]]matrix-element:1.11.52-1' resources: cpu: 20 memory: 16 + traefik: + enabled: true + csp: + script-src: "'self' https://usercontent.riot.im https://scalar.vector.im" + worker-src: "'self' blob:" + connect-src: "'self' https://scalar.vector.im https://api.maptiler.com" + img-src: "'self' data: blob: https://img.youtube.com https://*.ytimg.com" + frame-src: "'self' blob: https://scalar.vector.im/ https://meet.element.io" + middlewares: [] + # Override base_middlewares to remove csp-relaxed@file + base_middlewares: + - rate-limit-high@file + - inflight-high@file + - security-headers@file + - hsts@file + - compression@file + + admin: + base_middlewares: + - rate-limit-high@file + - inflight-high@file + - security-headers@file + - hsts@file + - compression@file + middlewares: [] + volumes: data: type: csi