What’s up guys! Welcome or welcome back to the blog. Now that our lab environment is up and running, it’s time to start laying down some of the core services that everything else will depend on. First up: DNS.

You’ve probably heard the classic joke: “It’s always DNS.” That’s because DNS is the backbone of your environment—it touches nearly everything. Think of it like a phone book. Without it, your systems wouldn’t know how to find anything by name.

Running your own DNS server isn’t just about speed. It’s about privacy and control. Keeping DNS queries local means you’re not handing your network data to third-party providers. In today’s post, we’re going to set up BIND9—an open-source DNS server that gives you complete control and helps you understand DNS from the inside out.

What is DNS?

DNS (Domain Name System) translates human-friendly names like google.com into IP addresses that machines use to communicate. It’s how you go from typing a name in your browser to loading a website.

In our setup, DNS will help internal devices refer to each other by name. Instead of remembering IP addresses, we’ll use fully qualified domain names (FQDNs). That makes everything cleaner and scalable.

Step 1: Set Up an LXC Container for BIND9

I’m using Proxmox for virtualization and running all my core services—including DNS and certificate authority—inside LXC containers. If you’re not familiar with LXC, check out my Proxmox Core Components video.

Pull down a container template (Ubuntu 25.04 in my case).

Create a new LXC container in Proxmox: 

  • Give it a descriptive name (e.g. dns-test).
  • Use an unprivileged container with nesting enabled for better security and full systemd support.
  • Assign a static IP (e.g. 192.168.2.3/24).
  • Set the gateway (e.g. 192.168.2.1).
  • Make sure “Start at boot” is enabled.

Once your container is created, SSH into it or use the Proxmox console. Make sure it has internet access and run the usual update commands:

  • apt update && apt upgrade -y

Step 2: Install BIND9

Inside the container:

  • apt install bind9 bind9utils bind9-doc -y
  • That will install the DNS server, its utilities, and documentation.

Step 3: Set Proper Permissions

Make sure the bind user owns the following directories:

  • chown -R bind:bind /etc/bind
  • chown -R bind:bind /var/cache/bind
  • mkdir -p /var/log/bind && chown -R bind:bind /var/log/bind

This prevents permission issues when BIND tries to read or write to those folders.

Step 4: Configure the Forward Zone

Edit /etc/bind/named.conf.local to define your forward zone:


zone "testlab.com" {
    type master;
    file "/etc/bind/db.teslab.com";
    allow-update { none; };
};


Then copy the default zone file to match your domain:

  • cp /etc/bind/db.local /etc/bind/db.testlab.com

Edit db.ktechlab.com and define your SOA and A records. For example:

Step 5: Configure the Reverse Zone

In the same named.conf.local file, add:


zone "2.168.192.in-addr.arpa" {
type master;
file "/etc/bind/db.192.168.2";
allow-update { none; };
};


Create the reverse zone file:

  • cp /etc/bind/db.127 /etc/bind/db.192.168.2

Update the PTR record to match your A record:

Step 6: Set Up a Recursive Resolver.

To make BIND recursive, create a root hints file:

  • wget -O /etc/bind/db.root https://www.internic.net/domain/named.cache

Then configure /etc/bind/named.conf.options like this:

options {
directory "/var/cache/bind";

// No forwarders  this server will perform full recursion
// forwarders { };

// Allow queries only from your subnet
allow-query {
192.168.2.0/24;
};

// Allow recursive queries only from your subnet
allow-recursion {
192.168.2.0/24;
};

recursion yes;

dnssec-validation auto;

// Listen only on this server's IP
listen-on {
192.168.2.3;
};

// Disable IPv6 completely
//listen-on-v6 { none; };
};

This locks down your DNS server so it only responds to your subnet and queries root servers directly (not public resolvers).

Step 7: Restart and Test

Restart BIND:

  • systemctl restart bind9
  • systemctl status bind9

Test forward and reverse lookups:

  • dig @localhost teslab.com
  • dig -x 192.168.2.3 @localhost

Update your container’s /etc/resolv.conf to use the new DNS server:

  • nameserver 192.168.2.3
  • search ktechlab.com

Final Thoughts

That’s it! You now have a fully functional, recursive BIND9 DNS server running in a Proxmox LXC container. We covered forward zones, reverse zones, and root hint configuration. Manual configuration takes effort, but it teaches you how DNS actually works under the hood.

In future videos, we’ll build on this foundation by setting up a certificate authority to secure internal services and eliminate SSL errors. If you enjoy this kind of content don’t forget to subscribe, and—as always—stay geeking. Peace!

About the author

Quiet Engineer

A lifelong learner with a passion for tech and soccer. Koroma Tech is where I share my journey and help others along the way. I enjoy taking on challenges and see each one as a chance to learn and grow.

>