When architecting a sovereign communication appliance, the engineering requirements for security and usability are frequently at war. This tension reaches its peak when configuring federation for a private Matrix homeserver.
By default, self-hosted Matrix setups inherit a classic, binary problem:
- The Air-Gapped Island: You lock the entire server inside a private WireGuard VPN. Your internal team can communicate securely, but you are completely isolated from the global Matrix ecosystem. You cannot talk to vendors, clients, or cross-company teams on external servers like
matrix.org. - The Exposed Perimeter: You open the homeserver to the public internet so foreign servers can discover your endpoints and federate. In doing so, you expose sensitive client login APIs, sync endpoints, and user metadata to the open web, inviting brute-force scripts and unvetted traffic straight to your front door.
When engineering the Remote Rails Sovereign Appliance, we rejected this compromise. We implemented a Split-Horizon Architecture using Traefik as our Layer 7 gateway alongside intelligent internal Docker routing. This design enforces an air-gapped network perimeter for internal operations while carving out a highly restricted, secure channel specifically for public Matrix federation.
Here is how we split the horizon to achieve zero-trust internal isolation without breaking global interoperability.
The Architecture: Designing the Split Perimeter
A standard Matrix homeserver deployment expects to face the web natively. In our topology, Tuwunel (our Matrix engine running on Conduit) is entirely hidden. To make this work while preserving security boundaries, we bifurcate the transport network using two distinct Traefik HTTP routers pointing to the exact same backend service.
┌──> [ tuwunel Router ] ───( vpn-only IP Whitelist )───> [ Private Sync / Auth ]
│
[ Inbound HTTPS (Port 443) ] ─── Traefik
│
└──> [ tuwunel-root Router ] ───( Path: /_matrix/ )────> [ Public Federation ]
Router 1: The Dark Internal Fortress (tuwunel)
The main entry point for day-to-day user interactions—including user authentication, token requests, file synchronization, and direct messaging—is bound to the tuwunel.${DOMAIN} host rules.
We secure this endpoint by passing it through our vpn-only@docker middleware. This middleware acts as a strict network-level firewall by enforcing an IP allowlist matching private IP ranges (e.g., 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16). If an unauthorized external entity attempts to access the main server endpoint, Traefik drops the traffic at the edge before a single byte hits the Matrix database.
Router 2: The Controlled Public Valve (tuwunel-root)
To allow external homeservers to communicate with us, we cannot use a blanket VPN restriction. Other federated servers in the global ecosystem are not connected to our WireGuard gateway.
To solve this, we define a separate router named tuwunel-root. This router matches traffic hitting the root domain (${DOMAIN}) but applies a highly restrictive Layer 7 filter using the PathPrefix('/_matrix/') rule.
When you decide to toggle on public federation (by changing the internal template settings from false to true), you simply drop the vpn-only@docker restriction strictly from this specific root-path router while leaving well-known-cors active:
YAML
- "traefik.http.routers.tuwunel-root.middlewares=well-known-cors"
Because the tuwunel-root router only exposes the standard Matrix federation endpoints under /_matrix/, it functions as a single, hardened public valve. External homeservers can cleanly sync room states and exchange messages, but they have absolutely no path to discover or attack your private client login infrastructure.
The Identity Paradox: Delegation via .well-known Routing
There is a glaring aesthetic and cryptographic paradox built into this architecture. If you look at our tuwunel.toml configuration, the server_name is strictly set to the root domain: server_name = "${DOMAIN}". This ensures that every user on the system receives a clean, professional, enterprise-grade Matrix ID: @user:domain.com.
Yet, from a network routing standpoint, our actual client traffic is completely siloed and whitelisted at the subdomain level: tuwunel.domain.com.
How can a server declare its identity on a root domain it isn’t explicitly listening on for client syncs?
The answer lies in Matrix’s native support for delegated discovery via the .well-known protocol. Matrix does not force you to host your heavy communications engine on your bare apex domain. Instead, it allows you to separate your identity namespace from your network infrastructure routing.
1. Inbound Client Discovery
When an internal user opens an Element client and logs in using @user:domain.com, the client doesn’t blindly guess where the server lives. It performs an initial, unauthenticated HTTPS GET request to the root apex: https://domain.com/.well-known/matrix/client.
Our stack handles this by running a lightweight Nginx container (well-known) directly on the root domain. This container serves a static JSON object compiled during our bootstrap process:
JSON
{
"m.homeserver": {
"base_url": "https://tuwunel.domain.com"
}
}
The client reads this file, realizes that the identity @user:domain.com actually routes through the network pipeline at https://tuwunel.domain.com, and transparently shifts all subsequent authentication, synchronization, and API traffic to the subdomain router.
2. Inbound Federation Discovery
The magic of this delegation model extends cleanly to the public federation layer. When a foreign homeserver (like matrix.org) tries to deliver a message to your user at @user:domain.com, it similarly checks https://domain.com/.well-known/matrix/server.
Our server-side delegation profile returns a completely different directive:
JSON
{
"m.server": "domain.com:443"
}
This tells the outside world that federation traffic should target the apex domain directly on standard HTTPS port 443.
The Traefik Handoff
This is where our two Traefik routers tie the entire loop together. When that external server hits https://domain.com/ looking to federate, it triggers our public tuwunel-root router because it’s looking for paths beginning with /_matrix/. Traefik catches it at the edge, strips away the VPN requirements, and forwards the payload internally to the backend.
By weaponizing Matrix delegation, we achieve an elite architectural state: your users get beautifully clean, branded @user:domain.com identities, while your actual infrastructure remains safely compartmentalized, air-gapped behind subdomains, and locked down behind deep network perimeters.
Bypassing Split-Brain DNS: Internal Loopback Optimization
Exposing external paths while restricting internal subdomains introduces another classic networking hazard: Split-Brain DNS.
When an internal companion service inside the appliance container network—such as the LiveKit JWT Token Service (lk-jwt-service) or the Stalwart Mail Server (stalwart-mail)—needs to talk to the homeserver to validate an access token, it will look up ${DOMAIN} or defguard.${DOMAIN}. If it resolves these domains to the server’s public IP via standard public DNS, the traffic will “hairpin” out to the public router.
This causes a critical failure mode:
- The public router will drop the internal request because it lacks the necessary VPN IP whitelist headers.
- The internal service crashes or reports:
Failed to look up user info from homeserver.
The Sane Solution: extra_hosts Anchoring
Rather than dealing with the administrative complexity of managing a heavy local BIND or Unbound DNS server inside the appliance just to handle local resolution, we use a lean container-level approach.
We map a direct host-to-gateway shortcut using the extra_hosts configuration within our docker-compose.yml for services that require strict internal validation loopbacks:
YAML
extra_hosts:
- "${DOMAIN}:host-gateway"
This flag tells the container’s internal network stack to bypass public DNS resolution entirely for our internal domains. When lk-jwt-service or stalwart-mail attempts to verify a user token against the homeserver, it resolves the root domain directly to the local host gateway (172.17.0.1 or the native bridge IP), routing the traffic cleanly inside the internal virtual network interface.
This guarantees lightning-fast token validation with sub-millisecond latency, completely immune to public firewall rules, external network jitter, or DNS leaks.
Clean Federation, Airtight Security
By combining path-specific Traefik ingress rules with container-level loopback routes, our appliance achieves total isolation where it matters, and fluid federation where it’s needed. The internal corporate chat matrix remains completely invisible to unauthenticated scanners, while the public federation protocol remains robust, lightning-fast, and natively encrypted. You own the network path, you dictate the boundaries, and you command the horizon.
