How to Compile Nginx From Source on Ubuntu 16.04

Published on: Fri, Jun 30, 2017 at 12:20 pm EST
Linux Guides System Admin Ubuntu Web Servers

NGINX can be used as an HTTP/HTTPS server, reverse proxy server, mail proxy server, load balancer, TLS terminator, or caching server. It is quite modular by design. It has native modules and third-party modules created by the community. Written in the C programming language, it's a very fast and lightweight piece of software.

NOTE: NGINX has two version streams that run in parallel - stable and mainline. Both versions can be used on a production server. It is recommended to use the mainline version in production.

Installing NGINX from source code is relatively "easy" - download the latest version of the NGINX source code, configure, build and install it.

In this tutorial I will use the mainline version, which is 1.13.1 at the time of writing. Update version numbers accordingly when newer versions become available.

Requirements for building NGINX from source

Mandatory requirements:

  • OpenSSL library version between 1.0.2 - 1.1.0
  • Zlib library version between 1.1.3 - 1.2.11
  • PCRE library version between 4.4 - 8.40
  • GCC Compiler

Optional requirements:

Before you begin

  1. Create regular user with sudo access.

  2. Switch to the new user:

    su - <username>
    
  3. Update system:

    sudo apt update && sudo apt upgrade -y
    

Build NGINX from source

  1. NGINX is a program written in C, so we need to install the C compiler (GCC).

    sudo apt install build-essential -y
    
  2. Download the latest version of NGINX source code and extract it:

    wget https://nginx.org/download/nginx-1.13.1.tar.gz && tar zxvf nginx-1.13.1.tar.gz
    
  3. Download the NGINX dependencies' source code and extract them:

    NGINX depends on 3 libraries: PCRE, zlib and OpenSSL:

    # PCRE version 4.4 - 8.40
    wget https://ftp.pcre.org/pub/pcre/pcre-8.40.tar.gz && tar xzvf pcre-8.40.tar.gz
    
    # zlib version 1.1.3 - 1.2.11
    wget http://www.zlib.net/zlib-1.2.11.tar.gz && tar xzvf zlib-1.2.11.tar.gz
    
    # OpenSSL version 1.0.2 - 1.1.0
    wget https://www.openssl.org/source/openssl-1.1.0f.tar.gz && tar xzvf openssl-1.1.0f.tar.gz
    
  4. Remove all .tar.gz files. We don't need them anymore:

    rm -rf *.tar.gz
    
  5. Go to the NGINX source directory:

    cd ~/nginx-1.13.1
    
  6. For help, you can list available configuration switches by running:

    ./configure --help
    
  7. Configure, compile, and install NGINX:

    ./configure --prefix=/usr/share/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=/run/nginx.pid \
                --lock-path=/var/lock/nginx.lock \
                --user=www-data \
                --group=www-data \
                --build=Ubuntu \
                --http-client-body-temp-path=/var/lib/nginx/body \
                --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
                --http-proxy-temp-path=/var/lib/nginx/proxy \
                --http-scgi-temp-path=/var/lib/nginx/scgi \
                --http-uwsgi-temp-path=/var/lib/nginx/uwsgi \
                --with-openssl=../openssl-1.1.0f \
                --with-openssl-opt=enable-ec_nistp_64_gcc_128 \
                --with-openssl-opt=no-nextprotoneg \
                --with-openssl-opt=no-weak-ssl-ciphers \
                --with-openssl-opt=no-ssl3 \
                --with-pcre=../pcre-8.40 \
                --with-pcre-jit \
                --with-zlib=../zlib-1.2.11 \
                --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_slice_module \
                --with-http_ssl_module \
                --with-http_sub_module \
                --with-http_stub_status_module \
                --with-http_v2_module \
                --with-http_secure_link_module \
                --with-mail \
                --with-mail_ssl_module \
                --with-stream \
                --with-stream_realip_module \
                --with-stream_ssl_module \
                --with-stream_ssl_preread_module \
                --with-debug \
                --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' \
                --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now'
    make 
    sudo make install
    
  8. Remove all downloaded files from the home directory, in this case /home/username:

    cd ~
    rm -r nginx-1.13.1/ openssl-1.1.0f/ pcre-8.40/ zlib-1.2.11/
    
  9. Check NGINX version and compile time options:

    sudo nginx -v && sudo nginx -V
    
    # nginx version: nginx/1.13.0 (Ubuntu)
    # built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
    # built with OpenSSL 1.1.0f  25 May 2017
    # TLS SNI support enabled
    # configure arguments: --prefix=/etc/nginx . . .
    # . . .
    # . . .
    
  10. Check syntax and potential errors:

    sudo nginx -t
    # Will throw this error nginx: [emerg] mkdir() "/var/lib/nginx/body" failed (2: No such file or directory)
    # Just create directory
    mkdir -p /var/lib/nginx && sudo nginx -t
    
  11. Create systemd unit file for NGINX:

    sudo vim /etc/systemd/system/nginx.service
    
  12. Copy/paste the following content:

    NOTE: The location of the PID file and the NGINX binary may be different depending on how NGINX was compiled.

    [Unit]
    Description=A high performance web server and a reverse proxy server
    After=network.target
    
    [Service]
    Type=forking
    PIDFile=/run/nginx.pid
    ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
    ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
    ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
    ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
    TimeoutStopSec=5
    KillMode=mixed
    
    [Install]
    WantedBy=multi-user.target
    
  13. Start and enable NGINX service:

    sudo systemctl start nginx.service && sudo systemctl enable nginx.service
    
  14. Check if NGINX will startup after a reboot:

    sudo systemctl is-enabled nginx.service
    # enabled
    
  15. Check if NGINX is running:

    sudo systemctl status nginx.service
    ps aux | grep nginx
    curl -I 127.0.0.1
    
  16. Reboot your Ubuntu VPS to verify that NGINX starts up automatically:

    sudo shutdown -r now
    
  17. Create UFW NGINX application profile:

    sudo vim /etc/ufw/applications.d/nginx
    
  18. Copy/paste the following content:

    [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
    
  19. Now, verify that UFW app profiles are created and recognized:

    sudo ufw app list
    
    # Available applications:
      # Nginx Full
      # Nginx HTTP
      # Nginx HTTPS
      # OpenSSH
    

Conclusion

That's it. You now have newest version of NGINX installed. It is compiled statically against some important libraries like OpenSSL. Often, the system OpenSSL version is outdated. By using this method of installing with a newer version of OpenSSL, you can take advantage of new ciphers like CHACHA20_POLY1305 and protocols like TLS 1.3 that will be available in OpenSSL 1.1.1 (which has not been released).

Want to contribute ?

You could earn up to $300 by adding new articles