Nginx Installation on Debian - Featured Image

Nginx Installation on Debian Linux: The Complete Guide

In Applications, System Administration & Devops by Željko JaguštLeave a Comment

In this guide, we will guide you through the steps required to set up the Nginx Web Server on the Debian Linux system. By the time you finish this tutorial, you will have a robust web server system ready to serve your static content or act as a proxy for various backend services. Let's dive in!

Introduction

Nginx is a robust, open-source web server and a highly efficient reverse proxy, renowned for its speed, light footprint, and scalability. It excels in managing many simultaneous connections and is a go-to choice for high-traffic websites, including major internet players. Nginx stands out for its minimal resource usage and advanced capabilities, such as load balancing, caching, and SSL/TLS termination. Its modular design and comprehensive configuration options provide immense flexibility to serve static and dynamic content.

Prerequisites

You will need Debian Linux (or any other Debian-based Linux distribution) installed on your computer or a server. If you don't have one, we have a couple of articles that can help you with Debian installation and initial configuration:

Home/Small Office – Debian Server

We picked Debian for our home or small office server. Stability was the main focus when choosing, and Debian is renowned for it.

Home/Small Office – Debian Server Initial Customization

Discover introductory steps to streamline performance, security, and administration in our Debian Server Initial Customization guide.

Nginx Installation

At the moment of writing this article, the latest mainline version of Nginx was 1.25.3, and the latest version available in the Debian APT package manager (Debian 12 - Bookworm) was 1.22.1. We will install Nginx on our server/computer using the APT package manager. To do so, execute the following command:
apt install -y nginx-extras

For any questions the installer might ask during the installation, accept the defaults by pressing Enter on your keyboard. Once installed, you will find all configuration files at the default location in the /etc/nginx directory.

In the next section of this guide, we will observe the function of the essential configuration files and perform the initial configuration of the Nginx web server.

Nginx Configuration

Here, we will check the essential Nginx configuration files and show you how to modify them so that Nginx can serve your static content. Let's observe the configuration files first.

Configuration Files Hierarchy

Once you install the Nginx, you will find all configuration files in the /etc/nginx directory. You will notice a couple of other files and sub-directories, along with the main configuration file, which allows us to fine-grain the Nginx configuration. Let's observe only the essential files required for Nginx to serve simple static content:

    • nginx.conf - Nginx main configuration file. It contains mainly "global" settings required for Nginx to work in general. You can use this single file to perform a complete Nginx configuration, but I would not recommend it. In cases where you need to host many websites, putting everything in a main configuration file will clutter it, thus making it difficult to maintain. The "correct" way of doing things is to use the include core functionality of Nginx to split our configuration files into a set featuring specific files stored in the main /etc/nginx directory or sub-directories.
    • mime.types - MIME types describe the media type of content. They are intended to help hint at how the content should be processed and displayed. This file is included in the main Nginx configuration: include /etc/nginx/mime.types;.
    • conf.d subdirectory - options previously specified in the primary nginx.conf file can be overridden by creating a file at this location. This file is included in the main Nginx configuration: include /etc/nginx/conf.d/*.conf;.
    • sites-available subdirectory - used to store all virtual host configurations, whether enabled or not.
    • sites-enabled subdirectory - used to store all active (enabled) virtual hosts. The ln command is used to enable a virtual host, and the virtual host configuration is symlinked to the sites-enabled directory. This file is included in the main Nginx configuration: include /etc/nginx/sites-enabled/*;.
    • snippets subdirectory - I use this directory to store the configurations that may optionally be included in other configuration files. In most cases, the virtual host configurations.

You may notice other files and directories like fastcgi.conf, proxy_params, etc. They are used for more advanced Nginx configurations, so I will not cover them in this guide. Now that you know how and where to store Nginx configurations, we can start with the configuration itself, and I will show you how in the following subsections.

Snippets - General Security

First, stop the Nginx service. To do so, please execute the following command:
systemctl stop nginx.service
In this snippet, we will define a couple of general security options. Later, this file can be included in other configuration files, but primarily, it is included in HTTPS-only virtual host configurations. Open a new file at /etc/nginx/snippets/general-security.conf and paste in the following content:
# Basic Security Headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

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

Let me explain a bit what we did here:

    • Strict-Transport-Security header - also known as HSTS header, it instructs browsers to communicate with your site only over HTTPS. Your website(s) will set this header every time someone visits, with an expiration date of two years (in seconds). I will cover all subdomains, including internal subdomains that are not publicly accessible. Use extra caution when setting preload.
    • X-Frame-Options header - ensures a website cannot be embedded in a frame or iframe (DENY). Sites can use this to avoid clickjacking attacks by ensuring that their content is not embedded into other sites.
    • X-Content-Type-Options header - this header is used to block browsers' MIME type sniffing, which can transform non-executable MIME types into executable MIME types.
    • location block - in this block, I have denied access to all "dotted" (hidden) files except the ".well-known" directory, which is required by LetsEncrypt (certbot).

Snippets - General Vhost

Each virtual host or website you're hosting may or may not have a favicon and robots definition files. The files mentioned are not mandatory for a website to function, and in cases where they are not present, we can tell our web server not to log their absence (otherwise, it will). To do so, open a new file at /etc/nginx/snippets/general-vhost.conf and paste in the following content:
# favicon.ico
location = /favicon.ico {
    log_not_found off;
    access_log off;
}

# robots.txt
location = /robots.txt {
    log_not_found off;
    access_log off;
}
This file can also be included in virtual host configuration files.

Nginx Main Configuration File

The main configuration file is located at /etc/nginx/nginx.conf. It contains "global" options applied each time Nginx is started/restarted. I would advise creating a backup of this file each time you modify it. Just so you can quickly revert to the previous "known" state in case of any errors. To do so, you can execute the following command:
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bkp
The configuration example below is something I consider a "sane" configuration for a small-to-medium traffic public web server. To apply it, open /etc/nginx/nginx.conf file and paste in the following content:
# Master Nginx Configuration

# User - change to nobody if using reverse proxy
#user nobody nogroup;
user www-data;

pid /var/run/nginx.pid;
worker_processes 4; # = number of CPU cores
worker_rlimit_nofile 65535;
timer_resolution 50ms;

# Include Modules
include /etc/nginx/modules-enabled/*.conf;

events {
    use epoll;
    worker_connections 1024;
    multi_accept on;
}

http {
    charset utf-8;
    sendfile on;
    tcp_nopush off;
    log_not_found off;

    # AIO Threads
    aio threads;
    aio_write on;

    # Server Tokens
    server_tokens off;
    more_set_headers 'Server: My WebServer';

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

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

    # Mandatory Master Settings
    # Enable if using reverse proxy
    #proxy_temp_path /home/nginx/proxy_temp 1 2;
    #proxy_buffers 16 16k;
    #proxy_buffer_size 16k;
    
    server_names_hash_max_size 2048;
    server_names_hash_bucket_size 256;
    keepalive_timeout 10s;
    keepalive_requests 100;
    keepalive_disable msie6;

    # Optional Master Settings
    client_body_timeout 60;
    client_header_timeout 60;
    gzip on;
    gzip_disable "MSIE [1-6].(?!.*SV1)";
    gzip_vary on;
    gzip_min_length 1000;
    gzip_buffers 16 8k;
    gzip_proxied expired no-cache no-store private auth;
    gzip_comp_level 6;
    gzip_http_version 1.0;
    gzip_types text/plain text/css application/x-javascript application/javascript text/xml text/csv application/x-shockwave-flash image/svg+xml;
    send_timeout 60;

    # SSL Settings - https://syslink.pl/cipherlist/
    # Enable (uncomment) only if SSL/HTTPS is used
    #ssl_session_timeout 10m;
    #ssl_session_cache shared:SSL:10m;
    #ssl_session_tickets off;
    #ssl_dhparam /etc/nginx/dhparam.pem; # openssl dhparam -out /etc/nginx/dhparam.pem 4096
    #ssl_protocols TLSv1.3;
    #ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
    #ssl_ecdh_curve secp384r1;
    #ssl_stapling on;
    #ssl_stapling_verify on;
    #ssl_prefer_server_ciphers on;
    #resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=300s;
    #resolver_timeout 5s;

    # Includes
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}
I will not explain the options I used since there are many, and I don't want to make this guide any longer than it already is. Instead, I strongly suggest you visit the official Nginx documentation website to clarify each option's effect. You can also use the documentation to tailor the configuration to suit your needs best.

Default Virtual Host Configuration

The default virtual host is something Nginx will use to "reply" in a case where everything else fails. To clarify, imagine you have several virtual hosts on your server, respectively, example01.com, example02.com, and example03.com. You also have a single public IP address that all virtual hosts are using (shared hosting), for example, 10.10.10.1. You can configure the "default virtual host" in one of the following three ways.

If you don't set the default virtual host, the server will elect a virtual host who is first in the alphabetical/numerical order to be the default virtual host. In our example, that will be example01.com.

You can select which virtual host you want to act as a default by setting the default and listen options in its configuration:

server_name example02.com default;
listen 10.10.10.1:80 default_server;
You can also define a dedicated default host configuration, which I recommend you do. I have several public web servers, and I've set the same default host configuration on each one so that, if accessed, the default host will redirect the connection to my primary website (i.e., example.com). You can do the same by opening a new file at /etc/nginx/sites-available/default and paste in the following content:
server {
    server_name default;
    listen 0.0.0.0:80 default_server;

    ##
    # Include general vhost configuration snippet
    ##
    include /etc/nginx/snippets/general-vhost.conf;

    # redirect everything to example.com
    rewrite ^(.*)$ https://example.com$1 permanent;
}
By setting the default virtual host like that, for example, if someone is trying to access the IP address 10.10.10.1, its connection will be redirected to the example.com website.

Virtual Hosts

In this subsection, we will configure our first virtual host (website). To do so, a few prerequisites need to be satisfied:

    • Domain Name: your domain name. To use a public domain, you must register it with a domain register and set the correct name servers. In case you want to use a test domain, you will need to either have a local DNS server or you will have to modify local hosts file (/etc/hosts on Linux systems, C:\Windows\System32\drivers\etc\hosts on MS Windows) by entering a correct hostname/IP address record (i.e., 10.10.10.1 example.com).
    • Content Location: a directory on the server where you will put your website content. The default location is /var/www/$DOMAIN (replace $DOMAIN with your domain name, i.e., example.com).

As an example, I will use the example.com domain name, and I will put the content in /var/www/example.com/public_html directory. I also want logging enabled for my website and logs to go into the/var/www/example.com/logs directory. I will first create the required directories:

mkdir -p /var/www/example.com/{public_html,logs}
To create a virtual host configuration, I will open a new file at /etc/nginx/sites-available/example.com, and I will paste in the following content:
server {
    listen 10.10.10.1:80;
    server_name example.com;
    
    ##
    # Include general vhost configuration snippet
    ##
    include /etc/nginx/snippets/general-vhost.conf;

    ##
    # Logging
    ##
    access_log  /var/www/example.com/logs/access.log;
    error_log   /var/www/example.com/logs/error.log info;

    root /var/www/example.com/public_html;
    index index.html;
    location / {
        try_files $uri $uri/ =404;
    }
}
Everything is ready with the virtual host configuration in place, and Nginx can be started now. First, you can test the configuration by executing the following command:
nginx -t
If everything is OK, you will notice the following messages:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
You may also notice some (if any) [info] messages, which are OK to ignore. With [warning] messages, you can still start the Nginx. In case of any [error] messages, you will not be able to start Nginx, and you will have to address the mistake and fix the configuration. I also suggest you check the configuration and manage the [warning] messages too. If everything is OK, you can start Nginx by executing the following command:
systemctl start nginx.service

Summary

At this point, you should be able to see the website you are serving on your Nginx server. If you don't have a DNS for your domain in place, or if you're doing local host testing, you can still check the website by entering the following line to your local hosts file (/etc/hosts on Linux systems, C:\Windows\System32\drivers\etc\hosts on MS Windows):
10.10.10.1 example.com
You can use your web browser to test the site or the curl command to do the same. I have created a small index.html file in the/var/www/example.com/public_html directory containing only a "Hello All!!!" message, and that is what I expect to see when I access the website:
curl example.com
Hello All!!!
If your website is accessible, you have successfully installed and configured the Nginx web server. Remember, Nginx is a powerful tool that requires careful configuration and optimization to achieve the best performance and security. Regularly monitor your server's performance and security to ensure smooth operation. Thank you for reading, and happy web serving!

Share if you like. Thank you in advance!


Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.