Hosted realms: AIRC for laptops, dynamic IPs and people without a domain#
Design note, 2026-09-26. Not built.
1. The problem#
The endorsed way to be on AIRC is to own a domain, run aircd, publish two DNS records, and open port 2472. That is right for an organisation with a server. It excludes most individuals: a developer with a laptop in a café is behind carrier-grade NAT, has an address that changes hourly, and owns no domain. Their agents should still be able to send and receive.
Rafael's framing: could a service, say airc.dev, let anyone register an AIRC presence (joes-laptop.airc.dev, or a "workspace") so that messages reach the laptop, ideally without airc.dev carrying the traffic?
2. How this problem is normally solved#
Four families, each used by systems you know:
| approach | examples | what it needs from the user's network | who carries the bytes |
|---|---|---|---|
| Dynamic DNS | DynDNS, DuckDNS, Cloudflare API | an inbound port that is actually reachable | nobody but the two ends |
| NAT traversal | WebRTC (STUN/ICE/TURN), Tailscale (DERP), libp2p (hole punching + relay) | nothing, but needs a signalling server, both sides online at once, and a relay fallback for the 10–20 % of NATs that cannot be punched | direct when it works, a relay when not |
| Reverse tunnel | ngrok, Cloudflare Tunnel, ssh -R, Tailscale Funnel | nothing: the laptop dials out and keeps the connection open | the tunnel service |
| Home server | email, XMPP, Matrix, IRC bouncers | nothing: the laptop is a client of a server that is always on | the home server |
Dynamic DNS alone fails the café case: the record can be perfect and the inbound connection still dies at the NAT. NAT traversal solves it but at the cost of a signalling protocol, candidate gathering, simultaneous connectivity, and a relay anyway for the unpunchable cases; it is the right tool for a video call, where the bytes are heavy and latency-sensitive, and the wrong tool for short text messages between agents that are often not online at the same time. Reverse tunnels and home servers are the same idea seen from two ends: an always-on party the laptop dials out to.
Every messaging protocol that lasted picked the home-server model, because it also solves the problem NAT traversal does not: the recipient is offline. A store-and-forward server is what makes "send now, read later" work, and AIRC already has that server.
3. What fits AIRC#
AIRC already assumes servers see message bodies; that is why origin authentication is per message and why policy runs at the server. So an airc.dev that carries Joe's messages is not a new trust concession; it is one more realm operator, and Joe's agents are its clients. The design then falls out of what exists:
3.1 A hosted realm with a remote client face#
airc.dev runs an ordinary aircd for the realm airc.dev. Today a client face is a Unix socket and identity comes from the connecting uid (§5 of the spec). A hosted realm needs a remote client face: a TLS listener on which a client proves who it is without a uid. Two ways, both reusing machinery the spec already has:
- Workspace key. Joe's laptop generates an ed25519 key once (the same kind a realm has). Registration binds the public key to a namespace:
airc.devrecordskey K → namespace joe. The client'shellocarriesns: ["joe"], anonce, atsand asigover"airc-client-hello\n<realm>\n<ns>\n<ts>\n<nonce>"(the client-side twin of §9.4). The server verifies against the registered key and answerswelcome.ns: ["joe"]. No passwords, nothing to leak in transit, and the same key can later make Joe's laptop a real realm of its own (§4). - Bearer token for environments that cannot hold a key. Simpler, weaker, optional.
From there Joe runs exactly what a fleet runs today: airc relay --namespace joe with a backend for his agent runtime, connecting out to airc.dev:2473 over TLS instead of to a local socket. It binds joe/, receives, acks. When the laptop sleeps, messages to //airc.dev/joe/… are spooled at airc.dev and delivered when the relay reconnects; the sender sees queued, then it arrives. Links and passports work unchanged, because they are per endpoint, not per host.
Names: //airc.dev/joe/reviewer. One realm, one key, one SRV record, one policy file; workspaces are namespaces. Vanity subdomains (//joe.airc.dev/reviewer) are a wildcard SRV pointing at the same server plus a rewrite, and can come later.
3.2 What airc.dev provides#
- An
aircdwith the remote client face, TLS, and the realm's key in DNS. - A registration API: create a workspace (namespace), register or rotate a workspace key, delete. Rate-limited, abuse-reportable, with a policy default that nothing outside the workspace's own links and passports can reach it (default-deny plus links, as recommended for any realm).
- Optionally, managed DNS for people who do have a reachable port (§4).
It is a conduit for those who need one and a directory for those who do not.
3.3 Cost and scale#
Per idle workspace: one TLS connection and one spool directory. Per message: one signature verification (the sending realm's), one policy check, one write. A single small server handles tens of thousands of idle workspaces; the Python reference implementation is single-core and would be the first thing to replace with the planned C++ service, but the shape does not change.
4. Direct connections, when they are possible#
Some users are not in a café: a home server on a residential connection with a dynamic IP and a forwardable port. For them airc.dev can be only DNS, which is the "return the real address" idea done the way DNS already does it:
- Joe registers
joes-houseand receives credentials to update records underjoes-house.airc.dev. - His server runs
aircdfor the realmjoes-house.airc.devwith its own key, and a small updater keeps_airc._tcp.joes-house.airc.dev SRVand the A record current (dynamic DNS), while_airc.joes-house.airc.dev TXTcarries his key. - Peers resolve and dial him directly;
airc.devnever sees a message.
This is a real realm in every sense; airc.dev is a registrar. The two modes share the registration API, and a workspace can move from hosted to direct by publishing records without changing its key.
5. The hybrid, if it is ever wanted#
A hosted workspace could advertise candidate direct addresses in its welcome/registry, and a peer could try them with the usual TLS plus signing before falling back to the hosted path. That is the NAT-traversal family again, and it only pays off when direct connectivity is likely (two laptops on the same LAN, a server with a port). It is compatible with everything above and not needed for the first version. If it is ever built, it should be done as in libp2p: the hosted connection stays the control channel, the direct one is an optimisation that can drop at any time.
6. What this needs in the spec and the reference implementation#
- Remote client face (
client_tls: host:port, withtls.cert/key), identity from a signed client hello against akey → namespacestable (client_keysin config, or a registry the API writes). About the size of the peer authentication work. - **
airc relay --server airc.dev:2473 --key ~/.airc/workspace.key**: the relay dials TLS, signs its hello, reconnects with backoff;airc sendlikewise for one-shot sends from a hosted client. - Registration API on
airc.dev: HTTPS, create/rotate/delete workspace, and for direct mode the dynamic-DNS update endpoint. Outside the protocol; a small service besideaircd. - Spec: a §5 addition for key-authenticated client hello; a note that a realm MAY host namespaces for remote clients; nothing else changes.
7. End-to-end privacy, separately#
A hosted realm reads bodies, like today's local server does. If people want airc.dev not to, the answer is end-to-end encryption of the body between endpoints (each endpoint publishes a key through its realm; the sender encrypts body to it and sets type accordingly). Servers route the same envelope and cannot read it; links, passports and policy still work on the envelope. That is a feature for any realm, not specific to hosting, and it is the right place to spend the effort that NAT traversal would have cost.