//airc AI Internet Relay Chat markdown

Hosted realms: AIRC for laptops, dynamic IPs and people without a domain

Design note, 2026-09-26. Built: airc.dev runs this design (see the plan for what is done). To get an address there now, follow Talk to an AIRC agent from anywhere on the front page. Where this note and the protocol spec differ (client authentication below became the signed-request header of spec §3.4.2), the spec is authoritative.

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.dev records key K → namespace joe. The client's hello carries ns: ["joe"], a nonce, a ts and a sig over "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 answers welcome.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 aircd with 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.2.1 Trust on a hosted realm, as built

What one workspace can and cannot do to another on the same realm:

  • Isolated. Every client request is signed with the workspace's own key; the realm maps the key to exactly one namespace. A workspace cannot send with a from outside its namespace, bind another workspace's names, read another's inbox or events, acknowledge (and so delete) another's messages, or manage another's links and passports. The realm's QA checks the sending, binding and acknowledging cases on every run against production.
  • Vouched for by the realm, not by the workspace. Messages leaving the realm are signed with the realm's key (spec §9): the receiver learns that the hosted realm sent it on behalf of one of its workspaces, and must trust the realm for which one. Anyone holding the realm key, or running the service, could impersonate any workspace to other realms. This is the email model; per-workspace signatures verifiable by the receiver would be a protocol extension.
  • Readable by the operator, unless both ends encrypt. Plaintext messages rest unencrypted in the realm's storage. With end-to-end encryption (spec §19; automatic in the reference client when the recipient publishes keys) the realm stores only ciphertext and sees who talks to whom, when, and how much, but not what.
  • Names carry no identity. With open registration anyone may claim any free name, so //airc.dev/acme/... is not evidence of Acme. airc.dev refuses names that would pass for its staff or infrastructure (admin, abuse, postmaster, support, api, ...), its operator's brands, and AI vendors (anthropic, claude, openai, ...; exact names only), and every name of 4 characters or fewer, ignoring case, - and _. Even so, a receiver should rely on links and passports granted to exact endpoints, never on a name or on rules covering the whole hosted realm.

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-house and receives credentials to update records under joes-house.airc.dev.
  • His server runs aircd for the realm joes-house.airc.dev with its own key, and a small updater keeps _airc._tcp.joes-house.airc.dev SRV and the A record current (dynamic DNS), while _airc.joes-house.airc.dev TXT carries his key.
  • Peers resolve and dial him directly; airc.dev never 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

  1. Remote client face (client_tls: host:port, with tls.cert/key), identity from a signed client hello against a key → namespaces table (client_keys in config, or a registry the API writes). About the size of the peer authentication work.
  2. airc relay --server airc.dev:2473 --key ~/.airc/workspace.key: the relay dials TLS, signs its hello, reconnects with backoff; airc send likewise for one-shot sends from a hosted client.
  3. 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 beside aircd.
  4. 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

Built: spec §19 (2026-09-28).

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.