Skip to content

Nginx Reverse Proxy

Live version data by pkgseek.com
Terminal window
sudo dnf install -y nginx

Start and enable at boot:

Terminal window
sudo systemctl enable --now nginx

Verify:

Terminal window
sudo systemctl status nginx
curl -I http://localhost

Open the firewall ports:

Terminal window
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

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 parameters

Core 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;
}

Each site is configured as a separate file in the /etc/nginx/conf.d/ directory.

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:

Terminal window
sudo mkdir -p /var/www/static.example.com
echo "<h1>Hello from RunEntLinux</h1>" | sudo tee /var/www/static.example.com/index.html

Test and reload the configuration:

Terminal window
sudo nginx -t
sudo systemctl reload nginx

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;
}
}
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;
}
}
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)”
  1. Install Certbot:

    Terminal window
    sudo dnf install -y certbot python3-certbot-nginx
  2. Obtain a certificate (Certbot will automatically modify the Nginx configuration):

    Terminal window
    sudo certbot --nginx -d app.example.com

    Or obtain a certificate only without modifying the configuration:

    Terminal window
    sudo certbot certonly --nginx -d app.example.com
  3. 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 parameters
    ssl_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;
    # HSTS
    add_header Strict-Transport-Security "max-age=63072000" always;
    # OCSP Stapling
    ssl_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;
    }
    }
  4. Set up automatic certificate renewal:

    Terminal window
    sudo systemctl enable --now certbot-renew.timer
    # Or manually test renewal
    sudo certbot renew --dry-run

On SELinux-enabled systems, Nginx is subject to the httpd_t SELinux policy.

Nginx cannot read files in a custom directory

Terminal window
# View current SELinux context
ls -laZ /var/www/static.example.com/
# Set the correct context
sudo 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)

Terminal window
# Allow httpd to make network connections
sudo setsebool -P httpd_can_network_connect 1

Nginx cannot connect to a backend on a specific port

Terminal window
# View ports httpd is allowed to connect to
sudo semanage port -l | grep http_port
# Add a custom port
sudo semanage port -a -t http_port_t -p tcp 8000

Nginx cannot bind to a non-standard port

Terminal window
# Allow Nginx to listen on a custom port
sudo semanage port -a -t http_port_t -p tcp 8443
Terminal window
# Test configuration syntax
sudo 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 log
sudo tail -f /var/log/nginx/error.log
# View access log
sudo tail -f /var/log/nginx/access.log

The Nginx version in EL 10’s AppStream repository has been updated:

VersionEL 9 system repoEL 10 system repo
Nginx1.22.x1.26.x

The installation command is identical — EL 10 will automatically install the corresponding version:

Terminal window
sudo dnf install -y nginx
nginx -v # confirm version

To pin a specific version, see Package Version Locking.