AWS Route 53
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 AWS Route 53 in Atrium → (admins only)
Setup
Atrium creates and removes app-subdomain records in your Route 53 hosted zone. It only ever CREATEs records (never overwrites), so existing zone records stay untouched. You need the zone id and a minimally-scoped IAM key.
- Find the hosted zone id. AWS Console → Route 53 → Hosted zones → your zone (e.g. ommax-intelligence.de). Copy the Hosted zone ID (starts with Z…). Open the console page ↗
- Create a scoped IAM policy. IAM → Policies → Create: allow route53:ChangeResourceRecordSets and route53:ListResourceRecordSets, Resource arn:aws:route53:::hostedzone/<ZONE_ID>. Nothing else.
- Create an IAM user + access key. IAM → Users → Create (programmatic access only), attach the policy, create an access key. Copy the key id + secret once.
- Paste everything below. Zone id, access key id and secret. The secret is stored encrypted (AES-256-GCM).
What you paste back into Atrium
In order, the values the steps above produce:
- Hosted zone ID
- Access key ID
- Secret access key
How it works
Atrium becomes the registry for app subdomains in one Route 53 hosted zone. It writes A and CNAME records with a 300-second TTL through ChangeResourceRecordSets, and it only ever creates. Route 53 is a global service, so the SDK region is fixed at us-east-1 and only routes the endpoint; it says nothing about where your zone is.
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 | Sends ChangeResourceRecordSets with Action=CREATE. AWS itself rejects the call when that name and type already exist, which Atrium maps to a conflict. The refusal is enforced by Route 53, not just by Atrium's own bookkeeping. |
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 IAM policy needs exactly two actions, ChangeResourceRecordSets and ListResourceRecordSets, on the one hosted zone ARN. Anything broader than that is over-granted.
- The secret access key is encrypted at rest (AES-256-GCM) and never returned to the browser.
What "Test connection" proves
Calls GetHostedZone on the configured zone id. A pass proves the credential authenticates and can see the exact zone Atrium is pointed at, without creating or touching any record. AWS error names are surfaced as-is (NoSuchHostedZone, AccessDenied, SignatureDoesNotMatch) because they are clearer than the raw message.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Test connection says the hosted zone was not found. | The zone id is wrong, or belongs to a different AWS account than the access key. | Copy the Hosted zone ID (it starts with Z) from the zone's own page, and confirm the IAM user lives in the same account. |
| Credentials rejected (SignatureDoesNotMatch, InvalidClientTokenId). | The access key id and secret do not belong together, or the key was deactivated. | Create a fresh access key on the IAM user and paste both halves. |
| A claim fails with a conflict on a name that looks unused. | A record with that name and type already exists in the zone, put there outside Atrium. Atrium refuses to overwrite it. | Either pick a different name or remove the pre-existing record in Route 53 deliberately. Atrium will not take it for you. |
| Records are created but the app does not resolve. | The zone is not the one actually serving the domain (a common split between a delegated subzone and the parent), or the ingress IP is wrong. | Check the zone's NS delegation, then the ingress IP the record points at. |
Required scopes
Grant the credential exactly these scopes; they are the least-privilege set the connector needs:
IAM user/role with route53:ChangeResourceRecordSets + route53:ListResourceRecordSets on the hosted 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 |
hostedZoneIdHosted zone ID | text | yes | e.g. Z0123456789ABCDEFGHIJ |
accessKeyIdAccess key ID | text | yes | e.g. AKIA… |
secretAccessKeySecret access key | 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).