Files
esh-pfi-infrastructure/docs/pfi/vm-102-matrix-synapse.md
T
vh e376d0aec9 Initial commit: PFI fleet inventory, stacks, tooling, and backup pipeline
Captures the full workspace state built up to this point:

  - CLAUDE.md + README.md describing conventions and the four-host fleet
    (ana-ml2, ana-docker, nh3-docker, esh-docker-vm).
  - Per-host notes under servers/<host>/ with ssh-target fallback files
    and latest system-details snapshots (two in-compose credential leaks
    scrubbed; the upstream compose files still need to move those to .env).
  - scripts/: server_inspect.sh (read-only remote diagnostic),
    refresh-server-info.sh (dir-driven discovery + snapshot capture with
    validation warnings), add-host.sh, sync-stacks.sh (pull
    compose/conf trees), deploy-stack.sh (push with per-file diff + prompt).
  - stacks/: canonical compose for backrest, beszel, dozzle, llama-swap,
    rest-server-ana, rest-server-nh3, vllm-qwen3, plus the retired
    infinity reference. All use the .env-driven + traefik-net + homepage
    label pattern.
  - configs/restic/ana-docker/: first resticprofile config + pre-backup
    hook (Synapse pg_dump, Seafile mysqldump, Vaultwarden SQLite); templates
    for the other three hosts to come.
  - docs/pfi/: general infrastructure reference carried over.
  - .gitignore excludes .env, stacks-mirror/, and assorted secret/state
    filenames to prevent re-leaks on later commits.
2026-04-20 14:29:48 -07:00

11 KiB

id, title, summary, tags, keywords, links, created, modified, path
id title summary tags keywords links created modified path
vm-102-matrix-synapse VM 102 — Matrix Synapse Deployment Docker deployment of Synapse homeserver with PostgreSQL and Element Web on VM 102 (PFI-ANA-Docker). Covers compose file, configuration, storage paths, and admin setup.
infrastructure
pfi
pfi-ana
matrix
docker
vm-102
synapse
self-hosted
deployment
matrix.pfi.local
synapse
element-web
10.250.50.70
VM-102
PFI-ANA-Docker
postgres:16
appservice
AIPA
[Matrix Protocol Reference](../Infrastructure-PFI-Project-Index.md)
[VM-102 Proxmox Config](../../../configs/pfi-ana/proxmox/vm-102.conf)
[Docker Stack Conventions](docker-stack.md)
2026-04-11T00:00:00+00:00 2026-04-11T00:00:00+00:00 docs/pfi-ana/vm-102-matrix-synapse.md

VM 102 — Matrix Synapse Deployment

Overview

Matrix (Synapse) is deployed on VM 102 (PFI-ANA-Docker, 10.250.50.70) as the primary human-to-agent communication channel for AIPA. The stack consists of:

  • Synapse — Matrix homeserver (event routing, auth, persistence)
  • PostgreSQL 16 — Synapse database backend
  • Element Web — Web client for users

Federation is disabled (internal-only deployment). Registration is disabled (admin-created accounts only).


Architecture

User (Element client)
       │  m.room.message events
       ▼
┌──────────────────────┐
│  Synapse             │  Matrix homeserver — event routing, auth, persistence
│  (homeserver)        │  Port 8008 (Client-Server API)
└──────────┬───────────┘
           │  Appservice push  PUT /_matrix/app/v1/transactions/{txnId}
           ▼
┌──────────────────────────────────────────┐
│  AIPA Matrix Bridge  (core/matrix_bridge.py)  │
│  Port 8009                                │
└──────────────────────────────────────────┘

Full appservice bridge details: VM 102 — Matrix Appservice Configuration


Components

Component Image Port Purpose
synapse matrixdotorg/synapse:latest 8008 Matrix homeserver (Client-Server API)
synapse-db postgres:16 Synapse database
element-web vectorim/element-web:latest 8080 Web client for users

Storage Paths

Host Path Purpose
/opt/docker/compose/synapse/ Compose file (managed by Dockge)
/opt/docker/conf/synapse/ Configuration files
/opt/docker/data/synapse/ Synapse data (homeserver.yaml, signing keys, appservice reg)
/opt/docker/conf/synapse/element-config.json Element Web client config

Follows the VM 102 convention: compose in /opt/docker/compose/<service>/, config in /opt/docker/conf/<service>/.

Volumes

Volume / Path Container Path Purpose
/opt/docker/data/synapse /data Synapse config, signing keys, media store
synapse-db-data (named vol) /var/lib/postgresql/data PostgreSQL persistent data

Step 1 — Create Directory Structure

mkdir -p /opt/docker/data/synapse
mkdir -p /opt/docker/conf/synapse
mkdir -p /opt/docker/compose/synapse

Step 2 — Generate Synapse Config

docker run --rm \
  -v /opt/docker/data/synapse:/data \
  -e SYNAPSE_SERVER_NAME=matrix.pfi.local \
  -e SYNAPSE_REPORT_STATS=no \
  matrixdotorg/synapse:latest generate

This writes /opt/docker/data/synapse/homeserver.yaml and /opt/docker/data/synapse/matrix.pfi.local.signing.key.

Do not modify server_name after generation — it is permanent.


Step 3 — Edit homeserver.yaml

Open /opt/docker/data/synapse/homeserver.yaml and apply:

# Use PostgreSQL instead of SQLite (required for production)
database:
  name: psycopg2
  args:
    user: synapse
    password: synapse_db_password   # match POSTGRES_PASSWORD in compose
    database: synapse
    host: synapse-db
    cp_min: 5
    cp_max: 10

# Disable open registration — accounts are created by admin only
enable_registration: false

# Disable federation (internal deployment only)
federation_domain_whitelist: []

# Allow the application service to be registered (add AFTER generating the AS file)
app_service_config_files:
  - /data/aipa_appservice.yaml

Step 4 — Docker Compose

File: /opt/docker/compose/synapse/docker-compose.yml

---
# =============================================================================
# Synapse Matrix Homeserver — AIPA internal deployment on VM 102
# =============================================================================
#
# Conventions:
#   - Config:  /opt/docker/conf/synapse/
#   - Data:    /opt/docker/data/synapse/  (bind mount) + synapse-db-data (named vol)
#   - Compose: /opt/docker/compose/synapse/
#   - Network: synapse-net (dedicated, not on traefik-net)
#
# Notes:
#   - Federation disabled (internal only)
#   - Port 8448 (federation) commented out
#   - Resource limits set for VM 102 (8 vCPU, 16 GB RAM)

services:
  synapse-db:
    image: postgres:16
    container_name: synapse-db
    restart: unless-stopped
    environment:
      POSTGRES_USER: synapse
      POSTGRES_PASSWORD: synapse_db_password
      POSTGRES_DB: synapse
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
    volumes:
      - synapse-db-data:/var/lib/postgresql/data
    networks:
      - synapse-net
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U synapse"]
      interval: 10s
      timeout: 5s
      retries: 5

  synapse:
    image: matrixdotorg/synapse:latest
    container_name: synapse
    restart: unless-stopped
    depends_on:
      synapse-db:
        condition: service_healthy
    ports:
      - "8008:8008"   # Client-Server API (HTTP)
      # - "8448:8448" # Server-Server API (federation) — disabled for internal use
    volumes:
      - /opt/docker/data/synapse:/data
    networks:
      - synapse-net
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: "2.0"
        reservations:
          memory: 256M
    healthcheck:
      test: ["CMD-SHELL", "curl -fsS http://localhost:8008/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

  element-web:
    image: vectorim/element-web:latest
    container_name: element-web
    restart: unless-stopped
    volumes:
      - /opt/docker/conf/synapse/element-config.json:/app/config.json:ro
    ports:
      - "8080:80"
    networks:
      - synapse-net

volumes:
  synapse-db-data:

networks:
  synapse-net:
    name: synapse-net

Start

cd /opt/docker/compose/synapse
docker compose up -d

Verify

docker compose ps
curl http://localhost:8008/health

Step 5 — Element Web Configuration

File: /opt/docker/conf/synapse/element-config.json

{
    "default_server_config": {
        "m.homeserver": {
            "base_url": "http://10.250.50.70:8008",
            "server_name": "matrix.pfi.local"
        }
    },
    "brand": "AIPA",
    "default_theme": "dark",
    "disable_guests": true,
    "disable_login_language_selector": true
}

Step 6 — Create Admin User

docker exec -it synapse register_new_matrix_user \
  -u admin \
  -p 'yourpassword' \
  -a \
  http://localhost:8008

The -a flag makes the user an admin. Omit for regular users.

Agent users (@atlas, @linus, @hermione) are virtual — managed by the appservice. Do not register them as real accounts.


Port Allocation

Port Service Purpose Protocol
8008 Synapse Client-Server API HTTP
8080 Element Web Web client HTTP
8009 AIPA Bridge Appservice endpoint HTTP

See docker-stack.md for the full VM 102 port allocation table.


Network

This deployment uses a dedicated synapse-net network (not traefik-net), because:

  • Synapse is accessed directly by IP (no public domain routing needed)
  • The AIPA bridge connects to Synapse at http://localhost:8008 from the host
  • Element Web connects at the VM IP:8008 from the browser

If TLS/reverse proxy is added later, join traefik-net and add Traefik labels.


Security Notes

  • Synapse is exposed on port 8008 (HTTP). For any externally accessible deployment, put it behind a TLS-terminating reverse proxy (Traefik/nginx) and restrict 8009 to internal access only.
  • Registration is disabled (enable_registration: false) — accounts created by admin only.
  • Federation is disabled (federation_domain_whitelist: []) — internal use only.
  • The as_token and hs_token in the appservice registration are secrets equivalent to admin credentials. Store in env.sh (gitignored), never commit.

Troubleshooting

Symptom Likely Cause Fix
Bridge starts but Synapse doesn't push events Appservice URL wrong in registration YAML Verify url: is reachable from the Synapse container; check docker inspect synapse network
401 errors from Synapse as_token mismatch Verify token in aipa_appservice.yaml matches MATRIX_AS_TOKEN env var
Element can't connect to homeserver Wrong base_url in element-config.json Must be the IP/hostname Element's browser can reach, not the Docker container name
Synapse won't start Database connection failure Verify synapse-db is healthy first; check password matches in homeserver.yaml and compose

Next Steps

After Synapse is running and healthy, configure the AIPA appservice bridge: → VM 102 — Matrix Appservice Configuration


Sources

  • Source deployment guide: projects/matrix/matrix-deployment.md (2026-04-11)
  • VM 102 Proxmox config: configs/pfi-ana/proxmox/vm-102.conf
  • Docker Stack conventions: docs/pfi-ana/docker-stack.md
  • Matrix Protocol Reference: infrastructure/matrix-docker-deployment.md (KB)