From 90669b4568e482d316dc3c72c91ca618a55d6935 Mon Sep 17 00:00:00 2001 From: patrick Date: Fri, 11 Sep 2026 15:38:07 +0200 Subject: [PATCH] feat: add universal Synapse install.sh for bare-metal/Proxmox-LXC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Own installer instead of relying only on the external bashclub script: builds homeserver.yaml straight from our homeserver.yaml.sample (so it inherits TalkTime's security defaults — no federation, no public registration — automatically), sets up Postgres, a systemd service, and prints the admin token ready to paste into backend/.env. Works identically in a Proxmox LXC and on bare metal (both are just a Debian userland). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01TBf3yfnnHzMQ5qhLV2285A --- synapse/README.md | 44 ++++++--- synapse/install.sh | 221 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 253 insertions(+), 12 deletions(-) create mode 100755 synapse/install.sh diff --git a/synapse/README.md b/synapse/README.md index 1b9602f..8731fa8 100644 --- a/synapse/README.md +++ b/synapse/README.md @@ -1,14 +1,18 @@ # Synapse Setup (lokal/Server) -Minimal-Setup für einen Matrix-Synapse-Homeserver als Backend für TalkTime. Drei Installationswege — Docker (empfohlen, einfacher zu warten), Bare-Metal manuell (Debian/Ubuntu, kein Docker verfügbar/gewünscht), oder ein fertiges Autoinstaller-Skript für Proxmox-LXC. +Minimal-Setup für einen Matrix-Synapse-Homeserver als Backend für TalkTime. Installationswege: -## Option C: Autoinstaller für Proxmox-LXC +- **Option A — Docker** (empfohlen, einfacher zu warten) +- **Option B — Bare-Metal/Proxmox-LXC**, per eigenem [`install.sh`](install.sh) (universell, setzt gleich alle TalkTime-Defaults richtig) oder manuell Schritt für Schritt +- **Option C — externer Autoinstaller** ([bashclub/zamba-lxc-toolbox](https://github.com/bashclub/zamba-lxc-toolbox/tree/main/src/matrix)), falls Nginx+Element Web gleich mit dabei sein sollen -[bashclub/zamba-lxc-toolbox](https://github.com/bashclub/zamba-lxc-toolbox/tree/main/src/matrix) bringt ein fertiges `install-service.sh` für Debian-LXC mit: installiert Synapse (apt-Repo) + PostgreSQL + nginx + Element Web, stellt auf Postgres um, setzt `registration_shared_secret`, legt per `register_new_matrix_user` einen Admin-User an, generiert Self-Signed-TLS. +## Option C: Externer Autoinstaller (bashclub/zamba-lxc-toolbox) -Praktisch als Schnellstart, wenn ein Proxmox-LXC zur Verfügung steht und Nginx+Element gleich mit dabei sein sollen. Skript vor Ausführung selbst prüfen (Repo-README/`zamba.conf` lesen) — nicht ungeprüft als root laufen lassen. Nach Lauf trotzdem `SYNAPSE_ADMIN_TOKEN` wie in Schritt 7/8 unten beschrieben ziehen und in TalkTime eintragen; `enable_registration` danach auf `false` setzen, da TalkTime die Benutzeranlage selbst übernimmt (siehe Schritt 5). +Alternative zu `install.sh`, wenn zusätzlich Nginx+Element Web (eigenständiger Matrix-Webclient, nicht Teil von TalkTime) gleich mit installiert werden sollen. `install-service.sh` installiert Synapse (apt-Repo) + PostgreSQL + nginx + Element Web, stellt auf Postgres um, setzt `registration_shared_secret`, legt per `register_new_matrix_user` einen Admin-User an, generiert Self-Signed-TLS. -Für volle Kontrolle (kein extra nginx/Element, schlankeres Setup) weiter mit Option A oder B unten. +Skript vor Ausführung selbst prüfen (Repo-README/`zamba.conf` lesen) — nicht ungeprüft als root laufen lassen. Nach Lauf trotzdem `SYNAPSE_ADMIN_TOKEN` wie in Option B "Admin-Zugang" beschrieben ziehen und in TalkTime eintragen; `enable_registration` danach auf `false` setzen, da TalkTime die Benutzeranlage selbst übernimmt. + +Für ein schlankeres Setup ohne extra Nginx/Element: `install.sh` in Option B unten. ## Voraussetzungen (beide Varianten) @@ -97,9 +101,25 @@ Das zurückgegebene `access_token` in `backend/.env` als `SYNAPSE_ADMIN_TOKEN` e --- -## Option B: Bare-Metal (Debian/Ubuntu, kein Docker) +## Option B: Bare-Metal (Debian/Ubuntu oder Proxmox-LXC, kein Docker) -### 1. Systempakete + venv +### Schnellweg: `install.sh` + +Eigener, universeller Installer — macht alle Schritte unten automatisch inklusive TalkTime-Sicherheits-Defaults (Registrierung/Föderation aus, eigene Secrets, Systemd-Service, Admin-User+Token): + +```bash +sudo ./synapse/install.sh chat.example.org +``` + +Läuft identisch in einem Proxmox-LXC (Debian-Template) und auf echtem Bare-Metal — beides ist aus Sicht des Skripts nur ein Debian-Userland mit `apt-get`. Am Ende gibt es `SYNAPSE_BASE_URL`/`SYNAPSE_ADMIN_TOKEN`/`SYNAPSE_SERVER_NAME` fix und fertig zum Eintragen in `backend/.env` aus. + +Optionale Env-Vars: `INSTALL_DIR` (default `/opt/synapse`), `DB_PASSWORD`, `ADMIN_USER`, `ADMIN_PASSWORD` (sonst zufällig generiert), `SYNAPSE_PORT` (default 8008). Nutzt `homeserver.yaml.sample` aus diesem Ordner als Vorlage — bei Änderungen an der Vorlage (siehe oben) übernimmt der Installer sie automatisch. + +Danach direkt weiter zu **"Reverse Proxy + TLS"** unten. + +### Manuell, Schritt für Schritt (falls `install.sh` nicht passt, z. B. anderer Linux-Flavor) + +#### 1. Systempakete + venv ```bash sudo apt update @@ -113,7 +133,7 @@ sudo -u postgres createdb -O synapse synapse -E UTF8 --locale=C --template=templ `-P` fragt beim Anlegen nach dem Passwort für den `synapse`-DB-User. -### 2. Synapse installieren +#### 2. Synapse installieren ```bash sudo mkdir -p /opt/synapse @@ -123,7 +143,7 @@ python3 -m venv /opt/synapse/venv /opt/synapse/venv/bin/pip install "matrix-synapse[postgres]" ``` -### 3. Konfiguration generieren +#### 3. Konfiguration generieren ```bash cd /opt/synapse @@ -136,11 +156,11 @@ cd /opt/synapse Erzeugt `homeserver.yaml` + Signing-Key im aktuellen Verzeichnis. -### 4. Datenbank umstellen, Registrierung absichern +#### 4. Datenbank umstellen, Registrierung absichern Wie Option A, Abschnitt 4 — [`homeserver.yaml.sample`](homeserver.yaml.sample) nach `/opt/synapse/homeserver.yaml` kopieren und Platzhalter ersetzen, nur `database.args.host: localhost` statt `synapse-db`. -### 5. Als systemd-Dienst starten +#### 5. Als systemd-Dienst starten ```ini # /etc/systemd/system/matrix-synapse.service @@ -172,7 +192,7 @@ Health-Check: curl http://localhost:8008/health ``` -### 6. Admin-Zugang für TalkTime einrichten +#### 6. Admin-Zugang für TalkTime einrichten ```bash /opt/synapse/venv/bin/register_new_matrix_user \ diff --git a/synapse/install.sh b/synapse/install.sh new file mode 100755 index 0000000..bc0f1db --- /dev/null +++ b/synapse/install.sh @@ -0,0 +1,221 @@ +#!/usr/bin/env bash +# Universal Synapse installer for TalkTime — Debian/Ubuntu, works in a Proxmox +# LXC or on bare metal identically (both are just a Debian userland). +# +# What it does, in order: +# 1. Install system packages + PostgreSQL +# 2. Create a dedicated Postgres role/database for Synapse +# 3. Install matrix-synapse into a venv (pip, not apt — works on any +# Debian/Ubuntu version without depending on the matrix.org apt repo) +# 4. Generate homeserver.yaml from synapse/homeserver.yaml.sample with all +# secrets filled in and TalkTime's secure defaults (registration off, +# federation off) +# 5. Install + start a systemd service +# 6. Create the admin user and fetch its access token +# +# Usage: +# sudo ./install.sh chat.example.org +# sudo SYNAPSE_SERVER_NAME=chat.example.org ADMIN_USER=admin ./install.sh +# +# Idempotent-ish: re-running skips steps whose result already exists +# (venv, database, service file) but always re-registers nothing — the +# admin user is only created once (step 6 fails loudly if it already exists, +# that's fine, just note the token from the first run). + +set -euo pipefail + +# ---- config (env vars override) -------------------------------------------- +SERVER_NAME="${1:-${SYNAPSE_SERVER_NAME:-}}" +INSTALL_DIR="${INSTALL_DIR:-/opt/synapse}" +SYNAPSE_USER="${SYNAPSE_USER:-synapse}" +DB_NAME="${DB_NAME:-synapse}" +DB_USER="${DB_USER:-synapse}" +DB_PASSWORD="${DB_PASSWORD:-$(openssl rand -hex 24)}" +ADMIN_USER="${ADMIN_USER:-admin}" +ADMIN_PASSWORD="${ADMIN_PASSWORD:-$(openssl rand -hex 16)}" +SYNAPSE_PORT="${SYNAPSE_PORT:-8008}" + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" + +if [[ -z "$SERVER_NAME" ]]; then + echo "Usage: $0 (e.g. chat.example.org)" >&2 + echo "Or set SYNAPSE_SERVER_NAME=... as an env var." >&2 + exit 1 +fi + +if [[ $EUID -ne 0 ]]; then + echo "Must run as root (sudo $0 ...)." >&2 + exit 1 +fi + +if ! command -v apt-get &>/dev/null; then + echo "This installer only supports Debian/Ubuntu (apt-get not found)." >&2 + exit 1 +fi + +log() { echo -e "\n== $* =="; } + +# ---- 1. system packages ----------------------------------------------------- +log "Installing system packages" +export DEBIAN_FRONTEND=noninteractive +apt-get update -qq +apt-get install -y -qq \ + python3-dev python3-pip python3-venv \ + libpq-dev build-essential libffi-dev libssl-dev libjpeg-dev libxslt1-dev \ + postgresql openssl >/dev/null + +# ---- 2. postgres role + database ------------------------------------------- +log "Setting up PostgreSQL database" +if ! sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='${DB_USER}'" | grep -q 1; then + sudo -u postgres psql -c "CREATE ROLE ${DB_USER} WITH LOGIN PASSWORD '${DB_PASSWORD}';" >/dev/null +else + echo "Role ${DB_USER} already exists, updating password." + sudo -u postgres psql -c "ALTER ROLE ${DB_USER} WITH PASSWORD '${DB_PASSWORD}';" >/dev/null +fi + +if ! sudo -u postgres psql -tAc "SELECT 1 FROM pg_database WHERE datname='${DB_NAME}'" | grep -q 1; then + sudo -u postgres createdb -O "${DB_USER}" "${DB_NAME}" -E UTF8 --locale=C --template=template0 +else + echo "Database ${DB_NAME} already exists, reusing." +fi + +# ---- 3. synapse into a venv -------------------------------------------------- +log "Installing matrix-synapse (this can take a few minutes)" +mkdir -p "${INSTALL_DIR}" +if ! id "${SYNAPSE_USER}" &>/dev/null; then + useradd -r -d "${INSTALL_DIR}" -s /usr/sbin/nologin "${SYNAPSE_USER}" +fi + +if [[ ! -d "${INSTALL_DIR}/venv" ]]; then + python3 -m venv "${INSTALL_DIR}/venv" +fi +"${INSTALL_DIR}/venv/bin/pip" install --upgrade pip -q +"${INSTALL_DIR}/venv/bin/pip" install -q "matrix-synapse[postgres]" + +# ---- 4. homeserver.yaml from our template ----------------------------------- +log "Writing homeserver.yaml" +if [[ ! -f "${INSTALL_DIR}/${SERVER_NAME}.signing.key" ]]; then + "${INSTALL_DIR}/venv/bin/python" -m synapse.app.homeserver \ + --server-name="${SERVER_NAME}" \ + --config-path="${INSTALL_DIR}/homeserver.generated.yaml" \ + --generate-config \ + --report-stats=no \ + --data-directory="${INSTALL_DIR}" >/dev/null + rm -f "${INSTALL_DIR}/homeserver.generated.yaml" "${INSTALL_DIR}/${SERVER_NAME}.log.config.generated" +fi + +REGISTRATION_SECRET="$(openssl rand -hex 32)" +MACAROON_SECRET="$(openssl rand -hex 32)" +FORM_SECRET="$(openssl rand -hex 32)" + +sed \ + -e "s||${SERVER_NAME}|g" \ + -e "s||${DB_PASSWORD}|g" \ + -e "s||PLACEHOLDER|g" \ + -e "s|/data/|${INSTALL_DIR}/|g" \ + -e "s|host: synapse-db|host: localhost|g" \ + -e "s|user: synapse|user: ${DB_USER}|g" \ + -e "s|database: synapse|database: ${DB_NAME}|g" \ + "${SCRIPT_DIR}/homeserver.yaml.sample" > "${INSTALL_DIR}/homeserver.yaml" + +mkdir -p "${INSTALL_DIR}/media_store" + +# Replace the three PLACEHOLDER secrets one at a time so each gets its own value. +python3 - "$INSTALL_DIR/homeserver.yaml" "$REGISTRATION_SECRET" "$MACAROON_SECRET" "$FORM_SECRET" <<'PYEOF' +import sys +path, reg, mac, form = sys.argv[1:5] +with open(path) as f: + content = f.read() +for value in (reg, mac, form): + content = content.replace("PLACEHOLDER", value, 1) +with open(path, "w") as f: + f.write(content) +PYEOF + +# Also write log config referenced by our template (Synapse needs the file to exist). +cat > "${INSTALL_DIR}/${SERVER_NAME}.log.config" < /etc/systemd/system/matrix-synapse.service </dev/null 2>&1; then + break + fi + sleep 1 +done +if ! curl -fs "http://localhost:${SYNAPSE_PORT}/health" >/dev/null 2>&1; then + echo "Synapse did not come up in time — check: journalctl -u matrix-synapse -e" >&2 + exit 1 +fi + +# ---- 6. admin user + access token ------------------------------------------- +log "Creating admin user" +"${INSTALL_DIR}/venv/bin/register_new_matrix_user" \ + -c "${INSTALL_DIR}/homeserver.yaml" \ + -u "${ADMIN_USER}" -p "${ADMIN_PASSWORD}" -a \ + "http://localhost:${SYNAPSE_PORT}" + +ADMIN_TOKEN="$(curl -fs -XPOST "http://localhost:${SYNAPSE_PORT}/_matrix/client/v3/login" \ + -d "{\"type\":\"m.login.password\",\"user\":\"${ADMIN_USER}\",\"password\":\"${ADMIN_PASSWORD}\"}" \ + | python3 -c 'import sys,json; print(json.load(sys.stdin)["access_token"])')" + +cat <