nginx — Web Server, Reverse Proxy and Load Balancer

Practical guide to nginx — service management, CLI commands, config testing, virtual hosts, TLS with Certbot and log analysis on Debian/Ubuntu and RHEL.

NGINX is one of the most widely deployed web servers on the internet, and it shines wherever many concurrent connections meet limited resources: thanks to its event-driven architecture, a single worker process handles thousands of connections in parallel. Beyond serving static files, NGINX acts as a reverse proxy, load balancer and TLS terminator in front of your applications. You control it through the lean nginx command and – on systemd distributions – through systemctl. This guide gathers the commands you reach for daily: service management, config testing, virtual hosts, certificates with Certbot and log analysis.

Service Management (systemctl)

systemctl start nginx — Start the NGINX web server.

systemctl start nginx

systemctl stop nginx — Stop the NGINX web server immediately.

systemctl stop nginx

systemctl restart nginx — Restart NGINX (stop + start). Briefly drops all active connections.

systemctl restart nginx

systemctl reload nginx — Reload NGINX configuration gracefully without dropping active connections.

systemctl reload nginx

systemctl status nginx — Show NGINX service status, PID, uptime, and recent log output.

systemctl status nginx

systemctl enable nginx — Enable NGINX to start automatically on system boot.

systemctl enable nginx

systemctl disable nginx — Disable NGINX from starting automatically on boot.

systemctl disable nginx

systemctl is-active nginx — Check if NGINX is currently running. Returns 'active' or 'inactive'.

systemctl is-active nginx

nginx CLI Commands

nginx -t — Test the NGINX configuration for syntax errors. Always run before reloading.

nginx -t

nginx -T — Test configuration and dump the entire resolved configuration to stdout.

nginx -T

nginx -s reload — Send the reload signal to the running NGINX master process (graceful config reload).

nginx -s reload

nginx -s stop — Send the stop signal to NGINX (fast shutdown, drops connections immediately).

nginx -s stop

nginx -s quit — Send the quit signal to NGINX (graceful shutdown, waits for requests to finish).

nginx -s quit

nginx -s reopen — Reopen log files. Used after rotating logs to start writing to the new file.

nginx -s reopen

nginx -v — Show the NGINX version.

nginx -v

nginx -V — Show the NGINX version, compiler flags, and all compiled-in modules.

nginx -V

nginx -c /path/to/nginx.conf — Start NGINX with a specific configuration file instead of the default.

nginx -c /etc/nginx/nginx.conf

nginx -p /path/to/prefix — Set the NGINX prefix path (used to resolve relative paths in the config).

nginx -p /etc/nginx

nginx -t && systemctl reload nginx — Validate config and reload only if there are no errors (recommended workflow).

nginx -t && systemctl reload nginx

Process Management

ps aux | grep nginx — List all running NGINX processes (master and worker processes).

ps aux | grep nginx

cat /var/run/nginx.pid — Show the PID of the NGINX master process.

cat /var/run/nginx.pid

kill -HUP $(cat /var/run/nginx.pid) — Send HUP signal to the master process to reload configuration gracefully.

kill -HUP $(cat /var/run/nginx.pid)

kill -USR1 $(cat /var/run/nginx.pid) — Reopen log files by sending USR1 signal (equivalent to nginx -s reopen).

kill -USR1 $(cat /var/run/nginx.pid)

kill -WINCH $(cat /var/run/nginx.pid) — Gracefully shut down worker processes (master stays alive, used during upgrades).

kill -WINCH $(cat /var/run/nginx.pid)

Virtual Hosts (Debian/Ubuntu)

ls /etc/nginx/sites-available/ — List all available virtual host configuration files.

ls /etc/nginx/sites-available/

ls /etc/nginx/sites-enabled/ — List all currently enabled virtual host configurations (symlinks).

ls /etc/nginx/sites-enabled/

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/ — Enable a virtual host by creating a symlink in sites-enabled/.

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

rm /etc/nginx/sites-enabled/example.com — Disable a virtual host by removing the symlink from sites-enabled/.

rm /etc/nginx/sites-enabled/example.com

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/ && nginx -t && systemctl reload nginx — Enable a site, validate config, and reload NGINX in one step.

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/ && nginx -t && systemctl reload nginx

nginx -T | grep server_name — List all configured server_name values across all virtual hosts.

nginx -T | grep server_name

Configuration Directories

/etc/nginx/nginx.conf — Main NGINX configuration file. Includes sites-enabled/ and conf.d/.

nano /etc/nginx/nginx.conf

/etc/nginx/sites-available/ — Directory for virtual host config files (Debian/Ubuntu). Not active until symlinked.

ls /etc/nginx/sites-available/

/etc/nginx/sites-enabled/ — Directory containing symlinks to active virtual host configs (Debian/Ubuntu).

ls /etc/nginx/sites-enabled/

/etc/nginx/conf.d/ — Drop-in config directory. All *.conf files here are automatically included.

ls /etc/nginx/conf.d/

/etc/nginx/snippets/ — Reusable configuration snippets (e.g. ssl-params.conf, fastcgi-php.conf).

ls /etc/nginx/snippets/

/var/log/nginx/ — Default log directory containing access.log and error.log.

ls /var/log/nginx/

Logs

tail -f /var/log/nginx/access.log — Follow the NGINX access log in real-time.

tail -f /var/log/nginx/access.log

tail -f /var/log/nginx/error.log — Follow the NGINX error log in real-time.

tail -f /var/log/nginx/error.log

tail -f /var/log/nginx/error.log | grep 'crit\|emerg\|alert' — Watch the error log and filter for critical-level messages only.

tail -f /var/log/nginx/error.log | grep 'crit\|emerg'

grep ' 500 \| 502 \| 503 ' /var/log/nginx/access.log — Find 5xx server error responses in the access log.

grep ' 500 \| 502 \| 503 ' /var/log/nginx/access.log

awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20 — Show the top 20 IP addresses by request count from the access log.

awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

nginx -t 2>&1 | grep -v 'successful' — Run a config test and show only warnings and errors (suppress the OK message).

nginx -t 2>&1 | grep -v 'successful'

journalctl -u nginx -f — Follow NGINX log output via systemd journal (includes start/stop events).

journalctl -u nginx -f

journalctl -u nginx --since '1 hour ago' — Show NGINX journal entries from the last hour.

journalctl -u nginx --since '1 hour ago'

SSL / TLS & Certbot

certbot --nginx -d example.com -d www.example.com — Obtain and automatically install a Let's Encrypt certificate for NGINX.

certbot --nginx -d example.com -d www.example.com

certbot certonly --nginx -d example.com — Obtain a certificate but do not modify NGINX config (manage SSL manually).

certbot certonly --nginx -d example.com

certbot renew --dry-run — Simulate the automatic renewal process to verify it would succeed.

certbot renew --dry-run

certbot renew — Renew all certificates that are due for renewal (run via cron or systemd timer).

certbot renew

certbot certificates — List all managed Let's Encrypt certificates and their expiry dates.

certbot certificates

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/self.key -out /etc/nginx/ssl/self.crt — Generate a self-signed SSL certificate valid for 365 days.

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.crt

openssl dhparam -out /etc/nginx/dhparam.pem 2048 — Generate a Diffie-Hellman parameter file for stronger SSL key exchange.

openssl dhparam -out /etc/nginx/dhparam.pem 2048

openssl s_client -connect example.com:443 -servername example.com — Test an SSL connection and inspect the certificate chain.

openssl s_client -connect example.com:443 -servername example.com

Debugging & Inspection

curl -I http://localhost — Send a HEAD request to the local NGINX and inspect response headers.

curl -I http://localhost

curl -I -H 'Host: example.com' http://localhost — Test a specific virtual host by overriding the Host header.

curl -I -H 'Host: example.com' http://localhost

curl -sk https://localhost -o /dev/null -w '%{http_code}' — Check the HTTP status code returned by NGINX over HTTPS.

curl -sk https://localhost -o /dev/null -w '%{http_code}'

nginx -T | grep -A5 'server_name example.com' — Find the full server block for a specific domain in the dumped configuration.

nginx -T | grep -A5 'server_name example.com'

ss -tlnp | grep nginx — Show which ports NGINX is listening on.

ss -tlnp | grep nginx

strace -p $(cat /var/run/nginx.pid) -e trace=network — Trace network system calls of the NGINX master process for low-level debugging.

strace -p $(cat /var/run/nginx.pid) -e trace=network

Conclusion

NGINX rewards a disciplined workflow: validate every change with nginx -t before you reload with nginx -s reload or systemctl reload nginx – the reload is graceful, so active connections never get dropped. After a log rotation, nginx -s reopen makes NGINX start writing to the fresh log files. If you want to fine-tune server, location and upstream blocks, you'll find the matching directives in the nginx-conf configuration reference.

Further Reading

  • apache – the classic web server with modular configuration
  • caddy – modern web server with automatic HTTPS
  • certbot – obtain and renew Let's Encrypt certificates