Skip to content

Custom Domains & WAF ​

Custom domains ​

A custom domain needs a hosted zone, a certificate, and DNS records pointing to the load balancer. Set domain.dns according to where the hosted zone is managed.

ModeThe zoneWhat Keel doesManual steps
route53 (default)Already exists in this AWS accountWrites validation + alias records; the apply waits for the certificateNone
route53-managedKeel creates itEverything, once you set the nameservers at your registrarSet 4 nameservers
externalStays where it is (Cloudflare, another account, corporate DNS)Issues the certificate; prints the records; writes noneCreate the records, then keel domains verify
bash
keel domains add app.example.com          # looks the zone up once and records the mode
keel domains add app.example.com --dns route53-managed
keel domains add app.example.com --dns external
keel domains status                       # live state: zone, delegation, certificate, what's left (--json)
keel domains records                      # the records to create by hand, in provider-form shape
keel domains verify                       # recheck; for external, records an issued certificate (--wait, --timeout 15m)
keel domains remove app.example.com

domains add supports --zone, --zone-id, --dns, repeatable --alias, --certificate-arn, and --no-force-https. It updates the target environment in keel.yml; run keel up to apply the change in AWS.

Declared in keel.yml:

yaml
domain:
  name: app.example.com
  zone: example.com          # required for the route53 modes; ignored for external
  # dns: route53             # route53 | route53-managed | external
  # aliases:
  #   - www.app.example.com
  #   - "*.app.example.com"  # on the certificate, deliberately not routed
  # certificate_arn: arn:aws:acm:...   # bring your own; Keel then issues nothing
  # certificate_issued: true # external only — written by 'keel domains verify'
  # force_https: true        # takes effect only once a certificate exists
  # validation_timeout: 20m

HTTPS activation ​

While a certificate is pending, port 80 continues to serve the application. force_https defaults to true and starts redirecting only after the certificate is issued and attached.

Delegation checks ​

keel domains status queries public DNS instead of relying only on Route 53, so it can detect a registrar that still delegates to another provider. It reports the next required step in order: zone, delegation, certificate, then attachment. For apex domains it also notes that DNS providers must use ALIAS or ANAME records rather than CNAME.

Retained managed zones ​

Keel retains hosted zones created with route53-managed when you run domains remove or keel destroy. Recreating a zone assigns different nameservers and would invalidate registrar delegation and remove records Keel may not manage. Delete a retained zone manually in AWS when it is no longer needed; AWS charges $0.50 per month for it.

External DNS takes two applies ​

With dns: external, run keel up to provision HTTP and print the validation records. Add those records at your DNS provider, run keel domains verify --wait, then run keel up again to attach HTTPS. Static sites use the same sequence with keel sites verify.

WAF ​

Keel supports AWS WAF with managed rule sets to protect your ALB. WAF requires load_balancer.enabled: true — and therefore at least one service; a sites-only app has no ALB to attach it to.

yaml
waf:
  enabled: true
  managed_rules:
    - AWSManagedRulesCommonRuleSet
bash
keel waf enable                # default rule set: AWSManagedRulesCommonRuleSet
keel waf enable --rules AWSManagedRulesCommonRuleSet,AWSManagedRulesSQLiRuleSet
keel waf status
keel waf disable

Changes are applied on the next keel up.

Keel — the missing platform layer for AWS.