Skip to main content

Overview

The Domain resource manages DNS infrastructure declared in TypeScript. Each domain lives in fjall/domains/<zone>/infrastructure.ts as a typed Domain construct — the file you edit is the file that deploys. It creates Route53 hosted zones, DNS records, ACM certificates, and cross-account delegation roles. BIND zone files are an interchange format only: fjall domain import --from-bind reads them and fjall domain export writes them, but the declaration surface is always infrastructure.ts.

Quick Start

The Domain Construct

A complete declaration, in the shape fjall domain create scaffolds:

Registrar modes

registrar is the discriminant of a typed union — each mode accepts different props: route53 creates the hosted zone, or — when hostedZoneId is set — adopts a live zone by reference, leaving the zone resource itself outside CloudFormation. Adopted zones go through the record-takeover ceremony on first deploy (see Lifecycle). external-delegated declares a child zone (delegatedSubdomain under zoneName). When Fjall manages the parent, the CLI injects parentDelegationRoleArn at deploy time and the child writes its own NS records into the parent zone — across accounts. phase: "zone" | "full" is the two-step guard the CLI drives automatically: zone and delegation first, certificates only after the delegation has propagated (otherwise ACM DNS validation hangs). An existing live child zone can be adopted by reference with hostedZoneId plus adoptedNameServers (set both together or neither): adoptedNameServers declares the zone’s already-live NS set, so the parent delegation is written and verified against the adopted zone rather than a newly minted one. external-records creates no hosted zone. The deploy emits the records — including certificate-validation records — for you to create at your external registrar.

Records

records accepts two shapes: Standard recordsA, AAAA, CNAME, MX, TXT, NS, SRV, CAA:
value is a string or an array of strings; ttl is optional. Alias recordsA or AAAA pointing at an AWS target. No ttl (Route53 aliases inherit the target’s):
aliasTo(dnsName, hostedZoneId) targets any alias-capable endpoint; the values pass through verbatim.

Record names

Record names follow BIND semantics:

Certificates

Each entry becomes a DNS-validated ACM certificate. An entry with cloudFront: true mints its certificate in us-east-1 — in-stack when the domain stack is already in us-east-1, otherwise via the paired us-east-1 certificate stack — and publishes the <zone>-us-east-1-certificate-arn stack export alongside the regional <zone>-certificate-arn. The managed-domain binding (below) carries both ARNs to consuming applications. At most one cloudFront certificate per Domain.

Lifecycle

Every destructive path (takeover, residue deletion, destroy) runs the destruction ceremony: a ticket names each affected record or zone, you consent per row with --remediate, and withheld consent exits 4 with nothing mutated. Records classified unknown are never offered for deletion. See fjall domain for the full verb and flag reference.

Application Binding

When Fjall manages a domain, application deploys receive a managed domain binding: the CLI resolves the domain stack’s outputs at deploy time and injects literal values — hosted zone ID, regional certificate ARN, us-east-1 certificate ARN for CloudFront, and the delegation role ARN. Literal values cross accounts and regions, so an application in another account binds to the zone with no extra wiring:
For bare-CDK synth outside the CLI, the export-name form (managedDomain: { hostedZoneIdExport, certificateArnExport, zoneName }) resolves via Fn.importValue() — same account and same region only.

Configuration

Fjall tracks managed domains in fjall-config.json under the domains field. Entries are auto-registered by fjall domain create and fjall domain import — a domain nested under an already-registered domain becomes delegated with the longest-suffix parent; everything else is apex:
An entry’s account key is the 12-digit AWS account id its domain stack deploys into, and region is where it deployed. Every successful fjall domain deploy (apex and delegated alike) records both automatically; they can also be added by hand. Record classification uses account to gather a child zone’s cross-account evidence, and region tells the child-account clients which region to search for the child stack.

Organisation Integration

Domains deploy automatically during fjall deploy organisation:
Apex domains deploy sequentially (delegation roles must exist first), then delegated children deploy in parallel.

Importing an existing zone

Import curates the declaration rather than copying the zone wholesale: records owned by other live CloudFormation stacks — an apex alias managed by an app stack, validation records for live certificates, a delegated child’s NS record — are deliberately left undeclared, with a file header explaining each omission. What remains is exactly what this Domain construct should own. Satellite ownership is proven from live evidence — CloudFormation stack templates, including Custom::CrossAccountZoneDelegation delegation resources, and ACM certificate ownership. The proof crosses accounts: a delegated child zone living in another AWS account classifies its parent-side NS row as satellite when its domain stack is live, claims the NS record via a literal DelegatedZoneName, and publishes a nameservers output matching the live NS values (order, case, and trailing-dot insensitive). Anything short of full proof fails closed to unknown with a warning naming the child domain and the fix, never a guess. The classifier locates the child through the delegated domain’s account key in fjall-config.json (see Configuration); an unreachable child account affects only that child’s row, leaving the rest of the zone’s evidence intact.

Interactive import

fjall domain import --interactive collects records through prompts. The flow shows a preview of the curated infrastructure.ts — satellite-owned records omitted by design — and writes nothing until the commit step is confirmed.

Large zones

fjall domain import --from-route53 caps at 5,000 records. Beyond that, export the zone with fjall domain export (or the AWS CLI), trim the BIND file to the records this construct should own, and import via --from-bind.

External DNS Registrar

For domains registered outside AWS, point your registrar’s nameservers to Route53:
  1. Run fjall domain create example.com
  2. Run fjall domain deploy example.com
  3. Run fjall domain verify example.com --show-delegation for the nameservers
  4. Update your registrar’s NS records to point to them
For subdomain-only delegation, declare the child with registrar: "external-delegated" and create the NS records the deploy reports at your registrar. To keep all DNS at the external registrar, use registrar: "external-records".

File Structure

Next Steps

fjall domain

Every domain verb, flag, and exit code.

Destructive Changes

The destruction ceremony and named consents.

Static Site Pattern

Serve a static site on your domain via CloudFront.

Deploy

Ship your domains and applications to AWS with the Fjall CLI.