Files
homelab-optimized/hosts/vms/matrix-ubuntu-vm/docs/MATRIX.md
Gitea Mirror Bot cd1988a21b
Some checks failed
Documentation / Deploy to GitHub Pages (push) Has been cancelled
Documentation / Build Docusaurus (push) Has been cancelled
Sanitized mirror from private repository - 2026-04-05 09:28:04 UTC
2026-04-05 09:28:04 +00:00

10 KiB

Matrix Synapse Setup

This VM runs two Matrix Synapse instances:

Instance server_name Domain Federation Purpose
Primary mx.vish.gg https://mx.vish.gg Yes Main server with federation
Legacy vish https://matrix.thevish.io No Historical data archive

Architecture

                         Internet
                            │
                   ┌────────┴────────┐
                   │   Cloudflare    │
                   └────────┬────────┘
                            │
              ┌─────────────┴─────────────┐
              │                           │
              ▼                           ▼
    ┌─────────────────┐         ┌─────────────────┐
    │  mx.vish.gg     │         │ matrix.thevish.io│
    │  (port 443)     │         │  (port 443)      │
    └────────┬────────┘         └────────┬─────────┘
             │                           │
             ▼                           ▼
    ┌─────────────────┐         ┌─────────────────┐
    │ Synology Reverse│         │ Synology Reverse│
    │ Proxy → :8082   │         │ Proxy → :8081   │
    └────────┬────────┘         └────────┬─────────┘
             │                           │
             └───────────┬───────────────┘
                         │
                         ▼
              ┌─────────────────────────────────────┐
              │        Ubuntu VM (192.168.0.154)    │
              │  ┌──────────────┐ ┌──────────────┐  │
              │  │ Nginx :8082  │ │ Nginx :8081  │  │
              │  │ mx.vish.gg   │ │ thevish.io   │  │
              │  └──────┬───────┘ └──────┬───────┘  │
              │         │                │          │
              │         ▼                ▼          │
              │  ┌──────────────┐ ┌──────────────┐  │
              │  │ Synapse:8018 │ │ Synapse:8008 │  │
              │  │ mx.vish.gg   │ │ vish         │  │
              │  └──────┬───────┘ └──────┬───────┘  │
              │         │                │          │
              │         ▼                ▼          │
              │  ┌──────────────┐ ┌──────────────┐  │
              │  │ synapse_mx   │ │ synapse      │  │
              │  │ PostgreSQL   │ │ PostgreSQL   │  │
              │  └──────────────┘ └──────────────┘  │
              └─────────────────────────────────────┘

Primary Server: mx.vish.gg

This is the main server with federation enabled.

Configuration

  • Location: /opt/synapse-mx/
  • Config: /opt/synapse-mx/homeserver.yaml
  • Signing Key: /opt/synapse-mx/mx.vish.gg.signing.key
  • Media Store: /opt/synapse-mx/media_store/
  • Database: synapse_mx (user: synapse_mx)
  • Port: 8018 (Synapse) → 8082 (Nginx)

User IDs

Users on this server have IDs like: @username:mx.vish.gg

Federation

  • Can communicate with matrix.org and other federated servers
  • Can join public rooms on other servers
  • Other users can find and message your users

Managing the Service

sudo systemctl start synapse-mx
sudo systemctl stop synapse-mx
sudo systemctl restart synapse-mx
sudo systemctl status synapse-mx

Service file: /etc/systemd/system/synapse-mx.service

Legacy Server: vish (matrix.thevish.io)

This server contains historical data and cannot federate.

Why No Federation?

The server_name is vish which is not a valid domain. Other Matrix servers cannot discover it because:

  • No DNS record for vish
  • Cannot serve .well-known at https://vish/

Configuration

  • Location: /opt/synapse/
  • Config: /opt/synapse/homeserver.yaml
  • Signing Key: /opt/synapse/vish.signing.key
  • Media Store: /opt/synapse/media_store/
  • Database: synapse (user: synapse)
  • Port: 8008 (Synapse) → 8081 (Nginx)

User IDs

Users on this server have IDs like: @username:vish

Managing the Service

sudo systemctl start synapse
sudo systemctl stop synapse
sudo systemctl restart synapse
sudo systemctl status synapse

Service file: /etc/systemd/system/synapse.service

TURN Server (coturn)

TURN server enables voice/video calls to work through NAT.

Configuration

  • Config: /etc/turnserver.conf
  • Ports: 3479 (TURN), 5350 (TURNS), 49201-49250 (Media relay UDP)
  • Realm: matrix.thevish.io
  • Auth Secret: Shared with Synapse (turn_shared_secret)

Key Settings

listening-port=3479
tls-listening-port=5350
listening-ip=0.0.0.0
external-ip=YOUR_WAN_IP/192.168.0.154
static-auth-secret=<shared-secret>
realm=matrix.thevish.io
min-port=49201
max-port=49250

Port Forwarding Required

Port Protocol Purpose
3479 TCP/UDP TURN
5350 TCP/UDP TURNS (TLS)
49201-49250 UDP Media relay

Element Web

Element Web is served by Nginx for both instances.

mx.vish.gg

matrix.thevish.io

Nginx Configuration

mx.vish.gg (port 8082)

Location: /etc/nginx/sites-available/mx-vish-gg

server {
    listen 8082;
    server_name mx.vish.gg;
    root /opt/element/web;

    location /health { proxy_pass http://127.0.0.1:8018; }
    location ~ ^(/_matrix|/_synapse/client) { proxy_pass http://127.0.0.1:8018; }
    location /_matrix/federation { proxy_pass http://127.0.0.1:8018; }
    location /.well-known/matrix/server { return 200 '{"m.server": "mx.vish.gg:443"}'; }
    location /.well-known/matrix/client { return 200 '{"m.homeserver": {"base_url": "https://mx.vish.gg"}}'; }
    location / { try_files $uri $uri/ /index.html; }
}

matrix.thevish.io (port 8081)

Location: /etc/nginx/sites-available/matrix-thevish

server {
    listen 8081;
    server_name matrix.thevish.io;
    root /opt/element/web-thevish;

    location /health { proxy_pass http://127.0.0.1:8008; }
    location ~ ^(/_matrix|/_synapse/client) { proxy_pass http://127.0.0.1:8008; }
    location /.well-known/matrix/server { return 200 '{"m.server": "matrix.thevish.io:443"}'; }
    location /.well-known/matrix/client { return 200 '{"m.homeserver": {"base_url": "https://matrix.thevish.io"}}'; }
    location / { try_files $uri $uri/ /index.html; }
}

Synology Reverse Proxy

Name Source (HTTPS) Destination (HTTP)
mx_vish_gg mx.vish.gg:443 192.168.0.154:8082
matrix_thevish matrix.thevish.io:443 192.168.0.154:8081

Cloudflare DNS

Type Name Content Proxy
A mx.vish.gg YOUR_WAN_IP Proxied
A matrix.thevish.io YOUR_WAN_IP Proxied

Database Backup

Backup mx.vish.gg

sudo -u postgres pg_dump -Fc synapse_mx > synapse_mx_backup_$(date +%Y%m%d).dump

Backup legacy vish

sudo -u postgres pg_dump -Fc synapse > synapse_vish_backup_$(date +%Y%m%d).dump

Restore

sudo -u postgres pg_restore -d <database_name> <backup_file.dump>

Testing Federation

Use the Matrix Federation Tester:

curl -s "https://federationtester.matrix.org/api/report?server_name=mx.vish.gg" | python3 -c "
import sys, json
d = json.load(sys.stdin)
print(f'Federation OK: {d.get(\"FederationOK\", False)}')
"

Creating Users

Via registration (if enabled)

Go to https://mx.vish.gg and click "Create account"

Via command line

cd /opt/synapse-mx
sudo -u synapse /opt/synapse/venv/bin/register_new_matrix_user \
  -c /opt/synapse-mx/homeserver.yaml \
  -u <username> -p <password> -a

Troubleshooting

Check if Synapse is running

sudo systemctl status synapse synapse-mx
curl -s http://localhost:8008/_synapse/admin/v1/server_version  # legacy
curl -s http://localhost:8018/_synapse/admin/v1/server_version  # mx

View logs

sudo journalctl -u synapse -f      # mx.vish.gg
sudo journalctl -u synapse-mx -f   # legacy vish

Test health endpoints

curl http://localhost:8018/health  # mx.vish.gg
curl http://localhost:8008/health  # legacy vish

Restart nginx

sudo nginx -t && sudo systemctl reload nginx

DB ownership fix (apply if migrations fail on upgrade)

If Synapse fails to start after upgrade with InsufficientPrivilege: must be owner of table, the DB tables need their ownership corrected. Run for the affected database:

# For synapse (legacy) DB:
sudo -u postgres psql synapse -t -c "
  SELECT 'ALTER TABLE public.' || tablename || ' OWNER TO synapse;'
  FROM pg_tables WHERE schemaname='public' AND tableowner <> 'synapse';
" | sudo -u postgres psql synapse

sudo -u postgres psql synapse -t -c "
  SELECT 'ALTER SEQUENCE ' || sequence_name || ' OWNER TO synapse;'
  FROM information_schema.sequences WHERE sequence_schema='public';
" | sudo -u postgres psql synapse

# For synapse_mx DB, replace 'synapse' with 'synapse_mx' throughout