diff --git a/group_vars/matrix_servers b/group_vars/matrix_servers index 4a989f03..d80072ef 100755 --- a/group_vars/matrix_servers +++ b/group_vars/matrix_servers @@ -864,6 +864,22 @@ matrix_postgres_db_name: "homeserver" +###################################################################### +# +# matrix-redis +# +###################################################################### + +matrix_redis_enabled: "{{ matrix_synapse_workers_enabled }}" + +###################################################################### +# +# /matrix-redis +# +###################################################################### + + + ###################################################################### # # matrix-client-element @@ -1003,6 +1019,11 @@ matrix_synapse_systemd_wanted_services_list: | (['matrix-mailer.service'] if matrix_mailer_enabled else []) }} +# Worker support with redis +matrix_synapse_redis_enabled: "{{ matrix_redis_enabled }}" +matrix_synapse_redis_host: "{{ 'matrix-redis' if matrix_redis_enabled else '' }}" +matrix_synapse_redis_password: "{{ matrix_redis_connection_password if matrix_redis_enabled else '' }}" + ###################################################################### # # /matrix-synapse diff --git a/roles/matrix-redis/defaults/main.yml b/roles/matrix-redis/defaults/main.yml new file mode 100644 index 00000000..f48ea542 --- /dev/null +++ b/roles/matrix-redis/defaults/main.yml @@ -0,0 +1,22 @@ +matrix_redis_enabled: true + +matrix_redis_connection_password: "" + +matrix_redis_base_path: "{{ matrix_base_data_path }}/redis" +matrix_redis_data_path: "{{ matrix_redis_base_path }}/data" + +matrix_redis_docker_image_v5: "redis:5.0-alpine" +matrix_redis_docker_image_v6: "redis:6.0-alpine" +matrix_redis_docker_image_latest: "{{ matrix_redis_docker_image_v6 }}" +matrix_redis_docker_image_to_use: '{{ matrix_redis_docker_image_latest }}' + +matrix_redis_docker_image_force_pull: "{{ matrix_redis_docker_image_to_use.endswith(':latest') }}" + +# A list of extra arguments to pass to the container +matrix_redis_container_extra_arguments: [] + +# Controls whether the matrix-redis container exposes a port (tcp/6379 in the container) +# that can be used to access redis from outside the container +# +# Takes an ":" or "" value (e.g. "127.0.0.1:6379"), or empty string to not expose. +matrix_redis_container_redis_bind_port: "" diff --git a/roles/matrix-redis/tasks/init.yml b/roles/matrix-redis/tasks/init.yml new file mode 100644 index 00000000..49068851 --- /dev/null +++ b/roles/matrix-redis/tasks/init.yml @@ -0,0 +1,3 @@ +- set_fact: + matrix_systemd_services_list: "{{ matrix_systemd_services_list + ['matrix-redis'] }}" + when: matrix_redis_enabled|bool diff --git a/roles/matrix-redis/tasks/main.yml b/roles/matrix-redis/tasks/main.yml new file mode 100644 index 00000000..595b09f5 --- /dev/null +++ b/roles/matrix-redis/tasks/main.yml @@ -0,0 +1,9 @@ +- import_tasks: "{{ role_path }}/tasks/init.yml" + tags: + - always + +- import_tasks: "{{ role_path }}/tasks/setup_redis.yml" + when: run_setup|bool + tags: + - setup-all + - setup-redis diff --git a/roles/matrix-redis/tasks/setup_redis.yml b/roles/matrix-redis/tasks/setup_redis.yml new file mode 100644 index 00000000..6f00282b --- /dev/null +++ b/roles/matrix-redis/tasks/setup_redis.yml @@ -0,0 +1,99 @@ +--- + +# +# Tasks related to setting up an internal redis server +# + +- name: Ensure redis Docker image is pulled + docker_image: + name: "{{ matrix_redis_docker_image_to_use }}" + source: "{{ 'pull' if ansible_version.major > 2 or ansible_version.minor > 7 else omit }}" + force_source: "{{ matrix_redis_docker_image_force_pull if ansible_version.major > 2 or ansible_version.minor >= 8 else omit }}" + force: "{{ omit if ansible_version.major > 2 or ansible_version.minor >= 8 else matrix_redis_docker_image_force_pull }}" + when: matrix_redis_enabled|bool + +- name: Ensure redis paths exist + file: + path: "{{ item }}" + state: directory + mode: 0700 + owner: "{{ matrix_user_username }}" + group: "{{ matrix_user_username }}" + with_items: + - "{{ matrix_redis_base_path }}" + - "{{ matrix_redis_data_path }}" + when: matrix_redis_enabled|bool + +# We do this as a separate task, because: +# - we'd like to do it for the data path only, not for the base path (which contains root-owned environment variable files we'd like to leave as-is) +# - we need to do it without `mode`, or we risk making certain `.conf` and other files's executable bit to flip to true +- name: Ensure redis data path ownership is correct + file: + path: "{{ matrix_redis_data_path }}" + state: directory + owner: "{{ matrix_user_username }}" + group: "{{ matrix_user_username }}" + recurse: yes + when: matrix_redis_enabled|bool + +- name: Ensure redis environment variables file created + template: + src: "{{ role_path }}/templates/{{ item }}.j2" + dest: "{{ matrix_redis_base_path }}/{{ item }}" + mode: 0644 + with_items: + - "redis.conf" + when: matrix_redis_enabled|bool + +- name: Ensure matrix-redis.service installed + template: + src: "{{ role_path }}/templates/systemd/matrix-redis.service.j2" + dest: "{{ matrix_systemd_path }}/matrix-redis.service" + mode: 0644 + register: matrix_redis_systemd_service_result + when: matrix_redis_enabled|bool + +- name: Ensure systemd reloaded after matrix-redis.service installation + service: + daemon_reload: yes + when: "matrix_redis_enabled|bool and matrix_redis_systemd_service_result.changed" + +# +# Tasks related to getting rid of the internal redis server (if it was previously enabled) +# + +- name: Check existence of matrix-redis service + stat: + path: "{{ matrix_systemd_path }}/matrix-redis.service" + register: matrix_redis_service_stat + when: "not matrix_redis_enabled|bool" + +- name: Ensure matrix-redis is stopped + service: + name: matrix-redis + state: stopped + daemon_reload: yes + when: "not matrix_redis_enabled|bool and matrix_redis_service_stat.stat.exists" + +- name: Ensure matrix-redis.service doesn't exist + file: + path: "{{ matrix_systemd_path }}/matrix-redis.service" + state: absent + when: "not matrix_redis_enabled|bool and matrix_redis_service_stat.stat.exists" + +- name: Ensure systemd reloaded after matrix-redis.service removal + service: + daemon_reload: yes + when: "not matrix_redis_enabled|bool and matrix_redis_service_stat.stat.exists" + +- name: Check existence of matrix-redis local data path + stat: + path: "{{ matrix_redis_data_path }}" + register: matrix_redis_data_path_stat + when: "not matrix_redis_enabled|bool" + +# We just want to notify the user. Deleting data is too destructive. +- name: Notify if matrix-redis local data remains + debug: + msg: "Note: You are not using a local redis instance, but some old data remains from before in `{{ matrix_redis_data_path }}`. Feel free to delete it." + when: "not matrix_redis_enabled|bool and matrix_redis_data_path_stat.stat.exists" diff --git a/roles/matrix-redis/templates/redis.conf.j2 b/roles/matrix-redis/templates/redis.conf.j2 new file mode 100644 index 00000000..23b07929 --- /dev/null +++ b/roles/matrix-redis/templates/redis.conf.j2 @@ -0,0 +1,2 @@ +#jinja2: lstrip_blocks: "True" +requirepass {{ matrix_redis_connection_password }} diff --git a/roles/matrix-redis/templates/systemd/matrix-redis.service.j2 b/roles/matrix-redis/templates/systemd/matrix-redis.service.j2 new file mode 100644 index 00000000..0752d23b --- /dev/null +++ b/roles/matrix-redis/templates/systemd/matrix-redis.service.j2 @@ -0,0 +1,36 @@ +#jinja2: lstrip_blocks: "True" +[Unit] +Description=Matrix Redis server +After=docker.service +Requires=docker.service + +[Service] +Type=simple +ExecStartPre=-/usr/bin/docker stop matrix-redis +ExecStartPre=-/usr/bin/docker rm matrix-redis + +ExecStart=/usr/bin/docker run --rm --name matrix-redis \ + --log-driver=none \ + --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ + --cap-drop=ALL \ + --read-only \ + --tmpfs=/tmp:rw,noexec,nosuid,size=100m \ + --network={{ matrix_docker_network }} \ + {% if matrix_redis_container_redis_bind_port %} + -p {{ matrix_redis_container_redis_bind_port }}:6379 \ + {% endif %} + -v {{ matrix_redis_base_path }}/redis.conf:/usr/local/etc/redis/redis.conf \ + {% for arg in matrix_redis_container_extra_arguments %} + {{ arg }} \ + {% endfor %} + {{ matrix_redis_docker_image_to_use }} \ + redis-server /usr/local/etc/redis/redis.conf + +ExecStop=-/usr/bin/docker stop matrix-redis +ExecStop=-/usr/bin/docker rm matrix-redis +Restart=always +RestartSec=30 +SyslogIdentifier=matrix-redis + +[Install] +WantedBy=multi-user.target diff --git a/roles/matrix-synapse/defaults/main.yml b/roles/matrix-synapse/defaults/main.yml index aad9fad3..c390421d 100644 --- a/roles/matrix-synapse/defaults/main.yml +++ b/roles/matrix-synapse/defaults/main.yml @@ -275,8 +275,8 @@ matrix_synapse_workers_enabled_list: - { worker: appservice, port: 18301 } - { worker: federation_sender, port: 18401 } - { worker: media_repository, port: 18501 } - - { worker: user_dir, port: 18502 } - - { worker: frontend_proxy, port: 18503 } + - { worker: user_dir, port: 18601 } + - { worker: frontend_proxy, port: 18701 } # The list of available workers (2020-08-28) matrix_synapse_workers_avail_list: @@ -288,8 +288,13 @@ matrix_synapse_workers_avail_list: - user_dir - frontend_proxy -# Ports used for communication between main synapse process and workers -matrix_synapse_replication_tcp_port: 9092 +# Redis information +matrix_synapse_redis_enabled: false +matrix_synapse_redis_host: "" +matrix_synapse_redis_port: 6379 +matrix_synapse_redis_password: "" + +# Port used for communication between main synapse process and workers matrix_synapse_replication_http_port: 9093 # Send ERROR logs to sentry.io for easier tracking diff --git a/roles/matrix-synapse/templates/synapse/homeserver.yaml.j2 b/roles/matrix-synapse/templates/synapse/homeserver.yaml.j2 index 9b92e05e..9bdc97d9 100644 --- a/roles/matrix-synapse/templates/synapse/homeserver.yaml.j2 +++ b/roles/matrix-synapse/templates/synapse/homeserver.yaml.j2 @@ -225,11 +225,6 @@ listeners: {% if matrix_synapse_workers_enabled %} # c.f. https://github.com/matrix-org/synapse/tree/master/docs/workers.md - # TCP replication: streaming data from the master to the workers - - port: {{ matrix_synapse_replication_tcp_port }} - bind_addresses: ['0.0.0.0'] - type: replication - # HTTP replication: for the workers to send data to the main synapse process - port: {{ matrix_synapse_replication_http_port }} bind_addresses: ['0.0.0.0'] @@ -2464,16 +2459,16 @@ opentracing: redis: # Uncomment the below to enable Redis support. # - #enabled: true + enabled: {{ matrix_synapse_redis_enabled }} # Optional host and port to use to connect to redis. Defaults to # localhost and 6379 # - #host: localhost - #port: 6379 + host: {{ matrix_synapse_redis_host }} + port: {{ matrix_synapse_redis_port }} # Optional password if configured on the Redis instance # - #password: + password: {{ matrix_synapse_redis_password }} # vim:ft=yaml diff --git a/roles/matrix-synapse/templates/synapse/worker.yaml.j2 b/roles/matrix-synapse/templates/synapse/worker.yaml.j2 index d5f78fdb..c99e97cd 100644 --- a/roles/matrix-synapse/templates/synapse/worker.yaml.j2 +++ b/roles/matrix-synapse/templates/synapse/worker.yaml.j2 @@ -2,7 +2,6 @@ worker_app: synapse.app.{{ item.worker }} worker_replication_host: 127.0.0.1 -worker_replication_port: {{ matrix_synapse_replication_tcp_port }} worker_replication_http_port: {{ matrix_synapse_replication_http_port }} {% if item.worker not in [ 'appservice', 'federation_sender', 'pusher' ] %} diff --git a/setup.yml b/setup.yml index 1c19d442..db9fbf88 100755 --- a/setup.yml +++ b/setup.yml @@ -7,6 +7,7 @@ - matrix-base - matrix-mailer - matrix-postgres + - matrix-redis - matrix-corporal - matrix-bridge-appservice-discord - matrix-bridge-appservice-slack