From 233e25326457fdbb6c65e74412c6f0f824a310f9 Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Sat, 25 Feb 2023 13:15:34 +0200 Subject: [PATCH] Add native Traefik support to rageshake --- group_vars/matrix_servers | 15 +++- .../matrix-nginx-proxy/defaults/main.yml | 5 -- .../matrix-nginx-proxy/templates/labels.j2 | 11 --- .../custom/matrix-rageshake/defaults/main.yml | 69 +++++++++++++++++-- .../custom/matrix-rageshake/tasks/install.yml | 18 ++++- .../matrix-rageshake/tasks/uninstall.yml | 3 +- .../tasks/validate_config.yml | 30 ++++++++ .../matrix-rageshake/templates/labels.j2 | 45 ++++++++++++ .../systemd/matrix-rageshake.service.j2 | 14 +++- 9 files changed, 180 insertions(+), 30 deletions(-) create mode 100644 roles/custom/matrix-rageshake/templates/labels.j2 diff --git a/group_vars/matrix_servers b/group_vars/matrix_servers index 2ad11473b..dc24392e3 100755 --- a/group_vars/matrix_servers +++ b/group_vars/matrix_servers @@ -2009,6 +2009,18 @@ matrix_rageshake_enabled: false matrix_rageshake_container_image_self_build: "{{ matrix_architecture not in ['amd64'] }}" +matrix_rageshake_hostname: "{{ matrix_server_fqn_rageshake }}" + +matrix_rageshake_container_network: "{{ matrix_docker_network if matrix_playbook_reverse_proxy_type == 'playbook-managed-nginx' else 'matrix-rageshake' }}" + +matrix_rageshake_container_additional_networks: "{{ [matrix_playbook_reverse_proxyable_services_additional_network] if matrix_playbook_reverse_proxyable_services_additional_network else [] }}" + +matrix_rageshake_container_http_host_bind_port: "{{ (matrix_playbook_service_host_bind_interface_prefix ~ '9110') if matrix_playbook_service_host_bind_interface_prefix else '' }}" + +matrix_rageshake_container_labels_traefik_enabled: "{{ matrix_playbook_traefik_labels_enabled }}" +matrix_rageshake_container_labels_traefik_docker_network: "{{ matrix_playbook_reverse_proxyable_services_additional_network }}" +matrix_rageshake_container_labels_traefik_entrypoints: "{{ devture_traefik_entrypoint_primary }}" + ###################################################################### # # /matrix-rageshake @@ -2403,7 +2415,7 @@ matrix_nginx_proxy_proxy_hydrogen_enabled: "{{ matrix_client_hydrogen_enabled an matrix_nginx_proxy_proxy_cinny_enabled: "{{ matrix_client_cinny_enabled and matrix_playbook_reverse_proxy_type in ['playbook-managed-nginx', 'other-nginx-non-container'] }}" matrix_nginx_proxy_proxy_buscarron_enabled: "{{ matrix_bot_buscarron_enabled }}" matrix_nginx_proxy_proxy_dimension_enabled: "{{ matrix_dimension_enabled }}" -matrix_nginx_proxy_proxy_rageshake_enabled: "{{ matrix_rageshake_enabled }}" +matrix_nginx_proxy_proxy_rageshake_enabled: "{{ matrix_rageshake_enabled and matrix_playbook_reverse_proxy_type in ['playbook-managed-nginx', 'other-nginx-non-container'] }}" matrix_nginx_proxy_proxy_etherpad_enabled: "{{ matrix_etherpad_enabled and matrix_etherpad_mode == 'standalone' }}" matrix_nginx_proxy_proxy_bot_go_neb_enabled: "{{ matrix_bot_go_neb_enabled }}" @@ -2421,7 +2433,6 @@ matrix_nginx_proxy_container_labels_traefik_entrypoints: "{{ devture_traefik_ent matrix_nginx_proxy_container_labels_traefik_proxy_matrix_enabled: true matrix_nginx_proxy_container_labels_traefik_proxy_buscarron_enabled: "{{ matrix_bot_buscarron_enabled }}" matrix_nginx_proxy_container_labels_traefik_proxy_dimension_enabled: "{{ matrix_dimension_enabled }}" -matrix_nginx_proxy_container_labels_traefik_proxy_rageshake_enabled: "{{ matrix_rageshake_enabled }}" matrix_nginx_proxy_container_labels_traefik_proxy_etherpad_enabled: "{{ matrix_etherpad_enabled and matrix_etherpad_mode == 'standalone' }}" matrix_nginx_proxy_container_labels_traefik_proxy_bot_go_neb_enabled: "{{ matrix_bot_go_neb_enabled }}" matrix_nginx_proxy_container_labels_traefik_proxy_jitsi_enabled: "{{ matrix_jitsi_enabled }}" diff --git a/roles/custom/matrix-nginx-proxy/defaults/main.yml b/roles/custom/matrix-nginx-proxy/defaults/main.yml index b5915dc40..061d8f936 100644 --- a/roles/custom/matrix-nginx-proxy/defaults/main.yml +++ b/roles/custom/matrix-nginx-proxy/defaults/main.yml @@ -71,11 +71,6 @@ matrix_nginx_proxy_container_labels_traefik_proxy_dimension_hostname: "{{ matrix matrix_nginx_proxy_container_labels_traefik_proxy_dimension_tls: "{{ matrix_nginx_proxy_container_labels_traefik_entrypoints != 'web' }}" matrix_nginx_proxy_container_labels_traefik_proxy_dimension_rule: "Host(`{{ matrix_nginx_proxy_container_labels_traefik_proxy_dimension_hostname }}`)" -matrix_nginx_proxy_container_labels_traefik_proxy_rageshake_enabled: false -matrix_nginx_proxy_container_labels_traefik_proxy_rageshake_hostname: "{{ matrix_server_fqn_rageshake }}" -matrix_nginx_proxy_container_labels_traefik_proxy_rageshake_tls: "{{ matrix_nginx_proxy_container_labels_traefik_entrypoints != 'web' }}" -matrix_nginx_proxy_container_labels_traefik_proxy_rageshake_rule: "Host(`{{ matrix_nginx_proxy_container_labels_traefik_proxy_rageshake_hostname }}`)" - matrix_nginx_proxy_container_labels_traefik_proxy_etherpad_enabled: false matrix_nginx_proxy_container_labels_traefik_proxy_etherpad_hostname: "{{ matrix_server_fqn_etherpad }}" matrix_nginx_proxy_container_labels_traefik_proxy_etherpad_tls: "{{ matrix_nginx_proxy_container_labels_traefik_entrypoints != 'web' }}" diff --git a/roles/custom/matrix-nginx-proxy/templates/labels.j2 b/roles/custom/matrix-nginx-proxy/templates/labels.j2 index 00c9c40a9..1e60ba6d9 100644 --- a/roles/custom/matrix-nginx-proxy/templates/labels.j2 +++ b/roles/custom/matrix-nginx-proxy/templates/labels.j2 @@ -62,17 +62,6 @@ traefik.http.routers.matrix-nginx-proxy-dimension.entrypoints={{ matrix_nginx_pr {% endif %} -{% if matrix_nginx_proxy_container_labels_traefik_proxy_rageshake_enabled %} -# Rageshake -traefik.http.routers.matrix-nginx-proxy-rageshake.rule={{ matrix_nginx_proxy_container_labels_traefik_proxy_rageshake_rule }} -traefik.http.routers.matrix-nginx-proxy-rageshake.service=matrix-nginx-proxy-web -traefik.http.routers.matrix-nginx-proxy-rageshake.tls={{ matrix_nginx_proxy_container_labels_traefik_proxy_rageshake_tls | to_json }} -{% if matrix_nginx_proxy_container_labels_traefik_proxy_rageshake_tls %} -traefik.http.routers.matrix-nginx-proxy-rageshake.tls.certResolver={{ matrix_nginx_proxy_container_labels_traefik_tls_certResolver }} -{% endif %} -traefik.http.routers.matrix-nginx-proxy-rageshake.entrypoints={{ matrix_nginx_proxy_container_labels_traefik_entrypoints }} -{% endif %} - {% if matrix_nginx_proxy_container_labels_traefik_proxy_etherpad_enabled %} # Etherpad traefik.http.routers.matrix-nginx-proxy-etherpad.rule={{ matrix_nginx_proxy_container_labels_traefik_proxy_etherpad_rule }} diff --git a/roles/custom/matrix-rageshake/defaults/main.yml b/roles/custom/matrix-rageshake/defaults/main.yml index 5be3a1ca1..456838ed9 100644 --- a/roles/custom/matrix-rageshake/defaults/main.yml +++ b/roles/custom/matrix-rageshake/defaults/main.yml @@ -4,21 +4,76 @@ matrix_rageshake_enabled: true +matrix_rageshake_scheme: https + +# The hostname at which rageshake is served. +matrix_rageshake_hostname: '' + +# The path at which rageshake is exposed. +# This value must either be `/` or not end with a slash (e.g. `/rageshake`). +matrix_rageshake_path_prefix: / + # There are no stable container image tags yet. # See: https://github.com/matrix-org/rageshake/issues/69 matrix_rageshake_version: "master" -matrix_rageshake_container_image: "{{ matrix_rageshake_container_image_name_prefix }}matrix-org/rageshake:{{ matrix_rageshake_version }}" -matrix_rageshake_container_image_name_prefix: "{{ 'localhost/' if matrix_rageshake_container_image_self_build else 'ghcr.io/' }}" -matrix_rageshake_container_image_force_pull: "{{ matrix_rageshake_container_image.endswith(':master') }}" matrix_rageshake_base_path: "{{ matrix_base_data_path }}/rageshake" matrix_rageshake_config_path: "{{ matrix_rageshake_base_path }}/config" matrix_rageshake_data_path: "{{ matrix_rageshake_base_path }}/data" +matrix_rageshake_container_src_files_path: "{{ matrix_rageshake_base_path }}/container-src" + +matrix_rageshake_container_image: "{{ matrix_rageshake_container_image_name_prefix }}matrix-org/rageshake:{{ matrix_rageshake_container_image_tag }}" +matrix_rageshake_container_image_name_prefix: "{{ 'localhost/' if matrix_rageshake_container_image_self_build else matrix_rageshake_container_registry_prefix }}" +matrix_rageshake_container_image_force_pull: "{{ matrix_rageshake_container_image.endswith(':master') }}" +matrix_rageshake_container_image_tag: "{{ matrix_rageshake_version }}" +matrix_rageshake_container_registry_prefix: ghcr.io/ matrix_rageshake_container_image_self_build: false -matrix_rageshake_container_repo: "https://github.com/matrix-org/rageshake/" -matrix_rageshake_container_repo_version: "{{ 'master' if matrix_rageshake_version == 'master' else matrix_rageshake_version }}" -matrix_rageshake_container_src_files_path: "{{ matrix_rageshake_base_path }}/container-src" +matrix_rageshake_container_image_self_build_repo: "https://github.com/matrix-org/rageshake/" +matrix_rageshake_container_image_self_build_repo_version: "{{ matrix_rageshake_version }}" + +# Controls whether the container exposes its HTTP port (tcp/9110 in the container). +# +# Takes an ":" or "" value (e.g. "127.0.0.1:9110"), or empty string to not expose. +matrix_rageshake_container_http_host_bind_port: '' + +# The base container network. It will be auto-created by this role if it doesn't exist already. +matrix_rageshake_container_network: matrix-rageshake + +# A list of additional container networks that the container would be connected to. +# The role does not create these networks, so make sure they already exist. +# Use this to expose this container to another reverse proxy, which runs in a different container network. +matrix_rageshake_container_additional_networks: [] + +# matrix_rageshake_container_labels_traefik_enabled controls whether labels to assist a Traefik reverse-proxy will be attached to the container. +# See `../templates/labels.j2` for details. +# +# To inject your own other container labels, see `matrix_rageshake_container_labels_additional_labels`. +matrix_rageshake_container_labels_traefik_enabled: true +matrix_rageshake_container_labels_traefik_docker_network: "{{ matrix_rageshake_container_network }}" +matrix_rageshake_container_labels_traefik_hostname: "{{ matrix_rageshake_hostname }}" +# The path prefix must either be `/` or not end with a slash (e.g. `/rageshake`). +matrix_rageshake_container_labels_traefik_path_prefix: "{{ matrix_rageshake_path_prefix }}" +matrix_rageshake_container_labels_traefik_rule: "Host(`{{ matrix_rageshake_container_labels_traefik_hostname }}`){% if matrix_rageshake_container_labels_traefik_path_prefix != '/' %} && PathPrefix(`{{ matrix_rageshake_container_labels_traefik_path_prefix }}`){% endif %}" +matrix_rageshake_container_labels_traefik_priority: 0 +matrix_rageshake_container_labels_traefik_entrypoints: web-secure +matrix_rageshake_container_labels_traefik_tls: "{{ matrix_rageshake_container_labels_traefik_entrypoints != 'web' }}" +matrix_rageshake_container_labels_traefik_tls_certResolver: default # noqa var-naming + +# Controls which additional headers to attach to all HTTP responses. +# To add your own headers, use `matrix_rageshake_container_labels_traefik_additional_response_headers_custom` +matrix_rageshake_container_labels_traefik_additional_response_headers: "{{ matrix_rageshake_container_labels_traefik_additional_response_headers_auto | combine(matrix_rageshake_container_labels_traefik_additional_response_headers_custom) }}" +matrix_rageshake_container_labels_traefik_additional_response_headers_auto: {} +matrix_rageshake_container_labels_traefik_additional_response_headers_custom: {} + +# matrix_rageshake_container_labels_additional_labels contains a multiline string with additional labels to add to the container label file. +# See `../templates/labels.j2` for details. +# +# Example: +# matrix_rageshake_container_labels_additional_labels: | +# my.label=1 +# another.label="here" +matrix_rageshake_container_labels_additional_labels: '' # A list of extra arguments to pass to the container matrix_rageshake_container_extra_arguments: [] @@ -29,7 +84,7 @@ matrix_rageshake_systemd_required_services_list: ["docker.service"] # List of systemd services that matrix-rageshake.service wants matrix_rageshake_systemd_wanted_services_list: [] -matrix_rageshake_config_api_prefix: "https://{{ matrix_server_fqn_rageshake }}/api/" +matrix_rageshake_config_api_prefix: "{{ matrix_rageshake_scheme }}://{{ matrix_rageshake_hostname }}{{ matrix_rageshake_path_prefix }}{{ '' if matrix_rageshake_path_prefix == '/' else '/' }}api/" # Default Rageshake configuration template which covers the generic use case. # You can customize it by controlling the various variables inside it. diff --git a/roles/custom/matrix-rageshake/tasks/install.yml b/roles/custom/matrix-rageshake/tasks/install.yml index a7b6a5b1e..f9461680f 100644 --- a/roles/custom/matrix-rageshake/tasks/install.yml +++ b/roles/custom/matrix-rageshake/tasks/install.yml @@ -1,4 +1,5 @@ --- + - name: Ensure rageshake paths exist ansible.builtin.file: path: "{{ item.path }}" @@ -23,6 +24,14 @@ group: "{{ matrix_user_groupname }}" mode: 0640 +- name: Ensure rageshake labels installed + ansible.builtin.template: + src: "{{ role_path }}/templates/labels.j2" + dest: "{{ matrix_rageshake_base_path }}/labels" + mode: 0640 + owner: "{{ matrix_user_username }}" + group: "{{ matrix_user_groupname }}" + - name: Ensure rageshake image is pulled community.docker.docker_image: name: "{{ matrix_rageshake_container_image }}" @@ -37,8 +46,8 @@ - name: Ensure rageshake repository is present on self-build ansible.builtin.git: - repo: "{{ matrix_rageshake_container_repo }}" - version: "{{ matrix_rageshake_container_repo_version }}" + repo: "{{ matrix_rageshake_container_image_self_build_repo }}" + version: "{{ matrix_rageshake_container_image_self_build_version }}" dest: "{{ matrix_rageshake_container_src_files_path }}" force: "yes" become: true @@ -55,6 +64,11 @@ {{ matrix_rageshake_container_src_files_path }} when: matrix_rageshake_container_image_self_build | bool +- name: Ensure rageshake container network is created + community.general.docker_network: + name: "{{ matrix_rageshake_container_network }}" + driver: bridge + - name: Ensure matrix-rageshake.service installed ansible.builtin.template: src: "{{ role_path }}/templates/systemd/matrix-rageshake.service.j2" diff --git a/roles/custom/matrix-rageshake/tasks/uninstall.yml b/roles/custom/matrix-rageshake/tasks/uninstall.yml index 133ac76d3..8f04d9894 100644 --- a/roles/custom/matrix-rageshake/tasks/uninstall.yml +++ b/roles/custom/matrix-rageshake/tasks/uninstall.yml @@ -1,4 +1,5 @@ --- + - name: Check existence of matrix-rageshake service ansible.builtin.stat: path: "{{ devture_systemd_docker_base_systemd_path }}/matrix-rageshake.service" @@ -18,7 +19,7 @@ path: "{{ devture_systemd_docker_base_systemd_path }}/matrix-rageshake.service" state: absent - - name: Ensure Matrix rageshake paths don't exist + - name: Ensure rageshake paths don't exist ansible.builtin.file: path: "{{ matrix_rageshake_base_path }}" state: absent diff --git a/roles/custom/matrix-rageshake/tasks/validate_config.yml b/roles/custom/matrix-rageshake/tasks/validate_config.yml index ed97d539c..b61a486d2 100644 --- a/roles/custom/matrix-rageshake/tasks/validate_config.yml +++ b/roles/custom/matrix-rageshake/tasks/validate_config.yml @@ -1 +1,31 @@ --- + +- name: Fail if required rageshake settings not defined + ansible.builtin.fail: + msg: > + You need to define a required configuration setting (`{{ item }}`). + when: "vars[item] == ''" + with_items: + - matrix_rageshake_hostname + - matrix_rageshake_path_prefix + - matrix_rageshake_container_network + +- when: matrix_rageshake_container_labels_traefik_enabled | bool + block: + - name: Fail if required rageshake Traefik settings not defined + ansible.builtin.fail: + msg: >- + You need to define a required configuration setting (`{{ item }}`). + when: "vars[item] == ''" + with_items: + - matrix_rageshake_container_labels_traefik_hostname + - matrix_rageshake_container_labels_traefik_path_prefix + + # We ensure it doesn't end with a slash, because we handle both (slash and no-slash). + # Knowing that `matrix_rageshake_container_labels_traefik_path_prefix` does not end with a slash + # ensures we know how to set these routes up without having to do "does it end with a slash" checks elsewhere. + - name: Fail if matrix_rageshake_container_labels_traefik_path_prefix ends with a slash + ansible.builtin.fail: + msg: >- + matrix_rageshake_container_labels_traefik_path_prefix (`{{ matrix_rageshake_container_labels_traefik_path_prefix }}`) must either be `/` or not end with a slash (e.g. `/rageshake`). + when: "matrix_rageshake_container_labels_traefik_path_prefix != '/' and matrix_rageshake_container_labels_traefik_path_prefix[-1] == '/'" diff --git a/roles/custom/matrix-rageshake/templates/labels.j2 b/roles/custom/matrix-rageshake/templates/labels.j2 new file mode 100644 index 000000000..cdaf5f6af --- /dev/null +++ b/roles/custom/matrix-rageshake/templates/labels.j2 @@ -0,0 +1,45 @@ +{% if matrix_rageshake_container_labels_traefik_enabled %} +traefik.enable=true + +{% if matrix_rageshake_container_labels_traefik_docker_network %} +traefik.docker.network={{ matrix_rageshake_container_labels_traefik_docker_network }} +{% endif %} + +{% set middlewares = [] %} + +{% if matrix_rageshake_container_labels_traefik_path_prefix != '/' %} +traefik.http.middlewares.matrix-rageshake-slashless-redirect.redirectregex.regex=({{ matrix_rageshake_container_labels_traefik_path_prefix | quote }})$ +traefik.http.middlewares.matrix-rageshake-slashless-redirect.redirectregex.replacement=${1}/ +{% set middlewares = middlewares + ['matrix-rageshake-slashless-redirect'] %} +{% endif %} + +{% if matrix_rageshake_container_labels_traefik_path_prefix != '/' %} +traefik.http.middlewares.matrix-rageshake-strip-prefix.stripprefix.prefixes={{ matrix_rageshake_container_labels_traefik_path_prefix }} +{% set middlewares = middlewares + ['matrix-rageshake-strip-prefix'] %} +{% endif %} + +{% if matrix_rageshake_container_labels_traefik_additional_response_headers.keys() | length > 0 %} +{% for name, value in matrix_rageshake_container_labels_traefik_additional_response_headers.items() %} +traefik.http.middlewares.matrix-rageshake-add-headers.headers.customresponseheaders.{{ name }}={{ value }} +{% endfor %} +{% set middlewares = middlewares + ['matrix-rageshake-add-headers'] %} +{% endif %} + +traefik.http.routers.matrix-rageshake.rule={{ matrix_rageshake_container_labels_traefik_rule }} +{% if matrix_rageshake_container_labels_traefik_priority | int > 0 %} +traefik.http.routers.matrix-rageshake.priority={{ matrix_rageshake_container_labels_traefik_priority }} +{% endif %} +traefik.http.routers.matrix-rageshake.service=matrix-rageshake +{% if middlewares | length > 0 %} +traefik.http.routers.matrix-rageshake.middlewares={{ middlewares | join(',') }} +{% endif %} +traefik.http.routers.matrix-rageshake.entrypoints={{ matrix_rageshake_container_labels_traefik_entrypoints }} +traefik.http.routers.matrix-rageshake.tls={{ matrix_rageshake_container_labels_traefik_tls | to_json }} +{% if matrix_rageshake_container_labels_traefik_tls %} +traefik.http.routers.matrix-rageshake.tls.certResolver={{ matrix_rageshake_container_labels_traefik_tls_certResolver }} +{% endif %} + +traefik.http.services.matrix-rageshake.loadbalancer.server.port=9110 +{% endif %} + +{{ matrix_rageshake_container_labels_additional_labels }} diff --git a/roles/custom/matrix-rageshake/templates/systemd/matrix-rageshake.service.j2 b/roles/custom/matrix-rageshake/templates/systemd/matrix-rageshake.service.j2 index 5e6cfecee..75006c2d5 100644 --- a/roles/custom/matrix-rageshake/templates/systemd/matrix-rageshake.service.j2 +++ b/roles/custom/matrix-rageshake/templates/systemd/matrix-rageshake.service.j2 @@ -16,23 +16,33 @@ Environment="HOME={{ devture_systemd_docker_base_systemd_unit_home_path }}" ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} kill matrix-rageshake 2>/dev/null || true' ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-rageshake 2>/dev/null || true' -ExecStart={{ devture_systemd_docker_base_host_command_docker }} run --rm --name matrix-rageshake \ +ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} create \ + --rm \ + --name=matrix-rageshake \ --log-driver=none \ --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ --cap-drop=ALL \ --read-only \ --tmpfs /tmp \ - --network={{ matrix_docker_network }} \ + --network={{ matrix_rageshake_container_network }} \ --mount type=bind,src={{ matrix_rageshake_config_path }},dst=/config \ --mount type=bind,src={{ matrix_rageshake_data_path }},dst=/bugs \ + --label-file={{ matrix_rageshake_base_path }}/labels \ {% for arg in matrix_rageshake_container_extra_arguments %} {{ arg }} \ {% endfor %} {{ matrix_rageshake_container_image }} \ --config /config/config.yml +{% for network in matrix_rageshake_container_additional_networks %} +ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} network connect {{ network }} matrix-rageshake +{% endfor %} + +ExecStart={{ devture_systemd_docker_base_host_command_docker }} start --attach matrix-rageshake + ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} kill matrix-rageshake 2>/dev/null || true' ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-rageshake 2>/dev/null || true' + Restart=always RestartSec=30 SyslogIdentifier=matrix-rageshake