378 lines
10 KiB
Bash
Executable File
378 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
# =============================================================================
|
|
# Matrix Synapse + Element Web Bare-Metal Install Script
|
|
# For Ubuntu 24.04 LTS
|
|
# =============================================================================
|
|
# Usage:
|
|
# export DOMAIN="mx.example.com"
|
|
# export ADMIN_USER="admin"
|
|
# export ADMIN_EMAIL="admin@example.com"
|
|
# curl -sSL https://git.vish.gg/Vish/matrix-element/raw/branch/main/install-baremetal.sh | bash
|
|
#
|
|
# Run as root on a fresh Ubuntu 24.04 VM
|
|
# =============================================================================
|
|
|
|
set -e
|
|
|
|
# Configuration
|
|
DOMAIN="${DOMAIN:-mx.example.com}"
|
|
ADMIN_USER="${ADMIN_USER:-admin}"
|
|
ADMIN_EMAIL="${ADMIN_EMAIL:-admin@example.com}"
|
|
TURN_DOMAIN="${TURN_DOMAIN:-$DOMAIN}"
|
|
TURN_PORT="${TURN_PORT:-3479}"
|
|
TURN_TLS_PORT="${TURN_TLS_PORT:-5350}"
|
|
TURN_MIN_PORT="${TURN_MIN_PORT:-49201}"
|
|
TURN_MAX_PORT="${TURN_MAX_PORT:-49250}"
|
|
ELEMENT_VERSION="${ELEMENT_VERSION:-v1.12.8}"
|
|
LISTEN_PORT="${LISTEN_PORT:-8080}"
|
|
|
|
echo "=========================================="
|
|
echo "Matrix Synapse + Element Web Installer"
|
|
echo "=========================================="
|
|
echo "Domain: $DOMAIN"
|
|
echo "Admin: $ADMIN_USER"
|
|
echo "=========================================="
|
|
|
|
# Check root
|
|
if [[ $EUID -ne 0 ]]; then
|
|
echo "This script must be run as root"
|
|
exit 1
|
|
fi
|
|
|
|
# Update system
|
|
echo "[1/10] Updating system..."
|
|
apt update && apt upgrade -y
|
|
|
|
# Install dependencies
|
|
echo "[2/10] Installing dependencies..."
|
|
apt install -y postgresql postgresql-contrib nginx coturn \
|
|
python3-pip python3-venv python3-dev build-essential \
|
|
libffi-dev libssl-dev libjpeg-dev libxslt1-dev \
|
|
curl wget git jq
|
|
|
|
# Create synapse user
|
|
echo "[3/10] Creating synapse user..."
|
|
useradd -r -m -d /opt/synapse -s /bin/bash synapse 2>/dev/null || true
|
|
mkdir -p /opt/synapse /opt/element
|
|
chown synapse:synapse /opt/synapse
|
|
|
|
# Setup PostgreSQL
|
|
echo "[4/10] Setting up PostgreSQL..."
|
|
DB_PASS="REDACTED_PASSWORD" rand -hex 16)
|
|
sudo -u postgres psql -c "CREATE USER synapse WITH PASSWORD 'REDACTED_PASSWORD';" 2>/dev/null || \
|
|
sudo -u postgres psql -c "ALTER USER synapse WITH PASSWORD 'REDACTED_PASSWORD';"
|
|
sudo -u postgres psql -c "CREATE DATABASE synapse ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' template=template0 OWNER synapse;" 2>/dev/null || true
|
|
|
|
# Install Synapse
|
|
echo "[5/10] Installing Synapse..."
|
|
sudo -u synapse bash << SYNAPSE_INSTALL
|
|
cd /opt/synapse
|
|
python3 -m venv venv
|
|
source venv/bin/activate
|
|
pip install --upgrade pip setuptools wheel
|
|
pip install matrix-synapse psycopg2-binary lxml 'prometheus-client<0.21'
|
|
SYNAPSE_INSTALL
|
|
|
|
# Generate config
|
|
echo "[6/10] Generating Synapse configuration..."
|
|
cd /opt/synapse
|
|
sudo -u synapse /opt/synapse/venv/bin/python -m synapse.app.homeserver \
|
|
--server-name "$DOMAIN" \
|
|
--config-path homeserver.yaml \
|
|
--generate-config \
|
|
--report-stats=no
|
|
|
|
# Get generated secrets
|
|
REG_SECRET=$(grep 'registration_shared_secret' homeserver.yaml | head -1 | awk '{print $2}')
|
|
MAC_SECRET=$(grep 'macaroon_secret_key' homeserver.yaml | head -1 | awk '{print $2}')
|
|
FORM_SECRET=$(grep 'form_secret' homeserver.yaml | head -1 | awk '{print $2}')
|
|
TURN_SECRET=$(openssl rand -hex 32)
|
|
|
|
# Create production config
|
|
cat > /opt/synapse/homeserver.yaml << YAML
|
|
server_name: "$DOMAIN"
|
|
pid_file: /opt/synapse/homeserver.pid
|
|
public_baseurl: https://$DOMAIN/
|
|
|
|
listeners:
|
|
- port: 8008
|
|
tls: false
|
|
type: http
|
|
x_forwarded: true
|
|
resources:
|
|
- names: [client, federation]
|
|
compress: false
|
|
|
|
database:
|
|
name: psycopg2
|
|
args:
|
|
user: synapse
|
|
password: "REDACTED_PASSWORD"
|
|
database: synapse
|
|
host: localhost
|
|
cp_min: 5
|
|
cp_max: 10
|
|
|
|
log_config: "/opt/synapse/$DOMAIN.log.config"
|
|
media_store_path: /opt/synapse/media_store
|
|
signing_key_path: "/opt/synapse/$DOMAIN.signing.key"
|
|
trusted_key_servers:
|
|
- server_name: "matrix.org"
|
|
|
|
registration_shared_secret: $REG_SECRET
|
|
macaroon_secret_key: $MAC_SECRET
|
|
form_secret: $FORM_SECRET
|
|
|
|
enable_registration: false
|
|
enable_registration_without_verification: false
|
|
|
|
turn_uris:
|
|
- "turn:$TURN_DOMAIN:$TURN_PORT?transport=udp"
|
|
- "turn:$TURN_DOMAIN:$TURN_PORT?transport=tcp"
|
|
- "turns:$TURN_DOMAIN:$TURN_TLS_PORT?transport=udp"
|
|
- "turns:$TURN_DOMAIN:$TURN_TLS_PORT?transport=tcp"
|
|
turn_shared_secret: "$TURN_SECRET"
|
|
turn_user_lifetime: 86400000
|
|
turn_allow_guests: true
|
|
|
|
max_upload_size: 100M
|
|
url_preview_enabled: true
|
|
url_preview_ip_range_blacklist:
|
|
- '127.0.0.0/8'
|
|
- '10.0.0.0/8'
|
|
- '172.16.0.0/12'
|
|
- '192.168.0.0/16'
|
|
- '100.64.0.0/10'
|
|
- '169.254.0.0/16'
|
|
- '::1/128'
|
|
- 'fe80::/64'
|
|
- 'fc00::/7'
|
|
|
|
suppress_key_server_warning: true
|
|
enable_metrics: false
|
|
report_stats: false
|
|
YAML
|
|
|
|
# Validate YAML configuration
|
|
echo "Validating Synapse configuration..."
|
|
python3 -c "import yaml; yaml.safe_load(open('/opt/synapse/homeserver.yaml'))" || {
|
|
echo "ERROR: Invalid YAML in homeserver.yaml"
|
|
exit 1
|
|
}
|
|
|
|
mkdir -p /opt/synapse/media_store
|
|
chown -R synapse:synapse /opt/synapse
|
|
|
|
# Configure coturn
|
|
echo "[7/10] Configuring TURN server..."
|
|
cat > /etc/turnserver.conf << TURN
|
|
listening-port=$TURN_PORT
|
|
tls-listening-port=$TURN_TLS_PORT
|
|
fingerprint
|
|
use-auth-secret
|
|
static-auth-secret=$TURN_SECRET
|
|
realm=$DOMAIN
|
|
total-quota=100
|
|
bps-capacity=0
|
|
stale-nonce=600
|
|
no-multicast-peers
|
|
min-port=$TURN_MIN_PORT
|
|
max-port=$TURN_MAX_PORT
|
|
log-file=/var/log/turnserver.log
|
|
TURN
|
|
|
|
# Download Element Web
|
|
echo "[8/10] Installing Element Web..."
|
|
cd /opt/element
|
|
wget -q "https://github.com/element-hq/element-web/releases/download/$ELEMENT_VERSION/element-$ELEMENT_VERSION.tar.gz"
|
|
tar xzf "element-$ELEMENT_VERSION.tar.gz"
|
|
mv "element-$ELEMENT_VERSION" web
|
|
rm "element-$ELEMENT_VERSION.tar.gz"
|
|
|
|
cat > /opt/element/web/config.json << ELEMENT
|
|
{
|
|
"default_server_config": {
|
|
"m.homeserver": {
|
|
"base_url": "https://$DOMAIN",
|
|
"server_name": "$DOMAIN"
|
|
}
|
|
},
|
|
"disable_guests": true,
|
|
"default_theme": "dark",
|
|
"room_directory": {
|
|
"servers": ["matrix.org", "$DOMAIN"]
|
|
}
|
|
}
|
|
ELEMENT
|
|
|
|
# Configure nginx
|
|
echo "[9/10] Configuring nginx..."
|
|
cat > /etc/nginx/sites-available/matrix << NGINX
|
|
server {
|
|
listen $LISTEN_PORT;
|
|
listen [::]:$LISTEN_PORT;
|
|
server_name $DOMAIN;
|
|
|
|
root /opt/element/web;
|
|
index index.html;
|
|
|
|
location ~ ^(/_matrix|/_synapse/client) {
|
|
proxy_pass http://127.0.0.1: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 100M;
|
|
proxy_http_version 1.1;
|
|
}
|
|
|
|
location /_matrix/federation {
|
|
proxy_pass http://127.0.0.1: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 100M;
|
|
}
|
|
|
|
location /.well-known/matrix/server {
|
|
default_type application/json;
|
|
return 200 '{"m.server": "$DOMAIN:443"}';
|
|
}
|
|
|
|
location /.well-known/matrix/client {
|
|
default_type application/json;
|
|
add_header Access-Control-Allow-Origin *;
|
|
return 200 '{"m.homeserver": {"base_url": "https://$DOMAIN"}}';
|
|
}
|
|
|
|
location / {
|
|
try_files \$uri \$uri/ /index.html;
|
|
}
|
|
}
|
|
NGINX
|
|
|
|
ln -sf /etc/nginx/sites-available/matrix /etc/nginx/sites-enabled/matrix
|
|
rm -f /etc/nginx/sites-enabled/default
|
|
nginx -t
|
|
|
|
# Create systemd service
|
|
cat > /etc/systemd/system/synapse.service << SERVICE
|
|
[Unit]
|
|
Description=Synapse Matrix Homeserver
|
|
After=network.target postgresql.service
|
|
|
|
[Service]
|
|
Type=notify
|
|
User=synapse
|
|
Group=synapse
|
|
WorkingDirectory=/opt/synapse
|
|
ExecStart=/opt/synapse/venv/bin/python -m synapse.app.homeserver --config-path=/opt/synapse/homeserver.yaml
|
|
ExecReload=/bin/kill -HUP \$MAINPID
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
SERVICE
|
|
|
|
# Start services
|
|
echo "[10/10] Starting services..."
|
|
systemctl daemon-reload
|
|
systemctl enable --now postgresql nginx coturn synapse
|
|
|
|
# Create admin user
|
|
sleep 3
|
|
ADMIN_PASS="REDACTED_PASSWORD" rand -hex 12)
|
|
cd /opt/synapse
|
|
sudo -u synapse /opt/synapse/venv/bin/register_new_matrix_user \
|
|
-c homeserver.yaml \
|
|
-u "$ADMIN_USER" \
|
|
-p "$ADMIN_PASS" \
|
|
-a \
|
|
http://localhost:8008
|
|
|
|
# Save secrets
|
|
cat > /root/.matrix_secrets << SECRETS
|
|
DOMAIN=$DOMAIN
|
|
DB_PASS="REDACTED_PASSWORD"
|
|
TURN_SECRET=$TURN_SECRET
|
|
ADMIN_USER=$ADMIN_USER
|
|
ADMIN_PASS="REDACTED_PASSWORD"
|
|
SECRETS
|
|
chmod 600 /root/.matrix_secrets
|
|
|
|
# Download helper scripts
|
|
echo "Downloading helper scripts..."
|
|
REPO_BASE="https://git.vish.gg/Vish/matrix-element/raw/branch/main"
|
|
mkdir -p /opt/matrix-scripts
|
|
for script in verify-matrix.sh fix-matrix.sh backup-matrix.sh update-matrix.sh; do
|
|
curl -sSL "$REPO_BASE/$script" -o "/opt/matrix-scripts/$script" 2>/dev/null || true
|
|
chmod +x "/opt/matrix-scripts/$script" 2>/dev/null || true
|
|
done
|
|
echo "Helper scripts installed to /opt/matrix-scripts/"
|
|
|
|
# Verify installation
|
|
echo ""
|
|
echo "Verifying installation..."
|
|
sleep 2
|
|
|
|
VERIFY_FAILED=0
|
|
|
|
# Check services
|
|
for svc in synapse nginx coturn postgresql; do
|
|
if systemctl is-active --quiet $svc; then
|
|
echo "✓ $svc is running"
|
|
else
|
|
echo "✗ $svc is NOT running"
|
|
VERIFY_FAILED=1
|
|
fi
|
|
done
|
|
|
|
# Check Matrix API
|
|
if curl -sf http://localhost:8008/_matrix/client/versions > /dev/null; then
|
|
echo "✓ Matrix API responding"
|
|
else
|
|
echo "✗ Matrix API not responding"
|
|
VERIFY_FAILED=1
|
|
fi
|
|
|
|
# Check Element Web
|
|
if curl -sf http://localhost:$LISTEN_PORT/ > /dev/null; then
|
|
echo "✓ Element Web accessible"
|
|
else
|
|
echo "✗ Element Web not accessible"
|
|
VERIFY_FAILED=1
|
|
fi
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
if [ $VERIFY_FAILED -eq 0 ]; then
|
|
echo "✅ Matrix Installation Complete!"
|
|
else
|
|
echo "⚠️ Installation complete with warnings"
|
|
fi
|
|
echo "=========================================="
|
|
echo ""
|
|
echo "Domain: $DOMAIN"
|
|
echo "Admin User: @$ADMIN_USER:$DOMAIN"
|
|
echo "Admin Password: "REDACTED_PASSWORD"
|
|
echo ""
|
|
echo "Listening on port $LISTEN_PORT (HTTP)"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo "1. Configure reverse proxy: HTTPS:443 → HTTP:$LISTEN_PORT"
|
|
echo "2. Forward TURN ports: $TURN_PORT, $TURN_TLS_PORT, $TURN_MIN_PORT-$TURN_MAX_PORT"
|
|
echo "3. Login at https://$DOMAIN and change password"
|
|
echo ""
|
|
echo "Secrets saved to /root/.matrix_secrets"
|
|
echo ""
|
|
echo "Helper scripts installed to /opt/matrix-scripts/"
|
|
echo " ./verify-matrix.sh - Check installation health"
|
|
echo " ./fix-matrix.sh - Diagnose and fix issues"
|
|
echo " ./backup-matrix.sh - Create full backup"
|
|
echo " ./update-matrix.sh - Update Synapse and Element"
|
|
echo ""
|
|
echo "Useful commands:"
|
|
echo " systemctl status synapse nginx coturn"
|
|
echo " journalctl -u synapse -f"
|
|
echo " curl http://localhost:8008/_matrix/client/versions"
|