What it does
nginx serves static files and passes requests to app servers (PHP-FPM, Python, Node, containers). It ends TLS (HTTPS), balances load over several backends, caches, limits request rates and adds security headers. On RHEL the service is nginx.service; it listens on ports 80 and 443.
The main config is /etc/nginx/nginx.conf; sites go in /etc/nginx/conf.d/*.conf. Always test the config with nginx -t before a reload. With SELinux, nginx may only use labelled ports and file contexts (httpd_sys_content_t, http_port_t) and needs httpd_can_network_connect to proxy to apps.
How to write it
nginx [-t] [-T] [-s signal] [-c file] [-g directives]
systemctl {start|reload|status} nginxMain parts
Config blocks
http{ … }- Settings for all web traffic.
server{ … }- One virtual host (listen port, server_name, TLS).
locationPATH{ … }- Rules for some URLs (root, proxy_pass, headers).
upstreamNAME{ … }- A group of backend servers for load balancing.
stream{ … }- TCP/UDP proxying (databases, other protocols).
Options 10
Most used
Command-line options
Nothing matches this filter.
Examples 11
$ run as a normal user# run as root (or with sudo)
1Install, open the firewall and start
dnf install -y nginx firewall-cmd --add-service={http,https} --permanent && firewall-cmd --reload systemctl enable --now nginx curl -I http://localhost/2Test and reload after a change
nginx -t nginx: configuration file /etc/nginx/nginx.conf test is successful systemctl reload nginxreload keeps open connections; a broken config is refused, the old one keeps running.
3Serve a static site
cat /etc/nginx/conf.d/site.conf server { listen 80; server_name www.example.com; root /srv/www/site; index index.html; } semanage fcontext -a -t httpd_sys_content_t '/srv/www(/.*)?' && restorecon -Rv /srv/www4Reverse proxy to an app on port 8080
cat /etc/nginx/conf.d/app.conf server { listen 80; server_name app.example.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } setsebool -P httpd_can_network_connect on5HTTPS with a certificate and HTTP redirect
cat /etc/nginx/conf.d/tls.conf server { listen 80; server_name shop.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl; http2 on; server_name shop.example.com; ssl_certificate /etc/pki/tls/certs/shop.crt; ssl_certificate_key /etc/pki/tls/private/shop.key; ssl_protocols TLSv1.2 TLSv1.3; add_header Strict-Transport-Security "max-age=31536000" always; }6Load-balance three app servers
cat /etc/nginx/conf.d/lb.conf upstream app { least_conn; server 10.30.2.11:8080; server 10.30.2.12:8080; server 10.30.2.13:8080 max_fails=3 fail_timeout=30s; } server { listen 80; location / { proxy_pass http://app; } }7Limit request rates (brute force, scrapers)
cat /etc/nginx/conf.d/limits.conf limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m; server { location /login { limit_req zone=login burst=5 nodelay; proxy_pass http://127.0.0.1:8080; } }8Add security headers and hide the version
cat /etc/nginx/conf.d/security.conf server_tokens off; add_header X-Content-Type-Options nosniff always; add_header X-Frame-Options DENY always; add_header Referrer-Policy strict-origin-when-cross-origin always;9Read the logs
10Show the full active configuration
nginx -T | grep -E "server_name|listen|proxy_pass"11Run nginx in a container
podman run -d --name web -p 8080:8080 -v ./site:/usr/share/nginx/html:ro,Z docker.io/nginxinc/nginx-unprivileged:1.27
Nothing matches this filter.
Watch out
nginx -tbefore every reload — a typo withrestarttakes the site down.- With SELinux: non-standard ports need
semanage port -a -t http_port_t; proxying to apps needshttpd_can_network_connect. - Do not expose
autoindex onor.git/.envfiles:location ~ /\. { deny all; }.
Files
/etc/nginx/nginx.conf- Main configuration.
/etc/nginx/conf.d/*.conf- Sites and extra settings.
/var/log/nginx/- access.log and error.log.
/usr/share/nginx/html- Default web root.
Tips to remember
- Test TLS with
curl -vI https://HOSTand SSL Labs; aim for TLS 1.2+ only. - Put shared proxy headers in a snippet file and
includeit in every location.
Exit codes
0 | Success (config OK). |
1 | Error (config test failed, signal not sent). |