Skip to content

Route53 DNS

CWIQ.IO uses split-horizon DNS: public zones for internet-facing records and private zones for internal VPC resolution. All zones live in the shared-services account.


Zone Structure

Zone Name Type Account Hosted In Purpose
cwiq.io Public shared-services Route53 Root domain, delegated from registrar
shared.cwiq.io Public shared-services Route53 Public records for shared-services services
shared.cwiq.io Private shared-services Route53 Internal VPC records (NLB, Tailscale IPs)
dev.cwiq.io Public shared-services Route53 Public records for dev services
dev.cwiq.io Private dev Route53 Internal dev VPC records

Management account has orphaned duplicate zones

The management account (921838417607) has stale duplicate Route53 zones for shared.cwiq.io and dev.cwiq.io. Never modify these. Always work in the shared-services account (308188966547).


Split-Horizon DNS

A split-horizon (split-brain) setup means the same hostname resolves to different IPs depending on where the query comes from:

Query Source Zone Used Resolves To
Internet / external Public zone ALB DNS name (e.g., GitLab ALB), Tailscale IP
Dev VPC instances Private zone (associated) VPC private IP or NLB private IP
Shared-services VPC Private zone (owner) VPC private IP

Example — nexus.shared.cwiq.io:

  • From internet or Tailscale client: resolves to Tailscale IP (100.x.x.x)
  • From dev VPC (EKS runner pod): resolves to VPC private IP (10.0.x.x) via private zone — no Tailscale needed, works over VPC peering

This pattern allows CI/CD jobs running as EKS pods (no Tailscale) to reach shared-services using the same hostname that human operators use via Tailscale.


Cross-Account Private Zone Association

The shared.cwiq.io private zone (owned by shared-services) is associated with the dev VPC. This requires resources in both accounts:

Shared-services account — creates authorization:

resource "aws_route53_vpc_association_authorization" "shared_internal_to_dev" {
  zone_id = <shared_internal_zone_id>
  vpc_id  = "<dev_vpc_id>"
}

Dev account — creates association:

resource "aws_route53_zone_association" "shared_internal" {
  zone_id = var.shared_internal_zone_id
  vpc_id  = var.vpc_id
}

After association, dev VPC instances can resolve *.shared.cwiq.io private records without going over the public internet.


DNS Record Inventory

Shared-Services Public Zone (shared.cwiq.io)

Record Type Target Notes
gitlab.shared.cwiq.io A (Alias) shared-gitlab-alb DNS Internet-facing ALB
registry.shared.cwiq.io A (Alias) shared-gitlab-alb DNS Container registry via same ALB
wiki.shared.cwiq.io A (Alias) shared-gitlab-alb DNS GitLab Pages via SNI routing
vault.shared.cwiq.io A Tailscale IP Vault server (Tailscale access)
nexus.shared.cwiq.io A Tailscale IP Nexus (Tailscale access)
grafana.shared.cwiq.io A Tailscale IP Grafana
prometheus.shared.cwiq.io A Tailscale IP Prometheus
loki.shared.cwiq.io A Tailscale IP Loki
sonarqube.shared.cwiq.io A Tailscale IP SonarQube (Tailscale)
defectdojo.shared.cwiq.io A Tailscale IP DefectDojo (Tailscale)
sso.shared.cwiq.io A NLB/Tailscale Authentik HA
icinga.shared.cwiq.io A Tailscale IP Icinga master
ansible-shared-cwiq-io.* Tailscale MagicDNS Managed by Tailscale

Shared-Services Private Zone (shared.cwiq.io)

Record Type Target Purpose
sonarqube.shared.cwiq.io A 10.0.10.8 VPC private IP for EKS runner pods
nexus.shared.cwiq.io A VPC private IP Docker pull for EKS runner pods
docker.nexus.shared.cwiq.io A VPC private IP Docker push/pull

Dev Zone (dev.cwiq.io)

Record Type Target Notes
orchestrator.dev.cwiq.io A 10.1.35.46 (VPC) or Tailscale Orchestrator DEV server
langfuse.dev.cwiq.io A Tailscale IP (100.119.26.88) LangFuse (Docker DNS resolution requires Tailscale IP)

Tailscale MagicDNS

Tailscale provides its own DNS layer (*.cwiq-io.ts.net or via MagicDNS hostnames using dashes). This is separate from Route53 and resolves directly to Tailscale IPs.

Use dashes for Tailscale hostnames, never dots

When configuring Alloy, Prometheus, or any service to reach another server over Tailscale, use the dash-format hostname (loki-shared-cwiq-io), not the FQDN (loki.shared.cwiq.io). The FQDN resolves to VPC private IPs that are not routable cross-VPC. See MagicDNS & Hostname Conventions for the full reference.


Terraform Location

DNS records are defined per service module:

terraform-plan/organization/environments/shared-services/ec2-instances/
├── gitlab/
│   └── route53.tf   ← ALB alias records for gitlab, registry, wiki
├── nexus/
│   └── main.tf      ← Tailscale IP + private zone records
├── sonarqube/
│   └── main.tf      ← Tailscale IP + private zone record (10.0.10.8)
└── ...