Skip to content

Installation

Trench is pure Python and needs 3.11 or newer. Nothing else is required — the admin console ships prebuilt inside the package, so there is no Node toolchain and no build step.

Trench is installed from GitHub. It is not published to any package index, so a bare pip install trench does not install this project — whatever it finds under that name is somebody else's.

Nothing is tagged yet

There is no tagged release, so the release wheel and docker pull ghcr.io/dev-doshi/trench do not exist yet. Install from the main branch or from a checkout until the first v* tag is pushed.

From GitHub

Into a virtual environment of its own — that is also the one shape of install Trench can update itself in (see Updating Trench itself):

python3 -m venv /opt/trench
/opt/trench/bin/pip install "git+https://github.com/dev-doshi/trench"

Pin a tag once releases exist:

/opt/trench/bin/pip install "git+https://github.com/dev-doshi/trench@v2.0.0"

From source

git clone https://github.com/dev-doshi/trench
cd trench
pip install -e ".[dev]"
pytest -q

That installs two commands: trenchd (the server) and trench (the CLI that talks to a running one).

trench --version
python3 -m trench --dns-port 5354 --upstream 1.1.1.1:53 \
                  --source data/default_blocklist.txt

data/default_blocklist.txt is resolved against the package when there is no such file in the working directory, so that same line works from a checkout and from an installed copy. Without --source nothing is blocked: Trench ships no list it did not compile, and the bundled seed list is 44 names — enough to prove the path works, not enough to be coverage.

Docker Compose

Also from a checkout — docker-compose.yml builds the image locally, so there is nothing to pull:

git clone https://github.com/dev-doshi/trench
cd trench
cp trench.example.yaml trench.yaml   # gitignored, so a clone has none
docker compose up -d

Run from anywhere else it fails with no configuration file provided: not found, which only means Compose could not see the file.

Skip the cp and Docker creates an empty directory named trench.yaml in its place, and the container fails to start.

It uses host networking, which is what lets the container serve DNS to the rest of the LAN, and mounts that trench.yaml. As copied, the example is a safe starter, not a LAN server: DNS answers on 127.0.0.1:5354 and the console on 127.0.0.1:8089, and DoT, DoH and DoQ are off until you give them a certificate. To serve the network, set server.do53.host to 0.0.0.0 and port to 53, and turn on security.rate_limit — the comments in the file walk through each. The database and blocklists live in the trench-data volume and survive rebuilds.

On macOS and Windows, Docker Desktop does not give a container the host's network the way Linux does; treat Compose there as a way to build and smoke-test the image, not as a way to serve your LAN.

On a Raspberry Pi use deploy/docker-compose.raspi.yml instead — it adds the memory ceiling that keeps a blocklist rebuild from being OOM-killed. See Deployment.

After the first release

Neither of these works until a v* tag has been pushed and the release workflow has published the artifacts. They are here so the commands are written down, not because they will work today.

Each GitHub release carries the wheel as an asset, and GitHub shows its sha256 next to it:

pip install https://github.com/dev-doshi/trench/releases/download/v2.0.0/trench_dns-2.0.0-py3-none-any.whl
docker run -d --name trench \
  --network host \
  -v /etc/trench/trench.yaml:/data/trench.yaml \
  -v trench-data:/data \
  ghcr.io/dev-doshi/trench:2.0.0

The image runs as root only long enough to bind port 53; set server.user in the config and it drops to an unprivileged account immediately afterwards.

First run

The shipped configuration is deliberately harmless: DNS on 127.0.0.1:5354, admin console on 127.0.0.1:8089, nothing exposed to the network.

cp trench.example.yaml /etc/trench/trench.yaml
trenchd --config /etc/trench/trench.yaml

Or without a config file at all, to try it out:

python3 -m trench --dns-port 5354 --upstream 1.1.1.1:53 \
                    --source data/default_blocklist.txt
dig @127.0.0.1 -p 5354 doubleclick.net     # 0.0.0.0 — blocked
dig @127.0.0.1 -p 5354 example.com         # resolves normally

The seed list is small on purpose (a few dozen domains, enough to prove the sinkhole works offline). Real coverage comes from the remote lists in filtering.sources; see Configuration.

The admin console generates an administrator password on first start and prints it once, to the log. If you miss it:

trench passwd            # set one offline, on the box

Serving the network

Two changes turn the loopback default into a LAN resolver, and they belong together:

server:
  do53:
    host: 0.0.0.0
    port: 53
  user: trench         # shed root once :53 is bound

security:
  rate_limit: 100        # queries/sec per client
  rate_burst: 200

Without rate_limit, anything that can reach port 53 can use the server for amplification. Trench logs a warning at startup if it finds a network-facing listener with rate limiting off, but it will still start — see Security.

Point clients at it by setting the DNS server in your router's DHCP settings.