0

I am using a reverse proxy and load balancing. In my scenario, I have three servers. The first server is the proxy. The second and third are docker servers that use swarm. Port 2020 is used for two replicas of the Apache service. Port 2021 is used for two replicas of the Nginx service. The balancing is done according to the replicas. As I am new to Nginx I was wondering if the following settings are enough. Would it be possible to improve this configuration? Is it safe?

proxy_config.conf:

##########
# Apache #
##########

  upstream apache {
        least_conn;

        #Container replicas
        server 192.168.0.4:2020;
        server 192.168.0.5:2020;
  }
  server {
        listen 80;
        server_name host.apache.domain.com;

        location / {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://apache;
        }
   }

#########
# Nginx #
#########

  upstream nginx {
        least_conn;

        #Container replicas
        server 192.168.0.4:2021;
        server 192.168.0.5:2021;
  }

  server {
        listen 80;
        server_name host.nginx.domain.com;

        location / {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://nginx;
        }
   }

In this specific case, I used the following:

    location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://nginx;
    }

If I only used the following configuration, wouldn't it be enough?

    location / {
            proxy_pass http://nginx;
    }

I read the Nginx documentation, but I need more examples.

1
  • Sure. BUT, your destination would have no idea where the request is coming from. The IP it's coming from. The host name it's coming from. Who it was forwarded for. This all goes into your server logs too. How will your troubleshoot things you cannot see?
    – suchislife
    Feb 19, 2021 at 22:49

1 Answer 1

3

Digital Ocean provides a free NGINX config tool with code comments and examples for you to learn from. Definetly play around with this. I wish it existed back when I was learning NGINX.

Visit nginxconfig.io

The SSL Reverse Proxy Server with Security Headers code below was generated with it. You can most definitely customize it while learning in the process

# Generated by nginxconfig.io
# https://www.digitalocean.com/community/tools/nginx?domains.0.php.php=false&domains.0.reverseProxy.reverseProxy=true&domains.0.routing.index=index.html&domains.0.routing.fallbackHtml=true&global.https.ocspCloudflare=false&global.https.ocspOpenDns=false&global.tools.modularizedStructure=false

user                 www-data;
pid                  /run/nginx.pid;
worker_processes     auto;
worker_rlimit_nofile 65535;

events {
    multi_accept       on;
    worker_connections 65535;
}

http {
    charset                utf-8;
    sendfile               on;
    tcp_nopush             on;
    tcp_nodelay            on;
    server_tokens          off;
    log_not_found          off;
    types_hash_max_size    2048;
    types_hash_bucket_size 64;
    client_max_body_size   16M;

    # MIME
    include                mime.types;
    default_type           application/octet-stream;

    # Logging
    access_log             /var/log/nginx/access.log;
    error_log              /var/log/nginx/error.log warn;

    # SSL
    ssl_session_timeout    1d;
    ssl_session_cache      shared:SSL:10m;
    ssl_session_tickets    off;

    # Diffie-Hellman parameter for DHE ciphersuites
    ssl_dhparam            /etc/nginx/dhparam.pem;

    # Mozilla Intermediate configuration
    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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

    # OCSP Stapling
    ssl_stapling           on;
    ssl_stapling_verify    on;
    resolver               8.8.8.8 8.8.4.4 valid=60s;
    resolver_timeout       2s;

    # Connection header for WebSocket reverse proxy
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ""      close;
    }

    # Load configs
    include /etc/nginx/conf.d/*.conf;

    # example.com
    server {
        listen                               443 ssl http2;
        listen                               [::]:443 ssl http2;
        server_name                          example.com;
        root                                 /var/www/example.com/public;

        # SSL
        ssl_certificate                      /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key                  /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_trusted_certificate              /etc/letsencrypt/live/example.com/chain.pem;

        # security headers
        add_header X-Frame-Options           "SAMEORIGIN" always;
        add_header X-XSS-Protection          "1; mode=block" always;
        add_header X-Content-Type-Options    "nosniff" always;
        add_header Referrer-Policy           "no-referrer-when-downgrade" always;
        add_header Content-Security-Policy   "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

        # . files
        location ~ /\.(?!well-known) {
            deny all;
        }

        # index.php fallback
        location ~ ^/api/ {
            try_files $uri $uri/ /index.php?$query_string;
        }

        # reverse proxy
        location / {
            proxy_pass                         http://127.0.0.1:3000;
            proxy_http_version                 1.1;
            proxy_cache_bypass                 $http_upgrade;

            # Proxy headers
            proxy_set_header Upgrade           $http_upgrade;
            proxy_set_header Connection        $connection_upgrade;
            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;
            proxy_set_header X-Forwarded-Host  $host;
            proxy_set_header X-Forwarded-Port  $server_port;

            # Proxy timeouts
            proxy_connect_timeout              60s;
            proxy_send_timeout                 60s;
            proxy_read_timeout                 60s;
        }

        # favicon.ico
        location = /favicon.ico {
            log_not_found off;
            access_log    off;
        }

        # robots.txt
        location = /robots.txt {
            log_not_found off;
            access_log    off;
        }

        # assets, media
        location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {
            expires    7d;
            access_log off;
        }

        # svg, fonts
        location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {
            add_header Access-Control-Allow-Origin "*";
            expires    7d;
            access_log off;
        }

        # gzip
        gzip            on;
        gzip_vary       on;
        gzip_proxied    any;
        gzip_comp_level 6;
        gzip_types      text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
    }

    # subdomains redirect
    server {
        listen                  443 ssl http2;
        listen                  [::]:443 ssl http2;
        server_name             *.example.com;

        # SSL
        ssl_certificate         /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key     /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
        return                  301 https://example.com$request_uri;
    }

    # HTTP redirect
    server {
        listen      80;
        listen      [::]:80;
        server_name .example.com;

        # ACME-challenge
        location ^~ /.well-known/acme-challenge/ {
            root /var/www/_letsencrypt;
        }

        location / {
            return 301 https://example.com$request_uri;
        }
    }
}
4
  • I am using the tool you indicated. But I still have a doubt. Since the server is a reverse proxy, do I need to specify "root /var/www/example.com/public?" From the documentation I understood that this would not be necessary. Is there any reason I don't know about?
    – campos
    Mar 22, 2021 at 15:52
  • Correct. Reverse proxy does nothing more than pass on the traffic to another server.
    – suchislife
    Mar 24, 2021 at 1:28
  • In nginxconfig.io I enabled the option "Routing" by mistake.
    – campos
    Mar 25, 2021 at 14:16
  • Aha! Practice and you will learn in no time! It's a great tool. Lots of custom options.
    – suchislife
    Mar 25, 2021 at 14:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .