Skip to content

🌐 Installing NGINX

nginx_banner

nginx_logo NGINX is a free, open-source, high-performance HTTP server and reverse proxy, as well as an IMAP/POP3 proxy server. NGINX is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption.


πŸ“₯ Installation

πŸ“¦ Install NGINX

NGINX is one of a handful of servers written to address the C10K problem. Unlike traditional servers, NGINX doesn't rely on threads to handle requests. Instead it uses a much more scalable event-driven (asynchronous) architecture. This architecture uses small, but more importantly, predictable amounts of memory under load. NGINX scales in all directions: from the smallest VPS all the way up to large clusters of servers.

# install NGINX
sudo apt-get install nginx

# check NGINX status
sudo nginx -t && sudo service nginx status

βš™οΈ Configure NGINX

debian places NGINX configuration files in /etc/nginx and its sub-directories. Shared configuration are kept in that root directory. Specific server setups reside in sites-available directory with symlinks in sites-enabled directory to make them active.

🚧 Install 404 webpage

404

The custom default 404 webpage is available here: download.
This configuration ensures that a 404 error page is served when a request does not match any defined virtual host.

Important

Before proceeding, define the required variable:

  • DEFAULT_404_DIR: The absolute path to the 404.html webpage.
# define the absolute path to the 404.html webpage
DEFAULT_404_DIR=/path/to/default
# check that the variable for the default 404 webpage is set, non-empty, and points to an existing directory
[ -n "${DEFAULT_404_DIR}" ] && [ -d "${DEFAULT_404_DIR}" ] || { echo "Error: DEFAULT_404_DIR is not set or not a valid directory"; exit 1; }

# download and copy 404 default webpage
cd ${DEFAULT_404_DIR}
wget https://docs.fum-server.fr/files/default.tar.gz
tar xf default.tar.gz && rm default.tar.gz

βš™οΈ Configure NGINX

# check that the variable for the default 404 webpage is set, non-empty, and points to an existing directory
[ -n "${DEFAULT_404_DIR}" ] && [ -d "${DEFAULT_404_DIR}" ] || { echo "Error: DEFAULT_404_DIR is not set or not a valid directory"; exit 1; }

# configure NGINX
sudo tee /etc/nginx/nginx.conf > /dev/null <<EOF
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
  worker_connections 1024;
}

http {
  ##
  # Core Settings
  ##
  sendfile on;
  tcp_nopush on;
  types_hash_max_size 2048;
  proxy_headers_hash_max_size 1024;
  proxy_headers_hash_bucket_size 128;
  client_max_body_size 10M;
  proxy_intercept_errors on;
  server_tokens off;

  ##
  # MIME types; default fallback
  ##
  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  ##
  # WebSocket upgrade map
  ##
  map \$http_upgrade \$connection_upgrade { default upgrade; '' close; }

  ##
  # One catch-all HTTP server: redirect everything to HTTPS
  ##
  server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 308 https://\$host\$request_uri;
  }

  ##
  # TLS/SSL Settings
  ##
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_prefer_server_ciphers off;
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 1d;
  ssl_session_tickets off;

  ##
  # Gzip Settings
  ##
  gzip on;
  gzip_comp_level 5;
  gzip_min_length 1400;
  gzip_vary on;
  gzip_proxied any;
  gzip_types
    application/atom+xml
    application/javascript
    application/json
    application/ld+json
    application/manifest+json
    application/wasm
    application/xhtml+xml
    application/xml
    image/svg+xml
    text/cache-manifest
    text/css
    text/plain
    text/vcard;

  ##
  # Logging Settings
  ##
  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  ##
  # Virtual Host Configs
  ##
  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/sites-enabled/*;
}
EOF
# check that the variable for the default 404 webpage is set, non-empty, and points to an existing directory
[ -n "${DEFAULT_404_DIR}" ] && [ -d "${DEFAULT_404_DIR}" ] || { echo "Error: DEFAULT_404_DIR is not set or not a valid directory"; exit 1; }

# configure NGINX
sudo tee /etc/nginx/snippets/error-404.conf > /dev/null <<EOF
##
# Common 404 page for all servers
##
location = /404.html {
  root ${DEFAULT_404_DIR};
  internal;
}
EOF

πŸ›‘οΈ Configure ACL rights

adduser adds debian to the www-data group, the same group that NGINX runs under in the default debian install. chgrp recursively updates the html directory and its children to belong to the www-data group.

# add debian to www-data group
sudo adduser "$USER" www-data
sudo chgrp www-data <dir>
chmod 775 <dir>
chmod g+s <dir>
sudo setfacl -m group:www-data:rwx <dir>
sudo setfacl -dm group:www-data:rwx <dir>
# log-out and log-in again

Setting unix right using ACL

See Configure ACL rights section for explanations.

Important

You need to reload your shell for the group association on your user account to take effect.
Logout and login back again.


πŸ”„ Restart NGINX

# restart NGINX service
sudo nginx -t && sudo service nginx restart

🧰 Web Tools

πŸ“¦ Install php-fpm

php-fpm is an advanced, highly-efficient processor for the PHP scripting language.

# install php-fpm
sudo apt-get install php-common php-cli php-fpm

# fix php-fpm security issue and set timezone
sudo sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' /etc/php/7.4/fpm/php.ini
sudo sed -i 's/;date.timezone =/date.timezone = Europe\/Paris/g' /etc/php/7.4/fpm/php.ini

# reduce memory and cpu usage
sudo sed -i 's/pm = dynamic/pm = static/g' /etc/php/7.4/fpm/pool.d/www.conf
sudo sed -i 's/pm.max_children = 5/pm.max_children = 1/g' /etc/php/7.4/fpm/pool.d/www.conf

# restart php-fpm service
sudo service php7.4-fpm restart
Danger

When pairing NGINX with PHP-FPM, it’s possible to return to NGINX a .php URI that does not actually exist within the site’s directory structure. The PHP processor will process the URI, and execute the .php file, because its job is to process anything handed to it by NGINX. This presents a security problem.

It’s important to limit what NGINX passes to PHP-FPM so malicious scripts can’t be injected into return streams to the server. Instead, the request is stopped, possibly then resulting in a 404. You’ll notice that ;cgi.fix_pathinfo=1 is commented out by default. Setting it to 0 and uncommenting it will enforce the configuration should there be any upstream changes in the default value in the future.

Note

This configuration should reduce by more than 50% the memory usage of nginx and php-fpm.

πŸ“¦ Install nodejs

Node.js is an open-source, cross-platform, back-end JavaScript runtime environment that runs on the V8 engine and executes JavaScript code outside a web browser.

sudo apt-get install curl software-properties-common
curl -sL https://deb.nodesource.com/setup_16.x | sudo bash -
sudo apt-get install -y nodejs

πŸ“¦ Install npm

npm (originally short for Node Package Manager) is the default package manager for the JavaScript runtime environment Node.js.

sudo npm install -g npm@latest

πŸ“¦ Install yarn

Yarn is a package manager that doubles down as project manager.

# remove yarn from cmdtest package
sudo apt remove cmdtest && sudo apt autoremove

# import the yarn repository and enable apt repository
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/yarnkey.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | sudo tee /etc/apt/sources.list.d/yarn.list > /dev/null

# install yarn
sudo apt-get update && sudo apt-get install yarn 

πŸ“¦ Install pm2

PM2 is a Production Process Manager for Node.js applications.
PM2 can serve static file very easily with the pm2 serve feature

# install pm2
sudo yarn global add pm2

# upgrade pm2
sudo npm install pm2@latest -g
pm2 update

# generate startup scripts
su git
pm2 startup
exit

Important

It's important to execute the pm2 startup command as user: git because servers will be added and saved with it.

The output of the pm2 startup command will be something like:

[PM2] Init System found: systemd  
[PM2] To setup the Startup Script, copy/paste the following command:  
sudo env PATH=$PATH:/usr/bin /usr/local/share/.config/yarn/global/node_modules/pm2/bin/pm2 startup systemd -u git --hp /home/git

Execute the last command-line to automatically start pm2 at boot.