Technitium DNS with Primary-Slave Installation on Debian Rumi, February 12, 2026February 12, 2026 Architectural Overview ┌─────────────────────────────────────────────────────────────┐ │ PRIMARY (MASTER) DNS SERVER │ │ Host: ns1.pioneer.com.bd │ │ IP: 114.130.94.3 │ │ Role: Zone origin, accepts dynamic updates │ └─────────────────────────────────────────────────────────────┘ │ │ AXFR/IXFR Zone Transfer (TCP 53) │ TSIG-authenticated ▼ ┌─────────────────────────────────────────────────────────────┐ │ SECONDARY (SLAVE) DNS SERVER │ │ Host: ns2.pioneer.com.bd │ │ IP: 114.130.223.3 │ │ Role: Read-only replica, answers queries │ └─────────────────────────────────────────────────────────────┘ Prerequisites (Both VMs) 1. Fresh Debian 12 Setup # Update system sudo apt update && sudo apt upgrade -y # Install essential tools sudo apt install -y \ curl \ wget \ gnupg \ ca-certificates \ ufw \ net-tools \ dnsutils \ git 2. Configure Hostnames & DNS Resolution On DNS1 (Primary): sudo hostnamectl set-hostname ns1.pioneer.com.bd echo "114.130.94.3 ns1.pioneer.com.bd ns1" | sudo tee -a /etc/hosts echo "114.130.223.3 ns2.pioneer.com.bd ns2" | sudo tee -a /etc/hosts On DNS2 (Secondary): sudo hostnamectl set-hostname ns2.pioneer.com.bd echo "114.130.94.3 ns1.pioneer.com.bd ns1" | sudo tee -a /etc/hosts echo "114.130.223.3 ns2.pioneer.com.bd ns2" | sudo tee -a /etc/hosts 3. Install Docker Engine (Both VMs) # Remove old versions sudo apt remove -y docker docker-engine docker.io containerd runc # Install prerequisites sudo apt install -y apt-transport-https ca-certificates curl gnupg # Add Docker GPG key curl -fsSL https://download.docker.com/linux/debian/gpg | \ sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # Add Docker repository echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \ https://download.docker.com/linux/debian $(lsb_release -cs) stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # Install Docker sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin # Verify installation sudo docker --version sudo systemctl enable --now docker # Add current user to docker group (optional but recommended) sudo usermod -aG docker $USER Primary DNS Server Configuration (ns1.pioneer.com.bd) 1. Create Persistent Storage Directory sudo mkdir -p /opt/technitium-dns/config sudo chown -R $USER:$USER /opt/technitium-dns 2. Generate TSIG Key for Secure Zone Transfers # Generate a strong TSIG key (HMAC-SHA256) openssl rand -base64 32 # Example output: "aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890AbCdEf==" # SAVE THIS KEY SECURELY - you'll use it on both servers 3. Create Docker Compose File cat > /opt/technitium-dns/docker-compose.yml << 'EOF' version: '3.8' services: dns-server: image: technitium/dns-server:latest container_name: technitium-dns restart: unless-stopped ports: - "53:53/tcp" - "53:53/udp" - "5380:5380/tcp" # Web console port volumes: - ./config:/etc/dns/config environment: - DNS_SERVER_DOMAIN=ns1.pioneer.com.bd - DNS_SERVER_ADMIN_PASSWORD=<MY_STRONG_PWD> # CHANGE THIS - DNS_SERVER_PREFER_IPV4=true - DNS_SERVER_RECURSIVE=true cap_add: - NET_ADMIN networks: - dns-net networks: dns-net: driver: bridge EOF 4. Deploy Primary DNS Server cd /opt/technitium-dns sudo docker compose up -d 5. Configure UFW Firewall Rules (Primary) # Reset UFW to default deny sudo ufw --force reset sudo ufw default deny incoming sudo ufw default allow outgoing # Allow SSH (critical!) sudo ufw allow 22/tcp comment 'SSH' # Allow DNS queries (UDP/TCP 53) sudo ufw allow from any to any port 53 proto udp comment 'DNS Queries (UDP)' sudo ufw allow from any to any port 53 proto tcp comment 'DNS Queries (TCP)' # Allow zone transfers ONLY from secondary server sudo ufw allow from 114.130.223.3 to any port 53 proto tcp comment 'AXFR/IXFR from ns2' # Allow web console access ONLY from admin network (EXAMPLE: replace with your admin IP) sudo ufw allow from 192.168.1.0/24 to any port 5380 proto tcp comment 'DNS Web Console' # Enable UFW sudo ufw --force enable sudo ufw status verbose 6. Initial Web Console Setup Access web console: http://114.130.94.3:5380 Login with password set in DNS_SERVER_ADMIN_PASSWORD Navigate to Settings → General:Set DNS Server Domain: ns1.pioneer.com.bd Set Allow Zone Transfers: ✅ Enabled Set Allow Zone Transfers Only To: 114.130.223.3 (secondary IP) Navigate to Settings → TSIG:Click Add TSIG Key Name: pioneer-transfer-key Algorithm: HMACSHA256 Key: [paste your generated key from Step 2] Click Save Secondary DNS Server Configuration (ns2.pioneer.com.bd) 1. Create Persistent Storage Directory sudo mkdir -p /opt/technitium-dns/config sudo chown -R $USER:$USER /opt/technitium-dns 2. Create Docker Compose File cat > /opt/technitium-dns/docker-compose.yml << 'EOF' version: '3.8' services: dns-server: image: technitium/dns-server:latest container_name: technitium-dns restart: unless-stopped ports: - "53:53/tcp" - "53:53/udp" - "5380:5380/tcp" # Web console port volumes: - ./config:/etc/dns/config environment: - DNS_SERVER_DOMAIN=ns2.pioneer.com.bd - DNS_SERVER_ADMIN_PASSWORD=<STRONG_PAWD> # CHANGE THIS - DNS_SERVER_PREFER_IPV4=true - DNS_SERVER_RECURSIVE=false # Secondary typically doesn't need recursion cap_add: - NET_ADMIN networks: - dns-net networks: dns-net: driver: bridge EOF 3. Deploy Secondary DNS Server cd /opt/technitium-dns sudo docker compose up -d 4. Configure UFW Firewall Rules (Secondary) # Reset UFW sudo ufw --force reset sudo ufw default deny incoming sudo ufw default allow outgoing # Allow SSH sudo ufw allow 22/tcp comment 'SSH' # Allow DNS queries (UDP/TCP 53) sudo ufw allow from any to any port 53 proto udp comment 'DNS Queries (UDP)' sudo ufw allow from any to any port 53 proto tcp comment 'DNS Queries (TCP)' # Allow zone transfer requests TO primary server (outbound) # UFW doesn't block outbound by default, but we'll be explicit sudo ufw allow out to 114.130.94.3 port 53 proto tcp comment 'AXFR/IXFR to ns1' # Allow web console access ONLY from admin network sudo ufw allow from 192.168.1.0/24 to any port 5380 proto tcp comment 'DNS Web Console' # Enable UFW sudo ufw --force enable sudo ufw status verbose 5. Configure Secondary Server via Web Console Access web console: http://114.130.223.3:5380 Login with admin password Navigate to Settings → TSIG:Add identical TSIG key as primary:Name: pioneer-transfer-key Algorithm: HMACSHA256 Key: [same key as primary] Navigate to Zones → Add Zone:Zone Type: Secondary Zone Name: pioneer.com.bd Primary Server: 114.130.94.3 TSIG Key Name: pioneer-transfer-key Click Save The secondary will automatically initiate zone transfer from primary within 5 minutes. ******************** FIX ******************** 1. Check Docker Container Status # Check if container exists/is running sudo docker ps -a # Check container logs for errors sudo docker logs technitium-dns 2>&1 | tail -50 Expected failure symptoms: bind: address already in use → Port conflict permission denied → AppArmor/SELinux issue Container exits immediately → Configuration error 2. Free Up Port 53 (Critical for Debian 12) Disable systemd-resolved (Recommended for DNS servers) # Stop and disable systemd-resolved sudo systemctl stop systemd-resolved sudo systemctl disable systemd-resolved # Remove symlink to prevent conflicts sudo rm -f /etc/resolv.conf echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf # Verify port 53 is free sudo ss -tulpn | grep ':53' # Should return NO OUTPUT (port is free) 3. Fix Docker Compose Configuration (Host Networking Required) The default bridge networking doesn’t work reliably for DNS servers on Linux. Switch to host networking: cat > /opt/technitium-dns/docker-compose.yml << 'EOF' version: '3.8' services: dns-server: image: technitium/dns-server:latest container_name: technitium-dns restart: unless-stopped network_mode: "host" # CRITICAL: Use host networking for DNS volumes: - ./config:/etc/dns/config environment: - DNS_SERVER_DOMAIN=ns1.pioneer.com.bd - DNS_SERVER_ADMIN_PASSWORD=<STRONG-PWD> # CHANGE THIS - DNS_SERVER_PREFER_IPV4=true - DNS_SERVER_RECURSIVE=true cap_add: - NET_ADMIN EOF 4. Rebuild Container with Fixed Configuration cd /opt/technitium-dns # Stop and remove existing container (if any) sudo docker compose down # Pull latest image (ensure you have newest version) sudo docker pull technitium/dns-server:latest # Start with host networking sudo docker compose up -d # Wait 15 seconds for startup sleep 15 # Verify container is running sudo docker ps -f name=technitium-dns --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" 5. Verify Ports Are Now Bound # Check if ports 53 and 5380 are listening sudo ss -tulpn | grep -E ':(53|5380)' # Expected output: # tcp LISTEN 0 4096 *:5380 *:* users:(("docker-proxy",pid=...,fd=...)) # tcp LISTEN 0 4096 *:53 *:* users:(("docker-proxy",pid=...,fd=...)) # udp UNCONN 0 0 *:53 *:* users:(("docker-proxy",pid=...,fd=...)) If you still see no output, check logs immediately: sudo docker logs technitium-dns 2>&1 | grep -i "error\|fail\|exception" 6. Test Web Console # Test locally on the server first (bypasses firewall/UFW) curl -I http://localhost:5380 # Expected: HTTP/1.1 200 OK or 302 Found (redirect to login) After applying these fixes, your netstat should show: root@ns1:/opt/technitium-dns# netstat -plntu | grep -E ':(53|5380)' tcp6 0 0 :::5380 :::* LISTEN 12345/docker-proxy tcp6 0 0 :::53 :::* LISTEN 12346/docker-proxy udp 0 0 0.0.0.0:53 0.0.0.0:* 12347/docker-proxy SECURITY HARDENING RECOMMENDATIONS ++++++++++++++++++++++ Restrict Web Console Access:Never expose port 5380 to the public internet Use SSH tunneling: ssh -L 5380:localhost:5380 user@ns1.pioneer.com.bd Then access via http://localhost:5380 Enable DNSSEC (in Web Console → Zones → pioneer.com.bd → DNSSEC):Sign your zone for authenticity. Publish DS records to your registrar Rate Limiting:Web Console → Settings → Advanced → Rate Limiting Set queries/sec limits to prevent abuse Regular Backups # Backup config directory daily tar -czf /backup/technitium-dns-$(date +%Y%m%d).tar.gz /opt/technitium-dns/config Automatic Security Updates sudo apt install -y unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades Administrations Configurations (Linux) Networking DebianDebian 12DNSDNS ServerMaster-Slave DNSPrimary-Secondary DNSTechnitium