Install from Source
This article describes how to install Nginx by compiling it from its source-code on a Ubuntu Server.
This is a little bit more complicated then a default install, but allows us to use the most current version and install additional 3rd-party modules like brotli compression, new ciphers with a more recent OpenSSL version and ngx_cache_purge.
Note
All the following steps are also available as
downloadable
shell
script.
Software Package Repository
The Nginx project releases its own ready-made Ubuntu software packages.
The ‘mainline’ releases contain the latest stable code as recommended for use by the project.
Add these software repositories to the systems package list:
$ sudo -s
echo "deb http://nginx.org/packages/mainline/ubuntu/ `lsb_release -sc` nginx" \
> /etc/apt/sources.list.d/nginx.org-mainline.list
$ echo "deb-src http://nginx.org/packages/mainline/ubuntu/ `lsb_release -sc` nginx" \
>> /etc/apt/sources.list.d/nginx.org-mainline.list
$ exit
All software packages released by the project are signed with a GPG key.
Add the signing key to the systems trusted keyring:
$ wget -O - http://nginx.org/keys/nginx_signing.key | sudo apt-key add -
For working with the source code later, the signing key needs to be added to the personal trusted keyring too:
$ wget -O - http://nginx.org/keys/nginx_signing.key | \
gpg --no-default-keyring --keyring ~/.gnupg/trustedkeys.gpg --import -
Update the systems packages list:
$ sudo apt update
Install required Software
Get all the stuff needed for building nginx and modules:
$ sudo apt install autoconf build-essential devscripts git \
libgd-dev libgeoip-dev libpcre3 libpcre3-dev libxslt1-dev libxml2-dev \
python-dev python2.7 unzip zlib1g-dev
$ sudo apt build-dep nginx
$ sudo apt-get install
Set Version Numbers
Set the Nginx Changes version number:
$ export NGX_VERSION=1.17.0
Set the OpenSSL version:
$ export OPENSSL_VERSION=1.1.1c
Set the ngx_cache_purge module version:
$ export NCP_VERSION=2.3
Set the Headers-More module version:
$ export NHM_VERSION=0.33
Set the ngx-fancyindex module version:
$ export FANCYINDEX_VERSION=0.4.3
Get the Source Code
Prepare source code directory:
$ sudo mkdir -p /usr/local/src/nginx
$ sudo chown $USER /usr/local/src/nginx
$ sudo chmod u+rwx /usr/local/src/nginx
Source Code for Nginx
Get the Nginx package source code:
$ cd /usr/local/src/nginx
$ apt source nginx
Modules:
$ apt source nginx-module-geoip nginx-module-image-filter nginx-module-xslt
Source Code for OpenSSL
Get and verify OpenSSL source:
$ cd /usr/local/src/nginx
$ wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz
$ wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz.asc
$ gpg2 --verify openssl-${OPENSSL_VERSION}.tar.gz.asc
$ tar -xzvf openssl-${OPENSSL_VERSION}.tar.gz
$ rm openssl-${OPENSSL_VERSION}.tar.gz
Build and install a standalone OpenSSL binary (optional):
$ cd /usr/local/src/nginx/openssl-${OPENSSL_VERSION}/
$ sudo mkdir -p /opt/openssl-${OPENSSL_VERSION}
$ ./config --prefix=/opt/openssl-${OPENSSL_VERSION} no-shared
$ make clean
$ make depend
$ make
$ make test
$ sudo make install_sw
$ /opt/openssl-${OPENSSL_VERSION}/bin/openssl version
Source Code for Brötli
Get and install Brötli source:
$ cd /usr/local/src/nginx
$ git clone https://github.com/google/brotli.git
$ cd brotli
$ sudo python setup.py install
Get Brötli Nginx module source:
$ cd /usr/local/src/nginx
$ git clone https://github.com/google/ngx_brotli.git
Make sure that the git submodule has been checked out:
cd /usr/local/src/nginx/ngx_brotli
git submodule update --init
Source Code for Cache Purge Module
Download the source code for the ngx_cache_purge module:
$ cd /usr/local/src/nginx
$ wget -O ngx_cache_purge-${NCP_VERSION}.zip \
https://github.com/FRiCKLE/ngx_cache_purge/archive/${NCP_VERSION}.zip
$ unzip ngx_cache_purge-${NCP_VERSION}.zip
Source Code for Headers More Module
Download the source code for the headers-more-nginx-module:
$ cd /usr/local/src/nginx
$ wget -O ngx_headers_more-${NHM_VERSION}.tar.gz \
https://github.com/openresty/headers-more-nginx-module/archive/v${NHM_VERSION}.tar.gz
$ tar -xzf ngx_headers_more-${NHM_VERSION}.tar.gz
Source Code for the Fancy Index Module
Download the source code for the ngx-fancyindex module:
$ cd /usr/local/src/nginx
$ wget -O ngx-fancyindex-${FANCYINDEX_VERSION}.tar.gz \
https://github.com/aperezdc/ngx-fancyindex/archive/v${FANCYINDEX_VERSION}.tar.gz
$ tar -xzf ngx-fancyindex-${FANCYINDEX_VERSION}.tar.gz
Package Configuration
Open the file /usr/local/src/nginx/nginx-${NGX_VERSION}/debian/rules
with your editor.
Add or modify lines of the ./configure commands in the Debian rules file. You have the following choices:
Remove unneeded modules by removing lines:
--with-http_flv_module \
--with-http_geoip_module=dynamic \
--with-http_image_filter_module \
--with-http_mp4_module \
--with-http_random_index_module \
--with-mail \
--with-stream \
Add additional modules:
--with-http_xslt_module \
--add-module=/usr/local/src/nginx/headers-more-nginx-module-${NHM_VERSION} \
--add-module=/usr/local/src/nginx/nginx-fancyindex-${FANCYINDEX_VERSION} \
--add-module=/usr/local/src/nginx/ngx_brotli \
--add-module=/usr/local/src/nginx/ngx_cache_purge-${NCP_VERSION} \
Set location of the OpenSSL source libraries instead of the system default:
--with-openssl=/usr/local/src/nginx/openssl-${OPENSSL_VERSION} \
Don’t forget to escape preceding lines with a backslash \
.
#!/usr/bin/make -f
#export DH_VERBOSE=1
export DEB_BUILD_MAINT_OPTIONS=hardening=+all,-pie
export DEB_CFLAGS_MAINT_APPEND=-Wp,-D_FORTIFY_SOURCE=2 -fPIC
export DEB_LDFLAGS_MAINT_APPEND=-Wl,--as-needed -pie
#DPKG_EXPORT_BUILDFLAGS = 1
include /usr/share/dpkg/buildflags.mk
PKGS = nginx nginx-dbg
BUILDDIR_nginx = $(CURDIR)/debian/build-nginx
BUILDDIR_nginx_debug = $(CURDIR)/debian/build-nginx-debug
INSTALLDIR = $(CURDIR)/debian/nginx
BASEDIR = $(CURDIR)
ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
ifeq (${NUMJOBS}, 0)
NUMJOBS = 1
endif
else
NUMJOBS = 1
endif
DO_PKGS = $(PKGS)
config.env.%:
dh_testdir
mkdir -p $(BUILDDIR_$*)
cp -Pa $(CURDIR)/auto $(BUILDDIR_$*)/
cp -Pa $(CURDIR)/conf $(BUILDDIR_$*)/
cp -Pa $(CURDIR)/configure $(BUILDDIR_$*)/
cp -Pa $(CURDIR)/contrib $(BUILDDIR_$*)/
cp -Pa $(CURDIR)/man $(BUILDDIR_$*)/
cp -Pa $(CURDIR)/src $(BUILDDIR_$*)/
touch $@
config.status.nginx: config.env.nginx
cd $(BUILDDIR_nginx) && \
CFLAGS="" ./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 \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--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 \
--user=nginx --group=nginx \
--with-compat --with-file-aio --with-threads \
--with-http_addition_module \
--with-http_auth_request_module \
--with-http_dav_module \
--with-http_geoip_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_realip_module \
--with-http_secure_link_module \
--with-http_slice_module \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_sub_module \
--with-http_v2_module \
--with-http_xslt_module \
--add-module=${SRC_DIR}/headers-more-nginx-module-${NHM_VERSION} \
--add-module=${SRC_DIR}/ngx-fancyindex-${FANCYINDEX_VERSION} \
--add-module=${SRC_DIR}/ngx_brotli \
--add-module=${SRC_DIR}/ngx_cache_purge-${NCP_VERSION} \
--with-openssl=${SRC_DIR}/openssl-${OPENSSL_VERSION} \
--with-openssl-opt='enable-ec_nistp_64_gcc_128 enable-tls1_3' \
--with-cc-opt="$(CFLAGS)" --with-ld-opt="$(LDFLAGS)"
touch $@
config.status.nginx_debug: config.env.nginx_debug
cd $(BUILDDIR_nginx_debug) && \
CFLAGS="" ./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 \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock \
--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 \
--user=nginx --group=nginx \
--with-compat --with-file-aio --with-threads \
--with-http_addition_module \
--with-http_auth_request_module \
--with-http_dav_module \
--with-http_geoip_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_realip_module \
--with-http_secure_link_module \
--with-http_slice_module \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_sub_module \
--with-http_v2_module \
--with-http_xslt_module \
--add-module=${SRC_DIR}/headers-more-nginx-module-${NHM_VERSION} \
--add-module=${SRC_DIR}/ngx-fancyindex-${FANCYINDEX_VERSION} \
--add-module=${SRC_DIR}/ngx_brotli \
--add-module=${SRC_DIR}/ngx_cache_purge-${NCP_VERSION} \
--with-openssl=${SRC_DIR}/openssl-${OPENSSL_VERSION} \
--with-openssl-opt='enable-ec_nistp_64_gcc_128 enable-tls1_3' \
--with-cc-opt="$(CFLAGS) -Wno-missing-field-initializers" --with-ld-opt="$(LDFLAGS)" \
--with-debug
touch $@
build-arch.%: config.status.%
dh_testdir
dh_prep
$(MAKE) -j$(NUMJOBS) -C $(BUILDDIR_$*) build
build-arch: build-arch.nginx build-arch.nginx_debug
dh_testdir
touch $@
build-dbg.%: install
dh_testdir
dh_strip --dbg-package=nginx-dbg
build-dbg: build-dbg.nginx
dh_testdir
touch $@
build-indep:
dh_testdir
touch $@
build: build-arch build-indep
dh_testdir
touch $@
clean:
dh_testdir
dh_testroot
dh_clean
rm -f $(CURDIR)/objs
rm -rf $(CURDIR)/debian/build-*
rm -f $(CURDIR)/debian/*.init
find $(CURDIR) -maxdepth 1 -size 0 -delete
post-build:
mv $(BUILDDIR_nginx_debug)/objs/nginx $(BUILDDIR_nginx_debug)/objs/nginx-debug
ln -s $(BUILDDIR_nginx)/objs $(CURDIR)/objs
cp $(BUILDDIR_nginx)/objs/nginx.8 $(BUILDDIR_nginx)/objs/nginx-debug.8
install:
dh_testdir
dh_testroot
dh_prep
dh_installdirs
dh_install
mkdir -p $(INSTALLDIR)/usr/lib/nginx/modules
mkdir -p $(INSTALLDIR)/usr/share/doc/nginx
install -m 644 debian/CHANGES $(INSTALLDIR)/usr/share/doc/nginx/changelog
install -m 644 debian/nginx.default.conf $(INSTALLDIR)/etc/nginx/conf.d/default.conf
ln -s /usr/lib/nginx/modules $(INSTALLDIR)/etc/nginx/modules
binary-indep: build post-build install
dh_testdir
dh_testroot
dh_installman -i -pnginx
dh_installdebconf
sed -e 's/%%PROVIDES%%/nginx/g' \
-e 's/%%DEFAULTSTART%%/2 3 4 5/g' \
-e 's/%%DEFAULTSTOP%%/0 1 6/g' \
< debian/nginx.init.in > debian/nginx.init
dh_installinit -i -pnginx --no-restart-on-upgrade --no-start --name=nginx
dh_systemd_enable -pnginx --name=nginx nginx.service
sed -e 's/%%PROVIDES%%/nginx-debug/g' \
-e 's/%%DEFAULTSTART%%//g' \
-e 's/%%DEFAULTSTOP%%/0 1 2 3 4 5 6/g' \
< debian/nginx.init.in > debian/nginx-debug.init
dh_installinit -i -pnginx --no-restart-on-upgrade --no-start --noscripts --name=nginx-debug
dh_systemd_enable -pnginx --name=nginx-debug --no-enable nginx-debug.service
dh_installlogrotate -i -pnginx --name=nginx
binary-arch: install build-dbg
dh_testdir
dh_testroot
dh_installchangelogs -a
dh_installdocs -a
dh_lintian -a
dh_link -aA
dh_compress -a
dh_perl -a
dh_fixperms -a
dh_installdeb -a
dh_shlibdeps -a
dh_gencontrol -a
dh_md5sums -a
dh_builddeb $(foreach p,$(DO_PKGS),-p$(p))
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install
Increase Package Version
Ubuntu will always remember, that our package was not installed from the official package source, and will therefore always offer to “upgrade” our package to the “newest version”, which is essentially the same version we already have. By increasing the version number of our package, we don’t get bothered with update notfications:
$ cd /usr/local/src/nginx/nginx-${NGX_VERSION}
$ dch
An editor opens where the package changes can be entered.
The scheme used by Ubuntu software packages is:
<Upstream Version>-<Debian Version>~Ubuntu<Ubuntu Package Version>
A new version number and your name are already pre-filled:
nginx (1.13.1-1~xenialubuntu1) UNRELEASED; urgency=medium
.
* Change server name reported in HTTP responses
* Build against OpenSSL 1.1.0c
* Added dynamic XSLT module
* Added 3rd-party brotli compression module
* Added 3rd-party cache purge module
* Added 3rd-party Google PageSpeed module
* Changed mail module to dynamic
After saving and closing the file the customized package source is ready for building.
Building the Software
In case you want to restart from a clean build:
$ cd /usr/local/src/nginx/nginx-${NGX_VERSION}
$ dpkg-buildpackage -rfakeroot -Tclean
Build the Nginx package as follows:
$ cd /usr/local/src/nginx/nginx-${NGX_VERSION}
$ dpkg-buildpackage -rfakeroot -uc -b
Depending on your options the building process might take anything form five minutes to over a half-hour to complete.
Package Installation
Install the package(s):
$ cd /usr/local/src/nginx
$ sudo dpkg --install nginx_${NGX_VERSION}-1~xenialubuntu1_amd64.deb
Nginx is installed and started as system service nginx running as user nginx.
Configuration files are found in the /etc/nginx
directory.
Prevent future releases to automatically overwrite our customized packages:
$ sudo apt-mark hold nginx
Test
Show version number and available modules:
$ nginx -V
nginx version: nginx/1.13.1
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