CLI Management
Learning Focus
Leave this lesson with a working understanding of cli management that you can apply immediately in production.
Every Nginx operation you need, from the terminal. No GUI, no web panel.
tmux Workflow
Keep your error log tailing in one pane while running commands in another:
# Pane 1: live error log
sudo tail -f /var/log/nginx/error.log
# Pane 2: your commands
Split: Ctrl+b % (vertical) or Ctrl+b " (horizontal)
Service Control
# === GRACEFUL RELOAD (zero downtime — use this for config changes) ===
sudo nginx -s reload
# or
sudo systemctl reload nginx
# === FULL RESTART (drops active connections) ===
sudo systemctl restart nginx
# Start / Stop
sudo systemctl start nginx
sudo systemctl stop nginx
# Status
sudo systemctl status nginx
# Enable / disable autostart
sudo systemctl enable nginx
sudo systemctl disable nginx
When to Use Which
| Situation | Command |
|---|---|
| Config file edited (server block, location, SSL) | nginx -s reload |
| Binary upgraded | systemctl restart nginx |
| PHP-FPM pool changed | systemctl reload php8.4-fpm |
| PHP ini changed | systemctl restart php8.4-fpm |
| Worker stuck / hung | systemctl restart nginx |
Config Testing
# Test syntax before reloading (run this EVERY time)
sudo nginx -t
# Test with full config dump (shows all includes merged)
sudo nginx -T
# Test specific config file
sudo nginx -t -c /etc/nginx/nginx.conf
# Test and reload in one safe command
sudo nginx -t && sudo nginx -s reload
Expected output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Version and Build Info
# Show version
nginx -v
# Show version and compile flags/modules
nginx -V
# Check which modules are compiled in
nginx -V 2>&1 | tr -- - '\n' | grep module
Signal Handling
Send signals directly to the master process:
# Get master PID
cat /run/nginx.pid
# Graceful reload (re-read config, keep serving)
sudo kill -HUP $(cat /run/nginx.pid)
# Graceful shutdown (finish current requests, then stop)
sudo kill -QUIT $(cat /run/nginx.pid)
# Fast shutdown (drop all connections)
sudo kill -TERM $(cat /run/nginx.pid)
# Reopen log files (after log rotation)
sudo kill -USR1 $(cat /run/nginx.pid)
# Upgrade binary gracefully (hot reload)
sudo kill -USR2 $(cat /run/nginx.pid)
Process Inspection
# Is Nginx running?
ps aux | grep nginx | grep -v grep
# Master process
ps aux | grep "nginx: master" | grep -v grep
# Worker count
ps aux | grep "nginx: worker" | grep -v grep | wc -l
# What ports is Nginx listening on?
sudo ss -tlnp | grep nginx
# Open file descriptors
sudo lsof -p $(cat /run/nginx.pid) | wc -l
# Nginx uptime
ps -p $(cat /run/nginx.pid) -o etime=
Log Access
# Live error log (most useful)
sudo tail -f /var/log/nginx/error.log
# Live access log
sudo tail -f /var/log/nginx/access.log
# Last N error lines
sudo tail -100 /var/log/nginx/error.log
# Search for a specific error
sudo grep "upstream" /var/log/nginx/error.log | tail -20
sudo grep "502\|503\|504" /var/log/nginx/access.log | tail -20
# Filter errors from last hour
sudo awk -v d="$(date '+%d/%b/%Y:%H')" '$0 ~ d' /var/log/nginx/error.log
# Per-site log (if configured)
sudo tail -f /var/log/nginx/example.com.error.log
Config File Management
# View main config
sudo cat /etc/nginx/nginx.conf
# List all site configs
ls -la /etc/nginx/sites-available/
ls -la /etc/nginx/sites-enabled/
ls -la /etc/nginx/conf.d/
# Enable a site (Debian/Ubuntu pattern)
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
# Disable a site
sudo rm /etc/nginx/sites-enabled/example.com
# Check what config files are loaded (from includes)
grep -rn "include" /etc/nginx/nginx.conf
# Search for server_name across all configs
sudo grep -rn "server_name" /etc/nginx/
# Search for all root directives
sudo grep -rn "^[[:space:]]*root " /etc/nginx/
# Find all proxy_pass targets
sudo grep -rn "proxy_pass" /etc/nginx/
SSL / TLS from CLI
# Test TLS handshake
openssl s_client -connect example.com:443 -servername example.com
# Check cert expiry
openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate
# Check cert subject and SANs
openssl s_client -connect example.com:443 2>/dev/null | \
openssl x509 -noout -subject -subjectAltName
# Verify cert file on disk
sudo openssl x509 -in /etc/ssl/certs/example.com.crt -noout -text | \
grep -E "Subject:|DNS:|Not After"
# Check private key matches certificate
sudo openssl x509 -noout -modulus -in /etc/ssl/certs/example.com.crt | openssl md5
sudo openssl rsa -noout -modulus -in /etc/ssl/private/example.com.key | openssl md5
# Both must output the same hash
Network Diagnostics
# Count HTTPS connections
sudo ss -tn state established '( dport = :443 )' | wc -l
# All Nginx connections
sudo ss -tnp | grep nginx | head -20
# Test response time from server
curl -w "Connect: %{time_connect}s | TTFB: %{time_starttransfer}s | Total: %{time_total}s\n" \
-o /dev/null -s https://example.com/
# Test with Host header
curl -H "Host: example.com" -I http://localhost/
# Test gzip
curl -H "Accept-Encoding: gzip" -I https://example.com/ | grep content-encoding
# Test HTTP/2
curl -I --http2 https://example.com/ | head -1
PHP-FPM Management
# Status
sudo systemctl status php8.4-fpm
# Restart (after php.ini changes)
sudo systemctl restart php8.4-fpm
# Reload (after pool config changes)
sudo systemctl reload php8.4-fpm
# PHP version
php8.4 -v
# or
php -v
# Loaded php.ini
php8.4 --ini | grep "Loaded Configuration"
# PHP workers count
ps aux | grep php-fpm | grep -v grep | wc -l
# PHP error log
sudo tail -f /var/log/php8.4-fpm.log
Permissions
# Fix web root ownership (Nginx runs as www-data on Debian)
sudo chown -R www-data:www-data /var/www/example.com/
# Fix directory permissions
sudo find /var/www/example.com -type d -exec chmod 755 {} \;
# Fix file permissions
sudo find /var/www/example.com -type f -exec chmod 644 {} \;
# Check what user Nginx workers run as
ps aux | grep "nginx: worker" | head -2 | awk '{print $1}'
grep "^user" /etc/nginx/nginx.conf
One-Line Health Check
echo "Nginx: $(systemctl is-active nginx) | $(nginx -v 2>&1) | Workers: $(ps aux | grep 'nginx: worker' | grep -v grep | wc -l) | FPM: $(ps aux | grep php-fpm | grep -v grep | wc -l) workers | Last error: $(sudo tail -1 /var/log/nginx/error.log)"
opencode AI Integration
# Analyze error log
sudo tail -200 /var/log/nginx/error.log | \
opencode "analyze these Nginx errors, group by type, identify root causes, give exact fixes"
# Generate server block
opencode "write a complete Nginx server block for a WordPress site at /var/www/example.com/public with PHP 8.4-FPM via UNIX socket, HTTPS redirect, security headers, and static asset caching"
# Review config for issues
sudo nginx -T | opencode "review this Nginx config for security weaknesses and performance improvements"
# Debug 502 error
(sudo tail -50 /var/log/nginx/error.log; sudo tail -50 /var/log/php8.4-fpm.log) | \
opencode "my Nginx is returning 502 errors, analyze these logs and suggest fixes"
tip
In tmux, keep opencode in one pane and your Nginx config in vim in another. Test each config section as you write it.
Hands-On Practice
# Verify Nginx is running
sudo systemctl status nginx
# Test config syntax
sudo nginx -t
# Reload without downtime
sudo nginx -s reload
# Check error log
sudo tail -20 /var/log/nginx/error.log
Common Pitfalls
| Pitfall | What happens | Fix |
|---|---|---|
| Editing config without reloading | Changes not applied | sudo nginx -s reload after every edit |
Not running nginx -t first | Reload breaks with syntax error | Always test syntax before reloading |
| Wrong socket path for PHP-FPM | 502 Bad Gateway | ls /run/php/ and verify the exact socket filename |
What's Next
- Continue to the next lesson in this module, or go to the module index for an overview.
- Use the Cheatsheets for quick CLI reference.