en Configuring Nginx for performance and security

Configuring Nginx for performance and security

In this tutorial, we’ll look at how to configure an Nginx web server for production.

A web server in a production environment differs from a web server in a test environment in terms of performance, security, and so on.

By default, after successfully installing Nginx web server, there are always configuration settings available out of the box. However, the default configuration is not sufficient for production environments. Therefore, we will focus on how to configure Nginx to improve performance during heavy traffic and regular traffic spikes, and how to protect Nginx from users who try to exploit it.

If you don’t have Nginx installed on your machine, you can learn how to install it here. Shows how to install Nginx on Unix platforms. Since the pre-built Nginx does not come with some of the modules used in this tutorial, we choose to install Nginx via source files.

Configuring Nginx for performance and security
Configuring Nginx for performance and security

requirements

You must have the following installed on your machine to run this tutorial on a Debian-based platform such as Ubuntu.

  • Ubuntu or other Debian-based platform
  • wigget
  • Vim (text editor)

Also, some commands in this tutorial must be run as the root user using the sudo command.

Configuring Nginx for performance and security
Configuring Nginx for performance and security

Understand the Nginx configuration structure

In this section we’ll look at:

  • Nginx structure
  • Sections for events, HTTP, email, etc.
  • Valid syntax for Nginx

At the end of this section, you will understand the structure of Nginx configuration, the purpose or role of sections, and how to define valid directives within sections.

A complete Nginx configuration file has a logical structure consisting of directives grouped into several sections such as event section , http section , mail section etc.

The main configuration file is located at /etc/nginx/nginx.conf , and other configuration files are located at /etc/nginx .

main context

This section or context contains directives that are outside of a specific section, such as mail section .

user nginx; , worker_processes 1; , error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid can be placed in the main section or in the context.

However, some of these directives, such as worker_processes , can also be present in event section .

section

The Nginx section defines the configuration of the Nginx module.

For example, http section defines the configuration for ngx_http_core module , event section defines the configuration for ngx_event_module , and the mail section defines the configuration for ngx_mail_module .

A complete list of Nginx sections can be found here .

directive

Nginx directives consist of a variable name and some arguments, like this:

worker_processes variable name and serves as auto argument.

 worker_processes  auto;

Directives end with a semicolon as shown above.

Finally, Nginx configuration files must follow a certain set of rules. The valid syntax for Nginx configuration is:

  • A valid directive begins with a variable name followed by one or more arguments
  • All valid directives end with a semicolon ;
  • Sections are defined with curly braces {}
  • Sections can be embedded within another section
  • Configurations outside the section are part of the Nginx global configuration.
  • Lines that begin with the hash symbol # are comments.
Configuring Nginx for performance and security
Configuring Nginx for performance and security

Tuning Nginx for performance

In this section, you will configure Nginx for better performance during heavy traffic or traffic spikes.

We’ll look at how to configure it below.

  • laborer
  • Disk I/O activity
  • network activity
  • buffer
  • compression
  • caching
  • timeout

Nevertheless, type the following command within the activated virtual environment to navigate to the Nginx directory and list its contents:

 cd nginx && ls

Search for folder conf . Inside this folder is the nginx.conf file.

Configure Nginx using this file

Then run the following command to go to the conf folder and open nginx.conf file in <a href="https://.com/best-vim-editors/">vim editor</a> .

 cd conf
sudo vim nginx.conf

Below is a screenshot showing how the nginx.conf file looks by default.

laborer

To improve Nginx performance, you need to configure workers in the events section. Configuring an Nginx worker allows it to efficiently handle connections from clients.

If you haven’t closed the vim editor, press the i button on your keyboard to edit the nginx.conf file.

Copy and paste the following inside events section as shown below.

 events { 
    worker_processes    auto;
    worker_connections  1024;
    worker_rlimit_nofile 20960;
    multi_accept        on;  
    mutex_accept        on; 
    mutex_accept_delay  500ms; 
    use                 epoll; 
    epoll_events        512;  
}

worker_processes : This directive controls the number of Nginx workers. The value of this directive is set to auto , allowing Nginx to determine the number of available cores, disks, server load, and network subsystems. However, you can check the number of cores by running the lscpu command in the terminal.

worker_connections : This directive sets a value for the number of simultaneous connections that a worker can open. The default value is 512 , but I set it to 1,024 so that one worker can accept many simultaneous connections from clients.

worker_rlimit_nofile: This directive is somehow related to worker_connections . Set to a large value to handle large numbers of concurrent connections.

multi_accept: This directive allows the worker to accept many connections in the queue at once. A queue in this context simply means a set of data objects waiting to be processed.

mutex_accept: This directive is turned off by default. However, since we have configured many workers with Nginx, we need to turn on Nginx as shown in the code above so that the workers can accept new connections one by one.

mutex_accept_delay: This directive determines how long the worker waits before accepting a new connection. accept_mutex When turned on, a mutex lock is assigned to the worker for the timeframe specified by accept_mutex_delay . Once the time has passed, the next worker is ready to accept new connections.

use: This directive specifies how connections from clients are handled. In this tutorial, since we are working on the Ubuntu platform, we decided to set the value to epoll . epoll method is the most efficient processing method for Linux platforms.

epoll_events: The value of this directive specifies the number of events that Nginx forwards to the kernel.

disk I/O

In this section, you will configure asynchronous I/O activity in Nginx so that you can perform effective data transfers and improve cache efficiency.

Disk I/O simply refers to write and read operations between the hard disk and RAM. Send a small file using <a href="https://linux.die.net/man/2/sendfile">sendfile(</a>) function in the kernel.

Directives in this area can include http section , location section , and server section .

You can embed or place location section , server section , http section to make the configuration readable.

Copy and paste the following code inside the location section embedded inside the HTTP section.

 location /pdf/  {
   sendfile on; 
   aio      on; 
  }  

location /audio/ {  
    directio    4m
    directio_alignment 512  
}

sendfile: Set the value of this directive to on to utilize operating system resources. sendfile transfers data between file descriptors in OS kernel space without sending the data to application buffers. This directive is used to serve small files.

directio: This directive improves cache efficiency by allowing reads and writes to be sent directly to the application. directio is a file system feature of all modern operating systems. This directive is used to serve large files such as videos.

aio: This directive enables multithreading when set to on for write and read operations. Multithreading is an execution model that allows multiple threads to run independently of each other while sharing hosting process resources.

directio_alignment: This directive assigns a block size value to data transfers. It was related to directio directive.

network layer

This section uses directives such as tcp_nodelay and tcp_nopush to prevent small packets from waiting a specified time window of approximately 200 milliseconds before being sent all at once.

Typically, when packets are transferred in “fragments”, a heavily loaded network tends to become saturated. So John Nagle built a buffering algorithm to solve this problem. The purpose of Nagle’s buffering algorithm is to prevent small packets from saturating a heavily loaded network.

Copy and paste the following code inside the HTTP section.

 http {   

  tcp_nopush  on; 
  tcp_nodelay on;

  }

tcp_nodelay: This directive is disabled by default and allows small packets to wait a specified period of time before being sent at once. Enable this directive to allow all data to be sent at once.

tcp_nopush: Enabling tcp_nodelay directive causes small packets to be sent at a time. However, if you still want to take advantage of John Nagle’s buffering algorithm, you can also enable tcp_nopush to append packets to each other and send them all at once.

buffer

Let’s take a look at how to configure request buffers in Nginx to handle requests effectively. A buffer is temporary storage that holds and processes data for a period of time.

You can copy the following to the server section.

 server { 

   client_body_buffer_size 8k;
   client_max_body_size 2m; 
   client_body_in_single_buffer on;  
   client_body_temp_pathtemp_files 1 2;
   client_header_buffer_size  1m; 
   large_client_header_buffers 4 8k;

 }

It’s important to understand what these buffer lines do.

client_body_buffer_size: This directive sets the request body buffer size. If you plan to run your web server on a 64-bit system, you should set the value to 16k. If you run the web server on a 32-bit system, set the value to 8k.

client_max_body_size: If you are handling large file uploads, this directive should be set to at least 2m or higher. By default it is set to 1m .

client_body_in_file_only: Use the hashtag symbol # to disable client_body_buffer_size directive, and if this directive client_body_in_file_only is set, Nginx stores the request buffer in a temporary file. This is not recommended for production environments.

client_body_in_single_buffer: Not all of the request body may be stored in the buffer. The rest is saved or written to temporary files. However, if you want to store or store the complete request buffer in a single buffer, you must enable this directive.

client_header_buffer_size: You can use this directive to set or allocate a buffer for request headers. This value can be set to 1m .

large_client_header_buffers: This directive is used to set the maximum number and size for reading large request headers. You can precisely set the maximum number and buffer size to 4 and 8k .

compression

Compressing the amount of data transferred over the network is another way to improve Web server performance. In this section, you will compress your data using directives such as gzip , gzip_comp_level , and gzip_min_length .

Paste the following code inside http section as shown below.

 http {  

  gzip on;
  gzip_comp_level  2;
  gzip_min_length  1000; 
  gzip_types  text/xml text/css; 
  gzip_http_version 1.1; 
  gzip_vary  on;  
  gzip_disable "MSIE [4-6] \."; 

}

gzip: Set the value of this directive to on to enable compression. Disabled by default.

gzip_comp_level: You can use this directive to set the compression level. You don’t need to set the compression level too high to avoid wasting CPU resources. You can set the compression level to 2 or 3 from 1 to 9 .

gzip_min_length: Set the minimum response length for compression via content-length response header field . Can be set to 20 bytes or more.

gzip_types: This directive allows you to select response types to compress. By default, response type text/html is always compressed. You can add other response types like text/css as shown in the code above.

gzip_http_version: This directive allows you to select the minimum HTTP version of the request for compressed responses. You can use the default value of 1.1 .

gzip_vary: If gzip directive is enabled, this directive adds the header field Vary:Accept Encoding to the response.

gzip_disabled: Some browsers, such as Internet Explorer 6 , do not support gzip compression . This directive leverages User-Agent request header field to disable compression for specific browsers.

caching

Leverage caching capabilities to reduce the number of times the same data is loaded multiple times. Nginx provides the ability to cache static content metadata via the open_file_cache directive.

This directive can be placed within server , location , and http sections.

 http {  

open_file_cache max=1,000 inactive=30s; 
open_file_cache_valid 30s; 
open_file_cache_min_uses 4; 
open_file_cache_errors on; 

 }

open_file_cache: This directive is disabled by default. Enable this if you want to implement caching with Nginx. This directive stores file and directory metadata that users often request.

open_file_cache_valid: This directive contains the backup information in open_file_cache directive. This directive allows you to set the expiration period, typically in seconds, before information related to files and directories is revalidated again.

open_file_cache_min_uses: Nginx typically clears the information in open_file_cache directives based on open_file_cache_min_uses after a period of inactivity. You can use this directive to set a minimum number of accesses and identify which files and directories are actively accessed.

open_file_cache_errors: You can use this directive to enable Nginx to cache errors such as “Permission Denied” or “This file cannot be accessed” when a file is accessed. Therefore, when an unauthorized user accesses a resource, Nginx displays the same error report: “Access is denied.”

timeout

Configure timeouts using directives such as keepalive_timeout and keepalive_requests to prevent long-waiting connections from wasting resources.

In the HTTP section, copy and paste the following code.

 http {  

 keepalive_timeout  30s; 
 keepalive_requests 30;
 send_timeout      30s;

}

keepalive_timeout : Keeps the connection alive for approximately 30 seconds. Default is 75 seconds.

keepalive_requests : Configure a number of requests to live for a specific period of time. The number of requests can be set to 20 or 30.

keepalive_disable : Use this directive if you want to disable keepalive connections for a specific group of browsers.

send_timeout : Set the timeout for sending data to the client.

Configuring Nginx for performance and security
Configuring Nginx for performance and security

Nginx security configuration

Below, we’ll focus only on how to safely configure Nginx, not web applications. Therefore, we do not discuss web-based attacks such as SQL injection.

In this section, we’ll look at how to configure:

  • Restrict access to files and directories
  • Configure logging to monitor malicious activity
  • Prevent DDoS
  • Disable directory listing

Restrict access to files and directories

Let’s see how to restrict access to sensitive files and directories using:

By using HTTP authentication

By requiring users or administrators to authenticate, you can restrict access to sensitive files and areas not intended for public access. If you don’t have the password file creation utility installed, run the following command to install it.

 apt-get install -y apache-utils

Next, create a password file and user using the htpasswd tool as shown below. htpasswd tool is provided by apache2-utils utility.

 sudo  htpasswd  -c  /etc/apache2/ .htpasswd mike

You can check if the user and random password were created successfully using the following command:

 cat  etc/apache2/ .htpasswd

You can prompt the user to authenticate using the auth_basic directive by pasting the following code inside the location section.

 location /admin {  

 basic_auth "Admin Area"; 
 auth_basic_user_file /etc/apache2/ .htpasswd; 

}

By using the “Allow” directive,

In addition to basic_auth directive, you can use allow directive to restrict access.

Use the following code within the location section to allow the specified IP address to access the sensitive area.

 location /admin {  
 allow 192.168.34.12; 
 allow 192.168.12.34; 
}

Configure logging to monitor malicious activity

In this section, you will configure error and access logs to specifically monitor valid and invalid requests. You can examine these logs to find out things like who logged in at a particular time or which users accessed a particular file.

error_log: Allows you to configure logging to specific files such as syslog or stderr . You can also specify the level of error messages to log.

access_log: User requests can be written to the file access.log .

Within the HTTP section you can use:

 http {  

  access_log  logs/access.log   combined; 
  error_log   logs/warn.log     warn;

}

Prevent DDO

You can protect Nginx from DDOS attacks in the following ways:

User request limits

You can use limit_req_zone and limit_req directives to limit the rate of requests your users send per minute.

Add the following code to location section embedded in the server section.

 limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;  

server {
 location /admin.html { 
   limit_req zone=one;
       }

}

Limit the number of connections

You can limit connections to specific locations or areas using limit_conn and limit_conn_zone directives. For example, the code below receives 15 connections from the client in a specific period.

The following code will move you to location section.

 limit_conn_zone $binary_remote_addr zone=addr:10m;

server {
   
    location /products/ {
        limit_conn addr 10;
       
    }
}

Terminate slow connections

You can control how long Nginx waits for writes from client body and client header using timeout directives such as client_body_timeout and client_header_timeout .

Add the following inside server section:

 server {
    client_body_timeout 5s;
    client_header_timeout 5s;
}

It’s also a good idea to leverage cloud-based solutions to stop DDoS attacks at the edge, as discussed here.

Disable directory listing

You can prevent directory listing using auto_index directive as shown in the code below. To disable directory listing, the value must be set to off .

 location / {  
 auto_index  off;
}

conclusion

Nginx web servers are configured to operate effectively and are protected from undue abuse in production environments. If you are using Nginx for your internet-facing web applications, you should also consider using CDN and cloud-based security to improve performance and security.

Configuring Nginx for performance and security
Configuring Nginx for performance and security