Products8 min read

Inside Apiary: one control plane for every domain you run

Run more than a handful of websites and a quiet tax starts to compound: a renewal you almost missed, a DNS record nobody remembers changing, an SPF check that has silently gone red. The usual fix is another browser tab — a registrar here, a host there, a mail dashboard somewhere else. Apiary is our answer: one console, and one capability‑scoped key, that brokers every one of those providers behind a single, audited door.

Apiary is a multi‑tenant operational control plane for every domain we run across five providers — Cloudflare (DNS, WAF, CDN), Cloudways (hosting and servers), Enom (registrar), and Elastic Mail and Mailgun (email sending and deliverability). It grew out of two internal tools — one for our Cloudflare and Cloudways fleet commands, one for email‑deliverability monitoring — which Apiary replaces and merges into a single console plus a single API. The rule underneath the whole thing is short enough to put on a sticker: lock everything down by default, and open specific writes deliberately.

The problem: a fleet with no single door

Every provider is a silo with its own login, its own idea of what a "domain" is, and its own blast radius. A Cloudways app can serve several domains; a sending domain is often a subdomain; a Cloudflare zone is a different thing again. Spread that across five providers and dozens of accounts and the simple questions get hard: what expires next month? which records drifted? who changed the WAF rule? Worse, the only way to fix anything is to hand a human the master credentials for a whole provider — an all‑or‑nothing key with no record of who did what.

Who it's for

Apiary is built for the people holding a large estate together: web agencies, managed‑service providers and in‑house ops teams responsible for sizeable domain portfolios. These are the teams most exposed to scattered accounts — missed renewals, inconsistent DNS, email‑authentication gaps — and the ones that gain the most from one authoritative view and one narrow, auditable way to act on it. It also serves a second, non‑human audience: agents — automation keys granted exactly one verb each, and nothing more.

Feature 1 — One inventory, service-aware tabs

At the centre of Apiary is a single unifying entity: a domain — the customer‑facing apex like example.com, owned by exactly one account. It deliberately does not map one‑to‑one onto a provider resource. Instead, provider resources attach to it through link records: a cloudflare_zone, a cloudways_app, a mail_domain, a registrar_domain. A tab shows up for a domain only when a link of that kind actually exists — so the interface is a fact about your data, not a configuration flag you maintain.

Provider links attach to a domain — tabs light up only for the services that exist
apiary.swarmlabs.io/app/domains
fieldhouse.studio
Cloudflare Cloudways Enom Mailgun
Overview DNS Security Hosting Registrar Delivery

Feature 2 — The capability model, with risk tiers

This is the heart of Apiary. Every action it can take is an atomic verb — named like domain.hosting.ssh.unlock or domain.dns.write — and every verb carries a risk tier. The tier, not a per‑grant checkbox, decides who may ever hold it. read and app‑write are customer‑eligible; server‑write (restart a box, edit an IP whitelist — shared blast radius) and registrar‑write (renew, change nameservers, transfer — irreversible) are structurally admin‑only, enforced server‑side no matter what grant a request waves around. A forged customer grant for an admin tier is rejected on principle, and that rejection is a tested guarantee.

A capability's tier decides who can ever hold it — the top two are admin-only by construction
registrar-writerenew · transferadmin only
server-writerestart · whitelistadmin only
app-writebackup · ssh.unlockcustomer
readdns · delivery · expirycustomer

Atomic verbs are what get stored, but nobody administers a checkbox grid: they are applied as named bundlesread_only, self_serve, deploy, dns_manager, full_app — with per‑capability overrides. The exact same machinery authorises a customer click and an agent API call. There is no second code path.

Feature 3 — One audited write path

Every mutation in Apiary — a console button, an admin command, an API call — funnels through exactly one relay: Provider.call(). That single chokepoint is where the authorize() capability check, the per‑key rate limit, the provider execution, the normalised error, and the append‑only audit log all attach. One write path means there is no forgotten side door, and every privileged action — who, what verb, which target, what result — lands in a log the app can only ever append to.

capability check → rate-limit → execute → audit — the one and only write path
request
authorize() rate-limit execute
CloudflareCloudways
audit · ssh.unlock · ok audit · dns.write · ok

Feature 4 — A scoped key for every agent

The same capability model powers the /api/v1 relay — the "complete API to open up specific write access and lock down everything else." An agent authenticates with Authorization: Bearer <api_key>, and that key carries a precise capability set and scope: an account, a list of domains, or — for a super‑admin‑issued global key — the whole estate as a read‑only god view. Hand an automation the verb domain.hosting.ssh.unlock for one app and that is the only write it can make; a DNS edit or a server restart from the same key comes back 403. Write keys are high‑entropy secrets, hashed at rest, rotatable and revocable on their own.

A scoped agent key: one write opens, everything else stays shut
Bearer apiary_k_7f3a… ssh.unlock · app‑42
POST/hosting/ssh:unlock200
POST/dns403
POST/hosting/server:restart403

Feature 5 — The sweep that watches while you sleep

Apiary does not wait to be asked. The console deploys as a single Cloudflare Worker whose scheduled() handler runs a cron sweep: it polls each provider on a tiered cadence (busy domains more often, with backoff when a provider complains), normalises what it finds into provider events, and rolls them up into daily metrics. That is what powers the alerts that matter — a domain creeping toward expiry, a DNS record that drifted, an SPF/DKIM/DMARC check that went red — surfaced before they turn into an outage or a bounced campaign.

A cron sweep polls every provider — expiry, DNS drift and SPF/DKIM/DMARC, watched for you
CFCWEnomElasticMailgun
SPF pass DKIM pass DMARC pass
fieldhouse.studio — expires in 12 days

How it works, end to end

Underneath the console the shape is deliberately small:

  • One domain, many links. Each domain is the apex; provider resources attach as link records, and the tabs you see are simply which links exist.
  • One capability funnel. Reads and writes both pass through authorize() — super‑admin, then risk tier, then account‑enabled, then the specific grant — so a customer click and an agent key are judged by the same rules.
  • One write path. Provider.call() performs the capability check, rate‑limits, relays to the provider, normalises the error, and appends to the audit log — with a targeted re‑read afterwards so a just‑done action shows up immediately instead of looking like it failed.
  • One sweep. The Worker's scheduled() handler polls the providers, ingests events and rolls up daily metrics for the alerts.

The stack is the same one we run across the studio: SvelteKit on Cloudflare Workers (the app and its cron live in a single Worker), Neon Postgres with Drizzle, better‑auth for accounts and memberships, and Tailwind 4, organised as a pnpm + Turborepo monorepo so the relay, schema and sync packages are shared by the request paths and the cron alike. Provider credentials are stored with envelope encryption and decrypted only at call time — the plaintext key never leaves the relay and is never sent to a browser.

Why we built it

Apiary is the operational backbone for the fleet of sites Swarm Labs runs — the thing that turns "I have the master credentials for five providers" into "I have one narrow, audited key for exactly the job in front of me." It is one of several internal tools we have grown into products, alongside Time Hive, Scout and SwarmGen — and it shares Time Hive's instinct that the only number worth reporting is one you can point at the data for. If that lock‑down‑by‑default approach to running real infrastructure is the kind of thing you want built for your own estate, the way we work is a good place to start, the rest of the hive's notes are worth a read, or see Apiary on our applications page and the live console itself.

One control plane
for every domain you run