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:
- Installing, Configuring and Securing NGINX (this)
- Compiling, Installing and Configuring the GeoIP2 module
- Installing and Configuring CertBot
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:
sudo vi /etc/apt/sources.list.d/nginx.listAdd the following content:
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.
To add the keys for the repositories:
sudo wget https://nginx.org/keys/nginx_signing.key
sudo apt-key add nginx_signing.keyor
curl -L https://nginx.org/keys/nginx_signing.key | sudo apt-key add -After that, update apt database with:
sudo apt updateNow you are ready to install the latest version, issue the following command:
sudo apt install nginxYou can check the available versions with apt show nginx.
To prioritise the mantainer repository over the distribution one, you need to create the preference file in /etc/apt/preferences.d/ with the name 99nginx for example, and add the following content:
Package: *
Pin: origin nginx.org
Pin: release o=nginx
Pin-Priority: 900By 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:
conf.d
fastcgi_params
mime.types
modules -> /usr/lib/nginx/modules
nginx.conf
scgi_params
uwsgi_paramsSome useful commands
If you want to check if NGINX is running, use:
sudo systemctl status nginx.serviceTo start the service you can use:
sudo systemctl start nginx.serviceTo stop NGINX use:
sudo systemctl stop nginx.serviceConfiguring 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:
sudo mkdir /etc/nginx/modules-enabledNow let’s create folders for the site’s configurations following the same pattern (available and enabled)
sudo mkdir /etc/nginx/sites-available
sudo mkdir /etc/nginx/sites-enabledAnd finally a folder for snippets of configuration that will be later used by CertBot (letsencrypt), General directives and Security directives.
sudo mkdir /etc/nginx/snippetsThe 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:
# 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_processesyou can leaveautoor use the output ofgrep processor /proc/cpuinfo | wc -l - For
worker_connectionsyou should use the output ofulimit -n. and finally generate the Diffie-Hellman keys withopenssl 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:
sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/sites-available/
sudo ln -s /etc/nginx/sites-available/default.conf /etc/nginx/sites-enabled/defaultEdit the file /etc/nginx/nginx.conf to add the following line at the end before the closing curly braces include /etc/nginx/sites-enabled/*;
The nginx.conf file should look like:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}Checking the configuration file
To check that all config and the loaded modules all is correct, you can issue the following command:
sudo nginx -ttIf 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:
sudo nginx -VThe output should be similar to this:
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:
sudo apt install ufwNow, let’s configure the basic rules to allow incoming and outgoing communication in both HTTP and HTTPS:
sudo ufw allow HTTP
sudo ufw allow HTTPSThe firewall is ready, if you are accessing your Debian via ssh, add also sudo ufw allow SSH.
sudo ufw allow 2222/tcp)Once that is complete you can proceed to activate the firewall with:
sudo ufw enableG