Files
hermes-agent/docs/synapse-deployment.md
Alexander Whitestone cc9d7705b6
Some checks failed
Forge CI / smoke-and-build (pull_request) Failing after 1m1s
feat(synapse): Matrix Phase 1 — Synapse homeserver deployment stack
Deploy Synapse on Ezra VPS with PostgreSQL backend, bot registration,
and management tooling.

Closes #272

Components:
- docker-compose.yml: Synapse + PostgreSQL 16 stack
- homeserver.yaml: Production config (registration disabled, rate limits, retention)
- setup.sh: One-shot deploy (generates secrets, starts stack, registers accounts, gets bot token)
- manage.sh: Day-to-day ops (status, restart, logs, backup, update, create-user, teardown)
- docs/synapse-deployment.md: Full deployment guide with Nginx TLS, DNS, troubleshooting

Security:
- Registration disabled by default
- Rate limiting on login/registration/messages
- Client API bound to localhost (Nginx proxy for public access)
- Secrets chmod 600, .gitignore'd
- Federation certificate verification enabled

Bot account auto-registered and access token acquired — credentials
written to synapse-credentials.env for hermes-agent integration.
2026-04-13 18:07:15 -04:00

7.6 KiB

Synapse Homeserver Deployment Guide

Matrix Phase 1: Deploy Synapse on Ezra VPS

Part of Epic #269: Matrix Integration — Sovereign Messaging for Timmy.

Architecture

┌─────────────────────────────────────────────────┐
│ Ezra VPS (143.198.27.163)                       │
│                                                 │
│  ┌──────────┐     ┌─────────────────────────┐   │
│  │  Nginx   │────▶│ Synapse (Docker)        │   │
│  │ :443→8008│     │ Client API: localhost:8008│  │
│  │ :8448→8448│    │ Federation: 0.0.0.0:8448│   │
│  └──────────┘     └──────────┬──────────────┘   │
│                              │                   │
│                     ┌────────▼──────────┐        │
│                     │ PostgreSQL 16     │        │
│                     │ (Docker volume)   │        │
│                     └───────────────────┘        │
│                                                 │
│  ┌──────────────────────────────────────────┐   │
│  │ hermes-agent (gateway)                   │   │
│  │ MATRIX_HOMESERVER=http://localhost:8008   │   │
│  └──────────────────────────────────────────┘   │
└─────────────────────────────────────────────────┘

Prerequisites

  • Docker + Docker Compose plugin on Ezra VPS
  • SSH access: ssh root@143.198.27.163
  • DNS A record pointing to the VPS IP
  • (Recommended) Nginx + Certbot for TLS termination

Quick Start

# SSH into Ezra
ssh root@143.198.27.163

# Clone hermes-agent (if not present)
cd /root
git clone https://forge.alexanderwhitestone.com/Timmy_Foundation/hermes-agent.git
cd hermes-agent/deploy/synapse

# Deploy Synapse
chmod +x setup.sh
./setup.sh matrix.timmy-time.xyz

# This will:
#   1. Generate .env with database password
#   2. Prepare homeserver.yaml
#   3. Start Synapse + PostgreSQL via Docker Compose
#   4. Wait for health
#   5. Register admin + bot accounts
#   6. Acquire bot access token
#   7. Write synapse-credentials.env

Step-by-Step

1. DNS Configuration

Point your Matrix domain to Ezra's IP:

Type  Name    Value
A     matrix  143.198.27.163

Federation uses SRV records for port discovery, but direct :8448 works without them.

2. Deploy Synapse

cd /root/hermes-agent/deploy/synapse
./setup.sh matrix.timmy-time.xyz hermes-bot 'your-secure-password'

Arguments:

Arg Default Description
server_name (required) Matrix domain (e.g., matrix.timmy-time.xyz)
admin_user timmy-admin Admin account username
admin_password (random) Admin account password
bot_user hermes-bot Bot account username
bot_password (random) Bot account password

3. TLS Termination (Nginx)

Install Nginx + Certbot:

apt install -y nginx certbot python3-certbot-nginx

# Client-server API
cat > /etc/nginx/sites-available/matrix <<'EOF'
server {
    listen 443 ssl http2;
    server_name matrix.timmy-time.xyz;

    ssl_certificate /etc/letsencrypt/live/matrix.timmy-time.xyz/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/matrix.timmy-time.xyz/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8008;
        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;
        client_max_body_size 50M;
    }
}

server {
    listen 8448 ssl http2;
    server_name matrix.timmy-time.xyz;

    ssl_certificate /etc/letsencrypt/live/matrix.timmy-time.xyz/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/matrix.timmy-time.xyz/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8008;
        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;
    }
}
EOF

ln -sf /etc/nginx/sites-available/matrix /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

# Get cert
certbot --nginx -d matrix.timmy-time.xyz

4. Wire Hermes Agent

Copy the generated credentials to hermes-agent's environment:

# From synapse-credentials.env, add to ~/.hermes/.env:
MATRIX_HOMESERVER=https://matrix.timmy-time.xyz
MATRIX_ACCESS_TOKEN=<from synapse-credentials.env>
MATRIX_USER_ID=@hermes-bot:matrix.timmy-time.xyz
MATRIX_DEVICE_ID=<from synapse-credentials.env>
MATRIX_ENCRYPTION=true

Then start the gateway:

hermes gateway --platform matrix

5. Verify

# Check Synapse health
curl -s https://matrix.timmy-time.xyz/_matrix/client/versions

# Check federation
curl -s https://matrix.timmy-time.xyz:8448/_matrix/federation/v1/version

# Check bot is connected
# (should appear online in Element or any Matrix client)

Management

Use the management script for day-to-day operations:

cd /root/hermes-agent/deploy/synapse

./manage.sh status        # container health
./manage.sh logs          # tail logs
./manage.sh restart       # restart Synapse
./manage.sh backup        # backup DB + data
./manage.sh update        # pull latest image
./manage.sh create-user alice 'password123'
./manage.sh create-user admin 'secret' admin

Backups

./manage.sh backup
# Creates: backups/YYYYMMDD_HHMMSS/
#   ├── synapse_db.sql       (PostgreSQL dump)
#   └── synapse_data.tar.gz  (media store + keys)

Automate with cron:

# Daily backup at 3 AM
0 3 * * * cd /root/hermes-agent/deploy/synapse && ./manage.sh backup >> /var/log/synapse-backup.log 2>&1

Troubleshooting

Synapse won't start

docker compose logs synapse
# Common: PostgreSQL not ready. Wait for healthcheck.

Bot can't connect

# Verify token is valid
curl -H "Authorization: Bearer $MATRIX_ACCESS_TOKEN" \
  https://matrix.timmy-time.xyz/_matrix/client/v3/account/whoami

Federation not working

# Check port 8448 is open
ss -tlnp | grep 8448
# Check firewall
ufw status

High memory usage

# Check resource limits in docker-compose.yml
docker stats synapse
# Tune in homeserver.yaml: event_cache_size, caches

Security Notes

  • Registration is disabled by default (enable_registration: false)
  • Rate limiting is enforced on login, registration, and messages
  • Federation certificate verification is enabled
  • .env and synapse-credentials.env are chmod 600
  • Client API binds to 127.0.0.1 only (use Nginx for public access)
  • Consider: firewall rules, fail2ban, regular backups

References