Upstream docs: https://element-hq.github.io/synapse/latest
Everything not listed in this document should behave the same as upstream Synapse. If a feature, setting, or behavior is not mentioned here, the upstream documentation is accurate and fully applicable.
Synapse is the battle-tested, reference implementation of the Matrix protocol -- a next-generation, federated, full-featured, encrypted, independent messaging system.
- Image and Container Runtime
- Volume and Data Layout
- Installation and First-Run Flow
- Configuration Management
- Network Access and Interfaces
- Actions (StartOS UI)
- Backups and Restore
- Health Checks
- Dependencies
- Limitations and Differences
- What Is Unchanged from Upstream
- Contributing
- Quick Reference for AI Consumers
| Property | Value |
|---|---|
| Synapse image | ghcr.io/element-hq/synapse (upstream pre-built image) |
| Nginx image | nginx Alpine (upstream unmodified) |
| PostgreSQL image | postgres Alpine (database sidecar) |
| Architectures | x86_64, aarch64 |
Synapse runs behind an Nginx reverse proxy. Nginx handles client requests on port 80, proxies Matrix API traffic to Synapse on port 8008, and serves the Synapse Admin dashboard on port 8080.
| Volume | Mount Point | Purpose |
|---|---|---|
main |
/data |
Synapse config, media, keys, appservices, StartOS state |
db |
/var/lib/postgresql |
PostgreSQL data |
Key files on the main volume:
homeserver.yaml-- primary Synapse configuration (managed by StartOS)homeserver.signing.key-- server signing key (auto-generated by Synapse)homeserver.log.config-- logging configurationmedia_store/-- uploaded media filesstore.json-- StartOS metadata (admin state, postgres password, SMTP config)appservices/*.yaml-- registered bridge/appservice configurations
| Step | Upstream | StartOS |
|---|---|---|
| Generate config | python -m synapse.app.homeserver --generate-config |
Automatic via setupOnInit |
| Set server name | Edit homeserver.yaml |
"Set Server Address/URL" action (critical task) |
| Create admin user | register_new_matrix_user CLI |
"Set Admin Password" action (critical task) -- generates a password; the actual user is registered when the service first starts |
Key difference: On first install, StartOS generates the initial Synapse config automatically. You must run the "Set Server Address/URL" action (created as a critical task) to choose your permanent domain before starting. Completing it surfaces "Set Admin Password" as a second critical task; running that generates and shows the credentials. Starting the service then registers the admin user with the chosen password.
Warning: The server address/URL is permanent and cannot be changed after the first start.
| Setting | Upstream Method | StartOS Method |
|---|---|---|
server_name |
homeserver.yaml |
"Set Server Address/URL" action (one-time) |
enable_registration |
homeserver.yaml |
"Config" action |
| Federation | homeserver.yaml listeners |
"Config" action (enable/disable + domain whitelist) |
max_upload_size |
homeserver.yaml |
"Config" action (1-2000 MB) |
| SMTP/email | homeserver.yaml |
"Config" action (disabled/system/custom) |
| Admin password | register_new_matrix_user |
"Set Admin Password" action |
| Appservices | Manual YAML files | Register/List/Delete Appservice actions |
Configuration NOT exposed on StartOS:
log_config-- fixed logging configurationdatabase-- always PostgreSQL via sidecar containertrusted_key_servers-- defaults tomatrix.orgreport_stats-- always disabled- Listener bind addresses and ports
| Interface | Port | Protocol | Type | Purpose |
|---|---|---|---|---|
| Homeserver | 80 (nginx) | HTTP | API | Matrix client and federation API |
| Admin Dashboard | 8080 (nginx) | HTTP | UI | Synapse Admin web interface |
Internally, Synapse listens on port 8008. Nginx proxies traffic from port 80, handles .well-known/matrix/server responses, and enforces max_upload_size on Matrix API routes.
| Property | Value |
|---|---|
| ID | set-server-name |
| Visibility | Hidden after first start |
| Availability | Only when stopped |
| Purpose | Choose permanent server domain (clearnet or Tor) |
Presents available hostnames from the homeserver interface. Sets server_name and public_baseurl in homeserver.yaml. Cannot be changed after first start.
| Property | Value |
|---|---|
| ID | set-admin-password |
| Visibility | Enabled |
| Availability | Any status |
| Purpose | Set or reset the admin account password |
Generates a random 22-character password, stores it in store.json as pendingAdminPassword, and displays it. The next time the service starts, an apply-admin-password oneshot in the daemon chain consumes the pending password: if no users exist in PostgreSQL it runs register_new_matrix_user to create the admin; otherwise it hashes the password with hash_password and UPDATEs the first-registered user's password_hash. The pending field is cleared on success.
| Property | Value |
|---|---|
| ID | config |
| Visibility | Enabled |
| Availability | Any status |
| Purpose | Configure registration, federation, upload limits, SMTP |
Settings:
| Setting | Default | Description |
|---|---|---|
| Registration | Disabled | Allow public account creation |
| Federation | Disabled | Enable/disable with optional domain whitelist |
| Max Upload Size | 50 MB | File upload limit (1-2000 MB) |
| SMTP | Disabled | Email notifications (disabled/system/custom) |
| Property | Value |
|---|---|
| ID | register-appservice |
| Visibility | Enabled |
| Availability | Any status |
| Purpose | Register a Matrix bridge with the homeserver |
Accepts appservice credentials (ID, tokens, URL, namespace regex) and writes the registration YAML. Typically triggered automatically by bridge services via the exported ensureAppserviceRegistration API.
| Property | Value |
|---|---|
| ID | list-appservices |
| Visibility | Enabled |
| Availability | Any status |
| Purpose | View all registered bridges |
| Property | Value |
|---|---|
| ID | delete-appservice |
| Visibility | Enabled |
| Availability | Any status |
| Purpose | Remove a registered bridge |
| Property | Value |
|---|---|
| ID | create-bot-user |
| Visibility | Hidden |
| Availability | Only when running |
| Purpose | Create non-admin bot accounts for bridge services |
Included in backup:
mainvolume -- Synapse config, media, keys, appservice registrations, StartOS statedbvolume -- PostgreSQL database (backed up viapg_dump, restored viapg_restore)
Restore behavior:
- All data, users, rooms, and settings are restored
- Server name, keys, and admin credentials remain the same
| Check | Method | Grace Period | Display |
|---|---|---|---|
| Database | pg_isready |
Default | "Database" |
| Homeserver | HTTP GET http://localhost:8008/health |
15 seconds | "Homeserver" |
| Nginx | Port listening on 80 | Default | Hidden |
| Admin Dashboard | HTTP GET http://localhost:8080 |
Default | "Admin Dashboard" |
None.
- Server name is permanent -- once set and started, the server address/URL cannot be changed
- Admin username fixed -- always
admin; only password can be changed - No workers -- runs as a single monolith process (no worker-based scaling)
- Fixed logging -- log configuration is not user-configurable (INFO level, 100 MB rotation)
- No direct
homeserver.yamlediting -- configuration is managed through StartOS actions - Tor federation limitations --
.onionservers can only federate with other.onionservers
- Full Matrix protocol compliance (client-server and server-server APIs)
- End-to-end encryption support
- Federation (when enabled)
- Room creation, membership, and permissions
- Media uploads and downloads
- Push notifications
- Account data and device management
- Presence and typing indicators
- All Matrix client compatibility (Element, FluffyChat, etc.)
See CONTRIBUTING.md for build instructions and development workflow.
package_id: synapse
images:
synapse: dockerTag (ghcr.io/element-hq/synapse)
nginx: nginx (Alpine)
postgres: postgres (Alpine)
architectures: [x86_64, aarch64]
volumes:
main: /data
db: /var/lib/postgresql
ports:
homeserver: 80 (nginx proxy to synapse:8008)
admin: 8080 (synapse-admin dashboard)
dependencies: none
database: PostgreSQL (sidecar, localhost-only, password auth)
startos_managed_config:
- server_name (one-time, permanent)
- enable_registration
- federation (listeners + domain whitelist)
- max_upload_size
- smtp
actions:
- set-server-name (enabled/hidden, only-stopped)
- set-admin-password (enabled, any)
- config (enabled, any)
- register-appservice (enabled, any)
- list-appservices (enabled, any)
- delete-appservice (enabled, any)
- create-bot-user (hidden, only-running)
health_checks:
- pg_isready (postgres)
- http_get: /health (port 8008, 15s grace)
- port_listening: 80
- http_get: / (port 8080)
backup_method: pg_dump + main volume
public_api:
- ensureAppserviceRegistration (for bridge services)