Dokploy

Synapse

Synapse is the reference homeserver implementation for Matrix, an open standard for secure, decentralised, real-time communication.

Synapse logo

Configuration

services:
  synapse:
    image: matrixdotorg/synapse:v1.156.0
    restart: unless-stopped
    # The stock entrypoint (/start.py) does not generate the signing key when a
    # config file is provided, so generate any missing keys on first boot and
    # make sure the data volume is owned by the synapse user (991) before
    # handing over to the regular entrypoint.
    entrypoint:
      - /bin/sh
      - -c
      - |
        python -m synapse.app.homeserver --config-path /config/homeserver.yaml --keys-directory /data --generate-keys
        chown -R 991:991 /data
        exec /start.py
    environment:
      SYNAPSE_CONFIG_PATH: /config/homeserver.yaml
    volumes:
      - synapse-data:/data
      - ../files/homeserver.yaml:/config/homeserver.yaml:ro
      - ../files/log.config:/config/log.config:ro
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "curl -fSs http://localhost:8008/health || exit 1"]
      interval: 15s
      timeout: 5s
      retries: 10
      start_period: 90s

  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: synapse
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: synapse
      # Synapse requires a database with C collation
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U synapse -d synapse"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  synapse-data:
  postgres-data:
[variables]
main_domain = "${domain}"
postgres_password = "${password:32}"
registration_shared_secret = "${password:32}"
macaroon_secret_key = "${password:32}"
form_secret = "${password:32}"

[config]
env = [
    "POSTGRES_PASSWORD=${postgres_password}",
]

[[config.domains]]
serviceName = "synapse"
port = 8008
host = "${main_domain}"

[[config.mounts]]
filePath = "homeserver.yaml"
content = """
# Synapse homeserver configuration
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html

server_name: "${main_domain}"
public_baseurl: "https://${main_domain}/"
pid_file: /data/homeserver.pid
signing_key_path: "/data/signing.key"
log_config: "/config/log.config"
media_store_path: /data/media_store
report_stats: false

# Serve /.well-known/matrix/server so other homeservers can federate with
# this server over port 443 (the dedicated federation port 8448 is not exposed).
serve_server_wellknown: true

listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    bind_addresses: ['0.0.0.0']
    resources:
      - names: [client, federation]
        compress: false

database:
  name: psycopg2
  args:
    user: synapse
    password: "${postgres_password}"
    database: synapse
    host: postgres
    port: 5432
    cp_min: 5
    cp_max: 10

# Public registration is disabled. Create users with the
# register_new_matrix_user tool (see the template instructions).
enable_registration: false
registration_shared_secret: "${registration_shared_secret}"

macaroon_secret_key: "${macaroon_secret_key}"
form_secret: "${form_secret}"

trusted_key_servers:
  - server_name: "matrix.org"
suppress_key_server_warning: true
"""

[[config.mounts]]
filePath = "log.config"
content = """
version: 1

formatters:
  precise:
    format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s'

handlers:
  console:
    class: logging.StreamHandler
    formatter: precise

loggers:
  synapse.storage.SQL:
    level: INFO

root:
  level: INFO
  handlers: [console]

disable_existing_loggers: false
"""

Base64

To import this template in Dokploy: create a Compose service → AdvancedBase64 import and paste the content below:

ewogICJjb21wb3NlIjogInNlcnZpY2VzOlxuICBzeW5hcHNlOlxuICAgIGltYWdlOiBtYXRyaXhkb3Rvcmcvc3luYXBzZTp2MS4xNTYuMFxuICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkXG4gICAgIyBUaGUgc3RvY2sgZW50cnlwb2ludCAoL3N0YXJ0LnB5KSBkb2VzIG5vdCBnZW5lcmF0ZSB0aGUgc2lnbmluZyBrZXkgd2hlbiBhXG4gICAgIyBjb25maWcgZmlsZSBpcyBwcm92aWRlZCwgc28gZ2VuZXJhdGUgYW55IG1pc3Npbmcga2V5cyBvbiBmaXJzdCBib290IGFuZFxuICAgICMgbWFrZSBzdXJlIHRoZSBkYXRhIHZvbHVtZSBpcyBvd25lZCBieSB0aGUgc3luYXBzZSB1c2VyICg5OTEpIGJlZm9yZVxuICAgICMgaGFuZGluZyBvdmVyIHRvIHRoZSByZWd1bGFyIGVudHJ5cG9pbnQuXG4gICAgZW50cnlwb2ludDpcbiAgICAgIC0gL2Jpbi9zaFxuICAgICAgLSAtY1xuICAgICAgLSB8XG4gICAgICAgIHB5dGhvbiAtbSBzeW5hcHNlLmFwcC5ob21lc2VydmVyIC0tY29uZmlnLXBhdGggL2NvbmZpZy9ob21lc2VydmVyLnlhbWwgLS1rZXlzLWRpcmVjdG9yeSAvZGF0YSAtLWdlbmVyYXRlLWtleXNcbiAgICAgICAgY2hvd24gLVIgOTkxOjk5MSAvZGF0YVxuICAgICAgICBleGVjIC9zdGFydC5weVxuICAgIGVudmlyb25tZW50OlxuICAgICAgU1lOQVBTRV9DT05GSUdfUEFUSDogL2NvbmZpZy9ob21lc2VydmVyLnlhbWxcbiAgICB2b2x1bWVzOlxuICAgICAgLSBzeW5hcHNlLWRhdGE6L2RhdGFcbiAgICAgIC0gLi4vZmlsZXMvaG9tZXNlcnZlci55YW1sOi9jb25maWcvaG9tZXNlcnZlci55YW1sOnJvXG4gICAgICAtIC4uL2ZpbGVzL2xvZy5jb25maWc6L2NvbmZpZy9sb2cuY29uZmlnOnJvXG4gICAgZGVwZW5kc19vbjpcbiAgICAgIHBvc3RncmVzOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeVxuICAgIGhlYWx0aGNoZWNrOlxuICAgICAgdGVzdDogW1wiQ01ELVNIRUxMXCIsIFwiY3VybCAtZlNzIGh0dHA6Ly9sb2NhbGhvc3Q6ODAwOC9oZWFsdGggfHwgZXhpdCAxXCJdXG4gICAgICBpbnRlcnZhbDogMTVzXG4gICAgICB0aW1lb3V0OiA1c1xuICAgICAgcmV0cmllczogMTBcbiAgICAgIHN0YXJ0X3BlcmlvZDogOTBzXG5cbiAgcG9zdGdyZXM6XG4gICAgaW1hZ2U6IHBvc3RncmVzOjE2LWFscGluZVxuICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkXG4gICAgZW52aXJvbm1lbnQ6XG4gICAgICBQT1NUR1JFU19VU0VSOiBzeW5hcHNlXG4gICAgICBQT1NUR1JFU19QQVNTV09SRDogJHtQT1NUR1JFU19QQVNTV09SRH1cbiAgICAgIFBPU1RHUkVTX0RCOiBzeW5hcHNlXG4gICAgICAjIFN5bmFwc2UgcmVxdWlyZXMgYSBkYXRhYmFzZSB3aXRoIEMgY29sbGF0aW9uXG4gICAgICBQT1NUR1JFU19JTklUREJfQVJHUzogXCItLWVuY29kaW5nPVVURi04IC0tbGMtY29sbGF0ZT1DIC0tbGMtY3R5cGU9Q1wiXG4gICAgdm9sdW1lczpcbiAgICAgIC0gcG9zdGdyZXMtZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGFcbiAgICBoZWFsdGhjaGVjazpcbiAgICAgIHRlc3Q6IFtcIkNNRC1TSEVMTFwiLCBcInBnX2lzcmVhZHkgLVUgc3luYXBzZSAtZCBzeW5hcHNlXCJdXG4gICAgICBpbnRlcnZhbDogMTBzXG4gICAgICB0aW1lb3V0OiA1c1xuICAgICAgcmV0cmllczogNVxuXG52b2x1bWVzOlxuICBzeW5hcHNlLWRhdGE6XG4gIHBvc3RncmVzLWRhdGE6XG4iLAogICJjb25maWciOiAiW3ZhcmlhYmxlc11cbm1haW5fZG9tYWluID0gXCIke2RvbWFpbn1cIlxucG9zdGdyZXNfcGFzc3dvcmQgPSBcIiR7cGFzc3dvcmQ6MzJ9XCJcbnJlZ2lzdHJhdGlvbl9zaGFyZWRfc2VjcmV0ID0gXCIke3Bhc3N3b3JkOjMyfVwiXG5tYWNhcm9vbl9zZWNyZXRfa2V5ID0gXCIke3Bhc3N3b3JkOjMyfVwiXG5mb3JtX3NlY3JldCA9IFwiJHtwYXNzd29yZDozMn1cIlxuXG5bY29uZmlnXVxuZW52ID0gW1xuICAgIFwiUE9TVEdSRVNfUEFTU1dPUkQ9JHtwb3N0Z3Jlc19wYXNzd29yZH1cIixcbl1cblxuW1tjb25maWcuZG9tYWluc11dXG5zZXJ2aWNlTmFtZSA9IFwic3luYXBzZVwiXG5wb3J0ID0gODAwOFxuaG9zdCA9IFwiJHttYWluX2RvbWFpbn1cIlxuXG5bW2NvbmZpZy5tb3VudHNdXVxuZmlsZVBhdGggPSBcImhvbWVzZXJ2ZXIueWFtbFwiXG5jb250ZW50ID0gXCJcIlwiXG4jIFN5bmFwc2UgaG9tZXNlcnZlciBjb25maWd1cmF0aW9uXG4jIGh0dHBzOi8vZWxlbWVudC1ocS5naXRodWIuaW8vc3luYXBzZS9sYXRlc3QvdXNhZ2UvY29uZmlndXJhdGlvbi9jb25maWdfZG9jdW1lbnRhdGlvbi5odG1sXG5cbnNlcnZlcl9uYW1lOiBcIiR7bWFpbl9kb21haW59XCJcbnB1YmxpY19iYXNldXJsOiBcImh0dHBzOi8vJHttYWluX2RvbWFpbn0vXCJcbnBpZF9maWxlOiAvZGF0YS9ob21lc2VydmVyLnBpZFxuc2lnbmluZ19rZXlfcGF0aDogXCIvZGF0YS9zaWduaW5nLmtleVwiXG5sb2dfY29uZmlnOiBcIi9jb25maWcvbG9nLmNvbmZpZ1wiXG5tZWRpYV9zdG9yZV9wYXRoOiAvZGF0YS9tZWRpYV9zdG9yZVxucmVwb3J0X3N0YXRzOiBmYWxzZVxuXG4jIFNlcnZlIC8ud2VsbC1rbm93bi9tYXRyaXgvc2VydmVyIHNvIG90aGVyIGhvbWVzZXJ2ZXJzIGNhbiBmZWRlcmF0ZSB3aXRoXG4jIHRoaXMgc2VydmVyIG92ZXIgcG9ydCA0NDMgKHRoZSBkZWRpY2F0ZWQgZmVkZXJhdGlvbiBwb3J0IDg0NDggaXMgbm90IGV4cG9zZWQpLlxuc2VydmVfc2VydmVyX3dlbGxrbm93bjogdHJ1ZVxuXG5saXN0ZW5lcnM6XG4gIC0gcG9ydDogODAwOFxuICAgIHRsczogZmFsc2VcbiAgICB0eXBlOiBodHRwXG4gICAgeF9mb3J3YXJkZWQ6IHRydWVcbiAgICBiaW5kX2FkZHJlc3NlczogWycwLjAuMC4wJ11cbiAgICByZXNvdXJjZXM6XG4gICAgICAtIG5hbWVzOiBbY2xpZW50LCBmZWRlcmF0aW9uXVxuICAgICAgICBjb21wcmVzczogZmFsc2VcblxuZGF0YWJhc2U6XG4gIG5hbWU6IHBzeWNvcGcyXG4gIGFyZ3M6XG4gICAgdXNlcjogc3luYXBzZVxuICAgIHBhc3N3b3JkOiBcIiR7cG9zdGdyZXNfcGFzc3dvcmR9XCJcbiAgICBkYXRhYmFzZTogc3luYXBzZVxuICAgIGhvc3Q6IHBvc3RncmVzXG4gICAgcG9ydDogNTQzMlxuICAgIGNwX21pbjogNVxuICAgIGNwX21heDogMTBcblxuIyBQdWJsaWMgcmVnaXN0cmF0aW9uIGlzIGRpc2FibGVkLiBDcmVhdGUgdXNlcnMgd2l0aCB0aGVcbiMgcmVnaXN0ZXJfbmV3X21hdHJpeF91c2VyIHRvb2wgKHNlZSB0aGUgdGVtcGxhdGUgaW5zdHJ1Y3Rpb25zKS5cbmVuYWJsZV9yZWdpc3RyYXRpb246IGZhbHNlXG5yZWdpc3RyYXRpb25fc2hhcmVkX3NlY3JldDogXCIke3JlZ2lzdHJhdGlvbl9zaGFyZWRfc2VjcmV0fVwiXG5cbm1hY2Fyb29uX3NlY3JldF9rZXk6IFwiJHttYWNhcm9vbl9zZWNyZXRfa2V5fVwiXG5mb3JtX3NlY3JldDogXCIke2Zvcm1fc2VjcmV0fVwiXG5cbnRydXN0ZWRfa2V5X3NlcnZlcnM6XG4gIC0gc2VydmVyX25hbWU6IFwibWF0cml4Lm9yZ1wiXG5zdXBwcmVzc19rZXlfc2VydmVyX3dhcm5pbmc6IHRydWVcblwiXCJcIlxuXG5bW2NvbmZpZy5tb3VudHNdXVxuZmlsZVBhdGggPSBcImxvZy5jb25maWdcIlxuY29udGVudCA9IFwiXCJcIlxudmVyc2lvbjogMVxuXG5mb3JtYXR0ZXJzOlxuICBwcmVjaXNlOlxuICAgIGZvcm1hdDogJyUoYXNjdGltZSlzIC0gJShuYW1lKXMgLSAlKGxpbmVubylkIC0gJShsZXZlbG5hbWUpcyAtICUocmVxdWVzdClzIC0gJShtZXNzYWdlKXMnXG5cbmhhbmRsZXJzOlxuICBjb25zb2xlOlxuICAgIGNsYXNzOiBsb2dnaW5nLlN0cmVhbUhhbmRsZXJcbiAgICBmb3JtYXR0ZXI6IHByZWNpc2VcblxubG9nZ2VyczpcbiAgc3luYXBzZS5zdG9yYWdlLlNRTDpcbiAgICBsZXZlbDogSU5GT1xuXG5yb290OlxuICBsZXZlbDogSU5GT1xuICBoYW5kbGVyczogW2NvbnNvbGVdXG5cbmRpc2FibGVfZXhpc3RpbmdfbG9nZ2VyczogZmFsc2VcblwiXCJcIlxuIgp9

Instructions

Instructions

Synapse is deployed with public registration disabled, so you need to create the first user (your admin account) from the command line.

Create the first user

Open a terminal on the server running Dokploy (or use the container terminal in the Dokploy UI) and run the following inside the synapse service container:

docker exec -it $(docker ps -qf "name=synapse" | head -n 1) \
  register_new_matrix_user http://localhost:8008 -c /config/homeserver.yaml

The tool prompts for a username and password, and asks whether the user should be an admin. It authenticates against the server using the registration_shared_secret that was generated for this deployment (stored in the mounted homeserver.yaml), so no registration needs to be enabled.

Log in

Point any Matrix client (for example Element Web at https://app.element.io) at your homeserver URL https://your-domain and log in with the user you just created. You can verify the server is up with:

curl https://your-domain/_matrix/client/versions

Notes

  • Data (signing keys, media uploads) is stored in the synapse-data volume and the database in the postgres-data volume.
  • Federation with other Matrix servers works through .well-known delegation over HTTPS (port 443). The dedicated federation port 8448 is not exposed.
  • To allow open registration instead, edit enable_registration in the mounted homeserver.yaml (see Synapse docs for the required spam-check options such as CAPTCHA or email verification).

Tags

matrix, communication


Version: v1.156.0

On this page