#!/bin/bash set -euo pipefail DOMAIN=$1 if [ -z ${DOMAIN} ]; then echo "Script usage: ./install.sh " return 1 fi BASE_DIR=/opt/matrix # Create directory and copy configs + docker-compose YAML mkdir -p ${BASE_DIR}/db cp -R . ${BASE_DIR} cd ${BASE_DIR} # Disable "Pending Kernel upgrade" banner sed -i "s|#\$nrconf{kernelhints} = -1;|\$nrconf{kernelhints} = -1;|g" /etc/needrestart/needrestart.conf # Disable "Daemon Using Outdated Libraries" banner sed -i "s|#\$nrconf{restart} = 'i';|\$nrconf{restart} = 'a';|g" /etc/needrestart/needrestart.conf # Baseline utils echo -e "Installing baseline utils\n" apt update apt upgrade -y apt install -y ca-certificates curl pwgen nginx python3-certbot-nginx ufw coturn # Open only needed ports echo -e "Opening ports and enabling ufw\n" # SSH ufw allow 22/tcp # Nginx (HTTP/HTTPS) ufw allow 80/tcp ufw allow 443/tcp ufw allow 8448/tcp # Coturn Ports ufw allow 3478/udp ufw allow 5443/udp ufw allow 49152:65535/udp # Enable firewall ufw --force enable # Configure Coturn TURN server echo -e "Install and configure coturn server\n" echo "TURNSERVER_ENABLED=1" > /etc/default/coturn cp config/turnserver.conf /etc/ TURN_PWD=$(pwgen -s 28 -1) TURN_STATIC_SECRET=$(pwgen -s 64 1) EXTERNAL_IP=$(curl -s checkip.amazonaws.com) sed -i "s|DOMAIN|${DOMAIN}|g" /etc/turnserver.conf sed -i "s|TURN_PWD|${TURN_PWD}|g" /etc/turnserver.conf sed -i "s|EXTERNAL_IP|${EXTERNAL_IP}|g" /etc/turnserver.conf sed -i "s|STATIC_SECRET|${TURN_STATIC_SECRET}|g" /etc/turnserver.conf # Custom coturn SystemD service file to allow coturn access to Letsencrypt SSL certs cp "${BASE_DIR}/coturn.service" /lib/systemd/system/coturn.service systemctl daemon-reload # Add Docker's official GPG key echo -e "Install docker\n" install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc # Add the repository to APT sources echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "${VERSION_CODENAME}") stable" | \ tee /etc/apt/sources.list.d/docker.list > /dev/null apt update # Install docker apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # Create docker network `matrix_server` echo -e "Create docker network\n" docker network create --driver=bridge --subnet=10.10.10.0/24 --gateway=10.10.10.1 matrix_server # Randomly pick a DB password PG_PASS=$(pwgen -s 28 -1) # Replace PG_PASS Password and DOMAIN in docker compose YAML sed -i "s|DOMAIN|${DOMAIN}|g" "${BASE_DIR}/docker-compose.yaml" sed -i "s|PG_PASS|${PG_PASS}|g" "${BASE_DIR}/docker-compose.yaml" # Generate synapse file echo -e "Generating synapse file..\n" docker compose run --rm -e SYNAPSE_SERVER_NAME=${DOMAIN} -e SYNAPSE_REPORT_STATS=yes synapse generate # Replace DB config in Synapse's homeserver.yaml echo -e "Configuring homeserver.yaml\n" # Granting all read permissions to cert files chmod 444 ${BASE_DIR}/config/synapse/${DOMAIN}.* # Config homeserver.yaml sed -i '$ d' "${BASE_DIR}/config/synapse/homeserver.yaml" sed -e '22r homeserver.yaml.db' -e '22,25d' "${BASE_DIR}/config/synapse/homeserver.yaml" > /tmp/homeserver.yaml cp /tmp/homeserver.yaml "${BASE_DIR}/config/synapse/homeserver.yaml" # Configure User Directory and TURN cat <> "${BASE_DIR}/config/synapse/homeserver.yaml" user_directory: enabled: true search_all_users: true prefer_local_users: true show_locked_users: true turn_allow_guests: False turn_user_lifetime: 86400000 turn_shared_secret: "${TURN_STATIC_SECRET}" turn_uris: [ "turn:${DOMAIN}?transport=udp" ] suppress_key_server_warning: true EOF # Replace Password in homeserver.yaml sed -i "s|PG_PASS|${PG_PASS}|g" "${BASE_DIR}/config/synapse/homeserver.yaml" # Replace Sliding Sync key SLIDING_SYNC_KEY=$(openssl rand -hex 32) sed -i "s|SLIDING_SYNC_KEY|${SLIDING_SYNC_KEY}|g" "${BASE_DIR}/docker-compose.yaml" # Replace domain in element config sed -i "s|DOMAIN|${DOMAIN}|g" "${BASE_DIR}/config/element/element-config.json" # Copy SystemD file and start the service echo -e "Setting up SystemD service\n" cp "${BASE_DIR}/matrix.service" /etc/systemd/system/ systemctl daemon-reload systemctl enable --now matrix.service # Configure Nginx echo -e "Configuring nginx\n" cat < /etc/nginx/sites-enabled/default server { listen 80; server_name ${DOMAIN}; location /.well-known/matrix/client { default_type application/json; add_header Access-Control-Allow-Origin *; return 200 '{"m.homeserver": {"base_url": "https://${DOMAIN}"}, "org.matrix.msc3575.proxy": {"url": "https://${DOMAIN}"}}'; } # Admin panel location /admin/ { proxy_pass http://10.10.10.6/; proxy_set_header X-Forwarded-For \$remote_addr; proxy_set_header X-Forwarded-Proto \$scheme; proxy_set_header Host \$host; proxy_http_version 1.1; } # Sydent identity server location ~ ^(/_matrix/identity) { proxy_pass http://10.10.10.5:8090; proxy_set_header X-Forwarded-For \$remote_addr; proxy_set_header X-Forwarded-Proto \$scheme; proxy_set_header Host \$host; proxy_http_version 1.1; } # Sliding Sync location ~ ^/(client/|_matrix/client/unstable/org.matrix.msc3575/sync) { proxy_pass http://10.10.10.7:8008; proxy_set_header X-Forwarded-For \$remote_addr; proxy_set_header X-Forwarded-Proto \$scheme; proxy_set_header Host \$host; } # Synapse Backend location ~ ^(\/_matrix|\/_synapse\/(client|admin)) { # Synapse Container Network IP proxy_pass http://10.10.10.4:8008; proxy_set_header X-Forwarded-For \$remote_addr; proxy_set_header X-Forwarded-Proto \$scheme; proxy_set_header Host \$host; client_max_body_size 50M; proxy_http_version 1.1; } # Element Frontend location / { # Element chat Container Network IP proxy_pass http://10.10.10.3; proxy_set_header X-Forwarded-For \$remote_addr; proxy_set_header X-Forwarded-Proto \$scheme; proxy_set_header Host \$host; # Nginx by default only allows file uploads up to 1M in size # Increase client_max_body_size to match max_upload_size defined in homeserver.yaml client_max_body_size 50M; # Synapse responses may be chunked, which is an HTTP/1.1 feature. proxy_http_version 1.1; } } EOF systemctl restart nginx systemctl enable --now nginx echo -e "Generate SSL cert\n" certbot --nginx -d ${DOMAIN} --agree-tos --register-unsafely-without-email # Add certbot SSL cert renewal to crontab crontab -l | { cat; echo '43 6 * * * certbot renew --post-hook "systemctl reload nginx"'; } | crontab - # Add custom 8448 SSL port for Matrix Federation sed -i '/listen\ 443\ ssl/a\\tlisten\ 8448\ ssl\;' /etc/nginx/sites-enabled/default nginx -s reload # Enable coturn systemctl enable --now coturn # Finally, start services # Ensuring the DB dir is clean before bootstrapping systemctl enable --now matrix.service