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_nameorlocation; - spot duplicate server names (
grep server_name); - check what a site actually inherits from
nginx.confandconf.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/nginxin 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 withdefault_serveron 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.