Unlocking the Power of Nginx Configuration: Tips and Tricks for High-Performance Web Serving

Photo by JJ Ying on Unsplash

Unlocking the Power of Nginx Configuration: Tips and Tricks for High-Performance Web Serving

Nginx is a high-performance web server, reverse proxy server and load balancer. It is widely used in modern web applications due to its excellent performance, scalability, and reliability. In many projects that I have worked on, I had to do various configurations using nGinx so that the user can reach the website or a docker container and easily communicate with other containers.

In this blog post, we will discuss various nginx configurations with coding examples, and also explain why we need those configurations.

Reverse Proxy Configuration

A reverse proxy server is a server that sits in front of web servers and directs client requests to the appropriate web server. This configuration can be used to improve the security, scalability, and reliability of web applications.

perlCopy code
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

In this configuration, we have defined a server block for example.com, and set the listen directive to port 80. We have also defined a location block that passes client requests to the web server running on port 3000.

Load Balancer Configuration

A load balancer is a server that distributes incoming traffic across multiple servers. This configuration can be used to improve the performance and scalability of web applications.

perlCopy code
upstream backend {
    server 192.168.0.10;
    server 192.168.0.11;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

In this configuration, we have defined an upstream block that defines two servers for load balancing. We have also defined a server block that listens on port 80 and directs traffic to the backend servers using the proxy_pass directive.

SSL/TLS Configuration

SSL/TLS is a protocol that encrypts data sent over the internet. This configuration can be used to improve the security of web applications.

bashCopy code
server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

In this configuration, we have defined a server block that listens on port 443 with SSL/TLS enabled. We have also defined the SSL certificate and key files using the ssl_certificate and ssl_certificate_key directives.

Caching Configuration

Caching is a technique that stores frequently accessed data in memory to improve performance. This configuration can be used to improve the performance of web applications.

bashCopy code
http {
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m inactive=60m;

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_cache my_cache;
            proxy_cache_valid 200 60m;
            proxy_pass http://localhost:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

In this configuration, we have defined a cache path and zone using the proxy_cache_path directive. We have also defined a server block that uses the proxy_cache directive to cache frequently accessed data.

Securing Nginx from Unwanted Requests

Nginx can be secured from unwanted requests by implementing various security measures such as rate limiting, IP blocking, and request filtering.

Rate Limiting

Rate limiting is a technique that limits the number of requests that can be made within a certain period. This can be used to prevent abuse and protect against DDoS attacks.

bashCopy code
http {
    limit_req_zone $binary_remote_addr zone=my_zone:10m rate=1r/s;

    server {
        listen 80;
        server_name example.com;

        location / {
            limit_req zone=my_zone;
            proxy_pass http://localhost:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

In this configuration, we have defined a limit_req_zone using the $binary_remote_addr variable to track requests from each IP address. We have also defined a server block that uses the limit_req directive to limit requests to 1 request per second.

IP Blocking

IP blocking is a technique that blocks access from specific IP addresses. This can be used to prevent access from known attackers or malicious users.

perlCopy code
http {
    deny 192.168.0.1;

    server {
        listen 80;
        server_name example.com;

        location / {
            allow all;
            proxy_pass http://localhost:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

In this configuration, we have defined a deny directive to block access from the IP address 192.168.0.1. We have also defined a server block that allows access to all other IP addresses.

Request Filtering

Request filtering is a technique that blocks requests that match certain patterns. This can be used to prevent access to sensitive files or prevent SQL injection attacks.

bashCopy code
http {
    server {
        listen 80;
        server_name example.com;

        location / {
            if ($request_uri ~* "(.*/)?\.git(/.*)?$") {
                return 403;
            }
            if ($query_string ~* "union.*select.*\(") {
                return 403;
            }
            proxy_pass http://localhost:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

In this configuration, we have defined two if statements to block requests that match certain patterns. The first if statement blocks requests that contain the ".git" string in the request URI, which can prevent access to sensitive Git repository files. The second if statement blocks requests that contain the "union select" string in the query string, which can prevent SQL injection attacks.

Creating a Load Balancer

To create a load balancer using nginx, we can use the upstream block and the proxy_pass directive as shown in the load balancer configuration above. We can define multiple servers in the upstream block and nginx will distribute incoming traffic across them.

markdownCopy code
upstream backend {
    server 192.168.0.10;
    server 192.168.0.11;
}

In this upstream block, we have defined two servers with IP addresses 192.168.0.10 and 192.168.0.11. We can then use the proxy_pass directive in the server block to direct traffic to the upstream servers.

perlCopy code
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

In this server block, we have defined the listen directive to port 80 and set the server_name directive to example.com. We have also defined a location block that uses the proxy_pass directive to direct traffic to the upstream servers defined in the backend upstream block.

In summary, Nginx is a powerful tool for web development that offers excellent performance, scalability, and reliability. In this blog post, we discussed various Nginx configurations with examples of their implementation and explained why they are important. We covered reverse proxy, load balancing, SSL/TLS, caching, and security measures such as rate limiting, IP blocking, and request filtering. By using these configurations, developers can improve the security and performance of their web applications, and ensure that users can easily communicate with the website or Docker container. We hope this post has been helpful and informative!