Securing and Optimizing Your Nginx Server on Amazon Linux 2

Welcome to the comprehensive guide on setting up an Nginx server on Amazon Linux 2, configuring SSL with Certbot for HTTPS, and securing your server with robust headers in your Nginx configuration file. This guide is designed to provide you with a step-by-step tutorial on deploying applications like PHP on Nginx, ensuring your server is both performant and secure.

Introduction

Nginx is a high-performance, open-source web server known for its stability, rich feature set, simple configuration, and low resource consumption. When deploying web applications, securing and optimizing your server is crucial for both performance and security. This guide will cover everything from initial setup to securing your server with HTTPS and recommended security headers.

Setting Up an AWS EC2 Instance

1. AWS Management Console: Navigate and log in to the AWS Management Console, and access the EC2 Dashboard.

2. Launch Instance: Click on "Launch Instance" and choose an Amazon Machine Image (AMI). For this project, the Amazon Linux 2 AMI is recommended.

3. Instance Type: Select a suitable instance type. For small to medium-sized backup needs, t2.micro offers a cost-effective solution that falls within the AWS Free Tier.

4. Instance Details: Configure your instance. The default settings are generally adequate for basic projects.

5. Add Storage: Adjust the storage settings based on the volume of data you plan to back up (default will work for testing).

6. Security Group: Configure the security group to allow SSH, HTTP & HTTPS access.

7. Launch: Review your settings, then launch the instance. You'll be prompted to select or create a new key pair. Download and securely store this key pair; it's essential for SSH access.

8. Connect to you EC2 Instance: Using you private key that you have generated earlier, connect to your EC2 Instance using the command,

ssh -i /path_to_key.pem ec2-user@<your_public_ip_address>

Setting Up Nginx on Amazon Linux 2

Step 1: Update Your System: Before installing any package, it's a good practice to update your system's package repository. This ensures you have the latest updates and patches.

sudo yum update -y

Step 2: Install Nginx: Amazon Linux’s package repository includes Nginx, so you can install it directly using the yum package manager.

sudo yum install nginx -y

Step 3: Start and Enable Nginx Service: Once the installation is complete, you need to start the Nginx service and ensure it starts automatically on boot.

sudo systemctl start nginx
sudo systemctl enable nginx

Step 4: Verify Nginx Installation: To verify that Nginx is running, you can access your server’s IP address in a web browser. You should see the default Nginx welcome page.

Understanding `nginx.conf`

The nginx.conf file is the primary configuration file for Nginx web servers. It provides directives to control many aspects of Nginx's behavior. Here, we'll walk through a typical nginx.conf file, explaining each section and key directives line by line.

Global Block

user nginx;
worker_processes auto;
  • user: Specifies the user that Nginx worker processes run as. By default, it's set to the nginx user.

  • worker_processes: Dictates the number of worker processes Nginx will spawn. Setting this to auto allows Nginx to determine the optimal number of worker processes based on the number of CPU cores.

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
  • error_log: Sets the path to the error log file and the minimum logging level (in this case, warn). Nginx logs errors that occur while handling requests here.

  • pid: Specifies the file that will store the process ID of the main Nginx process.

Events Block

events {
    worker_connections 1024;
}
  • events: This block configures the parameters that affect connection processing.

  • worker_connections: The maximum number of connections each worker process can handle. A value of 1024 is typical for a single-core setup but may need adjustment for higher traffic sites or servers with more cores.

HTTP Block

This block configures how Nginx handles HTTP(S) traffic.

http {
    include           /etc/nginx/mime.types;
    default_type      application/octet-stream;
  • include: Includes an external file, in this case, the mime.types file, which maps file extensions to MIME types.

  • default_type: Sets the default MIME type for responses.

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
  • log_format: Defines the format of the access logs. This configuration specifies how each log entry should be formatted, including client IP, time of request, HTTP method, and more.
    access_log  /var/log/nginx/access.log  main;
  • access_log: Specifies the path to the access log file and the log format (main as defined above).
    sendfile              on;
    tcp_nopush            on;
    tcp_nodelay           on;
    keepalive_timeout     65;
    types_hash_max_size   2048;
  • sendfile: Enables or disables the use of sendfile() for transferring files. This can speed up file transfer.

  • tcp_nopush: When enabled, sends HTTP headers in one packet.

  • tcp_nodelay: Disables the Nagle buffering algorithm. Useful for keeping connections interactive.

  • keepalive_timeout: Sets the timeout for keeping connections alive.

  • types_hash_max_size: Specifies the maximum size of the types hash tables. Increasing this can reduce request processing time for sites with many MIME types.

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
  • include: These lines include additional configuration files. The first line includes all .conf files from the /etc/nginx/conf.d/ directory. The second line is often used for per-site configurations, including any file from the /etc/nginx/sites-enabled/ directory, facilitating easy enabling and disabling of sites.

Server Block

Inside the http block, you'll typically define one or more server blocks, which represent individual websites or services hosted by the Nginx server.

server {
    listen       80;
    server_name  example.com www.example.com;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
  • server: Defines a server block.

  • listen: Specifies the port and, optionally, the IP address on which the server will listen for requests.

  • server_name: Defines the domain names that this server block will handle.

  • location /: Matches all requests and defines the root directory for these requests and the default files to serve.

  • error_page: Specifies the error pages for different HTTP errors.

  • location = /50x.html: A specific location block for serving the custom error page.

Enabling HTTPS with Certbot

Securing your site with HTTPS is essential for protecting your users' data. Certbot, developed by the Electronic Frontier Foundation, automates the installation of Let's Encrypt SSL certificates.

Step 1: Install Certbot

sudo amazon-linux-extras install epel -y
sudo yum install certbot-nginx -y

Step 2: Obtain and Install SSL Certificate

sudo certbot --nginx -d example.com -d www.example.com

Follow the prompts to complete the process. Certbot will automatically modify your Nginx configuration to use the SSL certificate. Make sure to change the example.com domain with your domain.

Enhancing Security with Headers in Nginx

Implementing specific HTTP headers in your Nginx configuration significantly enhances the security of your web applications by mitigating various types of web security vulnerabilities. Below is a detailed explanation of each header, why you should add it, and its advantages related to security:

1. Content Security Policy (CSP)

add_header Content-Security-Policy "default-src 'self'; script-src 'self' example.com";

Purpose: CSP allows you to control the resources that the client is allowed to load for a given page. With this policy, you can prevent a wide range of attacks, including Cross-Site Scripting (XSS) and other data injection attacks.

Advantages:

  • Mitigating XSS Attacks: By specifying which scripts can execute and from where, you can prevent malicious scripts from running.

  • Control Resources: CSP enables you to define the origins of various resources (scripts, stylesheets, images, etc.), effectively controlling where resources can be loaded from.

2. X-Content-Type-Options

add_header X-Content-Type-Options "nosniff";

Purpose: This header stops the browser from trying to MIME-sniff the content type of a response away from the one being declared by the server. This can prevent some types of attacks, such as style/script MIME type confusion.

Advantages:

  • Preventing MIME Type Confusion: Ensures that browsers do not execute or style non-executable MIME types as if they were executable, mitigating certain attack vectors.

3. X-Frame-Options

add_header X-Frame-Options "SAMEORIGIN";

Purpose: This header can prevent your content from being embedded into other sites via <frame>, <iframe>, <embed>, or <object>. It's a defense against clickjacking attacks.

Advantages:

  • Clickjacking Protection: Prevents attackers from embedding your site into a frame on a malicious website, protecting users from clickjacking attacks.

4. Strict-Transport-Security (HSTS)

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

Purpose: HSTS tells browsers to only use HTTPS, instead of HTTP, ensuring all communications between the browser and the website are encrypted and more secure.

Advantages:

  • Mitigating Man-in-the-Middle Attacks: Ensures that users can only access the server over a secure connection, even if they type http instead of https.

  • Preload List Eligibility: Websites with this header can be included in the HSTS preload list, ensuring even first-time visitors use HTTPS.

5. X-XSS-Protection

add_header X-XSS-Protection "1; mode=block";

Purpose: This header is designed to enable the cross-site scripting (XSS) filter built into most web browsers. It's not as necessary when a robust CSP is in place but can provide an additional layer of protection.

Advantages:

  • Blocking XSS Attacks: Instructs browsers to block responses that detect as containing XSS attacks.

6. Referrer-Policy

add_header Referrer-Policy "no-referrer-when-downgrade";

Purpose: This header controls how much referrer information should be included with requests. It's crucial for privacy and security, ensuring that sensitive URL parameters are not leaked.

Advantages:

  • Control Referrer Information: Helps in controlling and limiting the amount of referrer data that can be passed on to other websites.

  • Protects Sensitive Information: Prevents the possibility of leaking sensitive information through the Referrer header when navigating from HTTPS to HTTP sites.

Conclusion

Setting up an Nginx server on Amazon Linux 2 and securing it with HTTPS and recommended security headers is crucial for the performance and security of your web applications. By following this guide, you can ensure that your server is well-configured to handle web traffic securely and efficiently. Whether you are deploying PHP applications or any other type of web application, understanding how to configure your server properly is essential for any developer or system administrator.