A typo in an Nginx config can take every site on a server offline — but only if you apply it without checking. Two habits make Nginx changes safe: test before applying, and reload instead of restart.

Test the configuration

sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

On error, it tells you exactly where:

nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/example.com:42
nginx: configuration file /etc/nginx/nginx.conf test failed

nginx -t checks syntax, that referenced files exist (certificates, includes), and some semantic issues (duplicate listen options, unknown directives). It doesn’t check that upstream apps are running or that your rules do what you intend.

-q suppresses non-error output — handy in scripts.

See the full, merged configuration

sudo nginx -T | less

-T tests and prints the entire configuration with all includes expanded, each prefixed by its file name. Use it to:

  • find which file defines a server_name or location;
  • spot duplicate server names (grep server_name);
  • check what a site actually inherits from nginx.conf and conf.d/.

Reload, don’t restart

sudo systemctl reload nginx        # or: sudo nginx -s reload

On reload, the master process re-reads the config. If it’s valid, it starts new worker processes with the new config and tells old workers to finish their current requests and exit. No connections are dropped. If the new config is invalid, the master logs an error and keeps running with the old config.

restart stops Nginx completely and starts it again — active connections are cut, and if the new config is broken, Nginx doesn’t come back up. Only restart when needed (e.g. after upgrading the Nginx binary, or changing certain settings like worker_rlimit_nofile in some setups).

Always combine:

sudo nginx -t && sudo systemctl reload nginx

The reload runs only if the test passes.

Signals reference

Command Effect
nginx -s reload Reload configuration gracefully
nginx -s reopen Reopen log files (used by logrotate)
nginx -s quit Graceful shutdown
nginx -s stop Fast shutdown

After a reload: check it worked

sudo systemctl status nginx --no-pager
sudo tail -n 20 /var/log/nginx/error.log
curl -sI https://example.com | head -3

If the reload silently failed (the master kept the old config), the error log says so.

Editing safely

  • Keep a backup before larger edits: sudo cp -a /etc/nginx /root/nginx-backup-$(date +%F) — or track /etc/nginx in Git (etckeeper does this for all of /etc; see etckeeper).
  • Disable a site instead of deleting it: remove the symlink from sites-enabled.
  • One change at a time, test, reload, verify.
  • Use includes/snippets for shared settings (SSL, security headers) so a fix applies everywhere consistently.

Recovering from a broken config

If Nginx is down because of a bad restart:

sudo nginx -t                         # find the error
sudo journalctl -u nginx -n 30 --no-pager

Fix the reported line (or move the offending site out of sites-enabled), then sudo systemctl start nginx.

Common startup errors:

  • bind() to 0.0.0.0:80 failed (98: Address already in use) — another process (Apache, a container) holds the port: sudo ss -tlnp | grep ':80'.
  • cannot load certificate "/etc/letsencrypt/live/…" — certificate path wrong or not yet issued.
  • duplicate default server — two server blocks with default_server on the same port.
  • unknown directive "brotli" — a module isn’t installed or loaded.

Automating config changes

Configuration management tools should validate before reloading too. In Ansible:

- name: Nginx site config
  ansible.builtin.template:
    src: site.conf.j2
    dest: /etc/nginx/sites-available/site.conf
    validate: nginx -t -c /etc/nginx/nginx.conf
  notify: Reload nginx

(Template validation of a single included file needs care — many people validate in the handler with nginx -t before reloading.) See Ansible playbooks.

Related: installing Nginx and Nginx server blocks.

  • Nginx
  • Configuration
  • Linux