Enable ACME support in the docker image (#4566)

Also:

* Fix wrapping in docker readme
* Clean up some docs on the docker image
* a workaround for #4554
This commit is contained in:
Richard van der Hoff 2019-02-05 13:42:21 +00:00 committed by GitHub
parent 3ef71a6ea0
commit 40b35fb875
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 116 additions and 41 deletions

1
changelog.d/4566.feature Normal file
View file

@ -0,0 +1 @@
enable ACME support in the docker image

View file

@ -1,3 +1,16 @@
# Dockerfile to build the matrixdotorg/synapse docker images.
#
# To build the image, run `docker build` command from the root of the
# synapse repository:
#
# docker build -f docker/Dockerfile .
#
# There is an optional PYTHON_VERSION build argument which sets the
# version of python to build against: for example:
#
# docker build -f docker/Dockerfile --build-arg PYTHON_VERSION=3.6 .
#
ARG PYTHON_VERSION=2 ARG PYTHON_VERSION=2
### ###
@ -59,6 +72,6 @@ COPY ./docker/conf /conf
VOLUME ["/data"] VOLUME ["/data"]
EXPOSE 8008/tcp 8448/tcp EXPOSE 8008/tcp 8009/tcp 8448/tcp
ENTRYPOINT ["/start.py"] ENTRYPOINT ["/start.py"]

View file

@ -1,22 +1,21 @@
# Synapse Docker # Synapse Docker
This Docker image will run Synapse as a single process. It does not provide a database This Docker image will run Synapse as a single process. By default it uses a
server or a TURN server, you should run these separately. sqlite database; for production use you should connect it to a separate
postgres database.
The image also does *not* provide a TURN server.
## Run ## Run
We do not currently offer a `latest` image, as this has somewhat undefined semantics.
We instead release only tagged versions so upgrading between releases is entirely
within your control.
### Using docker-compose (easier) ### Using docker-compose (easier)
This image is designed to run either with an automatically generated configuration This image is designed to run either with an automatically generated
file or with a custom configuration that requires manual editing. configuration file or with a custom configuration that requires manual editing.
An easy way to make use of this image is via docker-compose. See the An easy way to make use of this image is via docker-compose. See the
[contrib/docker](../contrib/docker) [contrib/docker](../contrib/docker) section of the synapse project for
section of the synapse project for examples. examples.
### Without Compose (harder) ### Without Compose (harder)
@ -32,7 +31,7 @@ docker run \
-v ${DATA_PATH}:/data \ -v ${DATA_PATH}:/data \
-e SYNAPSE_SERVER_NAME=my.matrix.host \ -e SYNAPSE_SERVER_NAME=my.matrix.host \
-e SYNAPSE_REPORT_STATS=yes \ -e SYNAPSE_REPORT_STATS=yes \
docker.io/matrixdotorg/synapse:latest matrixdotorg/synapse:latest
``` ```
## Volumes ## Volumes
@ -53,6 +52,28 @@ In order to setup an application service, simply create an ``appservices``
directory in the data volume and write the application service Yaml directory in the data volume and write the application service Yaml
configuration file there. Multiple application services are supported. configuration file there. Multiple application services are supported.
## TLS certificates
Synapse requires a valid TLS certificate. You can do one of the following:
* Provide your own certificate and key (as
`${DATA_PATH}/${SYNAPSE_SERVER_NAME}.crt` and
`${DATA_PATH}/${SYNAPSE_SERVER_NAME}.key`, or elsewhere by providing an
entire config as `${SYNAPSE_CONFIG_PATH}`).
* Use a reverse proxy to terminate incoming TLS, and forward the plain http
traffic to port 8008 in the container. In this case you should set `-e
SYNAPSE_NO_TLS=1`.
* Use the ACME (Let's Encrypt) support built into Synapse. This requires
`${SYNAPSE_SERVER_NAME}` port 80 to be forwarded to port 8009 in the
container, for example with `-p 80:8009`. To enable it in the docker
container, set `-e SYNAPSE_ACME=1`.
If you don't do any of these, Synapse will fail to start with an error similar to:
synapse.config._base.ConfigError: Error accessing file '/data/<server_name>.tls.crt' (config for tls_certificate): No such file or directory
## Environment ## Environment
Unless you specify a custom path for the configuration file, a very generic Unless you specify a custom path for the configuration file, a very generic
@ -71,7 +92,7 @@ then customize it manually. No other environment variable is required.
Otherwise, a dynamic configuration file will be used. The following environment Otherwise, a dynamic configuration file will be used. The following environment
variables are available for configuration: variables are available for configuration:
* ``SYNAPSE_SERVER_NAME`` (mandatory), the current server public hostname. * ``SYNAPSE_SERVER_NAME`` (mandatory), the server public hostname.
* ``SYNAPSE_REPORT_STATS``, (mandatory, ``yes`` or ``no``), enable anonymous * ``SYNAPSE_REPORT_STATS``, (mandatory, ``yes`` or ``no``), enable anonymous
statistics reporting back to the Matrix project which helps us to get funding. statistics reporting back to the Matrix project which helps us to get funding.
* ``SYNAPSE_NO_TLS``, set this variable to disable TLS in Synapse (use this if * ``SYNAPSE_NO_TLS``, set this variable to disable TLS in Synapse (use this if
@ -80,7 +101,6 @@ variables are available for configuration:
the Synapse instance. the Synapse instance.
* ``SYNAPSE_ALLOW_GUEST``, set this variable to allow guest joining this server. * ``SYNAPSE_ALLOW_GUEST``, set this variable to allow guest joining this server.
* ``SYNAPSE_EVENT_CACHE_SIZE``, the event cache size [default `10K`]. * ``SYNAPSE_EVENT_CACHE_SIZE``, the event cache size [default `10K`].
* ``SYNAPSE_CACHE_FACTOR``, the cache factor [default `0.5`].
* ``SYNAPSE_RECAPTCHA_PUBLIC_KEY``, set this variable to the recaptcha public * ``SYNAPSE_RECAPTCHA_PUBLIC_KEY``, set this variable to the recaptcha public
key in order to enable recaptcha upon registration. key in order to enable recaptcha upon registration.
* ``SYNAPSE_RECAPTCHA_PRIVATE_KEY``, set this variable to the recaptcha private * ``SYNAPSE_RECAPTCHA_PRIVATE_KEY``, set this variable to the recaptcha private
@ -88,7 +108,9 @@ variables are available for configuration:
* ``SYNAPSE_TURN_URIS``, set this variable to the coma-separated list of TURN * ``SYNAPSE_TURN_URIS``, set this variable to the coma-separated list of TURN
uris to enable TURN for this homeserver. uris to enable TURN for this homeserver.
* ``SYNAPSE_TURN_SECRET``, set this to the TURN shared secret if required. * ``SYNAPSE_TURN_SECRET``, set this to the TURN shared secret if required.
* ``SYNAPSE_MAX_UPLOAD_SIZE``, set this variable to change the max upload size [default `10M`]. * ``SYNAPSE_MAX_UPLOAD_SIZE``, set this variable to change the max upload size
[default `10M`].
* ``SYNAPSE_ACME``: set this to enable the ACME certificate renewal support.
Shared secrets, that will be initialized to random values if not set: Shared secrets, that will be initialized to random values if not set:
@ -99,27 +121,25 @@ Shared secrets, that will be initialized to random values if not set:
Database specific values (will use SQLite if not set): Database specific values (will use SQLite if not set):
* `POSTGRES_DB` - The database name for the synapse postgres database. [default: `synapse`] * `POSTGRES_DB` - The database name for the synapse postgres
* `POSTGRES_HOST` - The host of the postgres database if you wish to use postgresql instead of sqlite3. [default: `db` which is useful when using a container on the same docker network in a compose file where the postgres service is called `db`] database. [default: `synapse`]
* `POSTGRES_PASSWORD` - The password for the synapse postgres database. **If this is set then postgres will be used instead of sqlite3.** [default: none] **NOTE**: You are highly encouraged to use postgresql! Please use the compose file to make it easier to deploy. * `POSTGRES_HOST` - The host of the postgres database if you wish to use
* `POSTGRES_USER` - The user for the synapse postgres database. [default: `matrix`] postgresql instead of sqlite3. [default: `db` which is useful when using a
container on the same docker network in a compose file where the postgres
service is called `db`]
* `POSTGRES_PASSWORD` - The password for the synapse postgres database. **If
this is set then postgres will be used instead of sqlite3.** [default: none]
**NOTE**: You are highly encouraged to use postgresql! Please use the compose
file to make it easier to deploy.
* `POSTGRES_USER` - The user for the synapse postgres database. [default:
`matrix`]
Mail server specific values (will not send emails if not set): Mail server specific values (will not send emails if not set):
* ``SYNAPSE_SMTP_HOST``, hostname to the mail server. * ``SYNAPSE_SMTP_HOST``, hostname to the mail server.
* ``SYNAPSE_SMTP_PORT``, TCP port for accessing the mail server [default ``25``]. * ``SYNAPSE_SMTP_PORT``, TCP port for accessing the mail server [default
* ``SYNAPSE_SMTP_USER``, username for authenticating against the mail server if any. ``25``].
* ``SYNAPSE_SMTP_PASSWORD``, password for authenticating against the mail server if any. * ``SYNAPSE_SMTP_USER``, username for authenticating against the mail server if
any.
## Build * ``SYNAPSE_SMTP_PASSWORD``, password for authenticating against the mail
server if any.
Build the docker image with the `docker build` command from the root of the synapse repository.
```
docker build -t docker.io/matrixdotorg/synapse . -f docker/Dockerfile
```
The `-t` option sets the image tag. Official images are tagged `matrixdotorg/synapse:<version>` where `<version>` is the same as the release tag in the synapse git repository.
You may have a local Python wheel cache available, in which case copy the relevant
packages in the ``cache/`` directory at the root of the project.

17
docker/conf/dummy.tls.crt Normal file
View file

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICnTCCAYUCAgPoMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNVBAMMCWxvY2FsaG9z
dDAeFw0xOTAxMTUwMDQxNTBaFw0yOTAxMTIwMDQxNTBaMBQxEjAQBgNVBAMMCWxv
Y2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMKqm81/8j5d
R1s7VZ8ueg12gJrPVCCAOkp0UnuC/ZlXhN0HTvnhQ+B0IlSgB4CcQZyf4jnA6o4M
rwSc7VX0MPE9x/idoA0g/0WoC6tsxugOrvbzCw8Tv+fnXglm6uVc7aFPfx69wU3q
lUHGD/8jtEoHxmCG177Pt2lHAfiVLBAyMQGtETzxt/yAfkloaybe316qoljgK5WK
cokdAt9G84EEqxNeEnx5FG3Vc100bAqJS4GvQlFgtF9KFEqZKEyB1yKBpPMDfPIS
V9hIV0gswSmYI8dpyBlGf5lPElY68ZGABmOQgr0RI5qHK/h28OpFPE0q3v4AMHgZ
I36wii4NrAUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAfD8kcpZ+dn08xh1qtKtp
X+/YNZaOBIeVdlCzfoZKNblSFAFD/jCfObNJYvZMUQ8NX2UtEJp1lTA6m7ltSsdY
gpC2k1VD8iN+ooXklJmL0kxc7UUqho8I0l9vn35h+lhLF0ihT6XfZVi/lDHWl+4G
rG+v9oxvCSCWrNWLearSlFPtQQ8xPtOE0nLwfXtOI/H/2kOuC38ihaIWM4jjbWXK
E/ksgUfuDv0mFiwf1YdBF5/M3/qOowqzU8HgMJ3WoT/9Po5Ya1pWc+3BcxxytUDf
XdMu0tWHKX84tZxLcR1nZHzluyvFFM8xNtLi9xV0Z7WbfT76V0C/ulEOybGInYsv
nQ==
-----END CERTIFICATE-----

View file

@ -2,10 +2,24 @@
## TLS ## ## TLS ##
{% if SYNAPSE_NO_TLS %}
no_tls: True
# workaround for https://github.com/matrix-org/synapse/issues/4554
tls_certificate_path: "/conf/dummy.tls.crt"
{% else %}
tls_certificate_path: "/data/{{ SYNAPSE_SERVER_NAME }}.tls.crt" tls_certificate_path: "/data/{{ SYNAPSE_SERVER_NAME }}.tls.crt"
tls_private_key_path: "/data/{{ SYNAPSE_SERVER_NAME }}.tls.key" tls_private_key_path: "/data/{{ SYNAPSE_SERVER_NAME }}.tls.key"
no_tls: {{ "True" if SYNAPSE_NO_TLS else "False" }}
tls_fingerprints: [] {% if SYNAPSE_ACME %}
acme:
enabled: true
port: 8009
{% endif %}
{% endif %}
## Server ## ## Server ##

View file

@ -47,9 +47,8 @@ if mode == "generate":
# In normal mode, generate missing keys if any, then run synapse # In normal mode, generate missing keys if any, then run synapse
else: else:
# Parse the configuration file
if "SYNAPSE_CONFIG_PATH" in environ: if "SYNAPSE_CONFIG_PATH" in environ:
args += ["--config-path", environ["SYNAPSE_CONFIG_PATH"]] config_path = environ["SYNAPSE_CONFIG_PATH"]
else: else:
check_arguments(environ, ("SYNAPSE_SERVER_NAME", "SYNAPSE_REPORT_STATS")) check_arguments(environ, ("SYNAPSE_SERVER_NAME", "SYNAPSE_REPORT_STATS"))
generate_secrets(environ, { generate_secrets(environ, {
@ -58,10 +57,21 @@ else:
}) })
environ["SYNAPSE_APPSERVICES"] = glob.glob("/data/appservices/*.yaml") environ["SYNAPSE_APPSERVICES"] = glob.glob("/data/appservices/*.yaml")
if not os.path.exists("/compiled"): os.mkdir("/compiled") if not os.path.exists("/compiled"): os.mkdir("/compiled")
convert("/conf/homeserver.yaml", "/compiled/homeserver.yaml", environ)
config_path = "/compiled/homeserver.yaml"
convert("/conf/homeserver.yaml", config_path, environ)
convert("/conf/log.config", "/compiled/log.config", environ) convert("/conf/log.config", "/compiled/log.config", environ)
subprocess.check_output(["chown", "-R", ownership, "/data"]) subprocess.check_output(["chown", "-R", ownership, "/data"])
args += ["--config-path", "/compiled/homeserver.yaml"]
args += [
"--config-path", config_path,
# tell synapse to put any generated keys in /data rather than /compiled
"--keys-directory", "/data",
]
# Generate missing keys and start synapse # Generate missing keys and start synapse
subprocess.check_output(args + ["--generate-keys"]) subprocess.check_output(args + ["--generate-keys"])
os.execv("/sbin/su-exec", ["su-exec", ownership] + args) os.execv("/sbin/su-exec", ["su-exec", ownership] + args)