#!/usr/bin/sh set -euo pipefail echo "=== Matrix Dendrite + Coturn auto-setup (Docker + standalone Coturn) ===" # ---- User Input ---- read -rp "Matrix domain (eg. matrix.example.com): " MATRIX_DOMAIN read -rp "TURN domain(eg. turn.example.com): " TURN_DOMAIN read -rp "Let's Encrypt certificate email: " EMAIL read -rp "Postgres secret: " DB_PASS read -rp "registration_shared_secret: " REG_SECRET read -rp "TURN shared secret: " TURN_SECRET read -rp "TURN IP (eg. 127.0.0.1): " TURN_SERVER_IP read -rp "MATRIX server IP (eg. 127.0.0.1): " MATRIX_SERVER_IP read -rp "Listening device (eg. eth0): " TURN_LISTENING_DEVICE INSTALL_DIR="/opt/matrix/$MATRIX_DOMAIN" mkdir -p "$INSTALL_DIR/config" cd "$INSTALL_DIR" cat < .env # PostgreSQL POSTGRES_HOSTNAME=postgres POSTGRES_VERSION=15-alpine POSTGRES_USER=dendrite POSTGRES_PASSWORD=$DB_PASS POSTGRES_DB=dendrite # Monolith MONOLITH_HOSTNAME=monolith MONOLITH_IMAGE=matrixdotorg/dendrite-monolith:latest MONOLITH_PORT_HTTP=8008 MONOLITH_PORT_HTTPS=8448 EOF cat <<'EOF' > compose.yml services: postgres: hostname: ${POSTGRES_HOSTNAME:-postgres} image: postgres:${POSTGRES_VERSION:-15-alpine} restart: always volumes: - ./dendrite_postgres_data:/var/lib/postgresql/data environment: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-itsasecret} POSTGRES_USER: ${POSTGRES_USER:-dendrite} POSTGRES_DB: ${POSTGRES_DB:-dendrite} healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-dendrite}"] interval: 5s timeout: 5s retries: 5 networks: - internal monolith: hostname: ${MONOLITH_HOSTNAME:-monolith} image: ${MONOLITH_IMAGE:-matrixdotorg/dendrite-monolith:latest} ports: - ${MONOLITH_PORT_HTTP:-8008}:8008 - ${MONOLITH_PORT_HTTPS:-8448}:8448 volumes: - ./config:/etc/dendrite - ./dendrite_media:/var/dendrite/media - ./dendrite_jetstream:/var/dendrite/jetstream - ./dendrite_search_index:/var/dendrite/searchindex - ./:/mnt depends_on: postgres: condition: service_healthy networks: - internal restart: unless-stopped networks: internal: attachable: true volumes: dendrite_postgres_data: dendrite_media: dendrite_jetstream: dendrite_search_index: EOF cat < config/dendrite.yaml version: 2 global: server_name: $MATRIX_DOMAIN private_key: /mnt/matrix_key.pem old_private_keys: key_validity_period: 168h0m0s database: connection_string: postgresql://dendrite:$DB_PASS@postgres/dendrite?sslmode=disable max_open_conns: 90 max_idle_conns: 5 conn_max_lifetime: -1 well_known_server_name: "$MATRIX_DOMAIN:443" well_known_client_name: "https://$MATRIX_DOMAIN" client_api: registration_disabled: true guests_disabled: true registration_shared_secret: "$REG_SECRET" turn: turn_user_lifetime: "5m" turn_uris: - turn:$TURN_DOMAIN?transport=udp - turn:$TURN_DOMAIN?transport=tcp turn_shared_secret: "$TURN_SECRET" federation_api: send_max_retries: 16 disable_tls_validation: false media_api: base_path: ./media_store max_file_size_bytes: 10485760 dynamic_thumbnails: false thumbnail_sizes: - width: 96 height: 96 method: crop - width: 640 height: 480 method: scale user_api: bcrypt_cost: 10 auto_join_rooms: - "#main:$MATRIX_DOMAIN" logging: - type: std level: info EOF cat < /etc/turnserver.conf listening-device=$TURN_LISTENING_DEVICE listening-port=3478 tls-listening-port=5349 listening-ip=$TURN_SERVER_IP min-port=49152 max-port=65535 use-auth-secret static-auth-secret=$TURN_SECRET syslog no-rfc5780 no-stun-backward-compatibility response-origin-only-with-rfc5780 EOF echo "[INFO] Generating server keys..." docker run --rm --entrypoint="" -v $(pwd):/mnt matrixdotorg/dendrite-monolith:latest /usr/bin/generate-keys -private-key /mnt/matrix_key.pem -tls-cert /mnt/server.crt -tls-key /mnt/server.key echo "[INFO] Booting up containers(HTTP-only test)..." docker compose up -d echo "[INFO] Waiting for dendrite monolith to answer..." for i in {1..30}; do if curl -fs "http://$MATRIX_SERVER_IP:8008/_matrix/client/versions" >/dev/null 2>&1; then echo "[OK] Monolith dziaƂa na http://$MATRIX_SERVER_IP:8008" break fi echo " ...retry $i" sleep 5 done echo "[INFO] Setting up NGINX RevPrx files" cat < /etc/nginx/sites-available/$MATRIX_DOMAIN server { listen 80; listen [::]:80; server_name $MATRIX_DOMAIN; location /.well-known/matrix/client { return 301 https://$host$request_uri; } location /.well-known/matrix/server { return 301 https://$host$request_uri; } location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name $MATRIX_DOMAIN; ssl_certificate /etc/letsencrypt/live/$MATRIX_DOMAIN/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/$MATRIX_DOMAIN/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { proxy_pass http://127.0.0.1:8008; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location /.well-known/matrix/client { default_type application/json; add_header Access-Control-Allow-Origin *; return 200 '{"m.homeserver": {"base_url": "https://$MATRIX_DOMAIN"}}'; } location /.well-known/matrix/server { default_type application/json; add_header Access-Control-Allow-Origin *; return 200 '{"m.server": "$MATRIX_DOMAIN:443"}'; } } EOF ln -s /etc/nginx/sites-available/$MATRIX_DOMAIN echo "============================================" echo " Matrix server setup finished!" echo " HomeServer: https://$MATRIX_DOMAIN:8448" echo " TURN: $TURN_DOMAIN (3478/5349)"