diff --git a/.gitignore b/.gitignore index b6e4761..248aa6d 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,6 @@ dmypy.json # Pyre type checker .pyre/ + +# others +*.tar.gz diff --git a/stacks/synapse/README.md b/stacks/synapse/README.md new file mode 100644 index 0000000..1b2cb33 --- /dev/null +++ b/stacks/synapse/README.md @@ -0,0 +1,49 @@ +# Synapse home server for matrix + +## `/opt/docker` folder structure + +```shell +root@server:~# tree -L 4 /opt/docker/ +/opt/docker/ +└── synapse + ├── caddy + │   ├── Caddyfile + │   ├── config + │   └── data + ├── postgres + │   ├── data + │   │   └── 18 + │   │   └── docker + │   └── runtime.env + └── synapse + ├── config + │   ├── chat.yourdomain.tld.log.config + │   ├── chat.yourdomain.tld.signing.key + │   └── homeserver.yaml + └── data + +17 directories, 8 files +``` + +## How to generate keys + +Source: [element installation](https://element-hq.github.io/synapse/latest/setup/installation.html) + +Before you can start Synapse, you will need to generate a configuration file. +To do this, run (in your virtualenv, as before): + +```shell +cd ~/synapse +python -m synapse.app.homeserver \ + --server-name chat.yourdomain.tld \ + --config-path homeserver.yaml \ + --generate-config \ + --report-stats=[yes|no] +``` + +substituting an appropriate value for --server-name and choosing whether or not +to report usage statistics (hostname, Synapse version, uptime, total users, +etc.) to the developers via the --report-stats argument. + +This command will generate you a config file that you can then customise, but +it will also generate a set of keys for you. diff --git a/stacks/synapse/docker-compose.yml b/stacks/synapse/docker-compose.yml new file mode 100644 index 0000000..dcb30c7 --- /dev/null +++ b/stacks/synapse/docker-compose.yml @@ -0,0 +1,86 @@ +--- +services: + caddy: + hostname: caddy + image: docker.io/caddy:2.10.2-alpine + restart: unless-stopped + ports: + - 80:80 + - 443:443 + - 443:443/udp + - 8008:8008 + - 8448:8448 + - 8448:8448/udp + volumes: + - /opt/docker/synapse/caddy/Caddyfile:/etc/caddy/Caddyfile:ro + - /opt/docker/synapse/caddy/data:/data + - /opt/docker/synapse/caddy/config:/config + networks: + - internal + postgres: + hostname: postgres + image: docker.io/postgres:18.0-alpine3.22 + restart: unless-stopped + environment: + POSTGRES_DB: synapse + POSTGRES_USER: synapse + POSTGRES_INITDB_ARGS: --encoding=UTF-8 --lc-collate=C --lc-ctype=C + env_file: + - /opt/docker/synapse/postgres/runtime.env + # `postgres` container starts as root but switches to user `postgres` + # with `uid` and `gid` number 70 + # $ sudo docker run --rm -it --entrypoint bash docker.io/postgres:17.6-alpine3.22 + # ae14e6d0f571:/# grep postgres /etc/passwd + # postgres:x:70:70::/var/lib/postgresql:/bin/sh + volumes: + - /opt/docker/synapse/postgres/data/18/docker:/var/lib/postgresql/18/docker + #- /home/ricdros/dump17.sql:/tmp/dump.sql:ro + healthcheck: + test: | + pg_isready -d "$${POSTGRES_DB}" -U "$${POSTGRES_USER}" + start_period: 80s + interval: 30s + timeout: 60s + retries: 5 + networks: + - internal + synapse: + hostname: synapse + image: ghcr.io/element-hq/synapse:v1.141.0 + restart: unless-stopped + environment: + SYNAPSE_CONFIG_DIR: /config + SYNAPSE_CONFIG_PATH: /config/homeserver.yaml + UID: 991 + GID: 991 + TZ: UTC + volumes: + - /opt/docker/synapse/synapse/config:/config + - /opt/docker/synapse/synapse/data:/data + depends_on: + postgres: + condition: service_healthy + healthcheck: + test: | + curl -fSs http://localhost:8008/health || exit 1 + start_period: 5s + interval: 15s + timeout: 5s + retries: 3 + networks: + - internal + matrix-registration-bot: + image: moanos/matrix-registration-bot:latest + environment: + LOGGING_LEVEL: DEBUG + BOT_SERVER: "https://chat.yourdomain.tld" + BOT_USERNAME: "" + API_BASE_URL: "https://chat.yourdomain.tld" + env_file: + - /opt/docker/synapse/matrix-registration-bot/runtime.env + depends_on: + synapse: + condition: service_healthy +networks: + internal: + attachable: true diff --git a/stacks/synapse/opt/docker/synapse/caddy/Caddyfile b/stacks/synapse/opt/docker/synapse/caddy/Caddyfile new file mode 100644 index 0000000..cf1cc2e --- /dev/null +++ b/stacks/synapse/opt/docker/synapse/caddy/Caddyfile @@ -0,0 +1,26 @@ +{ + admin off + email you@yourdomain.tld + # acme_ca https://acme-staging-v02.api.letsencrypt.org/directory +} + +http://chat.yourdomain.tld { + redir https://chat.yourdomain.tld{uri} permanent +} + +https://chat.yourdomain.tld { + reverse_proxy synapse:8008 +} + +http://chat.yourdomain.tld:8008 { + redir https://chat.yourdomain.tld:8448{uri} permanent + +} + +https://chat.yourdomain.tld:8448 { + reverse_proxy synapse:8008 +} + +:9180 { + metrics +} diff --git a/stacks/synapse/opt/docker/synapse/caddy/config/.gitkeep b/stacks/synapse/opt/docker/synapse/caddy/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/stacks/synapse/opt/docker/synapse/caddy/data/.gitkeep b/stacks/synapse/opt/docker/synapse/caddy/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/stacks/synapse/opt/docker/synapse/matrix-registration-bot/runtime.env b/stacks/synapse/opt/docker/synapse/matrix-registration-bot/runtime.env new file mode 100644 index 0000000..4363415 --- /dev/null +++ b/stacks/synapse/opt/docker/synapse/matrix-registration-bot/runtime.env @@ -0,0 +1,2 @@ +BOT_PASSWORD=YOURBOTPASSWORDHERE # pragma: allowlist secret +API_TOKEN=YOURAPITOKENHERE diff --git a/stacks/synapse/opt/docker/synapse/postgres/data/18/docker/.gitkeep b/stacks/synapse/opt/docker/synapse/postgres/data/18/docker/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/stacks/synapse/opt/docker/synapse/postgres/runtime.env b/stacks/synapse/opt/docker/synapse/postgres/runtime.env new file mode 100644 index 0000000..dd611df --- /dev/null +++ b/stacks/synapse/opt/docker/synapse/postgres/runtime.env @@ -0,0 +1 @@ +POSTGRES_PASSWORD=YOURSUPERSECUREPASSWORDHERE # pragma: allowlist secret diff --git a/stacks/synapse/opt/docker/synapse/synapse/config/chat.yourdomain.tld.log.config b/stacks/synapse/opt/docker/synapse/synapse/config/chat.yourdomain.tld.log.config new file mode 100644 index 0000000..284c379 --- /dev/null +++ b/stacks/synapse/opt/docker/synapse/synapse/config/chat.yourdomain.tld.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: /var/lib/matrix/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: WARN + +root: + level: WARN + # 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: [console] + +disable_existing_loggers: false +# vim:ft=yaml diff --git a/stacks/synapse/opt/docker/synapse/synapse/config/chat.yourdomain.tld.signing.key b/stacks/synapse/opt/docker/synapse/synapse/config/chat.yourdomain.tld.signing.key new file mode 100644 index 0000000..34a5b97 --- /dev/null +++ b/stacks/synapse/opt/docker/synapse/synapse/config/chat.yourdomain.tld.signing.key @@ -0,0 +1 @@ +YOUR ACTUAL SIGNING KEY HERE diff --git a/stacks/synapse/opt/docker/synapse/synapse/config/homeserver.yaml b/stacks/synapse/opt/docker/synapse/synapse/config/homeserver.yaml new file mode 100644 index 0000000..d62bbe2 --- /dev/null +++ b/stacks/synapse/opt/docker/synapse/synapse/config/homeserver.yaml @@ -0,0 +1,66 @@ +--- +# 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: "yourdomain.tld" +pid_file: /data/homeserver.pid +listeners: + - port: 8008 + tls: false + type: http + x_forwarded: true + resources: + - names: [client, federation] + compress: false +database: + name: psycopg2 + args: + user: synapse + host: postgres + password: YOURSUPERSECUREPASSWORDHERE # pragma: allowlist secret + database: synapse +log_config: "/config/chat.yourdomain.tld.log.config" +media_store_path: /data/media_store +registration_shared_secret: "yourregistartionsharedsecrethere" # pragma: allowlist secret +report_stats: false +macaroon_secret_key: "macaroonsecrethere" # pragma: allowlist secret +form_secret: "formsecrethere" # pragma: allowlist secret +signing_key_path: "/config/chat.yourdomain.tld.signing.key" +suppress_key_server_warning: true +trusted_key_servers: + - server_name: "chat.yourdomain.tld" + - server_name: "matrix.org" +email: + smtp_host: mail.yourdomain.tld + smtp_user: synapse + smtp_pass: "smtppasswordhere" + force_tls: true + notif_from: "No reply " + enable_notifs: true + notif_for_new_users: true + ## TODO reset to default (shortened for testing) + notif_delay_before_email: "2m" +public_baseurl: https://chat.yourdomain.tld +admin_contact: mailto:you@yourdomain.tld +default_room_version: '11' +enable_registration: true +registrations_require_3pid: + - email +disable_msisdn_registration: true +allowed_local_3pids: + - medium: email + pattern: ^you@yourdomain\.tld$ + - medium: email + pattern: ^someoneelse@theirdomain\.tld$ +# to get an access token +# curl -XPOST -d '{"type":"m.login.password", "user":"@yourmatrixusername:yourdomain.tld","password":"XXXXXXXXX"}' https://chat.yourdomain.tld/_matrix/client/r0/login +# accessible 443 +# vim:ft=yaml diff --git a/stacks/synapse/opt/docker/synapse/synapse/data/.gitkeep b/stacks/synapse/opt/docker/synapse/synapse/data/.gitkeep new file mode 100644 index 0000000..e69de29