DC Coms started with a simple idea: I wanted a small, private communications service I could host and control myself. Building a browser that can send a message was not the hard part. The work was everything around it: Matrix identity, encryption state, account recovery, TLS, PostgreSQL, service isolation, backups, storage growth, and a deployment process someone else could reproduce on a clean server.
That changed how I treated the project. By the time Community V1 was ready, the release looked much more like infrastructure than a web application. It had a defined operating system target, Podman containers under systemd, nginx as the only external application entry point, SELinux left enforcing, generated secrets, explicit backup state, health checks, and a clean-host release gate. The current general-availability build is DC Coms Community 1.0.1, released September 23, 2026.[1][2]
Matrix gave me the protocol. I still had to build the service.
DC Coms uses Matrix Synapse as the homeserver and a React browser client built on the Matrix JavaScript SDK. Matrix already provides the protocol and end-to-end encryption model. Matrix documents Olm and Megolm as the cryptographic ratchets used for end-to-end encrypted communication.[3]
That removed a problem I had no interest in inventing myself, but it did not remove the infrastructure work. A usable private service still needs a server identity, TLS termination, account provisioning, persistent database state, Matrix media, encryption and recovery state in the clients, service accounts, backup handling, monitoring, and an administrative path that does not require opening Synapse itself to the network.
Documented DC Coms sets Synapse to enable encryption by default for all locally created rooms. Synapse documents that encryption_enabled_by_default_for_room_type: all applies end-to-end encryption to locally created rooms unless a valid client-supplied encryption event takes precedence.[4] The browser client then has to handle the user-facing parts of encrypted operation, including device/session state, encrypted attachments, and security recovery.
The public interface is intentionally small
The deployed traffic path is simple on purpose. Clients connect to nginx over HTTPS on TCP 443. nginx serves the DC Coms frontend and reverse proxies Matrix client requests to Synapse. The Synapse process listens on port 8008 inside its container, but the Podman Quadlet publishes that port only to 127.0.0.1:8008 on the host. The room-administration API, password-reset API, and DC Ops collector follow the same localhost-only model on ports 8010, 8011, and 8012.[1][5]
PostgreSQL is not published as a host service. It sits on the DC Coms Podman network and is consumed by Synapse. Reminder Bot and DC Ops participate in Matrix as ordinary users, while the dedicated password-reset identity has the Synapse administrator role required for controlled password operations. Human administrative room deletion uses the logged-in administrator's Matrix authorization rather than a second long-lived Matrix admin identity in the room-delete service.[5][6]
Architecture point I wanted one obvious network entry point and a short list of reasons for anything else to exist. A support API that only nginx needs does not benefit from a LAN-facing socket. Keeping those services on loopback narrows what the firewall and the rest of the network ever see.
Private has to be expressed in configuration
A self-hosted service is not private because it happens to run on your hardware. The application and host configuration still have to close paths you do not intend to use.
DC Coms disables public Matrix registration and guest access. Synapse documents both controls directly, including that disabled public registration does not prevent controlled account creation through administrative mechanisms.[4] DC Coms also disables public room-list search and configures an empty room-list publication rule set, so rooms are not published into a server directory. URL previews are disabled as well. Synapse notes that its URL preview feature causes the homeserver to fetch URLs and requires explicit network protections when enabled.[4]
Documented Community V1 is also deliberately non-federating. Its Synapse template sets federation_domain_whitelist: [], which Synapse documents as the recommended way to disable federation, and the configured listener serves the Matrix client API rather than a federation listener. DC Coms is a single-homeserver private service, not a private federation.[4]
The host follows the same approach. The installer keeps SELinux enforcing, enables the required nginx network permission, configures firewalld for HTTPS, and does not intentionally expose the internal application ports. nginx terminates TLS and adds HSTS, content-type, frame, referrer, and permissions headers for the web service. TLS certificates remain an administrator responsibility rather than something the installer silently requests or renews.[5][7]
Secrets are generated per installation. Generated runtime configuration, signing material, tokens, database dumps, and TLS private keys are explicitly excluded from what should ever be committed or published. The initial administrator credential is written to a root-readable file so the first login can happen without embedding a default password in the project, and the installation guide tells the administrator to delete that file after changing the password.[7]
The host is part of the application design
Community V1 supports Rocky Linux 9, AlmaLinux 9, RHEL 9, and CentOS Stream 9. The deployment expects systemd, Podman, nginx, firewalld, and SELinux. The installer is deliberately aimed at a fresh dedicated host and refuses to act as an upgrade, migration, repair, or overwrite mechanism.[1][5]
That constraint is intentional. Installation automation becomes much harder to reason about when it is also expected to detect and safely reinterpret every possible older state. For the first public release I would rather have a narrow, reproducible install path than pretend an untested in-place upgrade is safe.
The service layout is fixed under /data/dccoms and /etc/dccoms. The installer renders the Synapse, nginx, Quadlet, frontend, and service configuration; pulls the required container images; builds the frontend and bot containers; creates accounts; starts services; creates an initial database backup; and runs local health checks. A separate preflight mode validates the site-specific configuration before installation makes changes.[5]
A PostgreSQL dump is not the whole recovery plan
The first backup implementation could have stopped at pg_dump. That would have protected an important part of the service while leaving several other pieces of state capable of breaking a recovery.
The DC Coms recovery documentation requires the PostgreSQL backups, Synapse state, Reminder Bot state, DC Ops state, and protected files under /etc/dccoms to be preserved together. The Synapse signing key is durable server identity material. Uploaded Matrix media is separate from the database. Bot directories can contain persistent state and encrypted Matrix session or store material.[8]
Synapse's own backup guidance makes the same broader point: configuration and the server signing key are part of homeserver recovery, not optional decoration around the database.[9]
Server recovery covers those components. Encrypted-history recovery is separate. Matrix end-to-end encryption depends on device-held keys, and DC Coms exposes cross-signing, secret storage, recovery-key handling, and encrypted session backup in its Security & Recovery workflow. Restoring Synapse, PostgreSQL, media, and server identity does not recreate a user's missing decryption keys. A user who loses every trusted device and a usable recovery path can have a healthy restored server and still be unable to decrypt older encrypted messages.[3][11]
Operational view If I restore the database and discover afterward that the homeserver identity, media, bot state, or generated credentials are missing, the database backup did not prove service recovery. Synapse 1.161 adds another recovery-specific requirement: restored database state must not reintroduce stale e2e_one_time_keys_json data. The original DC Coms 1.0.1 dump job did not exclude that table. The corrected main branch now excludes it from new dumps, and the recovery guide tells operators restoring 1.0.1 or older full dumps to truncate the table before Synapse starts.[8][9][12] Off-host backup placement remains the administrator's responsibility.
Reproducibility became the release gate
The private instance had already proven that the application could work. That was not enough to publish it.
The public package had to remove private hostnames, network references, credentials, generated runtime state, private emoji packs, and development debris. The release process adds a source/package audit, a manifest, a portable SHA256 checksum, configuration preflight, and a clean-host installation test. The clean-install gate then checks the running services, Matrix API, nginx, SELinux state, firewall exposure, listeners, database backups, external HTTPS, browser behavior, Reminder Bot, DC Ops, and administrative functions. Recovery validation is a separate final-release requirement.[1][2][10]
Community 1.0.0 reached GA after clean installation, browser and service regression, backup, and recovery validation passed. Version 1.0.1 followed the same day as a packaging and documentation hotfix, with no application runtime code changes. A later review against Synapse 1.161 backup guidance found the one-time-key restore issue described above. The public main branch now contains the backup and recovery correction, but 1.0.1 remains the current tagged GA release until that change is packaged and validated as a new release.[2][12]
That is the part of the project I care about most as an infrastructure person. Source code can work perfectly on the machine where it was developed and still be a bad release. A public infrastructure project needs a path from artifact to known running state that another person can follow without inheriting the developer's machine history.
What Community V1 does not pretend to solve
The limits are explicit. Community V1 does not provide HA or clustering. It does not migrate an existing Matrix deployment, upgrade an existing DC Coms install, manage TLS certificates, or configure off-host backup storage. The project also does not publish a validated minimum CPU, memory, or disk baseline yet.[5][10]
Those are real limitations, but they are better than undocumented assumptions. A small team can decide whether a single-host private communications service fits its needs. An enterprise that needs clustered availability, automated certificate lifecycle, centralized identity integration, formal mobile clients, or a supported rolling-upgrade path has a different design problem.
Why I released it
DC Coms is now public under the MIT License. The repository contains the application source, deployment templates, installer, release tooling, administration guide, backup and recovery guidance, troubleshooting steps, and the clean-install test used for release validation.[1]
I wanted the public version to be something another person could install, inspect, break, and improve, not a tarball of the machine I happened to be running. The chat interface is the visible part. The more interesting work is the service underneath it: who can create identities, what is reachable, what state has to survive, how the host is constrained, and whether a clean server can reproduce the result.
For a small self-hosted project, those questions are where software turns into infrastructure.
Key Takeaways
- DC Coms Community 1.0.1 is a self-hosted Matrix communications stack for small teams, not a generic Matrix installer.
- HTTPS on TCP 443 is the intended external application entry point; Synapse and support APIs are published only to localhost on the host.
- Public registration and guest access are disabled, federation is disabled, locally created rooms default to end-to-end encryption, and room-directory publication is closed down.
- Server recovery requires more than PostgreSQL, and Synapse database restores must also avoid reintroducing stale one-time-key data. Encrypted-history recovery is a separate user-crypto concern that depends on trusted devices or encrypted key backup plus a usable recovery key.
- Community V1 favors a clean, reproducible install over unproven in-place upgrade logic.
- The release process treats sanitization, clean-host installation, browser regression, backup, and recovery as release gates.
Source Notes
Product behavior changes. These sources were checked against public project and platform documentation available on September 23, 2026.
Subscribe
Get new articles by email.