Step-by-Step Guide to Compiling Nginx from Source on Debian 9

Nginx (pronounced “engine x”) is an open-source web server designed for high concurrency. It serves multiple purposes such as an HTTP/HTTPS server, reverse proxy server, mail proxy server, software load balancer, TLS terminator, and caching server.

Nginx is highly modular. Even components like GZIP and SSL, which might appear as default features, are implemented as modules that can be enabled or disabled during build time.

With a C language foundation, Nginx is a fast and lightweight software. It features core modules (native) and a variety of third-party modules created by the community. Currently, there are over a hundred third-party modules available, enabling extensive functionality.

Installing Nginx from source is straightforward—download the latest source version, configure, build, and install it. Decide between downloading the mainline or stable version, as the build process is the same for both.

This guide uses the mainline version 1.15.8. Update version numbers as newer versions are released.

Stable vs. Mainline Version

Nginx Open Source offers two versions:

  • Mainline: Features the latest additions and bug fixes. It is highly reliable but may contain experimental modules and potential new bugs.
  • Stable: Focuses on reliability, incorporating critical bug fixes found in the mainline version without including all the latest features.

Core Modules vs. Third-party Modules

Two types of modules can enhance Nginx functionality:

  • Core Modules: Developed by the Nginx team and included directly in the software.
  • Third-party Modules: Community-built extensions providing additional features. Notable examples include PageSpeed, ModSecurity, RTMP, and Lua.

Static Modules vs. Dynamic Modules

Initially, Nginx only supported static modules. Dynamic modules were introduced in Nginx 1.9.11+ (February 2016). Static modules are fixed at compile time with the ./configure script using --with-foo_bar_module or --add-module=PATH.

To compile core modules dynamically, use =dynamic, e.g., --with-http_image_filter_module=dynamic. For third-party modules, use --add-dynamic-module=/path/to/module and load them with the load_module directive in the nginx.conf file.

Requirements for Building Nginx from Source

Nginx is lightweight compared to other UNIX/Linux software, with only three mandatory library dependencies:

  • OpenSSL/LibreSSL/BoringSSL,
  • Zlib,
  • PCRE.

Libraries and versions required:

  • GCC
  • OpenSSL or compatible libraries (versions 1.0.2-1.1.1)
  • Zlib (versions 1.1.3-1.2.11)
  • PCRE (versions 4.4-8.42)

Optional requirements include:

  • Perl
  • LibGD
  • MaxMind GeoIP Legacy C Library
  • libxml2, libxslt

Requirements

  • A server running Debian 9 (stretch).
  • A non-root user with sudo privileges.

Initial Steps

Check the Debian version:

lsb_release -ds

Install necessary packages:

apt install -y wget curl sudo

Set up the timezone:

sudo dpkg-reconfigure tzdata

Update system packages:

apt update && apt upgrade -y

Build Nginx from Source

Nginx is written in C, so install compiler tools first:

sudo apt install -y build-essential git tree software-properties-common dirmngr apt-transport-https ufw

Download the latest Nginx mainline version source and extract it:

wget https://nginx.org/download/nginx-1.15.8.tar.gz && tar zxvf nginx-1.15.8.tar.gz

Fetch mandatory Nginx dependencies and extract:


      wget https://ftp.pcre.org/pub/pcre/pcre-8.42.tar.gz && tar xzvf pcre-8.42.tar.gz
      wget https://www.zlib.net/zlib-1.2.11.tar.gz && tar xzvf zlib-1.2.11.tar.gz
      wget https://www.openssl.org/source/openssl-1.1.1a.tar.gz && tar xzvf openssl-1.1.1a.tar.gz
    

Install optional dependencies:

sudo apt install -y perl libperl-dev libgd3 libgd-dev libgeoip1 libgeoip-dev geoip-bin libxml2 libxml2-dev libxslt1.1 libxslt1-dev

Remove temporary files:

rm -rf *.tar.gz

Enter Nginx source directory:

cd ~/nginx-1.15.8

List source directories and files:

tree -L 2 .

Copy Nginx manual page:


      sudo cp ~/nginx-1.15.8/man/nginx.8 /usr/share/man/man8
      sudo gzip /usr/share/man/man8/nginx.8
      ls /usr/share/man/man8/ | grep nginx.8.gz
      man nginx
    

Nginx manpage

Explore Nginx compile options:


      ./configure --help
      ./configure --help | grep -F =dynamic
    

Configure, compile, and install Nginx:


      ./configure --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 \
                  --pid-path=/var/run/nginx.pid \
                  --lock-path=/var/run/nginx.lock \
                  --user=nginx \
                  --group=nginx \
                  --build=Debian \
                  --builddir=nginx-1.15.8 \
                  --with-select_module \
                  --with-poll_module \
                  --with-threads \
                  --with-file-aio \
                  --with-http_ssl_module \
                  --with-http_v2_module \
                  --with-http_realip_module \
                  --with-http_addition_module \
                  --with-http_xslt_module=dynamic \
                  --with-http_image_filter_module=dynamic \
                  --with-http_geoip_module=dynamic \
                  --with-http_sub_module \
                  --with-http_dav_module \
                  --with-http_flv_module \
                  --with-http_mp4_module \
                  --with-http_gunzip_module \
                  --with-http_gzip_static_module \
                  --with-http_auth_request_module \
                  --with-http_random_index_module \
                  --with-http_secure_link_module \
                  --with-http_degradation_module \
                  --with-http_slice_module \
                  --with-http_stub_status_module \
                  --with-http_perl_module=dynamic \
                  --with-perl_modules_path=/usr/share/perl/5.24.1 \
                  --with-perl=/usr/bin/perl \
                  --http-log-path=/var/log/nginx/access.log \
                  --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 \
                  --with-mail=dynamic \
                  --with-mail_ssl_module \
                  --with-stream=dynamic \
                  --with-stream_ssl_module \
                  --with-stream_realip_module \
                  --with-stream_geoip_module=dynamic \
                  --with-stream_ssl_preread_module \
                  --with-compat \
                  --with-pcre=../pcre-8.42 \
                  --with-pcre-jit \
                  --with-zlib=../zlib-1.2.11 \
                  --with-openssl=../openssl-1.1.1a \
                  --with-openssl-opt=no-nextprotoneg \
                  --with-debug
      
      make
      sudo make install
    

Return to the home directory:

cd ~

Symlink /usr/lib/nginx/modules to /etc/nginx/modules:

sudo ln -s /usr/lib/nginx/modules /etc/nginx/modules

Display Nginx version and configuration details:


      sudo nginx -V
      nginx version: nginx/1.15.8 (Debian)
      built by gcc 6.3.0 (Debian 6.3.0-18+deb9u1)
      built with OpenSSL 1.1.1a 20 Nov 2018
      TLS SNI support enabled
      configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules
    

Create Nginx system group and user:


      sudo adduser --system --home /nonexistent --shell /bin/false --no-create-home --disabled-login --disabled-password --gecos "nginx user" --group nginx
    

Check Nginx syntax for errors:


      sudo nginx -t
      # Fix errors by creating required directories:
      sudo mkdir -p /var/cache/nginx/client_temp /var/cache/nginx/fastcgi_temp /var/cache/nginx/proxy_temp /var/cache/nginx/scgi_temp /var/cache/nginx/uwsgi_temp
      sudo chmod 700 /var/cache/nginx/*
      sudo chown nginx:root /var/cache/nginx/*
      sudo nginx -t
    

Create Nginx systemd unit file:

sudo vim /etc/systemd/system/nginx.service

Copy and paste the following into the file:


      [Unit]
      Description=nginx - high performance web server
      Documentation=https://nginx.org/en/docs/
      After=network-online.target remote-fs.target nss-lookup.target
      Wants=network-online.target

      [Service]
      Type=forking
      PIDFile=/var/run/nginx.pid
      ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf
      ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
      ExecReload=/bin/kill -s HUP $MAINPID
      ExecStop=/bin/kill -s TERM $MAINPID

      [Install]
      WantedBy=multi-user.target
    

Enable and start Nginx:


      sudo systemctl enable nginx.service
      sudo systemctl start nginx.service
    

Verify Nginx auto-start after reboot:

sudo systemctl is-enabled nginx.service

Check Nginx operation status:


      sudo systemctl status nginx.service
      # or
      ps aux | grep nginx
      #or
      curl -I 127.0.0.1
    

Access your domain or IP via browser to see the default Nginx page, indicating it is functional.

Nginx welcome page

Create a UFW Nginx application profile:

sudo vim /etc/ufw/applications.d/nginx

Add the following:


      [nginx HTTP]
      title=Web Server (nginx, HTTP)
      description=Small, but very powerful and efficient web server
      ports=80/tcp

      [nginx HTTPS]
      title=Web Server (nginx, HTTPS)
      description=Small, but very powerful and efficient web server
      ports=443/tcp

      [nginx Full]
      title=Web Server (nginx, HTTP + HTTPS)
      description=Small, but very powerful and efficient web server
      ports=80,443/tcp
    

Verify UFW profiles:


      sudo ufw app list
      # Available applications:
      # nginx Full
      # nginx HTTP
      # nginx HTTPS
    

Remove default backups:

sudo rm /etc/nginx/*.default

Enable syntax highlighting in Vim:


      mkdir ~/.vim/
      cp -r ~/nginx-1.15.8/contrib/vim/* ~/.vim/
      # For root user
      sudo mkdir /root/.vim/
      sudo cp -r ~/nginx-1.15.8/contrib/vim/* /root/.vim/
    

Nginx Syntax highlighting in Vim

Create essential directories in /etc/nginx:

sudo mkdir /etc/nginx/{conf.d,snippets,sites-available,sites-enabled}

Set log file permissions:


      sudo chmod 640 /var/log/nginx/*
      sudo chown nginx:adm /var/log/nginx/access.log /var/log/nginx/error.log
    

Configure log rotation:

sudo vim /etc/logrotate.d/nginx

Add the following configuration:


      /var/log/nginx/*.log {
          daily
          missingok
          rotate 52
          compress
          delaycompress
          notifempty
          create 640 nginx adm
          sharedscripts
          postrotate
                  if [ -f /var/run/nginx.pid ]; then
                          kill -USR1 `cat /var/run/nginx.pid`
                  fi
          endscript
      }
    

Clean up source files:


      cd ~
      rm -rf nginx-1.15.8/ openssl-1.1.1a/ pcre-8.42/ zlib-1.2.11/
    

Installation is complete. You now have the latest Nginx version built from source, optimized for critical libraries like OpenSSL. This installation method allows leveraging new ciphers like CHACHA20_POLY1305 and protocols such as TLS 1.3 available with OpenSSL 1.1.1.

Frequently Asked Questions (FAQ)

Q1: Why build Nginx from source?

By building from source, you can customize your Nginx installation with specific modules and features tailored to your needs, ensuring compatibility with the latest libraries and security protocols.

Q2: Are there any risks of using the mainline version?

The mainline version is stable but may contain experimental features. It is essential to test configurations thoroughly in a non-production environment before deployment.

Q3: What should I do if I encounter errors during the build process?

Double-check that all dependencies are installed and that you followed the steps correctly. Consider reviewing error logs for more detail and consult the Nginx documentation for further assistance.

Q4: How often should I update Nginx?

Regular updates are recommended to leverage improvements and patch vulnerabilities. Always follow the latest security advisories and update accordingly.

Q5: Can I add more third-party modules?

Yes, you can integrate additional third-party modules by adjusting the configuration steps to include their respective source paths during compilation.