Nginx Reverse Proxy
Versions Across Distributions
Section titled “Versions Across Distributions”Install Nginx
Section titled “Install Nginx”sudo dnf install -y nginxCreate /etc/yum.repos.d/nginx.repo:
[nginx-stable]name=nginx stable repobaseurl=http://nginx.org/packages/centos/$releasever/$basearch/gpgcheck=1enabled=1gpgkey=https://nginx.org/keys/nginx_signing.keymodule_hotfixes=trueThen install:
sudo dnf install -y nginxStart and enable at boot:
sudo systemctl enable --now nginxVerify:
sudo systemctl status nginxcurl -I http://localhostOpen the firewall ports:
sudo firewall-cmd --permanent --add-service=httpsudo firewall-cmd --permanent --add-service=httpssudo firewall-cmd --reloadConfiguration File Structure
Section titled “Configuration File Structure”The Nginx configuration directory structure on EL systems is as follows:
/etc/nginx/├── nginx.conf # Main configuration file├── conf.d/ # Site configuration directory (*.conf auto-loaded)│ └── default.conf # Default site configuration├── mime.types # MIME type definitions└── fastcgi_params # FastCGI parametersCore structure of the main configuration file /etc/nginx/nginx.conf:
user nginx;worker_processes auto;error_log /var/log/nginx/error.log;pid /run/nginx.pid;
events { worker_connections 1024;}
http { include /etc/nginx/mime.types; default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on; tcp_nopush on; keepalive_timeout 65; gzip on;
include /etc/nginx/conf.d/*.conf;}Server Blocks (Site Configuration)
Section titled “Server Blocks (Site Configuration)”Each site is configured as a separate file in the /etc/nginx/conf.d/ directory.
Static File Site
Section titled “Static File Site”Create /etc/nginx/conf.d/static.example.com.conf:
server { listen 80; server_name static.example.com;
root /var/www/static.example.com; index index.html;
# Static asset caching location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff2?)$ { expires 30d; add_header Cache-Control "public, immutable"; }
# Deny access to hidden files location ~ /\. { deny all; }
error_page 404 /404.html;}Create the website root directory:
sudo mkdir -p /var/www/static.example.comecho "<h1>Hello from RunEntLinux</h1>" | sudo tee /var/www/static.example.com/index.htmlTest and reload the configuration:
sudo nginx -tsudo systemctl reload nginxReverse Proxy Configuration
Section titled “Reverse Proxy Configuration”Basic Reverse Proxy
Section titled “Basic Reverse Proxy”Create /etc/nginx/conf.d/app.example.com.conf:
server { listen 80; server_name app.example.com;
location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }}Reverse Proxy with Load Balancing
Section titled “Reverse Proxy with Load Balancing”upstream app_backend { least_conn; server 127.0.0.1:8001; server 127.0.0.1:8002; server 127.0.0.1:8003;}
server { listen 80; server_name app.example.com;
location / { proxy_pass http://app_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
# Timeout settings proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; }}WebSocket Reverse Proxy
Section titled “WebSocket Reverse Proxy”server { listen 80; server_name ws.example.com;
location /ws { proxy_pass http://127.0.0.1:8000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 86400; }}SSL/TLS Configuration (Let’s Encrypt + Certbot)
Section titled “SSL/TLS Configuration (Let’s Encrypt + Certbot)”-
Install Certbot:
Terminal window sudo dnf install -y certbot python3-certbot-nginx -
Obtain a certificate (Certbot will automatically modify the Nginx configuration):
Terminal window sudo certbot --nginx -d app.example.comOr obtain a certificate only without modifying the configuration:
Terminal window sudo certbot certonly --nginx -d app.example.com -
Manually configure an SSL site. Create
/etc/nginx/conf.d/app.example.com.conf:server {listen 80;server_name app.example.com;return 301 https://$host$request_uri;}server {listen 443 ssl http2;server_name app.example.com;ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;# Secure SSL parametersssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;ssl_prefer_server_ciphers off;# HSTSadd_header Strict-Transport-Security "max-age=63072000" always;# OCSP Staplingssl_stapling on;ssl_stapling_verify on;location / {proxy_pass http://127.0.0.1:8000;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}} -
Set up automatic certificate renewal:
Terminal window sudo systemctl enable --now certbot-renew.timer# Or manually test renewalsudo certbot renew --dry-run
SELinux Configuration
Section titled “SELinux Configuration”On SELinux-enabled systems, Nginx is subject to the httpd_t SELinux policy.
Common Issues and Solutions
Section titled “Common Issues and Solutions”Nginx cannot read files in a custom directory
# View current SELinux contextls -laZ /var/www/static.example.com/
# Set the correct contextsudo semanage fcontext -a -t httpd_sys_content_t "/var/www/static.example.com(/.*)?"sudo restorecon -Rv /var/www/static.example.com/Nginx cannot connect to backend services (reverse proxy 502 error)
# Allow httpd to make network connectionssudo setsebool -P httpd_can_network_connect 1Nginx cannot connect to a backend on a specific port
# View ports httpd is allowed to connect tosudo semanage port -l | grep http_port
# Add a custom portsudo semanage port -a -t http_port_t -p tcp 8000Nginx cannot bind to a non-standard port
# Allow Nginx to listen on a custom portsudo semanage port -a -t http_port_t -p tcp 8443Common Operations Commands
Section titled “Common Operations Commands”# Test configuration syntaxsudo nginx -t
# Reload configuration (without interrupting service)sudo systemctl reload nginx
# View active connection status (requires stub_status module)# Add the following in a server block:# location /nginx_status {# stub_status on;# allow 127.0.0.1;# deny all;# }curl http://127.0.0.1/nginx_status
# View error logsudo tail -f /var/log/nginx/error.log
# View access logsudo tail -f /var/log/nginx/access.logEL 10 Notes
Section titled “EL 10 Notes”The Nginx version in EL 10’s AppStream repository has been updated:
| Version | EL 9 system repo | EL 10 system repo |
|---|---|---|
| Nginx | 1.22.x | 1.26.x |
The installation command is identical — EL 10 will automatically install the corresponding version:
sudo dnf install -y nginxnginx -v # confirm versionTo pin a specific version, see Package Version Locking.