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.pull/84/head
| @@ -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 | # 2019-01-17 | ||||
| ## (BC Break) Making the playbook's roles more independent of one another | ## (BC Break) Making the playbook's roles more independent of one another | ||||
| @@ -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) 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) | - (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) | - [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) | - [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) | ||||
| @@ -1,6 +1,6 @@ | |||||
| # Adjusting email-sending settings (optional) | # 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. | 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.) | 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" | 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 | ## 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`. | |||||
| If you're having trouble with email not being delivered, it may be useful to inspect the mailer logs: `journalctl -f -u matrix-mailer`. | |||||
| @@ -125,7 +125,7 @@ matrix_mxisd_dns_overwrite_homeserver_client_value: "http://{{ 'matrix-corporal: | |||||
| # By default, we send mail through the `matrix-mailer` service. | # 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_identity_from: "{{ matrix_mailer_sender_address }}" | ||||
| matrix_mxisd_threepid_medium_email_connectors_smtp_host: "matrix-mailer" | 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_threepid_medium_email_connectors_smtp_tls: 0 | ||||
| matrix_mxisd_systemd_wanted_services_list: | | 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_enabled: "{{ matrix_mailer_enabled }}" | ||||
| matrix_synapse_email_smtp_host: "matrix-mailer" | 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_smtp_require_transport_security: false | ||||
| matrix_synapse_email_notif_from: "Matrix <{{ matrix_mailer_sender_address }}>" | matrix_synapse_email_notif_from: "Matrix <{{ matrix_mailer_sender_address }}>" | ||||
| matrix_synapse_email_riot_base_url: "https://{{ hostname_riot }}" | matrix_synapse_email_riot_base_url: "https://{{ hostname_riot }}" | ||||
| @@ -2,7 +2,12 @@ matrix_mailer_enabled: true | |||||
| matrix_mailer_base_path: "{{ matrix_base_data_path }}/mailer" | 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_sender_address: "matrix@{{ hostname_identity }}" | ||||
| matrix_mailer_relay_use: false | 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_host_port: 587 | ||||
| matrix_mailer_relay_auth: false | matrix_mailer_relay_auth: false | ||||
| matrix_mailer_relay_auth_username: "" | matrix_mailer_relay_auth_username: "" | ||||
| matrix_mailer_relay_auth_password: "" | |||||
| matrix_mailer_relay_auth_password: "" | |||||
| @@ -1,8 +1,7 @@ | |||||
| MAILNAME={{ hostname_matrix }} | |||||
| {% if matrix_mailer_relay_use %} | {% 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 %} | {% endif %} | ||||
| {% if matrix_mailer_relay_auth %} | {% 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 %} | |||||
| SMTP_USERNAME={{ matrix_mailer_relay_auth_username }} | |||||
| SMTP_PASSWORD={{ matrix_mailer_relay_auth_password }} | |||||
| {% endif %} | |||||
| @@ -9,8 +9,10 @@ ExecStartPre=-/usr/bin/docker kill matrix-mailer | |||||
| ExecStartPre=-/usr/bin/docker rm matrix-mailer | ExecStartPre=-/usr/bin/docker rm matrix-mailer | ||||
| ExecStart=/usr/bin/docker run --rm --name matrix-mailer \ | ExecStart=/usr/bin/docker run --rm --name matrix-mailer \ | ||||
| --log-driver=none \ | --log-driver=none \ | ||||
| --user={{ matrix_mailer_container_user_uid }}:{{ matrix_mailer_container_user_gid }} \ | |||||
| --network={{ matrix_docker_network }} \ | --network={{ matrix_docker_network }} \ | ||||
| --env-file={{ matrix_mailer_base_path }}/env-mailer \ | --env-file={{ matrix_mailer_base_path }}/env-mailer \ | ||||
| --hostname={{ hostname_matrix }} \ | |||||
| {{ matrix_mailer_docker_image }} | {{ matrix_mailer_docker_image }} | ||||
| ExecStop=-/usr/bin/docker kill matrix-mailer | ExecStop=-/usr/bin/docker kill matrix-mailer | ||||
| ExecStop=-/usr/bin/docker rm matrix-mailer | ExecStop=-/usr/bin/docker rm matrix-mailer | ||||
| @@ -1,5 +1,8 @@ | |||||
| matrix_nginx_proxy_enabled: true | 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_docker_image: "nginx:1.15.8-alpine" | ||||
| matrix_nginx_proxy_data_path: "{{ matrix_base_data_path }}/nginx-proxy" | matrix_nginx_proxy_data_path: "{{ matrix_base_data_path }}/nginx-proxy" | ||||
| @@ -21,23 +21,30 @@ | |||||
| - "{{ matrix_nginx_proxy_data_path }}" | - "{{ matrix_nginx_proxy_data_path }}" | ||||
| - "{{ matrix_nginx_proxy_confd_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) | - name: Ensure Matrix nginx-proxy configured (generic) | ||||
| template: | 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" | dest: "{{ matrix_nginx_proxy_confd_path }}/nginx-http.conf" | ||||
| mode: 0644 | mode: 0644 | ||||
| when: "matrix_nginx_proxy_enabled" | when: "matrix_nginx_proxy_enabled" | ||||
| - name: Ensure Matrix nginx-proxy configuration for matrix domain exists | - name: Ensure Matrix nginx-proxy configuration for matrix domain exists | ||||
| template: | 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" | dest: "{{ matrix_nginx_proxy_confd_path }}/matrix-synapse.conf" | ||||
| mode: 0644 | mode: 0644 | ||||
| when: "matrix_nginx_proxy_proxy_matrix_enabled" | when: "matrix_nginx_proxy_proxy_matrix_enabled" | ||||
| - name: Ensure Matrix nginx-proxy configuration for riot domain exists | - name: Ensure Matrix nginx-proxy configuration for riot domain exists | ||||
| template: | 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" | dest: "{{ matrix_nginx_proxy_confd_path }}/matrix-riot-web.conf" | ||||
| mode: 0644 | mode: 0644 | ||||
| when: "matrix_nginx_proxy_proxy_riot_enabled" | when: "matrix_nginx_proxy_proxy_riot_enabled" | ||||
| @@ -104,3 +111,8 @@ | |||||
| state: absent | state: absent | ||||
| when: "not matrix_nginx_proxy_proxy_riot_enabled" | 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" | |||||
| @@ -15,6 +15,7 @@ | |||||
| mode: 0770 | mode: 0770 | ||||
| owner: "{{ matrix_user_username }}" | owner: "{{ matrix_user_username }}" | ||||
| group: "{{ matrix_user_username }}" | group: "{{ matrix_user_username }}" | ||||
| recurse: true | |||||
| with_items: | with_items: | ||||
| - "{{ matrix_ssl_log_dir_path }}" | - "{{ matrix_ssl_log_dir_path }}" | ||||
| - "{{ matrix_ssl_config_dir_path }}" | - "{{ matrix_ssl_config_dir_path }}" | ||||
| @@ -19,12 +19,15 @@ | |||||
| /usr/bin/docker run | /usr/bin/docker run | ||||
| --rm | --rm | ||||
| --name=matrix-certbot | --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_config_dir_path }}:/etc/letsencrypt | ||||
| -v {{ matrix_ssl_log_dir_path }}:/var/log/letsencrypt | -v {{ matrix_ssl_log_dir_path }}:/var/log/letsencrypt | ||||
| {{ matrix_ssl_lets_encrypt_certbot_docker_image }} | {{ matrix_ssl_lets_encrypt_certbot_docker_image }} | ||||
| certonly | certonly | ||||
| --non-interactive | --non-interactive | ||||
| --work-dir=/tmp | |||||
| --http-01-port 8080 | |||||
| {% if matrix_ssl_lets_encrypt_staging %}--staging{% endif %} | {% if matrix_ssl_lets_encrypt_staging %}--staging{% endif %} | ||||
| --standalone | --standalone | ||||
| --preferred-challenges http | --preferred-challenges http | ||||
| @@ -42,13 +45,16 @@ | |||||
| /usr/bin/docker run | /usr/bin/docker run | ||||
| --rm | --rm | ||||
| --name=matrix-certbot | --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 }} | --network={{ matrix_docker_network }} | ||||
| -v {{ matrix_ssl_config_dir_path }}:/etc/letsencrypt | -v {{ matrix_ssl_config_dir_path }}:/etc/letsencrypt | ||||
| -v {{ matrix_ssl_log_dir_path }}:/var/log/letsencrypt | -v {{ matrix_ssl_log_dir_path }}:/var/log/letsencrypt | ||||
| {{ matrix_ssl_lets_encrypt_certbot_docker_image }} | {{ matrix_ssl_lets_encrypt_certbot_docker_image }} | ||||
| certonly | certonly | ||||
| --non-interactive | --non-interactive | ||||
| --work-dir=/tmp | |||||
| --http-01-port 8080 | |||||
| {% if matrix_ssl_lets_encrypt_staging %}--staging{% endif %} | {% if matrix_ssl_lets_encrypt_staging %}--staging{% endif %} | ||||
| --standalone | --standalone | ||||
| --preferred-challenges http | --preferred-challenges http | ||||
| @@ -1,5 +1,5 @@ | |||||
| server { | server { | ||||
| listen 80; | |||||
| listen {{ 8080 if matrix_nginx_proxy_enabled else 80 }}; | |||||
| server_name {{ matrix_nginx_proxy_proxy_riot_hostname }}; | server_name {{ matrix_nginx_proxy_proxy_riot_hostname }}; | ||||
| server_tokens off; | server_tokens off; | ||||
| @@ -8,7 +8,7 @@ server { | |||||
| {% if matrix_nginx_proxy_enabled %} | {% if matrix_nginx_proxy_enabled %} | ||||
| {# Use the embedded DNS resolver in Docker containers to discover the service #} | {# Use the embedded DNS resolver in Docker containers to discover the service #} | ||||
| resolver 127.0.0.11 valid=5s; | resolver 127.0.0.11 valid=5s; | ||||
| set $backend "matrix-certbot:80"; | |||||
| set $backend "matrix-certbot:8080"; | |||||
| proxy_pass http://$backend; | proxy_pass http://$backend; | ||||
| {% else %} | {% else %} | ||||
| {# Generic configuration for use outside of our container setup #} | {# Generic configuration for use outside of our container setup #} | ||||
| @@ -22,8 +22,8 @@ server { | |||||
| } | } | ||||
| 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 }}; | server_name {{ matrix_nginx_proxy_proxy_riot_hostname }}; | ||||
| @@ -43,7 +43,7 @@ server { | |||||
| {% if matrix_nginx_proxy_enabled %} | {% if matrix_nginx_proxy_enabled %} | ||||
| {# Use the embedded DNS resolver in Docker containers to discover the service #} | {# Use the embedded DNS resolver in Docker containers to discover the service #} | ||||
| resolver 127.0.0.11 valid=5s; | resolver 127.0.0.11 valid=5s; | ||||
| set $backend "matrix-riot-web:80"; | |||||
| set $backend "matrix-riot-web:8080"; | |||||
| proxy_pass http://$backend; | proxy_pass http://$backend; | ||||
| {% else %} | {% else %} | ||||
| {# Generic configuration for use outside of our container setup #} | {# Generic configuration for use outside of our container setup #} | ||||
| @@ -1,5 +1,5 @@ | |||||
| server { | server { | ||||
| listen 80; | |||||
| listen {{ 8080 if matrix_nginx_proxy_enabled else 80 }}; | |||||
| server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }}; | server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }}; | ||||
| server_tokens off; | server_tokens off; | ||||
| @@ -8,7 +8,7 @@ server { | |||||
| {% if matrix_nginx_proxy_enabled %} | {% if matrix_nginx_proxy_enabled %} | ||||
| {# Use the embedded DNS resolver in Docker containers to discover the service #} | {# Use the embedded DNS resolver in Docker containers to discover the service #} | ||||
| resolver 127.0.0.11 valid=5s; | resolver 127.0.0.11 valid=5s; | ||||
| set $backend "matrix-certbot:80"; | |||||
| set $backend "matrix-certbot:8080"; | |||||
| proxy_pass http://$backend; | proxy_pass http://$backend; | ||||
| {% else %} | {% else %} | ||||
| {# Generic configuration for use outside of our container setup #} | {# Generic configuration for use outside of our container setup #} | ||||
| @@ -22,8 +22,8 @@ server { | |||||
| } | } | ||||
| 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 }}; | server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }}; | ||||
| @@ -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; | |||||
| } | |||||
| @@ -14,9 +14,11 @@ ExecStartPre=-/usr/bin/docker kill matrix-nginx-proxy | |||||
| ExecStartPre=-/usr/bin/docker rm matrix-nginx-proxy | ExecStartPre=-/usr/bin/docker rm matrix-nginx-proxy | ||||
| ExecStart=/usr/bin/docker run --rm --name matrix-nginx-proxy \ | ExecStart=/usr/bin/docker run --rm --name matrix-nginx-proxy \ | ||||
| --log-driver=none \ | --log-driver=none \ | ||||
| --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ | |||||
| --network={{ matrix_docker_network }} \ | --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_nginx_proxy_confd_path }}:/etc/nginx/conf.d:ro \ | ||||
| -v {{ matrix_ssl_config_dir_path }}:{{ matrix_ssl_config_dir_path }}: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 \ | -v {{ matrix_static_files_base_path }}:{{ matrix_static_files_base_path }}:ro \ | ||||
| @@ -3,19 +3,22 @@ | |||||
| # For renewal to work, matrix-nginx-proxy (or another webserver, if matrix-nginx-proxy is disabled) | # 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. | # 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 }}`. | # or outside (on the host) by proxying to `http://localhost:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }}`. | ||||
| docker run \ | docker run \ | ||||
| --rm \ | --rm \ | ||||
| --name=matrix-certbot \ | --name=matrix-certbot \ | ||||
| --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ | |||||
| --network="{{ matrix_docker_network }}" \ | --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_config_dir_path }}:/etc/letsencrypt \ | ||||
| -v {{ matrix_ssl_log_dir_path }}:/var/log/letsencrypt \ | -v {{ matrix_ssl_log_dir_path }}:/var/log/letsencrypt \ | ||||
| {{ matrix_ssl_lets_encrypt_certbot_docker_image }} \ | {{ matrix_ssl_lets_encrypt_certbot_docker_image }} \ | ||||
| renew \ | renew \ | ||||
| --non-interactive \ | --non-interactive \ | ||||
| --work-dir=/tmp \ | |||||
| --http-01-port 8080 | |||||
| {% if matrix_ssl_lets_encrypt_staging %} | {% if matrix_ssl_lets_encrypt_staging %} | ||||
| --staging \ | --staging \ | ||||
| {% endif %} | {% endif %} | ||||
| @@ -60,12 +60,13 @@ | |||||
| set_fact: | set_fact: | ||||
| matrix_postgres_import_command: >- | matrix_postgres_import_command: >- | ||||
| /usr/bin/docker run --rm --name matrix-postgres-import | /usr/bin/docker run --rm --name matrix-postgres-import | ||||
| --user={{ matrix_user_uid }}:{{ matrix_user_gid }} | |||||
| --network={{ matrix_docker_network }} | --network={{ matrix_docker_network }} | ||||
| --env-file={{ matrix_postgres_base_path }}/env-postgres-psql | --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 | --entrypoint=/bin/sh | ||||
| {{ matrix_postgres_docker_image_latest }} | {{ 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 '' }} | {{ 'gunzip |' if server_path_postgres_dump.endswith('.gz') else '' }} | ||||
| psql -v ON_ERROR_STOP=1 -h matrix-postgres' | psql -v ON_ERROR_STOP=1 -h matrix-postgres' | ||||
| @@ -70,6 +70,7 @@ | |||||
| - name: Perform Postgres database dump | - name: Perform Postgres database dump | ||||
| command: | | command: | | ||||
| /usr/bin/docker run --rm --name matrix-postgres-dump \ | /usr/bin/docker run --rm --name matrix-postgres-dump \ | ||||
| --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ | |||||
| --network={{ matrix_docker_network }} \ | --network={{ matrix_docker_network }} \ | ||||
| --env-file={{ matrix_postgres_base_path }}/env-postgres-psql \ | --env-file={{ matrix_postgres_base_path }}/env-postgres-psql \ | ||||
| -v {{ postgres_dump_dir }}:/out \ | -v {{ postgres_dump_dir }}:/out \ | ||||
| @@ -104,6 +105,7 @@ | |||||
| - name: Perform Postgres database import | - name: Perform Postgres database import | ||||
| command: | | command: | | ||||
| /usr/bin/docker run --rm --name matrix-postgres-import \ | /usr/bin/docker run --rm --name matrix-postgres-import \ | ||||
| --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ | |||||
| --network={{ matrix_docker_network }} \ | --network={{ matrix_docker_network }} \ | ||||
| --env-file={{ matrix_postgres_base_path }}/env-postgres-psql \ | --env-file={{ matrix_postgres_base_path }}/env-postgres-psql \ | ||||
| -v {{ postgres_dump_dir }}:/in:ro \ | -v {{ postgres_dump_dir }}:/in:ro \ | ||||
| @@ -27,6 +27,7 @@ | |||||
| group: "{{ matrix_user_username }}" | group: "{{ matrix_user_username }}" | ||||
| with_items: | with_items: | ||||
| - {src: "{{ role_path }}/templates/config.json.j2", name: "config.json"} | - {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"} | - {src: "{{ matrix_riot_web_homepage_template }}", name: "home.html"} | ||||
| when: matrix_riot_web_enabled | when: matrix_riot_web_enabled | ||||
| @@ -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; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -11,11 +11,14 @@ ExecStartPre=-/usr/bin/docker kill matrix-riot-web | |||||
| ExecStartPre=-/usr/bin/docker rm matrix-riot-web | ExecStartPre=-/usr/bin/docker rm matrix-riot-web | ||||
| ExecStart=/usr/bin/docker run --rm --name matrix-riot-web \ | ExecStart=/usr/bin/docker run --rm --name matrix-riot-web \ | ||||
| --log-driver=none \ | --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 }}/config.json:/etc/riot-web/config.json:ro \ | ||||
| -v {{ matrix_riot_web_data_path }}/home.html:/etc/riot-web/home.html:ro \ | -v {{ matrix_riot_web_data_path }}/home.html:/etc/riot-web/home.html:ro \ | ||||
| --network={{ matrix_docker_network }} \ | --network={{ matrix_docker_network }} \ | ||||
| {% if matrix_riot_web_container_expose_port %} | {% if matrix_riot_web_container_expose_port %} | ||||
| -p 127.0.0.1:8765:80 \ | |||||
| -p 127.0.0.1:8765:8080 \ | |||||
| {% endif %} | {% endif %} | ||||
| {{ matrix_riot_web_docker_image }} | {{ matrix_riot_web_docker_image }} | ||||
| ExecStop=-/usr/bin/docker kill matrix-riot-web | ExecStop=-/usr/bin/docker kill matrix-riot-web | ||||
| @@ -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 | 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" | 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) | # Tasks related to getting rid of matrix-mautrix-telegram (if it was previously enabled) | ||||
| @@ -20,11 +20,10 @@ ExecStartPre=/bin/sleep 5 | |||||
| {% endif %} | {% endif %} | ||||
| ExecStart=/usr/bin/docker run --rm --name matrix-synapse \ | ExecStart=/usr/bin/docker run --rm --name matrix-synapse \ | ||||
| --log-driver=none \ | --log-driver=none \ | ||||
| --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ | |||||
| --entrypoint=python \ | |||||
| --network={{ matrix_docker_network }} \ | --network={{ matrix_docker_network }} \ | ||||
| -e SYNAPSE_CONFIG_PATH=/data/homeserver.yaml \ | |||||
| -e SYNAPSE_CACHE_FACTOR={{ matrix_synapse_cache_factor }} \ | -e SYNAPSE_CACHE_FACTOR={{ matrix_synapse_cache_factor }} \ | ||||
| -e UID={{ matrix_user_uid }} \ | |||||
| -e GID={{ matrix_user_gid }} \ | |||||
| {% if matrix_synapse_federation_enabled %} | {% if matrix_synapse_federation_enabled %} | ||||
| -p 8448:8448 \ | -p 8448:8448 \ | ||||
| {% endif %} | {% endif %} | ||||
| @@ -37,7 +36,8 @@ ExecStart=/usr/bin/docker run --rm --name matrix-synapse \ | |||||
| {% for volume in matrix_synapse_container_additional_volumes %} | {% for volume in matrix_synapse_container_additional_volumes %} | ||||
| -v {{ volume.src }}:{{ volume.dst }}:{{ volume.options }} \ | -v {{ volume.src }}:{{ volume.dst }}:{{ volume.options }} \ | ||||
| {% endfor %} | {% 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 kill matrix-synapse | ||||
| ExecStop=-/usr/bin/docker rm matrix-synapse | ExecStop=-/usr/bin/docker rm matrix-synapse | ||||
| Restart=always | Restart=always | ||||