From 299a8c4c7c72244c8b4221927b0a740f5b9a4bb2 Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Sun, 27 Jan 2019 20:25:13 +0200 Subject: [PATCH] Make (most) containers start as non-root This makes all containers (except mautrix-telegram and mautrix-whatsapp), start as a non-root user. We do this, because we don't trust some of the images. In any case, we'd rather not trust ALL images and avoid giving `root` access at all. We can't be sure they would drop privileges or what they might do before they do it. Because Postfix doesn't support running as non-root, it had to be replaced by an Exim mail server. The matrix-nginx-proxy nginx container image is patched up (by replacing its main configuration) so that it can work as non-root. It seems like there's no other good image that we can use and that is up-to-date (https://hub.docker.com/r/nginxinc/nginx-unprivileged is outdated). Likewise for riot-web (https://hub.docker.com/r/bubuntux/riot-web/), we patch it up ourselves when starting (replacing the main nginx configuration). Ideally, it would be fixed upstream so we can simplify. --- CHANGELOG.md | 26 ++++ README.md | 4 +- docs/configuring-playbook-email.md | 6 +- group_vars/matrix-servers | 4 +- roles/matrix-mailer/defaults/main.yml | 9 +- roles/matrix-mailer/templates/env-mailer.j2 | 9 +- .../systemd/matrix-mailer.service.j2 | 2 + roles/matrix-nginx-proxy/defaults/main.yml | 3 + .../tasks/setup_nginx_proxy.yml | 18 ++- roles/matrix-nginx-proxy/tasks/ssl/main.yml | 1 + ...tup_ssl_lets_encrypt_obtain_for_domain.yml | 10 +- .../conf.d}/matrix-riot-web.conf.j2 | 10 +- .../conf.d}/matrix-synapse.conf.j2 | 8 +- .../conf.d}/nginx-http.conf.j2 | 0 .../templates/nginx/nginx.conf.j2 | 45 +++++++ .../systemd/matrix-nginx-proxy.service.j2 | 6 +- ...rix-ssl-lets-encrypt-certificates-renew.j2 | 7 +- .../matrix-postgres/tasks/import_postgres.yml | 5 +- .../tasks/upgrade_postgres.yml | 2 + .../matrix-riot-web/tasks/setup_riot_web.yml | 1 + roles/matrix-riot-web/templates/nginx.conf.j2 | 60 +++++++++ .../systemd/matrix-riot-web.service.j2 | 5 +- .../tasks/ext/mautrix-telegram/setup.yml | 126 +++++++++--------- .../synapse/systemd/matrix-synapse.service.j2 | 8 +- 24 files changed, 272 insertions(+), 103 deletions(-) rename roles/matrix-nginx-proxy/templates/{nginx-conf.d => nginx/conf.d}/matrix-riot-web.conf.j2 (85%) rename roles/matrix-nginx-proxy/templates/{nginx-conf.d => nginx/conf.d}/matrix-synapse.conf.j2 (94%) rename roles/matrix-nginx-proxy/templates/{nginx-conf.d => nginx/conf.d}/nginx-http.conf.j2 (100%) create mode 100644 roles/matrix-nginx-proxy/templates/nginx/nginx.conf.j2 create mode 100644 roles/matrix-riot-web/templates/nginx.conf.j2 diff --git a/CHANGELOG.md b/CHANGELOG.md index d96635b6..d3539962 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,29 @@ +# 2019-01-xx + +## Running container processes as non-root + +To improve security, this playbook no longer starts container processes as the `root` user. + +Usually, most containers were dropping privileges anyway, but by the time they do that, we were trusting them with `root` privileges. +Not anymore -- container processes now start as a non-root user (usually `matrix`) from the get-go. + +The only images that we still start as `root` and trust to drop privileges are the optional bridge extensions (disabled by default): + +- [tulir/mautrix-telegram](https://hub.docker.com/r/tulir/mautrix-telegram) +- [tulir/mautrix-whatsapp](https://hub.docker.com/r/tulir/mautrix-whatsapp) + + +## matrix-mailer is now based on Exim, not Postfix + +While we would have preferred to stay with [Postfix](http://www.postfix.org/), we found out that it cannot run as a non-root user. +We've had to replace it with [Exim](https://www.exim.org/) (via the [devture/exim-relay](https://hub.docker.com/r/devture/exim-relay) container image). + +The internal `matrix-mailer` service (running in a container) now listens on port `8025` (used to be `587` before). +The playbook will update your Synapse and mxisd email settings to match (`matrix-mailer:587` -> `matrix-mailer:8025`). + +Using the [devture/exim-relay](https://hub.docker.com/r/devture/exim-relay) container image instead of [panubo/postfix](https://hub.docker.com/r/panubo/postfix/) also gives us a nice disk usage reduction (~200MB -> 8MB). + + # 2019-01-17 ## (BC Break) Making the playbook's roles more independent of one another diff --git a/README.md b/README.md index 2b18df77..b43ba590 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Using this playbook, you can get the following services configured on your serve - (optional, default) an [mxisd](https://github.com/kamax-io/mxisd) Matrix Identity server -- (optional, default) a [Postfix](http://www.postfix.org/) mail server, through which all Matrix services send outgoing email (can be configured to relay through another SMTP server) +- (optional, default) an [Exim](https://www.exim.org/) mail server, through which all Matrix services send outgoing email (can be configured to relay through another SMTP server) - (optional, default) an [nginx](http://nginx.org/) web server, listening on ports 80 and 443 - standing in front of all the other services. Using your own webserver [is possible](docs/configuring-playbook-own-webserver.md) @@ -98,7 +98,7 @@ This playbook sets up your server using the following Docker images: - [ewoutp/goofys](https://hub.docker.com/r/ewoutp/goofys/) - the [Goofys](https://github.com/kahing/goofys) Amazon [S3](https://aws.amazon.com/s3/) file-system-mounting program (optional) -- [panubo/postfix](https://hub.docker.com/r/panubo/postfix/) - the [Postfix](http://www.postfix.org/) email server (optional) +- [devture/exim-relay](https://hub.docker.com/r/devture/exim-relay/) - the [Exim](https://www.exim.org/) email server (optional) - [devture/matrix-corporal](https://hub.docker.com/r/devture/matrix-corporal/) - [Matrix Corporal](https://github.com/devture/matrix-corporal): reconciliator and gateway for a managed Matrix server (optional) diff --git a/docs/configuring-playbook-email.md b/docs/configuring-playbook-email.md index 7fb35eed..59e080f3 100644 --- a/docs/configuring-playbook-email.md +++ b/docs/configuring-playbook-email.md @@ -1,6 +1,6 @@ # Adjusting email-sending settings (optional) -By default, this playbook sets up a [postfix](http://www.postfix.org/) email server through which all Matrix services send emails. +By default, this playbook sets up an [Exim](https://www.exim.org/) email server through which all Matrix services send emails. The email server would attempt to deliver emails directly to their final destination. This may or may not work, depending on your domain configuration (SPF settings, etc.) @@ -28,9 +28,7 @@ matrix_mailer_relay_auth_username: "another.sender@example.com" matrix_mailer_relay_auth_password: "some-password" ``` -Keep in mind that postfix will look up the MX record of your relay host (`matrix_mailer_relay_host_name`) and, if available, will actually use that instead of what you've defined. This behavior is [documented here](http://www.postfix.org/postconf.5.html#relayhost). If you'd like to suppress this and use the relay host value as is, wrap it in square brackets (e.g. `matrix_mailer_relay_host_name: "[mail.example.com]"`). - ## Troubleshooting -If you're having trouble with email not being delivered, it may be useful to inspect the mailer logs: `journalctl -f -u matrix-mailer`. \ No newline at end of file +If you're having trouble with email not being delivered, it may be useful to inspect the mailer logs: `journalctl -f -u matrix-mailer`. diff --git a/group_vars/matrix-servers b/group_vars/matrix-servers index 3167c612..70d63256 100644 --- a/group_vars/matrix-servers +++ b/group_vars/matrix-servers @@ -125,7 +125,7 @@ matrix_mxisd_dns_overwrite_homeserver_client_value: "http://{{ 'matrix-corporal: # By default, we send mail through the `matrix-mailer` service. matrix_mxisd_threepid_medium_email_identity_from: "{{ matrix_mailer_sender_address }}" matrix_mxisd_threepid_medium_email_connectors_smtp_host: "matrix-mailer" -matrix_mxisd_threepid_medium_email_connectors_smtp_port: 587 +matrix_mxisd_threepid_medium_email_connectors_smtp_port: 8025 matrix_mxisd_threepid_medium_email_connectors_smtp_tls: 0 matrix_mxisd_systemd_wanted_services_list: | @@ -269,7 +269,7 @@ matrix_synapse_database_database: "{{ matrix_postgres_db_name }}" matrix_synapse_email_enabled: "{{ matrix_mailer_enabled }}" matrix_synapse_email_smtp_host: "matrix-mailer" -matrix_synapse_email_smtp_port: 587 +matrix_synapse_email_smtp_port: 8025 matrix_synapse_email_smtp_require_transport_security: false matrix_synapse_email_notif_from: "Matrix <{{ matrix_mailer_sender_address }}>" matrix_synapse_email_riot_base_url: "https://{{ hostname_riot }}" diff --git a/roles/matrix-mailer/defaults/main.yml b/roles/matrix-mailer/defaults/main.yml index a820f087..3b652799 100644 --- a/roles/matrix-mailer/defaults/main.yml +++ b/roles/matrix-mailer/defaults/main.yml @@ -2,7 +2,12 @@ matrix_mailer_enabled: true matrix_mailer_base_path: "{{ matrix_base_data_path }}/mailer" -matrix_mailer_docker_image: "panubo/postfix:latest" +matrix_mailer_docker_image: "devture/exim-relay:4.91-r1-0" + +# The user/group that the container runs with. +# These match the `exim` user/group within the container image. +matrix_mailer_container_user_uid: 100 +matrix_mailer_container_user_gid: 101 matrix_mailer_sender_address: "matrix@{{ hostname_identity }}" matrix_mailer_relay_use: false @@ -10,4 +15,4 @@ matrix_mailer_relay_host_name: "mail.example.com" matrix_mailer_relay_host_port: 587 matrix_mailer_relay_auth: false matrix_mailer_relay_auth_username: "" -matrix_mailer_relay_auth_password: "" \ No newline at end of file +matrix_mailer_relay_auth_password: "" diff --git a/roles/matrix-mailer/templates/env-mailer.j2 b/roles/matrix-mailer/templates/env-mailer.j2 index 9cacf789..7765b8f9 100644 --- a/roles/matrix-mailer/templates/env-mailer.j2 +++ b/roles/matrix-mailer/templates/env-mailer.j2 @@ -1,8 +1,7 @@ -MAILNAME={{ hostname_matrix }} {% if matrix_mailer_relay_use %} -RELAYHOST={{ matrix_mailer_relay_host_name }}:{{ matrix_mailer_relay_host_port }} +SMARTHOST={{ matrix_mailer_relay_host_name }}::{{ matrix_mailer_relay_host_port }} {% endif %} {% if matrix_mailer_relay_auth %} -RELAYHOST_AUTH=yes -RELAYHOST_PASSWORDMAP={{ matrix_mailer_relay_host_name }}:{{ matrix_mailer_relay_auth_username }}:{{ matrix_mailer_relay_auth_password }} -{% endif %} \ No newline at end of file +SMTP_USERNAME={{ matrix_mailer_relay_auth_username }} +SMTP_PASSWORD={{ matrix_mailer_relay_auth_password }} +{% endif %} diff --git a/roles/matrix-mailer/templates/systemd/matrix-mailer.service.j2 b/roles/matrix-mailer/templates/systemd/matrix-mailer.service.j2 index f0adaa7c..e6d79857 100644 --- a/roles/matrix-mailer/templates/systemd/matrix-mailer.service.j2 +++ b/roles/matrix-mailer/templates/systemd/matrix-mailer.service.j2 @@ -9,8 +9,10 @@ ExecStartPre=-/usr/bin/docker kill matrix-mailer ExecStartPre=-/usr/bin/docker rm matrix-mailer ExecStart=/usr/bin/docker run --rm --name matrix-mailer \ --log-driver=none \ + --user={{ matrix_mailer_container_user_uid }}:{{ matrix_mailer_container_user_gid }} \ --network={{ matrix_docker_network }} \ --env-file={{ matrix_mailer_base_path }}/env-mailer \ + --hostname={{ hostname_matrix }} \ {{ matrix_mailer_docker_image }} ExecStop=-/usr/bin/docker kill matrix-mailer ExecStop=-/usr/bin/docker rm matrix-mailer diff --git a/roles/matrix-nginx-proxy/defaults/main.yml b/roles/matrix-nginx-proxy/defaults/main.yml index ccc51ac8..78b2da12 100644 --- a/roles/matrix-nginx-proxy/defaults/main.yml +++ b/roles/matrix-nginx-proxy/defaults/main.yml @@ -1,5 +1,8 @@ matrix_nginx_proxy_enabled: true +# We use an official nginx image, which we fix-up to run unprivileged. +# An alternative would be an `nginxinc/nginx-unprivileged` image, but +# those as more frequently out of date. matrix_nginx_proxy_docker_image: "nginx:1.15.8-alpine" matrix_nginx_proxy_data_path: "{{ matrix_base_data_path }}/nginx-proxy" diff --git a/roles/matrix-nginx-proxy/tasks/setup_nginx_proxy.yml b/roles/matrix-nginx-proxy/tasks/setup_nginx_proxy.yml index 59c3fe15..434cfad8 100644 --- a/roles/matrix-nginx-proxy/tasks/setup_nginx_proxy.yml +++ b/roles/matrix-nginx-proxy/tasks/setup_nginx_proxy.yml @@ -21,23 +21,30 @@ - "{{ matrix_nginx_proxy_data_path }}" - "{{ matrix_nginx_proxy_confd_path }}" +- name: Ensure Matrix nginx-proxy configured (main config override) + template: + src: "{{ role_path }}/templates/nginx/nginx.conf.j2" + dest: "{{ matrix_nginx_proxy_data_path }}/nginx.conf" + mode: 0644 + when: "matrix_nginx_proxy_enabled" + - name: Ensure Matrix nginx-proxy configured (generic) template: - src: "{{ role_path }}/templates/nginx-conf.d/nginx-http.conf.j2" + src: "{{ role_path }}/templates/nginx/conf.d/nginx-http.conf.j2" dest: "{{ matrix_nginx_proxy_confd_path }}/nginx-http.conf" mode: 0644 when: "matrix_nginx_proxy_enabled" - name: Ensure Matrix nginx-proxy configuration for matrix domain exists template: - src: "{{ role_path }}/templates/nginx-conf.d/matrix-synapse.conf.j2" + src: "{{ role_path }}/templates/nginx/conf.d/matrix-synapse.conf.j2" dest: "{{ matrix_nginx_proxy_confd_path }}/matrix-synapse.conf" mode: 0644 when: "matrix_nginx_proxy_proxy_matrix_enabled" - name: Ensure Matrix nginx-proxy configuration for riot domain exists template: - src: "{{ role_path }}/templates/nginx-conf.d/matrix-riot-web.conf.j2" + src: "{{ role_path }}/templates/nginx/conf.d/matrix-riot-web.conf.j2" dest: "{{ matrix_nginx_proxy_confd_path }}/matrix-riot-web.conf" mode: 0644 when: "matrix_nginx_proxy_proxy_riot_enabled" @@ -104,3 +111,8 @@ state: absent when: "not matrix_nginx_proxy_proxy_riot_enabled" +- name: Ensure Matrix nginx-proxy configuration for main config override deleted + file: + path: "{{ matrix_nginx_proxy_data_path }}/nginx.conf" + state: absent + when: "not matrix_nginx_proxy_enabled" diff --git a/roles/matrix-nginx-proxy/tasks/ssl/main.yml b/roles/matrix-nginx-proxy/tasks/ssl/main.yml index c78b4f35..2681164d 100644 --- a/roles/matrix-nginx-proxy/tasks/ssl/main.yml +++ b/roles/matrix-nginx-proxy/tasks/ssl/main.yml @@ -15,6 +15,7 @@ mode: 0770 owner: "{{ matrix_user_username }}" group: "{{ matrix_user_username }}" + recurse: true with_items: - "{{ matrix_ssl_log_dir_path }}" - "{{ matrix_ssl_config_dir_path }}" diff --git a/roles/matrix-nginx-proxy/tasks/ssl/setup_ssl_lets_encrypt_obtain_for_domain.yml b/roles/matrix-nginx-proxy/tasks/ssl/setup_ssl_lets_encrypt_obtain_for_domain.yml index cf97444f..1882400e 100644 --- a/roles/matrix-nginx-proxy/tasks/ssl/setup_ssl_lets_encrypt_obtain_for_domain.yml +++ b/roles/matrix-nginx-proxy/tasks/ssl/setup_ssl_lets_encrypt_obtain_for_domain.yml @@ -19,12 +19,15 @@ /usr/bin/docker run --rm --name=matrix-certbot - --net=host + --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ + -p 80:8080 -v {{ matrix_ssl_config_dir_path }}:/etc/letsencrypt -v {{ matrix_ssl_log_dir_path }}:/var/log/letsencrypt {{ matrix_ssl_lets_encrypt_certbot_docker_image }} certonly --non-interactive + --work-dir=/tmp + --http-01-port 8080 {% if matrix_ssl_lets_encrypt_staging %}--staging{% endif %} --standalone --preferred-challenges http @@ -42,13 +45,16 @@ /usr/bin/docker run --rm --name=matrix-certbot - -p 127.0.0.1:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }}:80 + --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ + -p 127.0.0.1:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }}:8080 --network={{ matrix_docker_network }} -v {{ matrix_ssl_config_dir_path }}:/etc/letsencrypt -v {{ matrix_ssl_log_dir_path }}:/var/log/letsencrypt {{ matrix_ssl_lets_encrypt_certbot_docker_image }} certonly --non-interactive + --work-dir=/tmp + --http-01-port 8080 {% if matrix_ssl_lets_encrypt_staging %}--staging{% endif %} --standalone --preferred-challenges http diff --git a/roles/matrix-nginx-proxy/templates/nginx-conf.d/matrix-riot-web.conf.j2 b/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-riot-web.conf.j2 similarity index 85% rename from roles/matrix-nginx-proxy/templates/nginx-conf.d/matrix-riot-web.conf.j2 rename to roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-riot-web.conf.j2 index 99172147..578a7e0c 100644 --- a/roles/matrix-nginx-proxy/templates/nginx-conf.d/matrix-riot-web.conf.j2 +++ b/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-riot-web.conf.j2 @@ -1,5 +1,5 @@ server { - listen 80; + listen {{ 8080 if matrix_nginx_proxy_enabled else 80 }}; server_name {{ matrix_nginx_proxy_proxy_riot_hostname }}; server_tokens off; @@ -8,7 +8,7 @@ server { {% if matrix_nginx_proxy_enabled %} {# Use the embedded DNS resolver in Docker containers to discover the service #} resolver 127.0.0.11 valid=5s; - set $backend "matrix-certbot:80"; + set $backend "matrix-certbot:8080"; proxy_pass http://$backend; {% else %} {# Generic configuration for use outside of our container setup #} @@ -22,8 +22,8 @@ server { } server { - listen 443 ssl http2; - listen [::]:443 ssl http2; + listen {{ 8443 if matrix_nginx_proxy_enabled else 443 }} ssl http2; + listen [::]:{{ 8443 if matrix_nginx_proxy_enabled else 443 }} ssl http2; server_name {{ matrix_nginx_proxy_proxy_riot_hostname }}; @@ -43,7 +43,7 @@ server { {% if matrix_nginx_proxy_enabled %} {# Use the embedded DNS resolver in Docker containers to discover the service #} resolver 127.0.0.11 valid=5s; - set $backend "matrix-riot-web:80"; + set $backend "matrix-riot-web:8080"; proxy_pass http://$backend; {% else %} {# Generic configuration for use outside of our container setup #} diff --git a/roles/matrix-nginx-proxy/templates/nginx-conf.d/matrix-synapse.conf.j2 b/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-synapse.conf.j2 similarity index 94% rename from roles/matrix-nginx-proxy/templates/nginx-conf.d/matrix-synapse.conf.j2 rename to roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-synapse.conf.j2 index 1a2d166b..3638e357 100644 --- a/roles/matrix-nginx-proxy/templates/nginx-conf.d/matrix-synapse.conf.j2 +++ b/roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-synapse.conf.j2 @@ -1,5 +1,5 @@ server { - listen 80; + listen {{ 8080 if matrix_nginx_proxy_enabled else 80 }}; server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }}; server_tokens off; @@ -8,7 +8,7 @@ server { {% if matrix_nginx_proxy_enabled %} {# Use the embedded DNS resolver in Docker containers to discover the service #} resolver 127.0.0.11 valid=5s; - set $backend "matrix-certbot:80"; + set $backend "matrix-certbot:8080"; proxy_pass http://$backend; {% else %} {# Generic configuration for use outside of our container setup #} @@ -22,8 +22,8 @@ server { } server { - listen 443 ssl http2; - listen [::]:443 ssl http2; + listen {{ 8443 if matrix_nginx_proxy_enabled else 443 }} ssl http2; + listen [::]:{{ 8443 if matrix_nginx_proxy_enabled else 443 }} ssl http2; server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }}; diff --git a/roles/matrix-nginx-proxy/templates/nginx-conf.d/nginx-http.conf.j2 b/roles/matrix-nginx-proxy/templates/nginx/conf.d/nginx-http.conf.j2 similarity index 100% rename from roles/matrix-nginx-proxy/templates/nginx-conf.d/nginx-http.conf.j2 rename to roles/matrix-nginx-proxy/templates/nginx/conf.d/nginx-http.conf.j2 diff --git a/roles/matrix-nginx-proxy/templates/nginx/nginx.conf.j2 b/roles/matrix-nginx-proxy/templates/nginx/nginx.conf.j2 new file mode 100644 index 00000000..3382d6c6 --- /dev/null +++ b/roles/matrix-nginx-proxy/templates/nginx/nginx.conf.j2 @@ -0,0 +1,45 @@ +# This is a custom nginx configuration file that we use in the container (instead of the default one), +# because it allows us to run nginx with a non-root user. +# +# For this to work, the default vhost file (`/etc/nginx/conf.d/default.conf`) also needs to be removed. +# +# The following changes have been done compared to a default nginx configuration file: +# - various temp paths are changed to `/tmp`, so that a non-root user can write to them +# - the `user` directive was removed, as we don't want nginx to switch users + +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /tmp/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + proxy_temp_path /tmp/proxy_temp; + client_body_temp_path /tmp/client_temp; + fastcgi_temp_path /tmp/fastcgi_temp; + uwsgi_temp_path /tmp/uwsgi_temp; + scgi_temp_path /tmp/scgi_temp; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + include /etc/nginx/conf.d/*.conf; +} diff --git a/roles/matrix-nginx-proxy/templates/systemd/matrix-nginx-proxy.service.j2 b/roles/matrix-nginx-proxy/templates/systemd/matrix-nginx-proxy.service.j2 index 62700157..7bfade3d 100644 --- a/roles/matrix-nginx-proxy/templates/systemd/matrix-nginx-proxy.service.j2 +++ b/roles/matrix-nginx-proxy/templates/systemd/matrix-nginx-proxy.service.j2 @@ -14,9 +14,11 @@ ExecStartPre=-/usr/bin/docker kill matrix-nginx-proxy ExecStartPre=-/usr/bin/docker rm matrix-nginx-proxy ExecStart=/usr/bin/docker run --rm --name matrix-nginx-proxy \ --log-driver=none \ + --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ --network={{ matrix_docker_network }} \ - -p 80:80 \ - -p 443:443 \ + -p 80:8080 \ + -p 443:8443 \ + -v {{ matrix_nginx_proxy_data_path }}/nginx.conf:/etc/nginx/nginx.conf:ro \ -v {{ matrix_nginx_proxy_confd_path }}:/etc/nginx/conf.d:ro \ -v {{ matrix_ssl_config_dir_path }}:{{ matrix_ssl_config_dir_path }}:ro \ -v {{ matrix_static_files_base_path }}:{{ matrix_static_files_base_path }}:ro \ diff --git a/roles/matrix-nginx-proxy/templates/usr-local-bin/matrix-ssl-lets-encrypt-certificates-renew.j2 b/roles/matrix-nginx-proxy/templates/usr-local-bin/matrix-ssl-lets-encrypt-certificates-renew.j2 index 12504d1f..b723da38 100644 --- a/roles/matrix-nginx-proxy/templates/usr-local-bin/matrix-ssl-lets-encrypt-certificates-renew.j2 +++ b/roles/matrix-nginx-proxy/templates/usr-local-bin/matrix-ssl-lets-encrypt-certificates-renew.j2 @@ -3,19 +3,22 @@ # For renewal to work, matrix-nginx-proxy (or another webserver, if matrix-nginx-proxy is disabled) # need to forward requests for `/.well-known/acme-challenge` to the certbot container. # -# This can happen inside the container network by proxying to `http://matrix-certbot:80` +# This can happen inside the container network by proxying to `http://matrix-certbot:8080` # or outside (on the host) by proxying to `http://localhost:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }}`. docker run \ --rm \ --name=matrix-certbot \ + --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ --network="{{ matrix_docker_network }}" \ - -p 127.0.0.1:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }}:80 \ + -p 127.0.0.1:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }}:8080 \ -v {{ matrix_ssl_config_dir_path }}:/etc/letsencrypt \ -v {{ matrix_ssl_log_dir_path }}:/var/log/letsencrypt \ {{ matrix_ssl_lets_encrypt_certbot_docker_image }} \ renew \ --non-interactive \ + --work-dir=/tmp \ + --http-01-port 8080 {% if matrix_ssl_lets_encrypt_staging %} --staging \ {% endif %} diff --git a/roles/matrix-postgres/tasks/import_postgres.yml b/roles/matrix-postgres/tasks/import_postgres.yml index 66b20a64..17590023 100644 --- a/roles/matrix-postgres/tasks/import_postgres.yml +++ b/roles/matrix-postgres/tasks/import_postgres.yml @@ -60,12 +60,13 @@ set_fact: matrix_postgres_import_command: >- /usr/bin/docker run --rm --name matrix-postgres-import + --user={{ matrix_user_uid }}:{{ matrix_user_gid }} --network={{ matrix_docker_network }} --env-file={{ matrix_postgres_base_path }}/env-postgres-psql - -v {{ server_path_postgres_dump }}:{{ server_path_postgres_dump }}:ro + -v {{ server_path_postgres_dump }}:/{{ server_path_postgres_dump|basename }}:ro --entrypoint=/bin/sh {{ matrix_postgres_docker_image_latest }} - -c 'cat {{ server_path_postgres_dump }} | + -c 'cat /{{ server_path_postgres_dump|basename }} | {{ 'gunzip |' if server_path_postgres_dump.endswith('.gz') else '' }} psql -v ON_ERROR_STOP=1 -h matrix-postgres' diff --git a/roles/matrix-postgres/tasks/upgrade_postgres.yml b/roles/matrix-postgres/tasks/upgrade_postgres.yml index 3e67dfc5..e1fcf639 100644 --- a/roles/matrix-postgres/tasks/upgrade_postgres.yml +++ b/roles/matrix-postgres/tasks/upgrade_postgres.yml @@ -70,6 +70,7 @@ - name: Perform Postgres database dump command: | /usr/bin/docker run --rm --name matrix-postgres-dump \ + --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ --network={{ matrix_docker_network }} \ --env-file={{ matrix_postgres_base_path }}/env-postgres-psql \ -v {{ postgres_dump_dir }}:/out \ @@ -104,6 +105,7 @@ - name: Perform Postgres database import command: | /usr/bin/docker run --rm --name matrix-postgres-import \ + --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ --network={{ matrix_docker_network }} \ --env-file={{ matrix_postgres_base_path }}/env-postgres-psql \ -v {{ postgres_dump_dir }}:/in:ro \ diff --git a/roles/matrix-riot-web/tasks/setup_riot_web.yml b/roles/matrix-riot-web/tasks/setup_riot_web.yml index 1eadf933..c9a84f91 100644 --- a/roles/matrix-riot-web/tasks/setup_riot_web.yml +++ b/roles/matrix-riot-web/tasks/setup_riot_web.yml @@ -27,6 +27,7 @@ group: "{{ matrix_user_username }}" with_items: - {src: "{{ role_path }}/templates/config.json.j2", name: "config.json"} + - {src: "{{ role_path }}/templates/nginx.conf.j2", name: "nginx.conf"} - {src: "{{ matrix_riot_web_homepage_template }}", name: "home.html"} when: matrix_riot_web_enabled diff --git a/roles/matrix-riot-web/templates/nginx.conf.j2 b/roles/matrix-riot-web/templates/nginx.conf.j2 new file mode 100644 index 00000000..a7707cd9 --- /dev/null +++ b/roles/matrix-riot-web/templates/nginx.conf.j2 @@ -0,0 +1,60 @@ +# This is a custom nginx configuration file that we use in the container (instead of the default one), +# because it allows us to run nginx with a non-root user. +# +# For this to work, the default vhost file (`/etc/nginx/conf.d/default.conf`) also needs to be removed. +# (mounting `/dev/null` over `/etc/nginx/conf.d/default.conf` works well) +# +# The following changes have been done compared to a default nginx configuration file: +# - default server port is changed (80 -> 8080), so that a non-root user can bind it +# - various temp paths are changed to `/tmp`, so that a non-root user can write to them +# - the `user` directive was removed, as we don't want nginx to switch users + +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /tmp/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + proxy_temp_path /tmp/proxy_temp; + client_body_temp_path /tmp/client_temp; + fastcgi_temp_path /tmp/fastcgi_temp; + uwsgi_temp_path /tmp/uwsgi_temp; + scgi_temp_path /tmp/scgi_temp; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + server { + listen 8080; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + } +} diff --git a/roles/matrix-riot-web/templates/systemd/matrix-riot-web.service.j2 b/roles/matrix-riot-web/templates/systemd/matrix-riot-web.service.j2 index 6ef2ad17..28228e23 100644 --- a/roles/matrix-riot-web/templates/systemd/matrix-riot-web.service.j2 +++ b/roles/matrix-riot-web/templates/systemd/matrix-riot-web.service.j2 @@ -11,11 +11,14 @@ ExecStartPre=-/usr/bin/docker kill matrix-riot-web ExecStartPre=-/usr/bin/docker rm matrix-riot-web ExecStart=/usr/bin/docker run --rm --name matrix-riot-web \ --log-driver=none \ + --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ + -v {{ matrix_riot_web_data_path }}/nginx.conf:/etc/nginx/nginx.conf:ro \ + -v /dev/null:/etc/nginx/conf.d/default.conf:ro \ -v {{ matrix_riot_web_data_path }}/config.json:/etc/riot-web/config.json:ro \ -v {{ matrix_riot_web_data_path }}/home.html:/etc/riot-web/home.html:ro \ --network={{ matrix_docker_network }} \ {% if matrix_riot_web_container_expose_port %} - -p 127.0.0.1:8765:80 \ + -p 127.0.0.1:8765:8080 \ {% endif %} {{ matrix_riot_web_docker_image }} ExecStop=-/usr/bin/docker kill matrix-riot-web diff --git a/roles/matrix-synapse/tasks/ext/mautrix-telegram/setup.yml b/roles/matrix-synapse/tasks/ext/mautrix-telegram/setup.yml index f85abb13..e0ffb77e 100644 --- a/roles/matrix-synapse/tasks/ext/mautrix-telegram/setup.yml +++ b/roles/matrix-synapse/tasks/ext/mautrix-telegram/setup.yml @@ -41,69 +41,69 @@ shell: /usr/bin/docker run --rm --name matrix-mautrix-telegram-gen -v {{ matrix_mautrix_telegram_base_path }}:/data:z {{ matrix_mautrix_telegram_docker_image }} python3 -m mautrix_telegram -g -c /data/config.yaml -r /data/registration.yaml when: "matrix_mautrix_telegram_enabled and mautrix_telegram_registration_file.stat.exists == False" -- set_fact: - matrix_synapse_app_service_config_file_mautrix_telegram: '/app-registration/mautrix-telegram.yml' - -- set_fact: - matrix_synapse_container_additional_volumes: > - {{ matrix_synapse_container_additional_volumes }} - + - {{ [{'src': '{{ matrix_mautrix_telegram_base_path }}/registration.yaml', 'dst': '{{ matrix_synapse_app_service_config_file_mautrix_telegram }}', 'options': 'ro'}] }} - when: "matrix_mautrix_telegram_enabled" - -- set_fact: - matrix_synapse_app_service_config_files: > - {{ matrix_synapse_app_service_config_files }} - + - {{ ["{{ matrix_synapse_app_service_config_file_mautrix_telegram }}"] | to_nice_json }} - when: "matrix_mautrix_telegram_enabled" - -- block: - - name: Fail if matrix-nginx-proxy role already executed - fail: - msg: > - Trying to append Mautrix Telegram's reverse-proxying configuration to matrix-nginx-proxy, - but it's pointless since the matrix-nginx-proxy role had already executed. - To fix this, please change the order of roles in your plabook, - so that the matrix-nginx-proxy role would run after the matrix-synapse role. - when: "matrix_nginx_proxy_role_executed" - - - name: Generate Mautrix Telegram proxying configuration for matrix-nginx-proxy - set_fact: - matrix_mautrix_telegram_matrix_nginx_proxy_configuration: | - location {{ matrix_mautrix_telegram_public_endpoint }} { - {% if matrix_nginx_proxy_enabled %} - {# Use the embedded DNS resolver in Docker containers to discover the service #} - resolver 127.0.0.11 valid=5s; - set $backend "matrix-mautrix-telegram:8080"; - proxy_pass http://$backend; - {% else %} - {# Generic configuration for use outside of our container setup #} - proxy_pass http://localhost:8080; - {% endif %} - } - - - name: Register Mautrix Telegram proxying configuration with matrix-nginx-proxy - set_fact: - matrix_nginx_proxy_proxy_matrix_additional_server_configuration_blocks: | - {{ - matrix_nginx_proxy_proxy_matrix_additional_server_configuration_blocks - + - [matrix_mautrix_telegram_matrix_nginx_proxy_configuration] - }} - - when: "matrix_mautrix_telegram_enabled and matrix_nginx_proxy_enabled|default(False)" - tags: - - always - -- name: Warn about reverse-proxying if matrix-nginx-proxy not used - debug: - msg: > - NOTE: You've enabled the Mautrix Telegram bridge but are not using the matrix-nginx-proxy - reverse proxy. - Please make sure that you're proxying the `{{ matrix_mautrix_telegram_public_endpoint }}` - URL endpoint to the matrix-mautrix-telegram container. - when: "matrix_mautrix_telegram_enabled and matrix_nginx_proxy_enabled is not defined" +# - set_fact: +# matrix_synapse_app_service_config_file_mautrix_telegram: '/app-registration/mautrix-telegram.yml' + +# - set_fact: +# matrix_synapse_container_additional_volumes: > +# {{ matrix_synapse_container_additional_volumes }} +# + +# {{ [{'src': '{{ matrix_mautrix_telegram_base_path }}/registration.yaml', 'dst': '{{ matrix_synapse_app_service_config_file_mautrix_telegram }}', 'options': 'ro'}] }} +# when: "matrix_mautrix_telegram_enabled" + +# - set_fact: +# matrix_synapse_app_service_config_files: > +# {{ matrix_synapse_app_service_config_files }} +# + +# {{ ["{{ matrix_synapse_app_service_config_file_mautrix_telegram }}"] | to_nice_json }} +# when: "matrix_mautrix_telegram_enabled" + +# - block: +# - name: Fail if matrix-nginx-proxy role already executed +# fail: +# msg: > +# Trying to append Mautrix Telegram's reverse-proxying configuration to matrix-nginx-proxy, +# but it's pointless since the matrix-nginx-proxy role had already executed. +# To fix this, please change the order of roles in your plabook, +# so that the matrix-nginx-proxy role would run after the matrix-synapse role. +# when: "matrix_nginx_proxy_role_executed" + +# - name: Generate Mautrix Telegram proxying configuration for matrix-nginx-proxy +# set_fact: +# matrix_mautrix_telegram_matrix_nginx_proxy_configuration: | +# location {{ matrix_mautrix_telegram_public_endpoint }} { +# {% if matrix_nginx_proxy_enabled %} +# {# Use the embedded DNS resolver in Docker containers to discover the service #} +# resolver 127.0.0.11 valid=5s; +# set $backend "matrix-mautrix-telegram:8080"; +# proxy_pass http://$backend; +# {% else %} +# {# Generic configuration for use outside of our container setup #} +# proxy_pass http://localhost:8080; +# {% endif %} +# } + +# - name: Register Mautrix Telegram proxying configuration with matrix-nginx-proxy +# set_fact: +# matrix_nginx_proxy_proxy_matrix_additional_server_configuration_blocks: | +# {{ +# matrix_nginx_proxy_proxy_matrix_additional_server_configuration_blocks +# + +# [matrix_mautrix_telegram_matrix_nginx_proxy_configuration] +# }} + +# when: "matrix_mautrix_telegram_enabled and matrix_nginx_proxy_enabled|default(False)" +# tags: +# - always + +# - name: Warn about reverse-proxying if matrix-nginx-proxy not used +# debug: +# msg: > +# NOTE: You've enabled the Mautrix Telegram bridge but are not using the matrix-nginx-proxy +# reverse proxy. +# Please make sure that you're proxying the `{{ matrix_mautrix_telegram_public_endpoint }}` +# URL endpoint to the matrix-mautrix-telegram container. +# when: "matrix_mautrix_telegram_enabled and matrix_nginx_proxy_enabled is not defined" # # Tasks related to getting rid of matrix-mautrix-telegram (if it was previously enabled) diff --git a/roles/matrix-synapse/templates/synapse/systemd/matrix-synapse.service.j2 b/roles/matrix-synapse/templates/synapse/systemd/matrix-synapse.service.j2 index dba102da..05023642 100644 --- a/roles/matrix-synapse/templates/synapse/systemd/matrix-synapse.service.j2 +++ b/roles/matrix-synapse/templates/synapse/systemd/matrix-synapse.service.j2 @@ -20,11 +20,10 @@ ExecStartPre=/bin/sleep 5 {% endif %} ExecStart=/usr/bin/docker run --rm --name matrix-synapse \ --log-driver=none \ + --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ + --entrypoint=python \ --network={{ matrix_docker_network }} \ - -e SYNAPSE_CONFIG_PATH=/data/homeserver.yaml \ -e SYNAPSE_CACHE_FACTOR={{ matrix_synapse_cache_factor }} \ - -e UID={{ matrix_user_uid }} \ - -e GID={{ matrix_user_gid }} \ {% if matrix_synapse_federation_enabled %} -p 8448:8448 \ {% endif %} @@ -37,7 +36,8 @@ ExecStart=/usr/bin/docker run --rm --name matrix-synapse \ {% for volume in matrix_synapse_container_additional_volumes %} -v {{ volume.src }}:{{ volume.dst }}:{{ volume.options }} \ {% endfor %} - {{ matrix_synapse_docker_image }} + {{ matrix_synapse_docker_image }} \ + -m synapse.app.homeserver -c /data/homeserver.yaml ExecStop=-/usr/bin/docker kill matrix-synapse ExecStop=-/usr/bin/docker rm matrix-synapse Restart=always