Contents

NGINX Installation on Debian

I like lighttpd, is easy in resources and to configure; but there are other players like NGINX which is a great alternative with tons of resources available on the internet and a great community and documentation.

This is the first of 3 posts where I will be:

Let’s start with some clarifications, I installed this as a test and to have great performance, the main installation was as a proxy for my python projects, and a few sites again just for test. Also, I have to spend a few weeks tweaking and hardening the configuration to make it robust for production, to get A+ on the test from SSLLabs at https://www.ssllabs.com/ssltest/.

You can also check the NGINX tool from Digital Ocean at https://www.digitalocean.com/community/tools/nginx, this tool will basically achieve a big part of the configuration and leave you a stable system to build on top.

Installing NGINX:

We will install the latest stable distribution from the NGINX repositories for Debian, this will give you a lean system and you will need to create some helpers like directories for the modules, sites and database.

If you just need what comes with Debian, trigger the installation with sudo apt update then sudo apt install nginx.

If like me, you want the latest Stable version from the NGINX repository, then the first thing is to add the NGINX official repository to apt, for that let’s create a file nginx.list in /etc/apt/sources.list.d as:

1
sudo vi /etc/apt/sources.list.d/nginx.list

Add the following content:

1
2
deb https://nginx.org/packages/debian/ <CODENAME> nginx
deb-src https://nginx.org/packages/debian/ <CODENAME> nginx

<CODENAME> should be your Debian distribution, e.g. buster (or whatever you get from lsb_release -cs) then save the file.

!!! NOTE: There are 2 branches available in the repository, one is the Mainline (Includes the latest features, it is reliable, but it may include some bugs) and Stable (Doesn’t include all of the latest features, but has critical bug fixes and is recommend for production servers). To access the Mainline change the url to https://nginx.org/packages/mainline/debian/.

To add the keys for the repositories:

1
2
sudo wget https://nginx.org/keys/nginx_signing.key
sudo apt-key add nginx_signing.key

or

1
curl -L https://nginx.org/keys/nginx_signing.key | sudo apt-key add -

After that, update apt database with:

1
sudo apt update

Now you are ready to install the latest version, issue the following command:

1
sudo apt install nginx

You can check the available versions with apt show nginx.

To prioritise the mantainer repository over the distribution one, yuo need to create the preference file in /etc/apt/preferences.d/ with the name 99nginx for example, and add the following content:

1
2
3
4
Package: *
Pin: origin nginx.org
Pin: release o=nginx
Pin-Priority: 900

By now you have installed the latest stable version of NGINX and it should be a lean installation. You can visit the server’s ip address using your browser to check that. It will not have any of the directories that have the Debian package distribution, only the following:

1
2
3
4
5
6
7
conf.d
fastcgi_params
mime.types
modules -> /usr/lib/nginx/modules
nginx.conf
scgi_params
uwsgi_params
Some useful commands

If you want to check if NGINX is running, use:

1
$ sudo systemctl status nginx.service

To start the service you can use:

1
$ sudo systemctl start nginx.service

To stop NGINX use:

1
$ sudo systemctl stop nginx.service

Configuring NGINX:

Initially, we will start with the configuration generated by the Digital Ocean Tool for NGINX, then we will tweak it. But first, we need to create some files and directories and get some values from the system.

As we installed NGINX from the project’s repositories, we only have a basic configuration to render a basic page, which you can see if the NINGX is running and you visit the server address. Also, we don’t have the directories to arrange the files, so let’s start with that.

This installation should have a modules directory where will be all modules for the installation, but let’s create a directory for the modules that will be enabled:

1
$ sudo mkdir /etc/nginx/modules-enabled

Now let’s create folders for the site’s configurations following the same pattern (available and enabled)

1
2
$ sudo mkdir /etc/nginx/sites-available
$ sudo mkdir /etc/nginx/sites-enabled

And finally a folder for snippets of configuration that will be later used by CertBot (letsencrypt), General directives and Security directives.

1
$ sudo mkdir /etc/nginx/snippets

The main configuration file for NGINX is nginx.conf located in /etc/nginx, open your favourite editor and copy what you got from the Digital Ocean Tool for NGINX for the nginx.conf file, it should be similar to the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# Generated by nginxconfig.io
# https://www.digitalocean.com/community/tools/nginx?domains.0.php.php=false&domains.0.routing.index=index.html&domains.0.routing.fallbackHtml=true

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

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

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               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=60s;
    resolver_timeout       2s;

    # Load configs
    include                /etc/nginx/conf.d/*.conf;
    include                /etc/nginx/sites-enabled/*;
}

Now let’s tweak what we have:

  • For worker_processes you can leave auto or use the output of grep processor /proc/cpuinfo | wc -l
  • For worker_connections you should use the output of ulimit -n. and finally generate the Diffie-Hellman keys with openssl dhparam -out /etc/nginx/dhparam.pem 4096. !!! If you are using a fresh installation you probably will need to install openssl and its dependencies.
The first server-block default

The first server-block configured is the default and should be in the file default under /etc/nginx/conf.d, we need to move it from the to the sites-available directory and then create a symbolic link to it from sites-enabled, let’s do that:

1
2
$ sudo mv /etc/nignx/conf.d/default.conf /etc/nignx/conf.d/sites-available/
$ sudo ln -s /etc/nginx/sites-available/default.conf /etc/nginx/sites-enabled/default

The default.conf file should look like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
server {
    listen       80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

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

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}
Checking the configuration

To check that all config and the loaded modules all is correct, you can issue the following command:

1
$ sudo nginx -tt

If there is any error or missing reference to a file, you will get an error meessage.

Checking NGINX build details

Sometime to add a module, you need to check if the installed version of NGINX actually support or has been compiled with support for the module you want to add, for that you can use the command:

1
$ sudo nginx -V

The output should be similar to this:

1
2
3
4
5
nginx version: nginx/1.20.1
built by gcc 8.3.0 (Debian 8.3.0-6)
built with OpenSSL 1.1.1d  10 Sep 2019
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.20.1/debian/debuild-base/nginx-1.20.1=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

In this output, you can see that the module http_realip_module has been included as a static module, so you just need to include the configuration snipped in the config file and it will work.

Securing NGINX:

For this task we will rely on ufw for simplicity of management of the iptables. To install let’s issue the following command:

1
$ sudo apt install ufw

Now, let’s configure the basic rules to allow incoming and outgoing communication in both HTTP and HTTPS:

1
2
$ sudo ufw allow HTTP
$ sudo ufw allow HTTPS

The firewall is ready, if you are accessing your Debian via ssh, add also sudo ufw allow SSH.

PORT
The SSH App Label will allow by default the port 22, if you have cnged your ssh port use the appropiated one (e.g. sudo ufw allow 2222/tcp)

Once that is complete you can proceed to activate the firewall with:

1
$ sudo ufw enable
Buy me a Coffee
Hope you find this useful, if you have any question please visit my twitter @bigg_blog and if you have a couple of pounds buy me a coffee.
G