Role
Backend architect and sole developer of the server, the threat model, and the deployment. A collaborator builds the Android client in Flutter.
Years
Since 2026
Status
In progress
Stack
Django, FastAPI, Nginx, PostgreSQL, Redis, WebRTC, WebSockets, and coturn

The problem

When a state cuts international connectivity, mainstream messengers stop working. Their servers, push infrastructure, CDNs, and STUN and TURN relays all sit outside the country.

Communication Platform is my answer to that failure. It is a private, invite-only messaging system that runs entirely from a single VPS inside the network it serves. At runtime it contacts no CDN, no FCM or APNs, no public STUN or TURN server, no external certificate authority, and no third-party API.

What I built

I designed and built the backend: Django 6 and FastAPI on uvicorn, with PostgreSQL and Redis bound to loopback, nginx terminating TLS 1.3 under a pre-distributed private certificate authority, and a self-hosted coturn relay for voice.

Seven Django apps hold the domain, and a FastAPI package composes the API over them. They cover:

  • account and device registration
  • device-scoped JWT authentication
  • cross-signing and hybrid classical and ML-KEM prekey distribution
  • a durable envelope queue
  • bucketed attachments
  • the WebSocket gateway
  • short-lived credentials for the voice relay

The API is frozen at v1. A generated OpenAPI document is its contract, and CI fails any change that does not regenerate it.

The repository also holds the deployment artifacts that stand the whole system up on one machine with no internet access. The operator builds a cache of hash-pinned Python wheels on the host while the network is still up, and the install then runs from that cache alone.

Security model

Security decides the design. All content is encrypted on the client. The server is a blind relay: it stores and routes opaque, padded ciphertext and public keys, and it enforces nothing that security depends on. No content-encryption key ever reaches it, so seizing the server yields no plaintext. The test suite asserts that invariant directly.

Direct messages start with a hybrid X25519 and ML-KEM-768 key agreement in the style of PQXDH, then run a Double Ratchet. Group chats are pairwise: each message is encrypted once for every member device, and the server keeps no roster, group object, or group key.

I documented the threat model, the key inventory, and the residual risk, including the limit that a single-server design cannot fix: an adversary with live root access can still infer who talks to whom, and when.

Voice

Voice is audio only: a full mesh of WebRTC connections between devices, relayed by the self-hosted coturn and keyed end to end by DTLS-SRTP. The server's whole part in a call is one route that mints a short-lived relay credential and stores nothing behind it. Getting there meant removing the media server and the server-side room object that the first design had.

Status

The backend is substantially built and tested. The Android client, built by a collaborator, handles registration, device enrollment, cross-signing, direct messaging, history transfer, background delivery, and notifications. Group chats are not yet available in the production client, and the client half of voice is not built. The system has had no external security audit. The code is licensed under Apache-2.0.