Cloudflare DNS
Gives every app a real address, first-claim-wins.
Capability: dns · DNS (App Subdomains). This is a core capability: the platform asks it questions, so exactly one connected instance is marked Primary and answers. The first instance you enable becomes Primary automatically; a second one never steals the role.
Vendor site · Connector implementation · Vendor docs
Configure Cloudflare DNS in Atrium → (admins only)
Setup
Atrium creates and removes app-subdomain records in your Cloudflare zone. It checks for an existing record first and refuses to touch records it did not create.
- Find the zone id. Cloudflare dashboard → your zone → Overview → API section (right column) → Zone ID.
- Create a scoped API token. My Profile → API Tokens → Create Token → "Edit zone DNS" template, scoped to the one zone. Copy it once. Open the console page ↗
- Paste zone id + token below. The token is stored encrypted (AES-256-GCM).
What you paste back into Atrium
In order, the values the steps above produce:
- Zone ID
- API token
How it works
Atrium becomes the registry for app subdomains in one Cloudflare zone, writing A and CNAME records with a 300-second TTL through the v4 API. Records are created unproxied (grey cloud), so traffic goes straight to the ingress IP rather than through Cloudflare's proxy.
What Atrium does, and when
| When this happens | Atrium does this |
|---|---|
| An app is registered | Auto-claims <slug>.atrium.<zone> pointing at the ingress IP, when that name is free. A collision fails the claim rather than taking the name. |
| An owner claims another subdomain from the app's settings, or an agent calls claim_dns_subdomain over MCP | Creates the record and locks the name to that app. Anyone claiming may use the open atrium namespace; apex-level names need an admin or the privileged group. |
| An owner releases a name | Deletes the record, passing the exact value Atrium stored, and frees the name for a future claim. |
| Any create | Lists the zone for that exact name and type FIRST. Anything already there is a conflict and the create is abandoned. Cloudflare has no create-only mode, so the guard is this explicit read rather than an API guarantee. |
| Any delete | Lists the name and type, and deletes only the record whose content still matches the value Atrium wrote. No match means it refuses. |
Guarantees and limits
- The client can CREATE and DELETE, and has no update or upsert operation at all. This is deliberate: records Atrium did not write are protected, so the client is built incapable of overwriting one rather than merely instructed not to.
- Deletes carry the exact value Atrium stored. A record someone re-pointed out of band no longer matches, so the delete fails loudly instead of destroying the newer record.
- First claim wins. A subdomain is locked to the app that claimed it, and only its owner can release it.
- The atrium namespace itself is hard-reserved, so the open lane can never take out the platform's own record.
- DNS is a core capability, but enumerating is the point here: one connector per zone, and every connected zone is readable. With several zones connected, a claim that does not name one is refused rather than guessed.
- The token needs Zone → DNS → Edit on the one target zone and nothing else. A global API key works and is the wrong instrument: it carries your whole account.
- Because the create-guard is a read-then-write rather than an atomic operation, two simultaneous claims for the same brand-new name are a theoretical race. Atrium's own first-wins lock is what actually serialises claims.
- The API token is encrypted at rest (AES-256-GCM) and never returned to the browser.
What "Test connection" proves
Reads the configured zone over the Cloudflare API. A 401 or 403 is reported as a token or scope problem, a 404 as the zone not existing. A pass proves the token authenticates and can see that specific zone, without writing anything.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Test connection returns 403. | The token is scoped to a different zone, or it has Zone Read but not DNS Edit. | Re-create it from the "Edit zone DNS" template scoped to this zone. |
| Test connection returns 404 on a zone that exists. | The Zone ID field was filled with the domain name or the account id instead of the zone id. | Cloudflare dashboard → the zone → Overview → API section in the right column → Zone ID. |
| A release fails saying the record changed out of band. | Someone edited the record in Cloudflare after Atrium created it, so the stored value no longer matches. | Intended refusal. Delete it in Cloudflare deliberately if that is what you want; Atrium will not destroy a record it no longer recognises. |
| The name resolves to a Cloudflare IP rather than the ingress IP. | The record was proxied. Atrium writes unproxied, so someone turned the orange cloud on afterwards. | Turn proxying back off for that record, or accept the proxy and expect the origin IP to be hidden. |
Required scopes
Grant the credential exactly these scopes; they are the least-privilege set the connector needs:
API token with Zone → DNS → Edit on the target zone
Configuration fields
| Field | Type | Required | Notes |
|---|---|---|---|
zoneNameZone name | text | yes | The DNS zone Atrium manages app subdomains in. e.g. ommax-intelligence.de |
defaultIngressIpDefault ingress IP (optional override) | text | no | Leave blank — hosting provides it. Set an IPv4 only to override the address auto-claimed A records point at. e.g. 136.243.7.169 |
zoneIdZone ID | text | yes | e.g. 023e105f4ecef8ad9ca31a8372d0c353 |
apiTokenAPI token | passwordsecret | yes | e.g. … |
Configured after connecting
Policy fields, set on the instance once credentials are in. They shape how the connector is used, not whether it can authenticate:
| Field | Type | Required | Notes |
|---|---|---|---|
privilegedGroupIdPrivileged group | group | no | Members of this group may claim apex-level subdomains (e.g. your leaders group). Admins always can. Leave unset to restrict apex names to admins. |
Operating notes
- Secret fields are encrypted at rest (AES-256-GCM) and never returned to the client. Editing an instance and leaving a secret field masked keeps the stored value.
- Adding a connector from the marketplace creates a disabled, credential-less instance ("Added, not yet connected"); it does nothing until an admin opens it, pastes credentials, and enables it.
- Use Test connection on the instance page before enabling: it performs a read-only probe with the credentials you entered.
- Connector credentials live in the Atrium database, not in container env vars; changing them here takes effect without a redeploy (within the resolver's 30-second cache).