---
title: "Despliega Synapse en Pethost con un clic"
description: "Tu propio servidor de Matrix: chatea con cualquiera en Matrix, desde Element o cualquier otra app. Una plantilla para Pethost: en un par de minutos la app está en marcha en tu máquina, con HTTPS en su propia dirección y backups cada noche."
---

[← Todas las plantillas](https://pethost.dev/es/templates/)

# Despliega Synapse en Pethost con un clic

Tu propio servidor de Matrix: chatea con cualquiera en Matrix, desde Element o cualquier otra app

[Desplegar en Pethost](https://console.pethost.dev/?template=synapse)

## Qué pasa

1. Inicias sesión en Pethost o creas una cuenta, con una passkey, GitHub o Google.
2. ¿Aún no tienes máquina? Eliges un plan y te preparamos una. El enlace espera en tu navegador hasta que esté lista.
3. Nuevo proyecto se abre en la app. Rellenas lo que pide y haces clic en Crear proyecto: **Nombre de usuario**, **Contraseña de administrador**.
4. En un par de minutos la app está en marcha en su propia dirección con HTTPS. Sus secretos se generan al azar para ella, y sus datos entran en el backup de cada noche.
5. Es un proyecto como cualquier otro: su compose.yaml, su .env, sus logs y un terminal están en el panel, y tu agente puede cambiarlo, volver a una versión anterior o restaurarlo.

## Primeros pasos

En Element (app.element.io) o cualquier app de Matrix, inicia sesión en el servidor synapse.sam.pethost.app con el nombre de usuario y la contraseña que indicaste: esa cuenta es la del administrador. Los nombres de usuario van en minúsculas. Las demás personas crean sus cuentas en synapse.sam.pethost.app con el token de registro, REGISTRATION_TOKEN en el .env del proyecto. La contraseña de .env solo se lee en el primer arranque; cámbiala en Element. El nombre del servidor queda ligado a esta dirección para siempre, así que dale al proyecto su dirección definitiva antes de que entre nadie. Los demás servidores de Matrix lo encuentran en synapse.sam.pethost.app, puerto 443.

## Qué ejecuta

La plantilla es este compose.yaml y las variables que escribe en el .env del proyecto. Pethost ejecuta el archivo tal como está escrito.

```
# Synapse, the Matrix homeserver, with PostgreSQL. Its server name is the project's address, and
# other servers find it there on port 443 through /.well-known/matrix/server, which Synapse serves.
services:
  synapse:
    image: matrixdotorg/synapse:v1.163.0
    restart: unless-stopped
    environment:
      SYNAPSE_SERVER_NAME: ${HOST}
      SYNAPSE_REPORT_STATS: "no"
      PUBLIC_URL: ${URL}
      DB_PASSWORD: ${DB_PASSWORD}
      ADMIN_USERNAME: ${ADMIN_USERNAME}
      ADMIN_PASSWORD: ${ADMIN_PASSWORD}
      REGISTRATION_TOKEN: ${REGISTRATION_TOKEN}
    # The first start generates homeserver.yaml and the signing key; every start writes
    # pethost.yaml, read after it, with what this project decides. The admin and the
    # registration token are made once from .env, by the setup below, once Synapse answers.
    entrypoint:
      - sh
      - -c
      - |
        set -e
        [ -f /data/homeserver.yaml ] || /start.py generate
        cat > /data/pethost.yaml <<EOF
        public_baseurl: $$PUBLIC_URL/
        serve_server_wellknown: true
        serve_client_wellknown: true
        listeners:
          - port: 8008
            type: http
            tls: false
            bind_addresses: ["0.0.0.0"]
            x_forwarded: true
            resources:
              - names: [client, federation]
                compress: false
        database:
          name: psycopg2
          args:
            user: synapse
            password: $$DB_PASSWORD
            dbname: synapse
            host: db
            cp_min: 5
            cp_max: 10
        enable_registration: true
        registration_requires_token: true
        suppress_key_server_warning: true
        EOF
        [ -f /data/.pethost-setup ] || python3 - <<'PY' &
        import hashlib, hmac, json, os, signal, time, urllib.error, urllib.request
        import yaml

        BASE = "http://127.0.0.1:8008"

        def call(method, path, body=None, token=None):
            request = urllib.request.Request(BASE + path, method=method, data=json.dumps(body).encode() if body is not None else None)
            request.add_header("Content-Type", "application/json")
            if token:
                request.add_header("Authorization", "Bearer " + token)
            try:
                with urllib.request.urlopen(request, timeout=30) as answer:
                    return answer.status, json.load(answer)
            except urllib.error.HTTPError as error:
                return error.code, json.load(error)

        def setup():
            for _ in range(600):
                try:
                    urllib.request.urlopen(BASE + "/health", timeout=5)
                    break
                except Exception:
                    time.sleep(1)
            user = os.environ["ADMIN_USERNAME"].strip().lower()
            password = os.environ["ADMIN_PASSWORD"]
            secret = yaml.safe_load(open("/data/homeserver.yaml"))["registration_shared_secret"]

            # The admin, by the shared secret, as register_new_matrix_user makes one.
            nonce = call("GET", "/_synapse/admin/v1/register")[1]["nonce"]
            mac = hmac.new(secret.encode(), digestmod=hashlib.sha1)
            mac.update(b"\x00".join([nonce.encode(), user.encode(), password.encode(), b"admin"]))
            status, made = call("POST", "/_synapse/admin/v1/register", {"nonce": nonce, "username": user, "password": password, "admin": True, "mac": mac.hexdigest()})
            if status != 200 and made.get("errcode") == "M_USER_IN_USE":
                status, made = call("POST", "/_matrix/client/v3/login", {"type": "m.login.password", "identifier": {"type": "m.id.user", "user": user}, "password": password})
            if status != 200:
                raise RuntimeError("the admin @%s could not be made: %s" % (user, made.get("error", made)))
            token = made["access_token"]

            # The token people register with, with no expiry and no limit of uses.
            status, answer = call("POST", "/_synapse/admin/v1/registration_tokens/new", {"token": os.environ["REGISTRATION_TOKEN"]}, token)
            if status != 200 and answer.get("errcode") != "M_INVALID_PARAM":
                raise RuntimeError("the registration token could not be made: %s" % answer.get("error", answer))
            call("POST", "/_matrix/client/v3/logout", {}, token)
            open("/data/.pethost-setup", "w").close()
            print("pethost: the admin @%s and the registration token are made" % user, flush=True)

        # A setup that fails stops Synapse, so the deploy fails with the reason in its log.
        try:
            setup()
        except Exception as error:
            print("pethost: %s" % error, flush=True)
            os.kill(1, signal.SIGTERM)
        PY
        exec /start.py run --config-path /data/homeserver.yaml --config-path /data/pethost.yaml
    volumes:
      - data:/data
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:17
    restart: unless-stopped
    environment:
      POSTGRES_USER: synapse
      POSTGRES_DB: synapse
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      # Synapse refuses a database whose collation is not C.
      POSTGRES_INITDB_ARGS: --encoding=UTF8 --locale=C
    volumes:
      - db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "synapse"]
      interval: 5s
      timeout: 5s
      retries: 10

volumes:
  data:
  db:
```

[compose.yaml](https://pethost.dev/templates/synapse/compose.yaml)[Verla en GitHub](https://github.com/pethost-dev/templates/tree/main/synapse)

Pethost · Stephan Gomer · NIP 1133096755

[Plantillas](https://pethost.dev/es/templates/) [Sobre nosotros](https://pethost.dev/about/) [Blog](https://pethost.dev/blog/) [Términos](https://pethost.dev/terms/) [Privacidad](https://pethost.dev/privacy/) [Reembolsos](https://pethost.dev/refunds/) [API](https://pethost.dev/docs/api/) [CLI](https://pethost.dev/docs/cli/) [Plugin](https://github.com/pethost-dev/plugin) [support@pethost.dev](mailto:support@pethost.dev)
