#!/usr/bin/env bash # Deploy/update the self-hosted Matrix stack (Synapse + Postgres + Element). # Idempotent: renders homeserver.yaml from the committed template, ensures # correct data-dir ownership, and starts containers. # # Secrets are read from an install-dir .env (written by jeannie deploy_matrix), # NOT from the repo. The signing key is created by Synapse on first boot. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ENV_FILE="${MATRIX_ENV_FILE:-${SCRIPT_DIR}/.env}" if [[ ! -f "${ENV_FILE}" ]]; then echo "Missing secret env file ${ENV_FILE}. Run jeannie deploy-matrix first." >&2 exit 1 fi set -a # shellcheck disable=SC1090 . "${ENV_FILE}" set +a MATRIX_SERVER_NAME="${MATRIX_SERVER_NAME:-matrix.lab2025.duckdns.org}" MATRIX_POSTGRES_DB="${MATRIX_POSTGRES_DB:-synapse}" MATRIX_POSTGRES_USER="${MATRIX_POSTGRES_USER:-synapse}" SYNAPSE_UID="${MATRIX_SYNAPSE_UID:-991}" POSTGRES_UID="${MATRIX_POSTGRES_UID:-70}" render_homeserver() { local tpl="${SCRIPT_DIR}/homeserver.yaml.tpl" local out="${SCRIPT_DIR}/synapse-data/homeserver.yaml" for var in MATRIX_SERVER_NAME MATRIX_POSTGRES_DB MATRIX_POSTGRES_USER \ MATRIX_POSTGRES_PASSWORD MATRIX_REGISTRATION_SHARED_SECRET \ MATRIX_MACAROON_SECRET_KEY MATRIX_FORM_SECRET; do if [[ -z "${!var:-}" ]]; then echo "Missing required secret/env ${var}" >&2 exit 1 fi done # shellcheck disable=SC2016 envsubst \ '${MATRIX_SERVER_NAME} ${MATRIX_POSTGRES_DB} ${MATRIX_POSTGRES_USER} ${MATRIX_POSTGRES_PASSWORD} ${MATRIX_REGISTRATION_SHARED_SECRET} ${MATRIX_MACAROON_SECRET_KEY} ${MATRIX_FORM_SECRET}' \ <"${tpl}" >"${out}" cp "${SCRIPT_DIR}/log_config.yaml" "${SCRIPT_DIR}/synapse-data/${MATRIX_SERVER_NAME}.log.config" } sudo mkdir -p "${SCRIPT_DIR}/synapse-data" "${SCRIPT_DIR}/postgres-data" # First boot: generate signing key + log config (the files a hand-written # homeserver.yaml would not provide). Without this Synapse fails to boot on a # missing signing key. Only touches the data dir (not postgres). if [[ ! -f "${SCRIPT_DIR}/synapse-data/${MATRIX_SERVER_NAME}.signing.key" ]]; then echo "First boot: generating Synapse signing key + log config..." docker compose --env-file "${ENV_FILE}" -f "${SCRIPT_DIR}/docker-compose.yml" \ run --rm --no-deps synapse generate --config-path /data/homeserver.yaml fi render_homeserver # Ownership foot-gun: wrong uid prevents boot (synapse 991, postgres 70). sudo chown -R "${SYNAPSE_UID}:${SYNAPSE_UID}" "${SCRIPT_DIR}/synapse-data" sudo chown -R "${POSTGRES_UID}:${POSTGRES_UID}" "${SCRIPT_DIR}/postgres-data" docker compose --env-file "${ENV_FILE}" -f "${SCRIPT_DIR}/docker-compose.yml" up -d echo "Matrix stack up:" echo " Synapse http://127.0.0.1:${MATRIX_SYNAPSE_PORT:-8008}" echo " Element http://127.0.0.1:${MATRIX_ELEMENT_PORT:-8081}" echo " server_name ${MATRIX_SERVER_NAME}" cat <<'EOF' Next: register users (hermes bot, and any humans) via the shared-secret CLI: docker exec -u 991 matrix-synapse register_new_matrix_user -c /data/homeserver.yaml -u NAME -p PASS [--no-admin] EOF