From 5f72ea1bdefb685686ca02ff45863870da379fec Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Mon, 11 Apr 2022 11:39:28 +0100 Subject: [PATCH] Move complement setup stuff into the Synapse repo (#12404) Fixes matrix-org/complement#330 (or it will, once we remove the old files). It's not quite a lift-and-shift: I've also taken the opportunity to get rid of the custom CA that we used to use to sign the TLS certs, which has been superceded by the CA exposed by Complement. --- .github/workflows/tests.yml | 18 +-- changelog.d/12404.misc | 1 + docker/README-testing.md | 44 +++---- docker/complement/Dockerfile | 22 ++++ docker/complement/README.md | 1 + docker/complement/SynapseWorkers.Dockerfile | 73 +++++++++++ .../conf-workers/caddy.complement.json | 72 +++++++++++ .../conf-workers/workers-shared.yaml | 77 +++++++++++ docker/complement/conf/homeserver.yaml | 122 ++++++++++++++++++ docker/complement/conf/log_config.yaml | 24 ++++ docker/complement/conf/start.sh | 30 +++++ scripts-dev/complement.sh | 17 +-- 12 files changed, 449 insertions(+), 52 deletions(-) create mode 100644 changelog.d/12404.misc create mode 100644 docker/complement/Dockerfile create mode 100644 docker/complement/README.md create mode 100644 docker/complement/SynapseWorkers.Dockerfile create mode 100644 docker/complement/conf-workers/caddy.complement.json create mode 100644 docker/complement/conf-workers/workers-shared.yaml create mode 100644 docker/complement/conf/homeserver.yaml create mode 100644 docker/complement/conf/log_config.yaml create mode 100755 docker/complement/conf/start.sh diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bbf99447e9..0fbffd159c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -363,27 +363,11 @@ jobs: (wget -O - "https://github.com/matrix-org/complement/archive/$BRANCH_NAME.tar.gz" | tar -xz --strip-components=1 -C complement) && break done - # Build initial Synapse image - - run: docker build -t matrixdotorg/synapse:latest -f docker/Dockerfile . - working-directory: synapse - env: - DOCKER_BUILDKIT: 1 - - # Build a ready-to-run Synapse image based on the initial image above. - # This new image includes a config file, keys for signing and TLS, and - # other settings to make it suitable for testing under Complement. - - run: docker build -t complement-synapse -f Synapse.Dockerfile . - working-directory: complement/dockerfiles - - # Run Complement - run: | set -o pipefail - go test -v -json -tags synapse_blacklist,msc2716,msc3030 ./tests/... 2>&1 | gotestfmt + COMPLEMENT_DIR=`pwd`/complement synapse/scripts-dev/complement.sh -json 2>&1 | gotestfmt shell: bash name: Run Complement Tests - env: - COMPLEMENT_BASE_IMAGE: complement-synapse:latest - working-directory: complement # a job which marks all the other jobs as complete, thus allowing PRs to be merged. tests-done: diff --git a/changelog.d/12404.misc b/changelog.d/12404.misc new file mode 100644 index 0000000000..00100fdfef --- /dev/null +++ b/changelog.d/12404.misc @@ -0,0 +1 @@ +Add files used to build the Docker image used for complement testing into the Synapse repository. diff --git a/docker/README-testing.md b/docker/README-testing.md index b010509275..c38cae7530 100644 --- a/docker/README-testing.md +++ b/docker/README-testing.md @@ -10,10 +10,10 @@ Note that running Synapse's unit tests from within the docker image is not suppo ## Testing with SQLite and single-process Synapse -> Note that `scripts-dev/complement.sh` is a script that will automatically build +> Note that `scripts-dev/complement.sh` is a script that will automatically build > and run an SQLite-based, single-process of Synapse against Complement. -The instructions below will set up Complement testing for a single-process, +The instructions below will set up Complement testing for a single-process, SQLite-based Synapse deployment. Start by building the base Synapse docker image. If you wish to run tests with the latest @@ -26,23 +26,22 @@ docker build -t matrixdotorg/synapse -f docker/Dockerfile . This will build an image with the tag `matrixdotorg/synapse`. -Next, build the Synapse image for Complement. You will need a local checkout -of Complement. Change to the root of your Complement checkout and run: +Next, build the Synapse image for Complement. ```sh -docker build -t complement-synapse -f "dockerfiles/Synapse.Dockerfile" dockerfiles +docker build -t complement-synapse -f "docker/complement/Dockerfile" docker/complement ``` -This will build an image with the tag `complement-synapse`, which can be handed to -Complement for testing via the `COMPLEMENT_BASE_IMAGE` environment variable. Refer to -[Complement's documentation](https://github.com/matrix-org/complement/#running) for +This will build an image with the tag `complement-synapse`, which can be handed to +Complement for testing via the `COMPLEMENT_BASE_IMAGE` environment variable. Refer to +[Complement's documentation](https://github.com/matrix-org/complement/#running) for how to run the tests, as well as the various available command line flags. ## Testing with PostgreSQL and single or multi-process Synapse -The above docker image only supports running Synapse with SQLite and in a -single-process topology. The following instructions are used to build a Synapse image for -Complement that supports either single or multi-process topology with a PostgreSQL +The above docker image only supports running Synapse with SQLite and in a +single-process topology. The following instructions are used to build a Synapse image for +Complement that supports either single or multi-process topology with a PostgreSQL database backend. As with the single-process image, build the base Synapse docker image. If you wish to run @@ -55,7 +54,7 @@ docker build -t matrixdotorg/synapse -f docker/Dockerfile . This will build an image with the tag `matrixdotorg/synapse`. -Next, we build a new image with worker support based on `matrixdotorg/synapse:latest`. +Next, we build a new image with worker support based on `matrixdotorg/synapse:latest`. Again, from the root of the repository: ```sh @@ -64,18 +63,17 @@ docker build -t matrixdotorg/synapse-workers -f docker/Dockerfile-workers . This will build an image with the tag` matrixdotorg/synapse-workers`. -It's worth noting at this point that this image is fully functional, and -can be used for testing against locally. See instructions for using the container +It's worth noting at this point that this image is fully functional, and +can be used for testing against locally. See instructions for using the container under [Running the Dockerfile-worker image standalone](#running-the-dockerfile-worker-image-standalone) below. Finally, build the Synapse image for Complement, which is based on -`matrixdotorg/synapse-workers`. You will need a local checkout of Complement. Change to -the root of your Complement checkout and run: +`matrixdotorg/synapse-workers`. ```sh -docker build -t matrixdotorg/complement-synapse-workers -f dockerfiles/SynapseWorkers.Dockerfile dockerfiles +docker build -t matrixdotorg/complement-synapse-workers -f docker/complement/SynapseWorkers.Dockerfile docker/complement ``` This will build an image with the tag `complement-synapse-workers`, which can be handed to @@ -91,10 +89,10 @@ bundling all necessary components together for a workerised homeserver instance. This includes any desired Synapse worker processes, a nginx to route traffic accordingly, a redis for worker communication and a supervisord instance to start up and monitor all -processes. You will need to provide your own postgres container to connect to, and TLS +processes. You will need to provide your own postgres container to connect to, and TLS is not handled by the container. -Once you've built the image using the above instructions, you can run it. Be sure +Once you've built the image using the above instructions, you can run it. Be sure you've set up a volume according to the [usual Synapse docker instructions](README.md). Then run something along the lines of: @@ -112,7 +110,7 @@ docker run -d --name synapse \ matrixdotorg/synapse-workers ``` -...substituting `POSTGRES*` variables for those that match a postgres host you have +...substituting `POSTGRES*` variables for those that match a postgres host you have available (usually a running postgres docker container). The `SYNAPSE_WORKER_TYPES` environment variable is a comma-separated list of workers to @@ -130,11 +128,11 @@ Otherwise, `SYNAPSE_WORKER_TYPES` can either be left empty or unset to spawn no (leaving only the main process). The container is configured to use redis-based worker mode. -Logs for workers and the main process are logged to stdout and can be viewed with -standard `docker logs` tooling. Worker logs contain their worker name +Logs for workers and the main process are logged to stdout and can be viewed with +standard `docker logs` tooling. Worker logs contain their worker name after the timestamp. Setting `SYNAPSE_WORKERS_WRITE_LOGS_TO_DISK=1` will cause worker logs to be written to `/logs/.log`. Logs are kept for 1 week and rotate every day at 00: -00, according to the container's clock. Logging for the main process must still be +00, according to the container's clock. Logging for the main process must still be configured by modifying the homeserver's log config in your Synapse data volume. diff --git a/docker/complement/Dockerfile b/docker/complement/Dockerfile new file mode 100644 index 0000000000..4823ce7364 --- /dev/null +++ b/docker/complement/Dockerfile @@ -0,0 +1,22 @@ +# A dockerfile which builds an image suitable for testing Synapse under +# complement. + +ARG SYNAPSE_VERSION=latest + +FROM matrixdotorg/synapse:${SYNAPSE_VERSION} + +ENV SERVER_NAME=localhost + +COPY conf/* /conf/ + +# generate a signing key +RUN generate_signing_key -o /conf/server.signing.key + +WORKDIR /data + +EXPOSE 8008 8448 + +ENTRYPOINT ["/conf/start.sh"] + +HEALTHCHECK --start-period=5s --interval=1s --timeout=1s \ + CMD curl -fSs http://localhost:8008/health || exit 1 diff --git a/docker/complement/README.md b/docker/complement/README.md new file mode 100644 index 0000000000..e075418e4a --- /dev/null +++ b/docker/complement/README.md @@ -0,0 +1 @@ +Stuff for building the docker image used for testing under complement. diff --git a/docker/complement/SynapseWorkers.Dockerfile b/docker/complement/SynapseWorkers.Dockerfile new file mode 100644 index 0000000000..982219a91e --- /dev/null +++ b/docker/complement/SynapseWorkers.Dockerfile @@ -0,0 +1,73 @@ +# This dockerfile builds on top of 'docker/Dockerfile-worker' in matrix-org/synapse +# by including a built-in postgres instance, as well as setting up the homeserver so +# that it is ready for testing via Complement. +# +# Instructions for building this image from those it depends on is detailed in this guide: +# https://github.com/matrix-org/synapse/blob/develop/docker/README-testing.md#testing-with-postgresql-and-single-or-multi-process-synapse +FROM matrixdotorg/synapse-workers + +# Download a caddy server to stand in front of nginx and terminate TLS using Complement's +# custom CA. +# We include this near the top of the file in order to cache the result. +RUN curl -OL "https://github.com/caddyserver/caddy/releases/download/v2.3.0/caddy_2.3.0_linux_amd64.tar.gz" && \ + tar xzf caddy_2.3.0_linux_amd64.tar.gz && rm caddy_2.3.0_linux_amd64.tar.gz && mv caddy /root + +# Install postgresql +RUN apt-get update +RUN apt-get install -y postgresql + +# Configure a user and create a database for Synapse +RUN pg_ctlcluster 13 main start && su postgres -c "echo \ + \"ALTER USER postgres PASSWORD 'somesecret'; \ + CREATE DATABASE synapse \ + ENCODING 'UTF8' \ + LC_COLLATE='C' \ + LC_CTYPE='C' \ + template=template0;\" | psql" && pg_ctlcluster 13 main stop + +# Modify the shared homeserver config with postgres support, certificate setup +# and the disabling of rate-limiting +COPY conf-workers/workers-shared.yaml /conf/workers/shared.yaml + +WORKDIR /data + +# Copy the caddy config +COPY conf-workers/caddy.complement.json /root/caddy.json + +# Expose caddy's listener ports +EXPOSE 8008 8448 + +ENTRYPOINT \ + # Replace the server name in the caddy config + sed -i "s/{{ server_name }}/${SERVER_NAME}/g" /root/caddy.json && \ + # Start postgres + pg_ctlcluster 13 main start 2>&1 && \ + # Start caddy + /root/caddy start --config /root/caddy.json 2>&1 && \ + # Set the server name of the homeserver + SYNAPSE_SERVER_NAME=${SERVER_NAME} \ + # No need to report stats here + SYNAPSE_REPORT_STATS=no \ + # Set postgres authentication details which will be placed in the homeserver config file + POSTGRES_PASSWORD=somesecret POSTGRES_USER=postgres POSTGRES_HOST=localhost \ + # Specify the workers to test with + SYNAPSE_WORKER_TYPES="\ + event_persister, \ + event_persister, \ + background_worker, \ + frontend_proxy, \ + event_creator, \ + user_dir, \ + media_repository, \ + federation_inbound, \ + federation_reader, \ + federation_sender, \ + synchrotron, \ + appservice, \ + pusher" \ + # Run the script that writes the necessary config files and starts supervisord, which in turn + # starts everything else + /configure_workers_and_start.py + +HEALTHCHECK --start-period=5s --interval=1s --timeout=1s \ + CMD /bin/sh /healthcheck.sh diff --git a/docker/complement/conf-workers/caddy.complement.json b/docker/complement/conf-workers/caddy.complement.json new file mode 100644 index 0000000000..09e2136af2 --- /dev/null +++ b/docker/complement/conf-workers/caddy.complement.json @@ -0,0 +1,72 @@ +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":8448" + ], + "routes": [ + { + "match": [ + { + "host": [ + "{{ server_name }}" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "handler": "reverse_proxy", + "upstreams": [ + { + "dial": "localhost:8008" + } + ] + } + ] + } + ] + } + ], + "terminal": true + } + ] + } + } + }, + "tls": { + "automation": { + "policies": [ + { + "subjects": [ + "{{ server_name }}" + ], + "issuers": [ + { + "module": "internal" + } + ], + "on_demand": true + } + ] + } + }, + "pki": { + "certificate_authorities": { + "local": { + "name": "Complement CA", + "root": { + "certificate": "/complement/ca/ca.crt", + "private_key": "/complement/ca/ca.key" + } + } + } + } + } + } diff --git a/docker/complement/conf-workers/workers-shared.yaml b/docker/complement/conf-workers/workers-shared.yaml new file mode 100644 index 0000000000..cdadb736f6 --- /dev/null +++ b/docker/complement/conf-workers/workers-shared.yaml @@ -0,0 +1,77 @@ +## Server ## +report_stats: False +trusted_key_servers: [] +enable_registration: true +enable_registration_without_verification: true +bcrypt_rounds: 4 + +## Federation ## + +# disable verification of federation certificates +# +# TODO: Figure out why this is still needed even though we are making use of the custom CA +federation_verify_certificates: false + +# trust certs signed by Complement's CA +federation_custom_ca_list: +- /complement/ca/ca.crt + +# unblacklist RFC1918 addresses +federation_ip_range_blacklist: [] + +# Disable server rate-limiting +rc_federation: + window_size: 1000 + sleep_limit: 10 + sleep_delay: 500 + reject_limit: 99999 + concurrent: 3 + +rc_message: + per_second: 9999 + burst_count: 9999 + +rc_registration: + per_second: 9999 + burst_count: 9999 + +rc_login: + address: + per_second: 9999 + burst_count: 9999 + account: + per_second: 9999 + burst_count: 9999 + failed_attempts: + per_second: 9999 + burst_count: 9999 + +rc_admin_redaction: + per_second: 9999 + burst_count: 9999 + +rc_joins: + local: + per_second: 9999 + burst_count: 9999 + remote: + per_second: 9999 + burst_count: 9999 + +federation_rr_transactions_per_room_per_second: 9999 + +## Experimental Features ## + +experimental_features: + # Enable history backfilling support + msc2716_enabled: true + # Enable spaces support + spaces_enabled: true + # Enable jump to date endpoint + msc3030_enabled: true + +server_notices: + system_mxid_localpart: _server + system_mxid_display_name: "Server Alert" + system_mxid_avatar_url: "" + room_name: "Server Alert" diff --git a/docker/complement/conf/homeserver.yaml b/docker/complement/conf/homeserver.yaml new file mode 100644 index 0000000000..be53c4aa2e --- /dev/null +++ b/docker/complement/conf/homeserver.yaml @@ -0,0 +1,122 @@ +## Server ## + +server_name: SERVER_NAME +log_config: /conf/log_config.yaml +report_stats: False +signing_key_path: /conf/server.signing.key +trusted_key_servers: [] +enable_registration: true +enable_registration_without_verification: true + +## Listeners ## + +tls_certificate_path: /conf/server.tls.crt +tls_private_key_path: /conf/server.tls.key +bcrypt_rounds: 4 +registration_shared_secret: complement + +listeners: + - port: 8448 + bind_addresses: ['::'] + type: http + tls: true + resources: + - names: [federation] + + - port: 8008 + bind_addresses: ['::'] + type: http + + resources: + - names: [client] + +## Database ## + +database: + name: "sqlite3" + args: + # We avoid /data, as it is a volume and is not transferred when the container is committed, + # which is a fundamental necessity in complement. + database: "/conf/homeserver.db" + +## Federation ## + + +# disable verification of federation certificates +# +# TODO: this is temporary; see +# https://github.com/matrix-org/synapse/issues/11803 +federation_verify_certificates: false + +# trust certs signed by the complement CA +federation_custom_ca_list: +- /complement/ca/ca.crt + +# unblacklist RFC1918 addresses +ip_range_blacklist: [] + +# Disable server rate-limiting +rc_federation: + window_size: 1000 + sleep_limit: 10 + sleep_delay: 500 + reject_limit: 99999 + concurrent: 3 + +rc_message: + per_second: 9999 + burst_count: 9999 + +rc_registration: + per_second: 9999 + burst_count: 9999 + +rc_login: + address: + per_second: 9999 + burst_count: 9999 + account: + per_second: 9999 + burst_count: 9999 + failed_attempts: + per_second: 9999 + burst_count: 9999 + +rc_admin_redaction: + per_second: 9999 + burst_count: 9999 + +rc_joins: + local: + per_second: 9999 + burst_count: 9999 + remote: + per_second: 9999 + burst_count: 9999 + +federation_rr_transactions_per_room_per_second: 9999 + +## API Configuration ## + +# A list of application service config files to use +# +app_service_config_files: +AS_REGISTRATION_FILES + +## Experimental Features ## + +experimental_features: + # Enable spaces support + spaces_enabled: true + # Enable history backfilling support + msc2716_enabled: true + # server-side support for partial state in /send_join + msc3706_enabled: true + # Enable jump to date endpoint + msc3030_enabled: true + +server_notices: + system_mxid_localpart: _server + system_mxid_display_name: "Server Alert" + system_mxid_avatar_url: "" + room_name: "Server Alert" diff --git a/docker/complement/conf/log_config.yaml b/docker/complement/conf/log_config.yaml new file mode 100644 index 0000000000..c33fd6cd00 --- /dev/null +++ b/docker/complement/conf/log_config.yaml @@ -0,0 +1,24 @@ +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +filters: + context: + (): synapse.logging.context.LoggingContextFilter + request: "" + +handlers: + console: + class: logging.StreamHandler + formatter: precise + filters: [context] + # log to stdout, for easier use with 'docker logs' + stream: 'ext://sys.stdout' + +root: + level: INFO + handlers: [console] + +disable_existing_loggers: false diff --git a/docker/complement/conf/start.sh b/docker/complement/conf/start.sh new file mode 100755 index 0000000000..5d8d0fe016 --- /dev/null +++ b/docker/complement/conf/start.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +set -e + +sed -i "s/SERVER_NAME/${SERVER_NAME}/g" /conf/homeserver.yaml + +# Add the application service registration files to the homeserver.yaml config +for filename in /complement/appservice/*.yaml; do + [ -f "$filename" ] || break + + as_id=$(basename "$filename" .yaml) + + # Insert the path to the registration file and the AS_REGISTRATION_FILES marker after + # so we can add the next application service in the next iteration of this for loop + sed -i "s/AS_REGISTRATION_FILES/ - \/complement\/appservice\/${as_id}.yaml\nAS_REGISTRATION_FILES/g" /conf/homeserver.yaml +done +# Remove the AS_REGISTRATION_FILES entry +sed -i "s/AS_REGISTRATION_FILES//g" /conf/homeserver.yaml + +# generate an ssl key and cert for the server, signed by the complement CA +openssl genrsa -out /conf/server.tls.key 2048 + +openssl req -new -key /conf/server.tls.key -out /conf/server.tls.csr \ + -subj "/CN=${SERVER_NAME}" +openssl x509 -req -in /conf/server.tls.csr \ + -CA /complement/ca/ca.crt -CAkey /complement/ca/ca.key -set_serial 1 \ + -out /conf/server.tls.crt + +exec python -m synapse.app.homeserver -c /conf/homeserver.yaml "$@" + diff --git a/scripts-dev/complement.sh b/scripts-dev/complement.sh index d1b59ff040..05e9e470ed 100755 --- a/scripts-dev/complement.sh +++ b/scripts-dev/complement.sh @@ -50,25 +50,18 @@ if [[ -n "$WORKERS" ]]; then export COMPLEMENT_BASE_IMAGE=complement-synapse-workers COMPLEMENT_DOCKERFILE=SynapseWorkers.Dockerfile + # And provide some more configuration to complement. - export COMPLEMENT_CA=true export COMPLEMENT_SPAWN_HS_TIMEOUT_SECS=25 else export COMPLEMENT_BASE_IMAGE=complement-synapse - COMPLEMENT_DOCKERFILE=Synapse.Dockerfile + COMPLEMENT_DOCKERFILE=Dockerfile fi # Build the Complement image from the Synapse image we just built. -docker build -t $COMPLEMENT_BASE_IMAGE -f "$COMPLEMENT_DIR/dockerfiles/$COMPLEMENT_DOCKERFILE" "$COMPLEMENT_DIR/dockerfiles" - -cd "$COMPLEMENT_DIR" - -EXTRA_COMPLEMENT_ARGS="" -if [[ -n "$1" ]]; then - # A test name regex has been set, supply it to Complement - EXTRA_COMPLEMENT_ARGS+="-run $1 " -fi +docker build -t $COMPLEMENT_BASE_IMAGE -f "docker/complement/$COMPLEMENT_DOCKERFILE" "docker/complement" # Run the tests! echo "Images built; running complement" -go test -v -tags synapse_blacklist,msc2716,msc3030 -count=1 $EXTRA_COMPLEMENT_ARGS ./tests/... +cd "$COMPLEMENT_DIR" +go test -v -tags synapse_blacklist,msc2716,msc3030 -count=1 "$@" ./tests/...