When managing multiple environments (production vs. development), it's common to want separate DNS control for subdomains. The key mechanism here is DNS delegation via NS records.
For your scenario with example.com
and dev.example.com
, here's how to delegate:
; Main zone file (example.com)
dev.example.com. IN NS ns1.dev.example.com.
dev.example.com. IN NS ns2.dev.example.com.
ns1.dev.example.com. IN A 192.0.2.1 ; IP of dev DNS server
ns2.dev.example.com. IN A 192.0.2.2 ; Secondary IP if available
On your development server's DNS (BIND example):
zone "dev.example.com" {
type master;
file "/etc/bind/zones/db.dev.example.com";
allow-transfer { 192.0.2.2; }; ; Secondary server
};
Then create the zone file:
; db.dev.example.com
@ IN SOA ns1.dev.example.com. admin.dev.example.com. (
2023080101 ; serial
3600 ; refresh
900 ; retry
604800 ; expire
86400 ; minimum TTL
)
@ IN NS ns1.dev.example.com.
@ IN NS ns2.dev.example.com.
ns1 IN A 192.0.2.1
ns2 IN A 192.0.2.2
a IN A 192.0.2.10
b IN A 192.0.2.11
*.a IN A 192.0.2.10 ; Wildcard for all a.* subdomains
Use dig
to test delegation:
dig +trace a.dev.example.com
dig NS dev.example.com
For AWS Route 53:
# Using AWS CLI
aws route53 create-hosted-zone --name dev.example.com \
--caller-reference $(date +%s) \
--hosted-zone-config Comment="Dev environment DNS"
# Then add NS records to parent zone
aws route53 change-resource-record-sets --hosted-zone-id Z123456789 \
--change-batch file://ns_update.json
Sample ns_update.json:
{
"Changes": [{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "dev.example.com",
"Type": "NS",
"TTL": 300,
"ResourceRecords": [
{"Value": "ns-123.awsdns-45.com"},
{"Value": "ns-678.awsdns-91.net"}
]
}
}]
}
- Ensure TTL values are low during initial setup (300 seconds)
- Verify NS records propagate using
dig +short NS dev.example.com
- Check firewall rules allow DNS traffic (UDP 53) between servers
When managing development infrastructure, it's common to want separate DNS control for development subdomains while keeping production DNS intact. The scenario:
Production:
- example.com (DNS Server A)
- a.example.com
- b.example.com
Development:
- dev.example.com (DNS Server B)
- a.dev.example.com
- b.dev.example.com
DNS delegation through NS (Name Server) records solves this elegantly. On your production DNS server (managing example.com), add:
dev.example.com. IN NS ns1.dev.example.com.
dev.example.com. IN NS ns2.dev.example.com.
ns1.dev.example.com. IN A 192.0.2.1
ns2.dev.example.com. IN A 192.0.2.2
Then configure your development DNS server to handle all queries for *.dev.example.com.
For a concrete implementation using BIND9:
Production Server named.conf
zone "example.com" {
type master;
file "/etc/bind/db.example.com";
allow-transfer { none; };
};
Production Zone File (db.example.com)
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (
2023081501
3600
1800
604800
86400 )
IN NS ns1.example.com.
IN NS ns2.example.com.
; Delegation for dev environment
dev IN NS ns1.dev.example.com.
dev IN NS ns2.dev.example.com.
ns1.dev IN A 192.0.2.1
ns2.dev IN A 192.0.2.2
Development Server named.conf
zone "dev.example.com" {
type master;
file "/etc/bind/db.dev.example.com";
};
Development Zone File (db.dev.example.com)
$TTL 86400
@ IN SOA ns1.dev.example.com. admin.dev.example.com. (
2023081501
3600
1800
604800
86400 )
IN NS ns1.dev.example.com.
IN NS ns2.dev.example.com.
@ IN A 192.0.2.10
a IN A 192.0.2.11
b IN A 192.0.2.12
Test your delegation with dig:
dig +trace a.dev.example.com
Should show the query being referred to your development nameservers.
For simpler setups without full DNS control:
*.dev.example.com. IN CNAME dev-gateway.example.com.
Then configure your dev-gateway server to handle virtual hosts.
- Ensure proper TTL values for faster propagation
- Consider DNSSEC complications if implemented
- Monitor DNS query logs during transition