List every domain on an Nginx server with one command

An Nginx server often hosts more sites than anyone remembers: one per client, a few old ones forgotten, some redirects. Before you can monitor them, you need to know which ones are there.

The good news: Nginx can already tell you. You only have to ask it for its full configuration.

The command

Run it on the server, with administrator rights:

sudo nginx -T 2>/dev/null \
  | awk '$1=="server_name" {for(i=2;i<=NF;i++){gsub(";","",$i); print $i}}' \
  | grep -v -E '^(_|~|\*)' \
  | sort -u

nginx -T prints the full configuration, included files too. awk keeps the names declared by server_name, grep drops the special names and sort -u removes duplicates. You get one domain per line.

Why nginx -T rather than sites-enabled

Many guides tell you to list the /etc/nginx/sites-enabled folder. That works on a standard Debian or Ubuntu, and nowhere else.

  • On RHEL, Rocky or AlmaLinux, sites live in conf.d, not in sites-enabled.
  • One file can include another (include), sometimes from a custom folder.
  • A file in sites-enabled may be included nowhere: it then has no effect.
  • A control panel (Plesk, for example) puts its files wherever it likes.

nginx -T reads the configuration Nginx really applies, includes and all. It is the most reliable source.

The pitfalls

  • The name _ is a convention for a default block: it is not a domain.
  • A name that starts with ~ is a regular expression, not a domain. A wildcard name (*.example.com) covers several subdomains without naming any.
  • A block can exist only to redirect (return 301): the domain is configured, but the site lives elsewhere.
  • A configured domain is not necessarily live: its DNS may have pointed elsewhere for a long time.
  • Server blocks in the mail and stream modules are not websites. If you have some, read the full output rather than the list alone.
  • nginx -T prints the whole configuration, including key paths and sometimes secrets. Do not paste its raw output into a ticket or a chat.

What about sites that do not go through Nginx?

Containers behind Traefik, or an Apache or Caddy server on the same machine, do not show up in this list. Apache has its own equivalent command (apachectl -S), and Traefik declares its domains in container labels. Checking all four by hand is possible, but it is exactly what people forget to redo after each new client.

What StatOps does

The StatOps agent runs nginx -T itself, extracts the server_name names and ignores _ and regular expressions. The server then drops localhost, IP addresses, wildcards and .local names. It does the same for Apache, Caddy, Traefik and Docker.

The agent reads domain names only, not the content of your sites. It runs under a dedicated user, with a sudo rule limited to a few read-only commands, nginx -T among them.

Each domain found shows up in the dashboard, ready to be attached to a client. It is then monitored (availability, certificate) and appears in the monthly report. See how to monitor your clients’ sites.

Frequently asked questions

How do I list Nginx domains without nginx -T?

By reading the files in /etc/nginx by hand with grep -r server_name. You will miss files included from another folder and you will list inactive files. nginx -T avoids both mistakes.

Do I need to be root to run nginx -T?

Root or sudo, yes: Nginx reads files that only root can open, such as certificate keys. The StatOps agent uses a sudo rule limited to this command.

Read also