diff --git a/.gitignore b/.gitignore index 698946d..551f5fc 100755 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ **/*.enc +**/generated-data newkey_out hosts diff --git a/proxy_resources/etc/wireguard/wg0.conf b/proxy_resources/etc/wireguard/wg0.conf index c44b2e1..81afdd1 100755 --- a/proxy_resources/etc/wireguard/wg0.conf +++ b/proxy_resources/etc/wireguard/wg0.conf @@ -37,9 +37,9 @@ PublicKey = {{ nextcloud_service_pubkey }} AllowedIPs = 10.0.0.5/32 PersistentKeepalive = 25 -# Chat Service +# Matrix Service [Peer] -PublicKey = {{ chat_service_pubkey }} +PublicKey = {{ matrix_service_pubkey }} AllowedIPs = 10.0.0.6/32 PersistentKeepalive = 25 diff --git a/serversecrets.example b/serversecrets.example index 67ab67f..e166368 100755 --- a/serversecrets.example +++ b/serversecrets.example @@ -29,7 +29,7 @@ git_service_privkey: temp invidious_service_privkey: temp searxng_service_privkey: temp nextcloud_service_privkey: temp -chat_service_privkey: temp +matrix_service_privkey: temp minecraft_service_privkey: temp kimai_service_privkey: temp icinga2_backend_privkey: temp @@ -42,7 +42,7 @@ git_service_pubkey: temp invidious_service_pubkey: temp searxng_service_pubkey: temp nextcloud_service_pubkey: temp -chat_service_pubkey: temp +matrix_service_pubkey: temp minecraft_service_pubkey: temp kimai_service_pubkey: temp icinga2_backend_pubkey: temp diff --git a/services/service_matrix/README.org b/services/service_matrix/README.org new file mode 100644 index 0000000..ff8626d --- /dev/null +++ b/services/service_matrix/README.org @@ -0,0 +1,11 @@ +* Generating the matrix configuration + +To generate a fresh homeserver.yaml, you can use the generate command. (See the documentation for more information.) You will need to specify appropriate values for at least the SYNAPSE_SERVER_NAME and SYNAPSE_REPORT_STATS environment variables. For example: + +docker-compose run --rm -e SYNAPSE_SERVER_NAME=my.matrix.host -e SYNAPSE_REPORT_STATS=yes synapse generate + +(This will also generate necessary signing keys.) + +Then, customize your configuration and run the server: + +docker-compose up -d diff --git a/services/service_matrix/ansible.cfg b/services/service_matrix/ansible.cfg index c36ea5d..b46bfad 100755 --- a/services/service_matrix/ansible.cfg +++ b/services/service_matrix/ansible.cfg @@ -1,5 +1,5 @@ [defaults] -inventory = hosts +inventory = ../../hosts [privilege_escalation] become_method=doas diff --git a/services/service_matrix/deploy-service.yml b/services/service_matrix/deploy-service.yml index cb07cee..6e4bfd2 100755 --- a/services/service_matrix/deploy-service.yml +++ b/services/service_matrix/deploy-service.yml @@ -6,20 +6,40 @@ - name: Create necessary directories ansible.builtin.file: path: "{{ item }}" - owner: service_git - group: service_git + owner: service_matrix + group: service_matrix state: directory loop: - - "{{ services_directory }}/service_git/postgres-data" - - name: Copy docker compose config and other git files + - "{{ services_directory }}/service_matrix/postgres-data" + - "{{ services_directory }}/service_matrix/synapse-data" + - name: Copy docker compose config ansible.builtin.template: src: "{{ item }}" - dest: "{{ services_directory }}/service_git/{{ item }}" - owner: service_git - group: service_git + dest: "{{ services_directory }}/service_matrix/{{ item }}" + owner: service_matrix + group: service_matrix loop: - docker-compose.yml + - name: Copy matrix main configuration + ansible.builtin.template: + src: "{{ item }}" + dest: "{{ services_directory }}/service_matrix/synapse-data/" + owner: service_matrix + group: service_matrix + loop: + - synapse-data/homeserver.yaml + - "generated-data/matrix.{{ domain_name }}.signing.key" + + - name: Copy matrix log configuration + ansible.builtin.template: + src: "{{ item }}" + dest: "{{ services_directory }}/service_matrix/synapse-data/matrix.{{ domain_name }}.log.config" + owner: service_matrix + group: service_matrix + loop: + - synapse-data/matrix.domain_name.log.config + - name: Debug Finish message debug: msg: Ansible playbook has finished! diff --git a/services/service_matrix/docker-compose.yml b/services/service_matrix/docker-compose.yml index 7362d91..e9ad9a7 100644 --- a/services/service_matrix/docker-compose.yml +++ b/services/service_matrix/docker-compose.yml @@ -1,8 +1,7 @@ -version: "3" services: # Gluetun is used to connect container to VPN - forgejo-gluetun: + matrix-gluetun: image: qmcgaw/gluetun cap_add: - NET_ADMIN @@ -12,68 +11,88 @@ services: - VPN_ENDPOINT_IP={{ proxy_server_ip }} - VPN_ENDPOINT_PORT={{ proxy_server_vpn_port }} - WIREGUARD_PUBLIC_KEY={{ vpn_server_pubkey }} - - WIREGUARD_PRIVATE_KEY={{ git_service_privkey }} - - WIREGUARD_ADDRESSES=10.0.0.3/32 - - FIREWALL_VPN_INPUT_PORTS=3000,22,222,5432 + - WIREGUARD_PRIVATE_KEY={{ matrix_service_privkey }} + - WIREGUARD_ADDRESSES=10.0.0.6/32 + - FIREWALL_VPN_INPUT_PORTS=8448,443 + - DOT=off ports: - - "3000:3000" - - "222:22" - networks: - forgejo: + - "8448:8448" deploy: - limits: - cpus: '0.10' - memory: 512M + resources: + limits: + cpus: '0.10' + memory: 512M - forgejo: - image: codeberg.org/forgejo/forgejo:1.21 - network_mode: "service:forgejo-gluetun" + matrix-synapse: + user: "1007:1008" # This should be replaced with the respective user ID/GID running the docker container IE user service_matrix + network_mode: "service:matrix-gluetun" + #build: + # context: ../.. + # dockerfile: docker/Dockerfile + image: docker.io/matrixdotorg/synapse:latest + # Since synapse does not retry to connect to the database, restart upon + # failure + restart: unless-stopped + # See the readme for a full documentation of the environment settings + # NOTE: You must edit homeserver.yaml to use postgres, it defaults to sqlite environment: - # Service git UID and GID - - USER_UID=1006 - - USER_GID=1007 - - - FORGEJO__database__DB_TYPE=postgres - - FORGEJO__database__HOST=11.1.0.22:5432 - - FORGEJO__database__NAME=forgejo - - FORGEJO__database__USER=forgejo - - FORGEJO__database__PASSWD={{ service_git_postgres_pass }} - restart: always + - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml volumes: - - ./forgejo-data:/data - - /etc/timezone:/etc/timezone:ro - - /etc/localtime:/etc/localtime:ro - deploy: - limits: - cpus: '0.25' - memory: 512M + # You may either store all the files in a local folder + - ./synapse-data:/data + # .. or you may split this between different storage points + # - ./files:/data + # - /path/to/ssd:/data/uploads + # - /path/to/large_hdd:/data/media depends_on: - - forgejo-db - - forgejo-db: - image: postgres:16-alpine - restart: always - environment: - - POSTGRES_DB=forgejo - - POSTGRES_USER=forgejo - - POSTGRES_PASSWORD={{ service_git_postgres_pass }} - volumes: - - ./postgres-data:/var/lib/postgresql/data - networks: - forgejo: - ipv4_address: 11.1.0.22 + - matrix-db + # In order to expose Synapse, remove one of the following, you might for + # instance expose the TLS port directly: + #ports: + # - 8448:8448/tcp + # ... or use a reverse proxy, here is an example for traefik: + #labels: + # # The following lines are valid for Traefik version 1.x: + # - traefik.enable=true + # - traefik.frontend.rule=Host:my.matrix.Host + # - traefik.port=8008 + # # Alternatively, for Traefik version 2.0: + # - traefik.enable=true + # - traefik.http.routers.http-synapse.entryPoints=http + # - traefik.http.routers.http-synapse.rule=Host(`my.matrix.host`) + # - traefik.http.middlewares.https_redirect.redirectscheme.scheme=https + # - traefik.http.middlewares.https_redirect.redirectscheme.permanent=true + # - traefik.http.routers.http-synapse.middlewares=https_redirect + # - traefik.http.routers.https-synapse.entryPoints=https + # - traefik.http.routers.https-synapse.rule=Host(`my.matrix.host`) + # - traefik.http.routers.https-synapse.service=synapse + # - traefik.http.routers.https-synapse.tls=true + # - traefik.http.services.synapse.loadbalancer.server.port=8008 + # - traefik.http.routers.https-synapse.tls.certResolver=le-ssl deploy: - limits: - cpus: '0.10' - memory: 128M + resources: + limits: + cpus: '0.25' + memory: 4096M -networks: - forgejo: - driver: bridge - driver_opts: - com.docker.network.bridge.name: forgejo - # com.docker.network.driver.enable_ip_masquerade: 0 - ipam: - config: - - subnet: 11.1.0.0/16 - # gateway: 11.5.0.1 + matrix-db: + network_mode: "service:matrix-gluetun" + image: docker.io/postgres:16-alpine + # Change that password, of course! + environment: + - POSTGRES_DB=synapse + - POSTGRES_USER=synapse + - POSTGRES_PASSWORD={{ service_matrix_postgres_pass }} + # ensure the database gets created correctly + # https://element-hq.github.io/synapse/latest/postgres.html#set-up-database + - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C + volumes: + # You may store the database tables in a local folder.. + - ./postgres-data:/var/lib/postgresql/data + # .. or store them on some high performance storage for better results + # - /path/to/ssd/storage:/var/lib/postgresql/data + deploy: + resources: + limits: + cpus: '0.10' + memory: 512M diff --git a/services/service_matrix/matrix-genconfig.sh b/services/service_matrix/matrix-genconfig.sh old mode 100644 new mode 100755 index a3bd21d..4cbf85b --- a/services/service_matrix/matrix-genconfig.sh +++ b/services/service_matrix/matrix-genconfig.sh @@ -1,7 +1,8 @@ #!/bin/sh +# Replace {{ domain_name }} with your domain name and generate a sample config/signing key pair config, this will be used in deploy-service.yml docker run -it --rm \ --mount type=bind,src=./generated-data,dst=/data \ - -e SYNAPSE_SERVER_NAME=my.matrix.host \ + -e SYNAPSE_SERVER_NAME=matrix.{{ domain_name }} \ -e SYNAPSE_REPORT_STATS=yes \ matrixdotorg/synapse:latest generate diff --git a/services/service_matrix/prox-deploy-service.yml b/services/service_matrix/prox-deploy-service.yml new file mode 100644 index 0000000..efae83e --- /dev/null +++ b/services/service_matrix/prox-deploy-service.yml @@ -0,0 +1,22 @@ +- hosts: + - "{{ proxy_server_hostname }}" + # - "{{ proxy_server_hostname }}"-defaultport + become: 'yes' + vars: + ansible_become_method: doas + tasks: + # Ensure NGinx site reverse proxy configuration is updated + - name: Ensure all NGinx site configurations are updated + template: + src: proxy_resources/etc/nginx/sites-available/matrix.domain + dest: "/etc/nginx/sites-available/matrix.{{ domain_name }}" + - name: Ensure NGinx site reverse proxy configuration is enabled + ansible.builtin.file: + src: "/etc/nginx/sites-available/matrix.{{ domain_name }}" + dest: "/etc/nginx/sites-enabled/matrix.{{ domain_name }}" + state: link + + - name: Debug Finish message + debug: + msg: Ansible playbook has finished! + diff --git a/services/service_matrix/proxy_resources/etc/nginx/sites-available/matrix.domain b/services/service_matrix/proxy_resources/etc/nginx/sites-available/matrix.domain new file mode 100755 index 0000000..7a96009 --- /dev/null +++ b/services/service_matrix/proxy_resources/etc/nginx/sites-available/matrix.domain @@ -0,0 +1,61 @@ +# {{ ansible_managed }} + +# Matrix Instance Proxy +server { + + server_name matrix.{{ domain_name }} www.matrix.{{ domain_name }}; + + location ~ ^(/_matrix|/_synapse/client) { + # note: do not add a path (even a single /) after the port in `proxy_pass`, + # otherwise nginx will canonicalise the URI and cause signature verification + # errors. + + proxy_pass http://10.0.0.6:8448; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $host; # so matrix knows domain + proxy_http_version 1.1; # to keep alive + #proxy_set_header Connection ""; # to keep alive + include proxy_params; + } + + client_max_body_size 512M; + + listen [::]:443 ssl http2; + listen 443 ssl http2; + + # For the federation port + listen 8448 ssl http2 default_server; + listen [::]:8448 ssl http2 default_server; + + ssl_certificate /etc/letsencrypt/live/{{ domain_name }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ domain_name }}/privkey.pem; + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + + +} + + + +server { + if ($host = www.matrix.{{ domain_name }}) { + return 301 https://$host$request_uri; + } + + + if ($host = matrix.{{ domain_name }}) { + return 301 https://$host$request_uri; + } + + + listen 80; + listen [::]:80; + + server_name matrix.{{ domain_name }} www.matrix.{{ domain_name }}; + return 404; + + + + +} diff --git a/services/service_matrix/servicesecrets.example b/services/service_matrix/servicesecrets.example index be1c9ab..8f35469 100755 --- a/services/service_matrix/servicesecrets.example +++ b/services/service_matrix/servicesecrets.example @@ -1,2 +1,5 @@ # Example service secrets for git docker service, to be encrypted with ansible vault and called servicesecrets.enc -service_git_postgres_pass: *** +service_matrix_postgres_pass: *** +registration_shared_secret: *** +macaroon_secret_key: *** +form_secret: *** diff --git a/services/service_matrix/synapse-data/homeserver.yaml b/services/service_matrix/synapse-data/homeserver.yaml new file mode 100644 index 0000000..d6507b5 --- /dev/null +++ b/services/service_matrix/synapse-data/homeserver.yaml @@ -0,0 +1,50 @@ +# {{ ansible_managed }} +# Configuration file for Synapse. +# +# This is a YAML file: see [1] for a quick introduction. Note in particular +# that *indentation is important*: all the elements of a list or dictionary +# should have the same indentation. +# +# [1] https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html +# +# For more information on how to configure Synapse, including a complete accounting of +# each option, go to docs/usage/configuration/config_documentation.md or +# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html +server_name: "matrix.{{ domain_name }}" +pid_file: /data/homeserver.pid +listeners: + - port: 8448 + tls: false + type: http + x_forwarded: true + resources: + - names: [client, federation] + compress: false + #database: + # name: sqlite3 + # args: + # database: /data/homeserver.db +database: + name: psycopg2 + args: + user: synapse + password: {{ service_matrix_postgres_pass }} + dbname: synapse + host: 127.0.0.1 + cp_min: 5 + cp_max: 10 + +log_config: "/data/matrix.{{ domain_name }}.log.config" +media_store_path: /data/media_store +registration_shared_secret: "{{ registration_shared_secret }}" +enable_registration: false +enable_registration_without_verification: false +report_stats: true +macaroon_secret_key: "{{ macaroon_secret_key }}" +form_secret: "{{ form_secret }}" +signing_key_path: "/data/matrix.{{ domain_name }}.signing.key" +trusted_key_servers: + - server_name: "matrix.org" + + +# vim:ft=yaml diff --git a/services/service_matrix/synapse-data/matrix.domain_name.log.config b/services/service_matrix/synapse-data/matrix.domain_name.log.config new file mode 100644 index 0000000..0b522eb --- /dev/null +++ b/services/service_matrix/synapse-data/matrix.domain_name.log.config @@ -0,0 +1,75 @@ +# Log configuration for Synapse. +# +# This is a YAML file containing a standard Python logging configuration +# dictionary. See [1] for details on the valid settings. +# +# Synapse also supports structured logging for machine readable logs which can +# be ingested by ELK stacks. See [2] for details. +# +# [1]: https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema +# [2]: https://element-hq.github.io/synapse/latest/structured_logging.html + +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +handlers: + file: + class: logging.handlers.TimedRotatingFileHandler + formatter: precise + filename: /data/homeserver.log + when: midnight + backupCount: 3 # Does not include the current log file. + encoding: utf8 + + # Default to buffering writes to log file for efficiency. + # WARNING/ERROR logs will still be flushed immediately, but there will be a + # delay (of up to `period` seconds, or until the buffer is full with + # `capacity` messages) before INFO/DEBUG logs get written. + buffer: + class: synapse.logging.handlers.PeriodicallyFlushingMemoryHandler + target: file + + # The capacity is the maximum number of log lines that are buffered + # before being written to disk. Increasing this will lead to better + # performance, at the expensive of it taking longer for log lines to + # be written to disk. + # This parameter is required. + capacity: 10 + + # Logs with a level at or above the flush level will cause the buffer to + # be flushed immediately. + # Default value: 40 (ERROR) + # Other values: 50 (CRITICAL), 30 (WARNING), 20 (INFO), 10 (DEBUG) + flushLevel: 30 # Flush immediately for WARNING logs and higher + + # The period of time, in seconds, between forced flushes. + # Messages will not be delayed for longer than this time. + # Default value: 5 seconds + period: 5 + + # A handler that writes logs to stderr. Unused by default, but can be used + # instead of "buffer" and "file" in the logger handlers. + console: + class: logging.StreamHandler + formatter: precise + +loggers: + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: INFO + +root: + level: INFO + + # Write logs to the `buffer` handler, which will buffer them together in memory, + # then write them to a file. + # + # Replace "buffer" with "console" to log to stderr instead. + # + handlers: [buffer] + +disable_existing_loggers: false