Skip to main content
An Nginx can be a proxy of DNZ, next to Traefik, Caddy and DNZ Proxy. Traefik and Caddy fetch their configuration from DNZ, while open source Nginx only reads files, so a small program runs next to it: dnz-nginx-agent. It connects out to DNZ with the proxy’s token, as Traefik and Caddy do; DNZ never reaches into the server. Moving to DNZ Proxy instead gets you every feature: importing an Nginx configuration makes that a matter of checking a plan. It works in two ways, picked when it is added:
  • Read only: DNZ keeps DNS records for the sites in your own configuration, and writes nothing to Nginx. The agent reads the server_names from nginx -T, on the server.
  • Managed: DNZ writes a file of its own under conf.d, checks it with nginx -t, and reloads only when that passes. Routes are made as for any proxy (below). Your own files stay as they are.

Versions

The agent shares DNZ’s version number, and the commands name that version, never latest: latest can be newer than the DNZ it talks to.
The first DNZ release with the agent is v2.5.0.
  • An older agent keeps working, and the proxy’s page marks it Older than DNZ.
  • An agent newer than its DNZ is refused with a message naming both versions, and nothing is written to Nginx until they match.
Older than 1.18 is refused with a clear message: the agent says so on the proxy’s page and in its log, and reads and writes nothing. The binary is for x86_64 and aarch64, Linux with glibc 2.34 or newer (so not Alpine: use the image).

Adding one

Proxy → Proxies → Add proxy → Nginx, then Nginx proxy (managed) or Keep my Nginx configuration (read only), or:
You get the proxy’s token, once, with the steps filled in. A read-only proxy’s settings are those of any read-only proxy: the addresses or CNAME DNS answers with, DNS only or through DNZ, the TTL, the division whose zones get the records, how often the sites are read, and whether a site that leaves keeps its records. A new one starts paused: install the agent, look at the Preview, and apply it.

Installing the agent

DNZ’s address is the one the Nginx server reaches DNZ on, not the one in your browser. localhost or 127.0.0.1 works only when DNZ runs on that same server.
On the server that runs Nginx, as one paste. It needs root: nginx -t and nginx -T read Nginx’s certificates, and a reload signals its master process. Set the three values at the top:
The Add proxy dialog shows this with the values filled in. Follow it with journalctl -u dnz-nginx-agent -f. SHA256SUMS in each release has the binary’s checksum.

Settings

DNZ_NGINX_LOG sets how much it logs (info by default).

A new token

The token is shown once. Connect on the proxy’s card makes a new one (the old one stops working), or dnz proxy nginx token web-1.

Updating the agent

Update DNZ first: an agent newer than its DNZ is refused.
In Docker, change the image’s tag and start it again. Updating the agent from DNZ, as DNZ Proxy nodes do, isn’t there yet.

Removing the agent

Nginx keeps running with its own files. A managed proxy’s file stays until you remove it and reload: sudo rm /etc/nginx/conf.d/dnz.conf && sudo nginx -s reload. In Docker: docker rm -f dnz-nginx && docker volume rm dnz-nginx. Then remove the proxy in DNZ, with or without its records.

Read only

Which hostnames get records, and how, works as for any read-only proxy. From nginx -T:
  • Every server_name of a server block in http. .example.com is example.com and *.example.com.
  • _, regular expressions and www.example.* are no name DNS could hold; they show as skipped on the proxy’s page. stream and mail aren’t sites.
  • A read that fails changes nothing, and neither does an agent that stopped: its last report counts for 3 minutes, and after that a sync says so and leaves the records alone. An Nginx with no name at all fails too, so one that just started empty never looks like sites that left.
nginx -T prints every file Nginx reads. The agent takes only the names from it; the rest never leaves the server.

Managed

DNZ builds the configuration from the proxy’s routes, upstreams and middlewares, as for Traefik and Caddy. On every change the agent:
  1. writes it to a file of its own, /etc/nginx/conf.d/dnz.conf (--conf-file), never touching your files;
  2. runs nginx -t, and checks that Nginx really reads that file;
  3. reloads Nginx only if that passes.
A refused configuration changes nothing that serves: the last good file goes back at once, and Nginx reads files only when it reloads. What nginx -t said shows on the proxy’s page and under dnz proxy nginx show, and dnz_nginx_config_check_ok goes to 0. It tries again a minute later, as the cause may be in your own files. The file sits beside your configuration, so it never takes default_server: a name no route serves gets whatever your own configuration answers.

Certificates

HTTPS routes get their certificates from DNZ’s automatic certificates, as on a DNZ Proxy. The agent receives them and writes them where only root reads them, in certs/ under its state folder. Names under DNZ’s private CA get theirs from it. HTTP-01 is answered through a location for the challenge in what DNZ generates, which passes the question on to DNZ: Nginx must reach DNZ at the address the agent uses. A wildcard needs DNS-01. Until a name has its certificate it has no HTTPS on Nginx (it serves plain HTTP if a route says so), and the proxy’s page says so.

What Nginx gets

What it doesn’t get

Left out, and listed on the proxy’s page with a warning, as for Caddy. Never dropped without a word:
  • DNZ Proxy only: the web application firewall, the browser check (under attack), the waiting room, the cache, shields, AI crawler controls and DNZ Proxy’s analytics. The route is served without them.
  • The route stays out altogether when what it would lose is its lock: sign-in through DNZ (Nginx’s auth_request can’t pass DNZ’s redirect to the visitor, and the route dialog refuses it here) or a firewall.
  • A route’s rules, and conditions on a method, header, query or address: DNZ writes no if. The route dialog refuses rules here; a route with such conditions stays out, and is named.
  • Active health checks aren’t in open source Nginx: it takes a server out after visits fail. Per-server certificate checks and health paths are DNZ Proxy only; sticky sessions by cookie too.
  • TCP and UDP routes and a name each proxy looks up itself: refused or left out, and named.
  • A priority: Nginx picks a location by its path. Entry points: it listens on 80 and 443.
  • DNS filtering’s block page: it would need the default server of your Nginx.
The whole file is on the proxy’s page (GET /api/proxies/{id}/nginx, dnz proxy nginx show --json). A long hostname may need server_names_hash_bucket_size raised in your nginx.conf: nginx -t says so.

Commands

An assistant reads the same with the MCP tool proxy_nginx, and writes nothing. Prometheus: dnz_nginx_agent_connected, dnz_nginx_agent_last_seen_timestamp_seconds, dnz_nginx_agent_behind_dnz, dnz_nginx_problem, dnz_nginx_config_check_ok, dnz_nginx_reloads_total, dnz_nginx_reload_failures_total and dnz_nginx_last_reload_timestamp_seconds, each per proxy.