I spent the end of February turning Matrix from a rough idea into a real stack layout.

The main goal was not just "run Synapse." It was to run it in the same style as the rest of my infrastructure:

  • one Unix user per app stack,
  • rootless containers,
  • a reverse-proxy chain instead of direct public exposure,
  • and a clear split between static config and runtime state.

The Shape I Wanted

The stack had five main parts:

  • Synapse as the homeserver,
  • Postgres as the database,
  • coturn for TURN,
  • a backend NGINX layer for the app-facing HTTP flow,
  • and a TLS sidecar in front of that backend.

I also wanted the external routing to match the pattern I already used elsewhere:

  • public edge proxy first,
  • internal environment proxy second,
  • application stack behind that,
  • and loopback-bound internal entry points wherever possible.

Why I Did Not Want A Flat Compose File

A simple one-container or two-container setup would have been faster.

But for long-term operations it would have mixed too many concerns:

  • public routing,
  • internal TLS,
  • Synapse config,
  • TURN exposure,
  • and database persistence.

Once those concerns are separated, the stack becomes easier to reason about:

  • proxy issues stay proxy issues,
  • app issues stay app issues,
  • and the files on disk line up with the service boundaries.

The Practical Layout

The directory structure mattered almost as much as the containers:

  • one directory for backend proxy config,
  • one for Synapse data,
  • one for TURN config,
  • one for TLS material,
  • one for logs,
  • and one for persistent database data.

That sounds boring, but it is the difference between a stack you can recover and a stack you can only remember.

What Turned Out To Matter Most

The best early decision was keeping the stack under its own Unix user.

That gave me:

  • cleaner file ownership,
  • less accidental secret sharing,
  • easier Vault integration later,
  • and a more obvious mental model for what belongs to Matrix and what does not.

The whole thing stopped feeling like "a service running somewhere" and started feeling like a defined application boundary.

That was the right foundation for everything that came after: Vault integration, MatrixRTC, MAS, and backup work.