diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bbf99447e964..0fbffd159cf8 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 000000000000..00100fdfeffe --- /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 b0105092758b..c38cae75308e 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 000000000000..4823ce7364a9 --- /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 000000000000..e075418e4a96 --- /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 000000000000..982219a91e7e --- /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 000000000000..09e2136af2e2 --- /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 000000000000..cdadb736f6ff --- /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 000000000000..be53c4aa2e33 --- /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 000000000000..c33fd6cd00a7 --- /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 000000000000..5d8d0fe016cf --- /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 d1b59ff0401b..05e9e470ed03 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/...