Compiling Nginx from Source on CentOS 7

Nginx (pronounced “engine x”) is a versatile open-source web server renowned for its high concurrency capabilities. It can function as an HTTP/HTTPS server, reverse proxy server, mail proxy server, software load balancer, TLS terminator, and caching server.

Nginx is highly modular, with components like GZIP and SSL designed as modules that can be enabled or disabled during build time.

It features core modules and an extensive library of third-party modules developed by the community, enhancing its functionality in various ways.

Written in C, Nginx is recognized for its speed and lightweight nature.

Installing Nginx from source is straightforward: download the latest source code, configure it, and then build and install. Choose between the mainline or stable versions. The building process remains the same for both.

This guide will walk you through building Nginx with all available modules in the open-source version using the mainline version 1.15.7 (please update to the latest version number where applicable).

Stable vs. Mainline Version

  • Mainline – Contains the newest features and bug fixes. It is reliable yet might include experimental modules and newly introduced bugs.
  • Stable – Focuses on extensive testing with backported critical fixes from the mainline version.

Core Modules vs. Third-party Modules

Nginx provides two types of modules:

  • Core Modules: Built by the Nginx developers, forming part of the primary software.
  • Third-party Modules: Created by the community, extending Nginx’s functionality with options like PageSpeed, ModSecurity, Lua, and more.

Static Modules vs. Dynamic Modules

Nginx introduced dynamic modules in version 1.9.11, allowing extended flexibility. While static modules are built into the binary at compile-time, dynamic modules can be added later using the load_module directive in nginx.conf.

Building Nginx: Requirements

  • Mandatory: GCC, OpenSSL/LibreSSL/BoringSSL, Zlib, PCRE
  • Optional: Perl, LibGD, MaxMind GeoIP, libxml2, libxslt

Environmental Requirements

  • CentOS 7 system
  • Non-root user with sudo privileges

Installation Steps

Verify CentOS version:

cat /etc/centos-release
# CentOS Linux release 7.6.1810 (Core)

Set the time zone:

timedatectl list-timezones
sudo timedatectl set-timezone 'Region/City'

Update CentOS packages:

sudo yum update -y

Install essential packages:

sudo yum install -y vim curl wget tree

Building Nginx from Source

Install compiler tools for Nginx:

sudo yum groupinstall -y 'Development Tools'

Download and extract Nginx source code:

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

Download and extract dependencies:

# PCRE version 8.42
wget https://ftp.pcre.org/pub/pcre/pcre-8.42.tar.gz && tar xzvf pcre-8.42.tar.gz

# zlib version 1.2.11
wget https://www.zlib.net/zlib-1.2.11.tar.gz && tar xzvf zlib-1.2.11.tar.gz

# OpenSSL version 1.1.1a
wget https://www.openssl.org/source/openssl-1.1.1a.tar.gz && tar xzvf openssl-1.1.1a.tar.gz

Install optional dependencies:

sudo yum install -y perl perl-devel perl-ExtUtils-Embed libxslt libxslt-devel libxml2 libxml2-devel gd gd-devel GeoIP GeoIP-devel

Clean up unnecessary files:

rm -rf *.tar.gz

Navigate to Nginx source directory:

cd ~/nginx-1.15.7

List Nginx source code files with tree:

tree -L 2 .

Copy Nginx manual page:

sudo cp ~/nginx-1.15.7/man/nginx.8 /usr/share/man/man8
sudo gzip /usr/share/man/man8/nginx.8
ls /usr/share/man/man8/ | grep nginx.8.gz
# Check that Man page for Nginx is working:
man nginx
Nginx manpage

For assistance, view compile-time options:

./configure --help
# To list core modules that can be built dynamically:
./configure --help | grep -F =dynamic

Configure, compile, and install Nginx:

./configure --prefix=/etc/nginx \
    --sbin-path=/usr/sbin/nginx \
    --modules-path=/usr/lib64/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=CentOS \
    --builddir=nginx-1.15.7 \
    --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/lib64/perl5 \
    --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 ~

Create a symlink for Nginx modules:

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

Determine Nginx version and build parameters:

sudo nginx -V
# nginx version: nginx/1.15.7 (CentOS)
# built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
# 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/lib64/nginx/modules
# . . .
# . . .

Create Nginx system group and user:

sudo useradd --system --home /var/cache/nginx --shell /sbin/nologin --comment "nginx user" --user-group nginx

Check Nginx syntax for errors:

sudo nginx -t

Create a systemd unit file for Nginx:

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

Insert the following content into /etc/systemd/system/nginx.service:

[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

Starting and Enabling Nginx

Enable and start Nginx:

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

Ensure Nginx starts on reboot:

sudo systemctl is-enabled nginx.service
# enabled

Evaluate Nginx service status:

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

Alternatively, verify Nginx by visiting your server’s domain or IP address.

Nginx welcome page

Remove default backup configuration files:

sudo rm /etc/nginx/*.default

Add syntax highlighting for Nginx in Vim:

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

Nginx Syntax highlighting in Vim

Create necessary Nginx directories:

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

Adjust log file permissions:

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

Create logrotate configuration for Nginx:

sudo vim /etc/logrotate.d/nginx

Add the following content to the configuration file:

/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 temporary installation files:

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

Conclusion

You have now successfully built and installed the latest Nginx version from source. This approach provides flexibility, allowing you to leverage the latest features of libraries such as OpenSSL and more control over Nginx’s functionality compared to pre-built binaries.

Frequently Asked Questions

  • What is the difference between the stable and mainline versions?
    The stable version prioritizes extensive testing and reliability, while the mainline version offers the newest features and updates but may introduce new bugs.
  • Why should I compile Nginx from source?
    Compiling from source gives you control over module selection, enables the use of the latest security features, and allows for customization to suit specific application needs.
  • How do I ensure Nginx starts after a system reboot?
    Use the command sudo systemctl enable nginx.service to configure Nginx to start automatically on boot.
  • Can I update Nginx modules without recompiling?
    With dynamic modules, yes. They allow you to add or update modules without recompiling the entire Nginx binary.
  • Where can I find additional Nginx modules?
    Third-party Nginx modules can be found on the Nginx community module wiki.