Nginx (pronounced "engine x") is an open source web server software designed with high concurrency in mind, that can be used as HTTP/HTTPS server, reverse proxy server, mail proxy server, software load balancer, TLS terminator, caching server...
It is an extremely modular piece of software. Even some of the seemingly "built-in" pieces of the software, such as GZIP or SSL, are actually built as modules that can be enabled and disabled during the build time.
It has core (native) modules and third-party (external) modules created by the community. Right now, there are over a hundred third-party modules that we can utilize.
Written in C language, it's a very fast and lightweight piece of software.
Installing Nginx from source code is relatively "easy" - download the latest version of Nginx source code, configure, build and install it.
You’ll need to choose whether to download the mainline or stable version, but building them is exactly the same.
In this tutorial, we will build Nginx with all available modules in the open source version of Nginx and we will use mainline version which is at 1.15.8 at the time of this writing. Update version numbers when newer versions become available.
Stable vs. mainline version
Nginx Open Source is available in two versions:
- Mainline – Includes the latest features and bug fixes and is always up to date. It is reliable, but it may include some experimental modules, and it may also have some number of new bugs.
- Stable – Doesn’t include all of the latest features, but has critical bug fixes that are always backported to the mainline version.
Core modules vs. third-party modules
Nginx has two types of modules that you can utilize: core modules and third-party modules.
Core modules are built by the core Nginx developers and they are part of the software itself.
Third-party modules are built by the community and you can use them to extend Nginx functionality. There are a lot of helpful third-party modules, the most famous among them are: PageSpeed, ModSecurity, RTMP, Lua etc...
Static modules vs. dynamic modules
Static modules exist in Nginx from the very first version. Dynamic modules were introduced with Nginx 1.9.11+ in February 2016.
With static modules, set of modules that constitute a Nginx binary is fixed at compile time by the ./configure
script. Static modules use --with-foo_bar_module
or --add-module=PATH
syntax.
To compile core (standard) module as dynamic we add =dynamic
, for example --with-http_image_filter_module=dynamic
.
To compile third-party module as dynamic we use --add-dynamic-module=/path/to/module
syntax and then we load them by using load_module
directive in the global context of the nginx.conf
file.
Requirements for building Nginx from source
In comparison with some other UNIX/Linux software, Nginx is pretty lightweight and doesn’t have many library dependencies. The default build configuration depends on only 3 libraries to be installed: OpenSSL/LibreSSL/BoringSSL, Zlib and PCRE.
- Mandatory requirements:
- Optional requirements:
Requirements
- A server running Fedora 29 system.
- A non-root user with sudo privileges.
Initial Steps
Check your Fedora version:
cat /etc/fedora-release
# Fedora release 29 (Twenty Nine)
Set up the timezone:
timedatectl list-timezones
sudo timedatectl set-timezone 'Region/City'
Update your Fedora operating system’s packages:
sudo dnf upgrade -y
Install vim, curl, wget and tree packages:
sudo dnf install -y vim curl wget tree
Build Nginx from source
Nginx is a program written in C, so you will first need to install a compiler tools:
sudo dnf groupinstall -y 'Development Tools'
Download latest mainline version of Nginx source code and extract it. Nginx source code is distributed as compressed archive (gzipped tarball), as most Unix and Linux software:
wget https://nginx.org/download/nginx-1.15.8.tar.gz && tar zxvf nginx-1.15.8.tar.gz
Download the mandatory Nginx dependencies' source code and extract them:
# 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 Nginx dependencies:
sudo dnf install -y perl perl-devel perl-ExtUtils-Embed libxslt libxslt-devel libxml2 libxml2-devel gd gd-devel GeoIP GeoIP-devel
Clean up all .tar.gz
files, as they are not necessary anymore:
rm -rf *.tar.gz
Enter the Nginx source directory:
cd ~/nginx-1.15.8
For good measure list directories and files that compose Nginx source code with tree
utility:
tree -L 2 .
Copy Nginx manual page to /usr/share/man/man8/
directory:
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
# Check that Man page for Nginx is working:
man nginx
For help, you can see the full list of up-to-date Nginx compile-time options by running:
./configure --help
# To see want core modules can be build as dynamic run:
./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=Fedora \
--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/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
After building Nginx, navigate to home (~
) directory:
cd ~
Symlink /usr/lib64/nginx/modules
to /etc/nginx/modules
directory. etc/nginx/modules
is a standard place for Nginx modules:
sudo ln -s /usr/lib64/nginx/modules /etc/nginx/modules
Print the Nginx version, compiler version, and configure script parameters:
sudo nginx -V
# nginx version: nginx/1.15.8 (Fedora)
# built by gcc 8.2.1 20150623 (Red Hat 8.2.1-6) (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 and potential errors:
sudo nginx -t
# Will throw this error -> nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (2: No such file or directory)
# Create NGINX cache directories and set proper permissions
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/*
# Re-check syntax and potential errors.
sudo nginx -t
Create Nginx systemd unit file:
sudo vim /etc/systemd/system/nginx.service
Copy/paste the below content into /etc/systemd/system/nginx.service
file:
NOTE: The location of the PID
file and the Nginx binary may be different depending on how Nginx was compiled.
[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 Nginx to start on boot and start Nginx immediately:
sudo systemctl enable nginx.service
sudo systemctl start nginx.service
Check if Nginx will automatically initiate after a reboot:
sudo systemctl is-enabled nginx.service
# enabled
Check if Nginx is running by running one of the following commands:
sudo systemctl status nginx.service
# or
ps aux | grep nginx
# or
curl -I 127.0.0.1
You can also open your browser and navigate to your domain/IP address to see default Nginx page. That is an indicator that Nginx is up and running.
Nginx by default, generates backup .default
files in /etc/nginx
. Remove .default
files from /etc/nginx
directory:
sudo rm /etc/nginx/*.default
Place syntax highlighting of Nginx configuration for Vim editor into ~/.vim
:
# For regular non-root user 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/
NOTE: By doing the above step, you will get a nice syntax highlighting when editing Nginx configuration files in Vim editor.
Create conf.d
, snippets
, sites-available
and sites-enabled
directories in /etc/nginx
directory:
sudo mkdir /etc/nginx/{conf.d,snippets,sites-available,sites-enabled}
Change permissions and group ownership of Nginx log files:
sudo chmod 640 /var/log/nginx/*
sudo chown nginx:adm /var/log/nginx/access.log /var/log/nginx/error.log
Create log rotation config for Nginx.
sudo vim /etc/logrotate.d/nginx
Populate the file with the below text, then save and exit:
/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
}
Remove all downloaded files from the home directory:
cd ~
rm -rf nginx-1.15.8/ openssl-1.1.1a/ pcre-8.42/ zlib-1.2.11/
That's it. Now, you have the latest version of Nginx installed by building it from source code. It is compiled statically against some important libraries like OpenSSL. Often, system-supplied version of OpenSSL 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 is supported in OpenSSL 1.1.1.
Also, by compiling your own binary, you are able to tailor what functionality your Nginx will provide, which is much more flexible than installing a pre-built binary.