Configuration & Usage

Here, you’ll learn how to configure ZeroDNS and launch it with Docker. I recommend copying the docker-compose.yml file below before moving about with getting things from ZeroTier.

Getting the Docker container

Note that this container follows the general architecture of LinuxServer containers. You can read more about those here.

docker-compose.yml (recommended)
version: "3.8"

services:
  zerodns:
    container_name: zerodns
    image: jmuchovej/zerodns:latest
    ports:
      - "53:5353/udp"
      - "53:5353/tcp"
    devices:
      - "/dev/net/tun"
    cap_add:
      - "NET_ADMIN"
      - "SYS_ADMIN"
    restart: unless-stopped
    # All items above this line should be left untouched
    volumes:
      - "/path/to/zerodns/config:/config"
    environment:
      # This should be replace with the output of `id -u`
      PUID: 1000
      # This should be replace with the output of `id -g`
      PGID: 1000
      # This should closely match your `/etc/localtime`
      TZ: America/New_York
      # Your Access Token (described below)
      ACCESS_TOKEN: "SomeSuperDuperSecretToken"
      # TLDs are the ".com", ".org", etc. parts of a URL.
      TLDS: .com,.zt
    dns:
      - "127.0.0.1" # KEEP this entry, it MUST be first
      - "1.1.1.1"  # Change this to your preferred DNS servers
      - "1.0.0.1"  # Change this to your preferred DNS servers

docker.sh
#!/usr/bin/env bash

# Check the `docker-compose.yml` file for comments on what to change

docker run \
    jmuchovej/zerodns:latest \
    -n zerodns --rm \
    --restart unless-stopped \
    --cap-add NET_ADMIN --cap-add SYS_ADMIN \
    --device /dev/net/tun \
    -p 53:5353/udp -p 53:5353/tcp \
    -v "/path/to/zerodns/config:/config" \
    -e PUID=1000 -e PGID=1000 -e TZ="America/New_York" \
    -e ACCESS_TOKEN="SomeSuperDuperSecretToken" \
    --dns 127.0.0.1 --dns 1.1.1.1 --dns 1.0.0.1

Check the comments in the docker-compose.yml file above for details on what items need to be changed (and how). This container requires the SYS_ADMIN1 and NET_ADMIN2 privileges – to learn more about what these do, take a look at the linked footnotes.

Collect the files & tokens for ZeroDNS to work

In your browser: Head to ZeroTier Central. We’ll need two things:

  1. an Access Token, and
  2. the Network ID (repeat this step for each newtork).

Using your favorite text editor:

  1. Replace SomeSuperDuperSecretToken with the Access Token you retrieved from here.
  2. Create a folder for ZeroDNS' configurations to live (e.g. zerodns).
  3. Create an empty <network-id>.conf file within zerodns using Network IDs you retrieved from here.
  4. Edit the docker-compose.yml (or docker command) accordingly, replacing environment variable values and DNS choices as you see fit.

Running ZeroDNS & configuring your local DNS

  1. Ensure you have no services using port 53 (the standard DNS port) as we’ll need this for ZeroDNS to work. You can check using lsof | grep ":53". Any services you find using port 53 will need to be stopped/disabled. Check your OS’s manual/wiki on how to do that.
  2. Launch the ZeroDNS container using your typical docker compose up command(s). If you’re unfamiliar with docker compose, take a look at LinuxServer’s docker primer3.
  3. In your DNS settings, list 127.0.0.1 as your first entry (so that ZeroDNS) receives all outbound traffic and can resolve whatever network/TLD combinations your network uses.
  4. Optional: Reboot your device to clear any network caches that may have been made.
You should now be able to run ping, dig, nslookup, and the like from your devices (that also run ZeroDNS).

  1. The SYS_ADMIN essentially allows eroDNS to create /dev/net/tun and bind to privileged ports (ports < 1024). This lets ZeroDNS work as your DNS server since port 53 is the expected listener for DNS queries. ↩︎

  2. The NET_ADMIN capability allows ZeroDNS to create /dev/net/tun and bind to privileged ports (ports < 1024). This lets ZeroDNS work as your DNS server since port 53 is the expected listener for DNS queries. ↩︎

  3. For a solid primer on Docker, head over to LinuxServer’s Docs. Many parameters passed into the containers are all well-described there. ↩︎