No description
  • Shell 96%
  • Makefile 4%
Find a file
2026-06-02 23:54:49 +02:00
config refactor: move docker-compose.yml to config/template, not tracked 2026-06-02 23:34:06 +02:00
landing update .gitignore 2026-06-02 22:41:43 +02:00
scripts feat: clean target, setup banner, docker-compose as template, LiveKit voip stack 2026-06-02 23:50:48 +02:00
.gitignore refactor: move docker-compose.yml to config/template, not tracked 2026-06-02 23:34:06 +02:00
Makefile feat: clean target, setup banner, docker-compose as template, LiveKit voip stack 2026-06-02 23:50:48 +02:00
README.md Initial Matrix stack setup 20260426-1437 2026-05-21 17:39:43 +02:00
setup.sh Initial Matrix stack setup 20260426-1437 2026-05-21 17:39:43 +02:00

Matrix Stack

Self-hosted Matrix homeserver stack based on Synapse, with Cinny web client, Ketesa admin UI, and a multilingual landing page.

The server name (which determines Matrix user IDs) can be set up in two ways:

  • Root domaindomain.tld → users are @user:domain.tld (recommended)
  • Subdomainsub.domain.tld → users are @user:sub.domain.tld

The setup script detects subdomain input and guides through the options interactively.

Components

Service Description Default Port
Synapse Matrix homeserver 8008
PostgreSQL Database for Synapse internal
Cinny Web-based Matrix client 8009
Ketesa Matrix admin UI 8010
Landing Static landing page (nginx) 8080

Prerequisites

System packages

Package Purpose
make Run Makefile targets
docker Container runtime
docker compose Multi-container orchestration
python3 Config file patching during setup
curl Health checks

Debian/Ubuntu:

sudo apt update && sudo apt install -y make curl python3

Alpine:

apk add make curl python3

Docker (all distros): Follow the official guide: https://docs.docker.com/engine/install/

DNS

Users will be @user:domain.tld. All A-Records point to the server IP:

Record Type Value
domain.tld A <server IP>
matrix.domain.tld A <server IP>
cinny.domain.tld A <server IP>
ketesa.domain.tld A <server IP>

Option B: Subdomain setup

Users will be @user:sub.domain.tld. The .well-known delegation must be served from the webroot of sub.domain.tld.

Record Type Value
sub.domain.tld A <server IP>
matrix.sub.domain.tld A <server IP>
cinny.sub.domain.tld A <server IP>
ketesa.sub.domain.tld A <server IP>

Or with services under the root domain:

Record Type Value
sub.domain.tld A <server IP>
matrix.domain.tld A <server IP>
cinny.domain.tld A <server IP>
ketesa.domain.tld A <server IP>

Reverse Proxy (NPM)

Nginx Proxy Manager must be running and ports 80/443 must be open. Proxy hosts are configured after setup -- see NPM Setup below.


Quick Start

# 1. Check prerequisites and launch menu
./setup.sh

# 2. Full interactive setup (first time)
make generate

# 3. Start the stack
make up

# 4. Create admin user
make admin

File Structure

matrix/
├── setup.sh                    # Prerequisite check + make launcher
├── Makefile                    # All management targets
├── docker-compose.yml          # Stack definition
├── .env                        # Generated secrets (do not commit)
├── scripts/
│   ├── generate.sh             # Full interactive setup
│   ├── smtp.sh                 # SMTP config helper
│   └── admin.sh                # Create admin user
├── config/
│   ├── setup.conf              # All settings (generated, do not commit)
│   ├── smtpserver.conf         # SMTP credentials (generated, do not commit)
│   ├── smtpserver.conf.sample  # SMTP template (safe to commit)
│   ├── cinny/config.json       # Cinny web client config
│   └── ketesa/config.json      # Ketesa admin UI config
├── landing/
│   └── index.html              # Multilingual landing page (DE/EN)
└── data/
    ├── postgres/               # PostgreSQL data volume
    └── synapse/                # Synapse data + homeserver.yaml

Make Targets

make                  Show this help
make generate         Full first-time interactive setup
make smtp             Add or update SMTP configuration
make up               Start all containers
make down             Stop all containers
make restart          Restart all containers
make update           Pull latest images and restart
make logs             Follow all container logs
make logs-synapse     Follow Synapse logs only
make status           Show container status
make admin            Create a Matrix admin user
make shell-synapse    Shell into Synapse container
make shell-postgres   PostgreSQL shell

NPM Setup

After make up, configure the following proxy hosts in Nginx Proxy Manager:

Domain Forward to Port SSL
yourdomain.tld localhost 8080 Let's Encrypt
matrix.yourdomain.tld localhost 8008 Let's Encrypt
cinny.yourdomain.tld localhost 8009 Let's Encrypt
ketesa.yourdomain.tld localhost 8010 Let's Encrypt

well-known delegation (on yourdomain.tld proxy host)

Add two Custom Locations:

/.well-known/matrix/server

default_type application/json;
return 200 '{"m.server":"matrix.yourdomain.tld:443"}';
add_header Access-Control-Allow-Origin *;

/.well-known/matrix/client

default_type application/json;
return 200 '{"m.homeserver":{"base_url":"https://matrix.yourdomain.tld"},"m.identity_server":{"base_url":"https://vector.im"}}';
add_header Access-Control-Allow-Origin *;

Security Notes

  • config/setup.conf and config/smtpserver.conf contain plaintext passwords
  • Both files are chmod 600 and must not be committed to Git
  • .env must not be committed to Git
  • See .gitignore for the full exclusion list

Federation

Federation is active by default. Verify with:

curl https://yourdomain.tld/.well-known/matrix/server
# Expected: {"m.server":"matrix.yourdomain.tld:443"}

Online tester: https://federationtester.matrix.org/


Password Reset

Password reset via email requires SMTP configuration. Run make smtp to configure, or set it up during make generate.

Users can reset their password via the Cinny web client login page, or an admin can reset it via Ketesa.


Updates

make update

Pulls latest images for all services and restarts the stack.