Split playbook into multiple roles

As suggested in #63 (Github issue), splitting the
playbook's logic into multiple roles will be beneficial for
maintainability.

This patch realizes this split. Still, some components
affect others, so the roles are not really independent of one
another. For example:
- disabling mxisd (`matrix_mxisd_enabled: false`), causes Synapse
and riot-web to reconfigure themselves with other (public)
Identity servers.

- enabling matrix-corporal (`matrix_corporal_enabled: true`) affects
how reverse-proxying (by `matrix-nginx-proxy`) is done, in order to
put matrix-corporal's gateway server in front of Synapse

We may be able to move away from such dependencies in the future,
at the expense of a more complicated manual configuration, but
it's probably not worth sacrificing the convenience we have now.

As part of this work, the way we do "start components" has been
redone now to use a loop, as suggested in #65 (Github issue).
This should make restarting faster and more reliable.
This commit is contained in:
Slavi Pantaleev
2019-01-12 17:53:00 +02:00
parent 7d1561b506
commit 51312b8250
122 changed files with 931 additions and 787 deletions

View File

@ -0,0 +1,50 @@
# By default, this playbook sets up its own nginx proxy server on port 80/443.
# This is fine if you're dedicating the whole server to Matrix.
# But in case that's not the case, you may wish to prevent that
# and take care of proxying by yourself.
matrix_nginx_proxy_enabled: true
matrix_nginx_proxy_docker_image: "nginx:1.15.8-alpine"
matrix_nginx_proxy_data_path: "{{ matrix_base_data_path }}/nginx-proxy"
matrix_nginx_proxy_confd_path: "{{ matrix_nginx_proxy_data_path }}/conf.d"
# The addresses where the Matrix Client API is.
# Certain extensions (like matrix-corporal) may override this in order to capture all traffic.
matrix_nginx_proxy_matrix_client_api_addr_with_proxy_container: "matrix-synapse:8008"
matrix_nginx_proxy_matrix_client_api_addr_sans_proxy_container: "localhost:8008"
# Specifies when to reload the matrix-nginx-proxy service so that
# a new SSL certificate could go into effect.
matrix_nginx_proxy_reload_cron_time_definition: "20 4 */5 * *"
# Specifies which SSL protocols to use when serving Riot and Synapse
# Note TLSv1.3 is not yet available in dockerized nginx
# See: https://github.com/nginxinc/docker-nginx/issues/190
matrix_nginx_proxy_ssl_protocols: "TLSv1.1 TLSv1.2"
# By default, this playbook automatically retrieves and auto-renews
# free SSL certificates from Let's Encrypt.
#
# The following retrieval methods are supported:
# - "lets-encrypt" - the playbook obtains free SSL certificates from Let's Encrypt
# - "self-signed" - the playbook generates and self-signs certificates
# - "manually-managed" - lets you manage certificates by yourself (manually; see below)
#
# If you decide to manage certificates by yourself (`matrix_ssl_retrieval_method: manually-managed`),
# you'd need to drop them into the directory specified by `matrix_ssl_config_dir_path`
# obeying the following hierarchy:
# - <matrix_ssl_config_dir_path>/live/<domain>/fullchain.pem
# - <matrix_ssl_config_dir_path>/live/<domain>/privkey.pem
# where <domain> refers to the domains that you need (usually `hostname_matrix` and `hostname_riot`).
matrix_ssl_retrieval_method: "lets-encrypt"
# Controls whether to obtain production or staging certificates from Let's Encrypt.
matrix_ssl_lets_encrypt_staging: false
matrix_ssl_lets_encrypt_certbot_docker_image: "certbot/certbot:v0.30.0"
matrix_ssl_lets_encrypt_certbot_standalone_http_port: 2402
matrix_ssl_lets_encrypt_support_email: "{{ host_specific_matrix_ssl_lets_encrypt_support_email }}"
matrix_ssl_base_path: "{{ matrix_base_data_path }}/ssl"
matrix_ssl_config_dir_path: "{{ matrix_ssl_base_path }}/config"
matrix_ssl_log_dir_path: "{{ matrix_ssl_base_path }}/log"

View File

@ -0,0 +1,3 @@
- set_fact:
matrix_systemd_services_list: "{{ matrix_systemd_services_list + ['matrix-nginx-proxy'] }}"
when: "matrix_nginx_proxy_enabled"

View File

@ -0,0 +1,23 @@
- import_tasks: "{{ role_path }}/tasks/init.yml"
tags:
- always
- import_tasks: "{{ role_path }}/tasks/ssl/main.yml"
when: run_setup
tags:
- setup-all
- setup-nginx-proxy
- setup-ssl
- import_tasks: "{{ role_path }}/tasks/setup_nginx_proxy.yml"
when: run_setup
tags:
- setup-all
- setup-nginx-proxy
- import_tasks: "{{ role_path }}/tasks/self_check_well_known.yml"
delegate_to: 127.0.0.1
become: false
when: run_self_check
tags:
- self-check

View File

@ -0,0 +1,65 @@
---
- set_fact:
well_known_url_matrix: "https://{{ hostname_matrix }}/.well-known/matrix/client"
well_known_url_identity: "https://{{ hostname_identity }}/.well-known/matrix/client"
# These well-known files may be served without a `Content-Type: application/json` header,
# so we can't rely on the uri module's automatic parsing of JSON.
- name: Check .well-known on the matrix hostname
uri:
url: "{{ well_known_url_matrix }}"
follow_redirects: false
return_content: true
register: result_well_known_matrix
ignore_errors: true
- name: Fail if .well-known not working on the matrix hostname
fail:
msg: "Failed checking that well-known is configured at `{{ hostname_matrix }}` (checked endpoint: `{{ well_known_url_matrix }}`). Is port 443 open in your firewall? Full error: {{ result_well_known_matrix }}"
when: "result_well_known_matrix.failed"
- name: Parse JSON for well-known payload at the matrix hostname
set_fact:
well_known_matrix_payload: "{{ result_well_known_matrix.content|from_json }}"
- name: Fail if .well-known not CORS-aware on the matrix hostname
fail:
msg: "Well-known serving for `{{ hostname_matrix }}` (checked endpoint: `{{ well_known_url_matrix }}`) is not CORS-aware. The file needs to be served with an Access-Control-Allow-Origin header set."
when: "'access_control_allow_origin' not in result_well_known_matrix"
- name: Report working .well-known on the matrix hostname
debug:
msg: "well-known is configured correctly for `{{ hostname_matrix }}` (checked endpoint: `{{ well_known_url_matrix }}`)"
- name: Check .well-known on the identity hostname
uri:
url: "{{ well_known_url_identity }}"
follow_redirects: false
return_content: true
register: result_well_known_identity
ignore_errors: true
- name: Fail if .well-known not working on the identity hostname
fail:
msg: "Failed checking that well-known is configured at `{{ hostname_identity }}` (checked endpoint: `{{ well_known_url_identity }}`). Is port 443 open in your firewall? Full error: {{ result_well_known_identity }}"
when: "result_well_known_identity.failed"
- name: Parse JSON for well-known payload at the identity hostname
set_fact:
well_known_identity_payload: "{{ result_well_known_identity.content|from_json }}"
- name: Fail if .well-known not CORS-aware on the identity hostname
fail:
msg: "Well-known serving for `{{ hostname_identity }}` (checked endpoint: `{{ well_known_url_identity }}`) is not CORS-aware. The file needs to be served with an Access-Control-Allow-Origin header set. See docs/configuring-well-known.md"
when: "'access_control_allow_origin' not in result_well_known_identity"
# For people who manually copy the well-known file, try to detect if it's outdated
- name: Fail if well-known is different on matrix hostname and identity hostname
fail:
msg: "The well-known files at `{{ hostname_matrix }}` and `{{ hostname_identity }}` are different. Perhaps you copied the file manually before and now it's outdated?"
when: "well_known_matrix_payload != well_known_identity_payload"
- name: Report working .well-known on the identity hostname
debug:
msg: "well-known is configured correctly for `{{ hostname_identity }}` (checked endpoint: `{{ well_known_url_identity }}`)"

View File

@ -0,0 +1,83 @@
---
#
# Generic tasks that we always want to happen, regardless
# if the user wants matrix-nginx-proxy or not.
#
# If the user would set up their own nginx proxy server,
# the config files from matrix-nginx-proxy can be reused.
#
# It doesn't hurt to put them in place, even if they turn out
# to be unnecessary.
#
- name: Ensure Matrix nginx-proxy paths exist
file:
path: "{{ item }}"
state: directory
mode: 0750
owner: root
group: root
with_items:
- "{{ matrix_nginx_proxy_data_path }}"
- "{{ matrix_nginx_proxy_confd_path }}"
- name: Ensure Matrix nginx-proxy configured
template:
src: "{{ role_path }}/templates/nginx-conf.d/{{ item }}.j2"
dest: "{{ matrix_nginx_proxy_confd_path }}/{{ item }}"
mode: 0644
with_items:
- "nginx-http.conf"
- "matrix-synapse.conf"
- "matrix-riot-web.conf"
#
# Tasks related to setting up matrix-nginx-proxy
#
- name: Ensure nginx Docker image is pulled
docker_image:
name: "{{ matrix_nginx_proxy_docker_image }}"
when: matrix_nginx_proxy_enabled
- name: Allow access to nginx proxy ports in firewalld
firewalld:
service: "{{ item }}"
state: enabled
immediate: yes
permanent: yes
with_items:
- "http"
- "https"
when: "ansible_os_family == 'RedHat' and matrix_nginx_proxy_enabled"
- name: Ensure matrix-nginx-proxy.service installed
template:
src: "{{ role_path }}/templates/systemd/matrix-nginx-proxy.service.j2"
dest: "/etc/systemd/system/matrix-nginx-proxy.service"
mode: 0644
when: matrix_nginx_proxy_enabled
#
# Tasks related to getting rid of matrix-nginx-proxy (if it was previously enabled)
#
- name: Check existence of matrix-nginx-proxy service
stat:
path: "/etc/systemd/system/matrix-nginx-proxy.service"
register: matrix_nginx_proxy_service_stat
- name: Ensure matrix-nginx-proxy is stopped
service:
name: matrix-nginx-proxy
state: stopped
daemon_reload: yes
register: stopping_result
when: "not matrix_nginx_proxy_enabled and matrix_nginx_proxy_service_stat.stat.exists"
- name: Ensure matrix-nginx-proxy.service doesn't exist
file:
path: "/etc/systemd/system/matrix-nginx-proxy.service"
state: absent
when: "not matrix_nginx_proxy_enabled and matrix_nginx_proxy_service_stat.stat.exists"

View File

@ -0,0 +1,24 @@
- set_fact:
matrix_well_known_file_path: "{{ matrix_static_files_base_path }}/.well-known/matrix/client"
# We need others to be able to read these directories too,
# so that matrix-nginx-proxy's nginx user can access the files.
#
# For running with another webserver, we recommend being part of the `matrix` group.
- name: Ensure Matrix static-files path exists
file:
path: "{{ item }}"
state: directory
mode: 0755
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_username }}"
with_items:
- "{{ matrix_static_files_base_path }}/.well-known/matrix"
- name: Ensure Matrix /.well-known/matrix/client configured
template:
src: "{{ role_path }}/templates/well-known/matrix-client.j2"
dest: "{{ matrix_static_files_base_path }}/.well-known/matrix"
mode: 0644
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_username }}"

View File

@ -0,0 +1,38 @@
---
- name: Fail if using unsupported SSL certificate retrieval method
fail:
msg: "The `matrix_ssl_retrieval_method` variable contains an unsupported value"
when: "matrix_ssl_retrieval_method not in ['lets-encrypt', 'self-signed', 'manually-managed']"
# Common tasks, required by any method below.
- name: Determine domains that we require certificates for (Matrix)
set_fact:
domains_requiring_certificates: "['{{ hostname_matrix }}']"
- name: Determine domains that we require certificates for (Riot)
set_fact:
domains_requiring_certificates: "{{ domains_requiring_certificates + [hostname_riot] }}"
when: "matrix_riot_web_enabled"
- name: Ensure SSL certificate paths exists
file:
path: "{{ item }}"
state: directory
mode: 0770
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_username }}"
with_items:
- "{{ matrix_ssl_log_dir_path }}"
- "{{ matrix_ssl_config_dir_path }}"
# Method specific tasks follow
- import_tasks: tasks/ssl/setup_ssl_lets_encrypt.yml
- import_tasks: tasks/ssl/setup_ssl_self_signed.yml
- import_tasks: tasks/ssl/setup_ssl_manually_managed.yml

View File

@ -0,0 +1,114 @@
---
# This is a cleanup/migration task, because of to the new way we manage cronjobs (`cron` module) and the new script name.
# This migration task can be removed some time in the future.
- name: (Migration) Remove deprecated Let's Encrypt SSL certificate management files
file:
path: "{{ item }}"
state: absent
with_items:
- /usr/local/bin/matrix-ssl-certificates-renew
- /etc/cron.d/matrix-ssl-certificate-renewal
- /etc/cron.d/matrix-nginx-proxy-periodic-restarter
#
# Tasks related to setting up Let's Encrypt's management of certificates
#
- name: (Deprecation) Fail if using outdated configuration
fail:
msg: "You're using the `host_specific_matrix_ssl_support_email` variable, which has been superseded by `host_specific_matrix_ssl_lets_encrypt_support_email`. Please change your configuration to use the new name!"
when: "matrix_ssl_retrieval_method == 'lets-encrypt' and host_specific_matrix_ssl_support_email is defined"
- name: Allow access to HTTP/HTTPS in firewalld
firewalld:
service: "{{ item }}"
state: enabled
immediate: yes
permanent: yes
with_items:
- http
- https
when: "matrix_ssl_retrieval_method == 'lets-encrypt' and ansible_os_family == 'RedHat'"
- name: Ensure certbot Docker image is pulled
docker_image:
name: "{{ matrix_ssl_lets_encrypt_certbot_docker_image }}"
when: "matrix_ssl_retrieval_method == 'lets-encrypt'"
- name: Obtain Let's Encrypt certificates
include_tasks: "{{ role_path }}/tasks/ssl/setup_ssl_lets_encrypt_obtain_for_domain.yml"
with_items: "{{ domains_requiring_certificates }}"
loop_control:
loop_var: domain_name
when: "matrix_ssl_retrieval_method == 'lets-encrypt'"
- name: Ensure Let's Encrypt SSL renewal script installed
template:
src: "{{ role_path }}/templates/usr-local-bin/matrix-ssl-lets-encrypt-certificates-renew.j2"
dest: /usr/local/bin/matrix-ssl-lets-encrypt-certificates-renew
mode: 0750
when: "matrix_ssl_retrieval_method == 'lets-encrypt'"
- block:
- name: Ensure periodic SSL renewal cronjob configured (MAILTO)
cron:
user: root
cron_file: matrix-ssl-lets-encrypt
env: yes
name: MAILTO
value: "{{ matrix_ssl_lets_encrypt_support_email }}"
- name: Ensure periodic SSL renewal cronjob configured (matrix-ssl-lets-encrypt-certificates-renew)
cron:
user: root
cron_file: matrix-ssl-lets-encrypt
name: matrix-ssl-lets-encrypt-certificates-renew
state: present
hour: 4
minute: 15
day: "*/5"
job: /usr/local/bin/matrix-ssl-lets-encrypt-certificates-renew
- name: Ensure periodic reloading of matrix-nginx-proxy is configured for SSL renewal (matrix-nginx-proxy-reload)
cron:
user: root
cron_file: matrix-ssl-lets-encrypt
name: matrix-nginx-proxy-reload
state: present
hour: 4
minute: 20
day: "*/5"
job: /usr/bin/systemctl reload matrix-nginx-proxy.service
when: matrix_nginx_proxy_enabled
when: "matrix_ssl_retrieval_method == 'lets-encrypt'"
#
# Tasks related to getting rid of Let's Encrypt's management of certificates
#
# When nginx-proxy is disabled, make sure its reloading cronjob is gone.
# Other cronjobs can potentially remain there (see below).
- name: Ensure matrix-nginx-proxy-reload cronjob removed
cron:
user: root
cron_file: matrix-ssl-lets-encrypt
name: matrix-nginx-proxy-reload
state: absent
when: "not matrix_nginx_proxy_enabled"
# When Let's Encrypt is not used at all, remove all cronjobs in that cron file.
- name: Ensure matrix-ssl-lets-encrypt-renew cronjob removed
cron:
user: root
cron_file: matrix-ssl-lets-encrypt
state: absent
when: "matrix_ssl_retrieval_method != 'lets-encrypt'"
- name: Ensure Let's Encrypt SSL renewal script removed
file:
path: /usr/local/bin/matrix-ssl-lets-encrypt-certificates-renew
state: absent
when: "matrix_ssl_retrieval_method != 'lets-encrypt'"

View File

@ -0,0 +1,70 @@
- debug:
msg: "Dealing with SSL certificate retrieval for domain: {{ domain_name }}"
- set_fact:
domain_name_certificate_path: "{{ matrix_ssl_config_dir_path }}/live/{{ domain_name }}/cert.pem"
- name: Check if a certificate for the domain already exists
stat:
path: "{{ domain_name_certificate_path }}"
register: domain_name_certificate_path_stat
- set_fact:
domain_name_needs_cert: "{{ not domain_name_certificate_path_stat.stat.exists }}"
# This will fail if there is something running on port 80 (like matrix-nginx-proxy).
# We suppress the error, as we'll try another method below.
- name: Attempt initial SSL certificate retrieval with standalone authenticator (directly)
shell: >-
/usr/bin/docker run
--rm
--name=matrix-certbot
--net=host
-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
{% if matrix_ssl_lets_encrypt_staging %}--staging{% endif %}
--standalone
--preferred-challenges http
--agree-tos
--email={{ matrix_ssl_lets_encrypt_support_email }}
-d {{ domain_name }}
when: "domain_name_needs_cert"
register: result_certbot_direct
ignore_errors: true
# If matrix-nginx-proxy is configured from a previous run of this playbook,
# and it's running now, it may be able to proxy requests to `matrix_ssl_lets_encrypt_certbot_standalone_http_port`.
- name: Attempt initial SSL certificate retrieval with standalone authenticator (via proxy)
shell: >-
/usr/bin/docker run
--rm
--name=matrix-certbot
-p 127.0.0.1:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }}:80
--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
{% if matrix_ssl_lets_encrypt_staging %}--staging{% endif %}
--standalone
--preferred-challenges http
--agree-tos
--email={{ matrix_ssl_lets_encrypt_support_email }}
-d {{ domain_name }}
when: "domain_name_needs_cert and result_certbot_direct.failed"
register: result_certbot_proxy
ignore_errors: true
- name: Fail if all SSL certificate retrieval attempts failed
fail:
msg: |
Failed to obtain a certificate directly (by listening on port 80)
and also failed to obtain by relying on the server at port 80 to proxy the request.
See above for details.
You may wish to set up proxying of /.well-known/acme-challenge to {{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }} or,
more easily, stop the server on port 80 while this playbook runs.
when: "domain_name_needs_cert and result_certbot_direct.failed and result_certbot_proxy.failed"

View File

@ -0,0 +1,8 @@
---
- name: Verify certificates
include_tasks: "{{ role_path }}/tasks/ssl/setup_ssl_manually_managed_verify_for_domain.yml"
with_items: "{{ domains_requiring_certificates }}"
loop_control:
loop_var: domain_name
when: "matrix_ssl_retrieval_method == 'manually-managed'"

View File

@ -0,0 +1,23 @@
---
- set_fact:
matrix_ssl_certificate_verification_cert_path: "{{ matrix_ssl_config_dir_path }}/live/{{ domain_name }}/fullchain.pem"
matrix_ssl_certificate_verification_cert_key_path: "{{ matrix_ssl_config_dir_path }}/live/{{ domain_name }}/privkey.pem"
- name: Check if SSL certificate file exists
stat:
path: "{{ matrix_ssl_certificate_verification_cert_path }}"
register: matrix_ssl_certificate_verification_cert_path_stat_result
- fail:
msg: "Failed finding a certificate file (for domain `{{ domain_name }}`) at `{{ matrix_ssl_certificate_verification_cert_path }}`"
when: "not matrix_ssl_certificate_verification_cert_path_stat_result.stat.exists"
- name: Check if SSL certificate key file exists
stat:
path: "{{ matrix_ssl_certificate_verification_cert_key_path }}"
register: matrix_ssl_certificate_verification_cert_key_path_stat_result
- fail:
msg: "Failed finding a certificate key file (for domain `{{ domain_name }}`) at `{{ matrix_ssl_certificate_verification_cert_key_path }}`"
when: "not matrix_ssl_certificate_verification_cert_key_path_stat_result.stat.exists"

View File

@ -0,0 +1,24 @@
---
- name: Ensure OpenSSL installed (RedHat)
yum:
name:
- openssl
state: present
update_cache: no
when: "matrix_ssl_retrieval_method == 'self-signed' and ansible_os_family == 'RedHat'"
- name: Ensure APT usage dependencies are installed (Debian)
apt:
name:
- openssl
state: present
update_cache: no
when: "matrix_ssl_retrieval_method == 'self-signed' and ansible_os_family == 'Debian'"
- name: Generate self-signed certificates
include_tasks: "{{ role_path }}/tasks/ssl/setup_ssl_self_signed_obtain_for_domain.yml"
with_items: "{{ domains_requiring_certificates }}"
loop_control:
loop_var: domain_name
when: "matrix_ssl_retrieval_method == 'self-signed'"

View File

@ -0,0 +1,40 @@
---
- set_fact:
matrix_ssl_certificate_csr_path: "{{ matrix_ssl_config_dir_path }}/live/{{ domain_name }}/csr.csr"
matrix_ssl_certificate_cert_path: "{{ matrix_ssl_config_dir_path }}/live/{{ domain_name }}/fullchain.pem"
matrix_ssl_certificate_cert_key_path: "{{ matrix_ssl_config_dir_path }}/live/{{ domain_name }}/privkey.pem"
- name: Check if SSL certificate file exists
stat:
path: "{{ matrix_ssl_certificate_cert_path }}"
register: matrix_ssl_certificate_cert_path_stat_result
# In order to do any sort of generation (below), we need to ensure the directory exists first
- name: Ensure SSL certificate directory exists
file:
path: "{{ matrix_ssl_certificate_csr_path|dirname }}"
state: directory
mode: 0750
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_username }}"
when: "not matrix_ssl_certificate_cert_path_stat_result.stat.exists"
# The proper way to do this is by using a sequence of
# `openssl_privatekey`, `openssl_csr` and `openssl_certificate`.
#
# Unfortunately, `openssl_csr` and `openssl_certificate` require `PyOpenSSL>=0.15` to work,
# which is not available on CentOS 7 (at least).
#
# We'll do it in a more manual way.
- name: Generate SSL certificate
command: |
openssl req -x509 \
-sha256 \
-newkey rsa:4096 \
-nodes \
-subj "/CN={{ domain_name }}" \
-keyout {{ matrix_ssl_certificate_cert_key_path }} \
-out {{ matrix_ssl_certificate_cert_path }} \
-days 3650
when: "not matrix_ssl_certificate_cert_path_stat_result.stat.exists"

View File

@ -0,0 +1,55 @@
server {
listen 80;
server_name {{ hostname_riot }};
server_tokens off;
location /.well-known/acme-challenge {
{% 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";
proxy_pass http://$backend;
{% else %}
{# Generic configuration for use outside of our container setup #}
proxy_pass http://localhost:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }};
{% endif %}
}
location / {
return 301 https://$http_host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ hostname_riot }};
server_tokens off;
root /dev/null;
gzip on;
gzip_types text/plain application/json application/javascript text/css image/x-icon font/ttf image/gif;
ssl_certificate {{ matrix_ssl_config_dir_path }}/live/{{ hostname_riot }}/fullchain.pem;
ssl_certificate_key {{ matrix_ssl_config_dir_path }}/live/{{ hostname_riot }}/privkey.pem;
ssl_protocols {{ matrix_nginx_proxy_ssl_protocols }};
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
location / {
{% 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";
proxy_pass http://$backend;
{% else %}
{# Generic configuration for use outside of our container setup #}
proxy_pass http://localhost:8765;
{% endif %}
proxy_set_header X-Forwarded-For $remote_addr;
}
}

View File

@ -0,0 +1,112 @@
server {
listen 80;
server_name {{ hostname_matrix }};
server_tokens off;
location /.well-known/acme-challenge {
{% 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";
proxy_pass http://$backend;
{% else %}
{# Generic configuration for use outside of our container setup #}
proxy_pass http://localhost:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }};
{% endif %}
}
location / {
return 301 https://$http_host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ hostname_matrix }};
server_tokens off;
root /dev/null;
gzip on;
gzip_types text/plain application/json;
ssl_certificate {{ matrix_ssl_config_dir_path }}/live/{{ hostname_matrix }}/fullchain.pem;
ssl_certificate_key {{ matrix_ssl_config_dir_path }}/live/{{ hostname_matrix }}/privkey.pem;
ssl_protocols {{ matrix_nginx_proxy_ssl_protocols }};
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
location /.well-known/matrix/client {
root {{ matrix_static_files_base_path }};
expires 1m;
default_type application/json;
add_header Access-Control-Allow-Origin *;
}
{% if matrix_corporal_enabled and matrix_corporal_http_api_enabled %}
location /_matrix/corporal {
{% 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-corporal:41081";
proxy_pass http://$backend;
{% else %}
{# Generic configuration for use outside of our container setup #}
proxy_pass http://localhost:41081;
{% endif %}
}
{% endif %}
{% if matrix_mxisd_enabled %}
location /_matrix/identity {
{% 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-mxisd:8090";
proxy_pass http://$backend;
{% else %}
{# Generic configuration for use outside of our container setup #}
proxy_pass http://localhost:8090;
{% endif %}
}
{% endif %}
{% if matrix_mautrix_telegram_enabled %}
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 %}
}
{% endif %}
location /_matrix {
{% 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_nginx_proxy_matrix_client_api_addr_with_proxy_container }}";
proxy_pass http://$backend;
{% else %}
{# Generic configuration for use outside of our container setup #}
proxy_pass http://{{ matrix_nginx_proxy_matrix_client_api_addr_sans_proxy_container }};
{% endif %}
proxy_set_header X-Forwarded-For $remote_addr;
client_body_buffer_size 25M;
client_max_body_size {{ matrix_synapse_max_upload_size_mb }}M;
proxy_max_temp_file_size 0;
}
location / {
rewrite ^/$ /_matrix/static/ last;
}
}

View File

@ -0,0 +1,5 @@
# The default is aligned to the CPU's cache size,
# which can sometimes be too low to handle our 2 vhosts (Synapse and Riot).
#
# Thus, we ensure a larger bucket size value is used.
server_names_hash_bucket_size 64;

View File

@ -0,0 +1,36 @@
[Unit]
Description=Matrix nginx proxy server
After=docker.service
Requires=docker.service
Wants=matrix-synapse.service
{% if matrix_corporal_enabled %}
Wants=matrix-corporal.service
{% endif %}
{% if matrix_riot_web_enabled %}
Wants=matrix-riot-web.service
{% endif %}
{% if matrix_mxisd_enabled %}
Wants=matrix-mxisd.service
{% endif %}
[Service]
Type=simple
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 \
--network={{ matrix_docker_network }} \
-p 80:80 \
-p 443:443 \
-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 \
{{ matrix_nginx_proxy_docker_image }}
ExecStop=-/usr/bin/docker kill matrix-nginx-proxy
ExecStop=-/usr/bin/docker rm matrix-nginx-proxy
ExecReload=/usr/bin/docker exec matrix-nginx-proxy /usr/sbin/nginx -s reload
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,26 @@
#!/bin/bash
# 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`
# or outside (on the host) by proxying to `http://localhost:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }}`.
docker run \
--rm \
--name=matrix-certbot \
--network="{{ matrix_docker_network }}" \
-p 127.0.0.1:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }}:80 \
-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 \
{% if matrix_ssl_lets_encrypt_staging %}
--staging \
{% endif %}
--quiet \
--standalone \
--preferred-challenges http \
--agree-tos \
--email={{ matrix_ssl_lets_encrypt_support_email }}