> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dnzwithazee.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Port 53 and systemd-resolved

> Free port 53 when systemd-resolved or another DNS server already uses it.

Ubuntu, Debian, Fedora and many other distributions run **systemd-resolved**, which already listens
on `127.0.0.53:53`. DNZ then can't bind `0.0.0.0:53`:

```text theme={null}
error: cannot bind DNS (udp) on 0.0.0.0:53: Address already in use (os error 98)
Something already serves DNS here. On Ubuntu/Debian it is usually systemd-resolved on 127.0.0.53 ...
```

See what's using the port:

```bash theme={null}
sudo ss -lunp 'sport = :53'
```

## Option 1: turn off the stub listener (recommended)

**1. Turn off systemd-resolved's stub listener**

```bash theme={null}
sudo mkdir -p /etc/systemd/resolved.conf.d
printf '[Resolve]\nDNSStubListener=no\n' | sudo tee /etc/systemd/resolved.conf.d/dnz.conf
```

**2. Repoint /etc/resolv.conf**

`/etc/resolv.conf` usually points at the `127.0.0.53` stub, which no longer exists. Point it at
systemd-resolved's real DNS list, so this server can still resolve names itself (`apt update`,
`curl` and so on):

```bash theme={null}
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
```

> [!WARNING]
>
> Skip this and the rest of the server (`apt`, `curl` and so on) can no longer resolve any name
> once the stub is off. DNZ itself keeps working: see [DNZ's own lookups](#dnzs-own-lookups).

**3. Restart systemd-resolved, then DNZ**

```bash theme={null}
sudo systemctl restart systemd-resolved
sudo systemctl restart dnz        # or: docker compose restart
```

**4. Check**

```bash theme={null}
sudo ss -lunp 'sport = :53'       # only dnz now
dig @127.0.0.1 example.com
```

### DNZ's own lookups

DNZ's own connections (Cloudflare, ACME, S3 backups, webhooks, block lists, the release check)
don't depend on `/etc/resolv.conf`. When the system resolver fails, DNZ looks the name up through
its own DNS server on loopback, then through public resolvers (`1.1.1.1`, `8.8.8.8`, `9.9.9.9`).
Connecting Cloudflare works even while `/etc/resolv.conf` still points at the dead stub.

### Use DNZ as this server's resolver

Writing `nameserver 127.0.0.1` into `/etc/resolv.conf` by hand doesn't last: systemd-resolved,
NetworkManager, netplan or DHCP rewrite the file. Tell systemd-resolved instead, and keep
`/etc/resolv.conf` linked to the file it maintains:

```bash theme={null}
sudo mkdir -p /etc/systemd/resolved.conf.d
printf '[Resolve]\nDNS=127.0.0.1\nDNSStubListener=no\n' | sudo tee /etc/systemd/resolved.conf.d/dnz.conf
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
sudo systemctl restart systemd-resolved
grep nameserver /etc/resolv.conf   # 127.0.0.1 first, then the network's DNS
```

`127.0.0.1` comes first and the DNS servers from DHCP stay behind it, so the machine still
resolves names while DNZ is stopped.

> [!TIP]
>
> If you use encrypted upstreams by name, add `#ip` to them to avoid a loop; see
> [upstream addresses](https://docs.dnzwithazee.com/dns/forwarding.md#upstream-address-format).

## Option 2: bind DNZ to one address

Leave systemd-resolved alone and listen only on the server's LAN address:

```bash /etc/dnz/dnz.env theme={null}
DNZ_DNS_ADDR=192.168.1.10:53
```

With Docker, publish the port on that address instead:

```yaml theme={null}
    ports:
      - "192.168.1.10:53:53/udp"
      - "192.168.1.10:53:53/tcp"
```

## Other programs on port 53

`dnsmasq`, `bind9`, `unbound` and `pihole-FTL` use port 53 too. Stop that program, for example
`sudo systemctl disable --now dnsmasq`, or bind DNZ to another address.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.