-
-
Save esfand/93e8d9d9e4edb889e375ce314a1b9b81 to your computer and use it in GitHub Desktop.
Shell Script: Build NGINX from Source with Third Party Modules (Cache Purge, GeoIP2), Completely Non-Interactive, No User Input Required
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash -e | |
# build_nginx_from_source.sh | |
# Author: Aaron Luna | |
# Website: alunablog.com | |
# | |
# This script downloads the source code for the latest version of NGINX | |
# (libraries required to build various NGINX modules are also downloaded) | |
# and builds NGINX according to the options specified in the ./configure | |
# command. Many of the possible configuration options are explained at | |
# the link below: | |
# | |
# https://www.nginx.com/resources/wiki/start/topics/tutorials/installoptions/ | |
# | |
# This script includes examples of various ways NGINX can be customized | |
# such as: specifying the version of OpenSSL or GeoIP libraries to use, | |
# adding modules NOT enabled by default and adding third-party modules | |
# such as the GeoIP2 and cache purge modules. | |
# | |
# This script produces a .deb package file which can be used to | |
# uninstall this version of NGINX via apt-get remove nginx or | |
# dpkg ––remove nginx. The .deb package can also be used to install | |
# this version of nginx on another system with the same architecture. | |
# For more info on the checkinstall program which creates the .deb | |
# package, please see: | |
# | |
# https://wiki.debian.org/CheckInstall | |
# | |
# After NGINX is built, all of the source code is added to a .tar.gz | |
# archive file and stored in the $INSTALL_PKG_PATH along with the .deb | |
# package file. Finally, the script creates the systemd unit file and | |
# UFW app profile settings file and copies them to their correct | |
# locations. Finally, the nginx service is enabled and the server is | |
# rebooted to verify that nginx automatically starts. | |
########################################################################## | |
########################################################################## | |
# Environment Variables: KEEP UP TO DATE WITH MOST RECENT VERSION NUMBERS | |
# | |
# Check for latest NGINX version here: | |
# http://www.nginx.org/en/download.html | |
NGINX_VER=1.13.12 | |
# Check for latest PCRE version here: | |
# https://sourceforge.net/projects/pcre/files/pcre/ | |
# NOTE: NGINX requires the orignal PCRE library, NOT PCRE2 | |
PCRE_VER=8.42 | |
# Check for latest zlib version here: | |
# http://zlib.net | |
ZLIB_VER=1.2.11 | |
# Check for latest OpenSSL version here: | |
# https://www.openssl.org/source/ | |
# NOTE: NGINX can be built with either version 1.1.0.x or 1.0.2.x | |
# Per the website: The latest stable version is the 1.1.0 series. | |
# The 1.0.2 series is the Long Term Support (LTS) release, supported | |
# until 31st December 2019. The 0.9.8, 1.0.0 and 1.0.1 versions are | |
# now out of support and should not be used. | |
OPENSSL_VER=1.1.0h | |
#OPENSSL_VER=1.0.2o | |
# GeoIP databases are updated on the first Tuesday of each month, | |
# change the value below to the most recent corresponding date | |
# in YYYYMMDD format, prefixed with the underscore character | |
# Check for latest GeoIP databases here: | |
# https://dev.maxmind.com/geoip/geoip2/geolite2/ | |
GEOIP_VER=_20180403 | |
# IMPORTANT NOTE: | |
# The NGINX source files and the .deb package generated by this script | |
# are both needed to install this customized build on another system. | |
# The folder structure must be exactly the same on the system using the | |
# .deb package as it is on this machine. | |
# | |
# Thus, it is not a good idea to use a path containing the user's home | |
# folder in the value of the $DOWNLOAD_PATH environment variable (the same | |
# username must be used for the install on both systems if the $DOWNLOAD_PATH | |
# contains the user's home folder). | |
# | |
# Directory where all source files used to build NGINX will be stored | |
# temporarily: | |
DOWNLOAD_PATH=/opt | |
# Name of the folder where the .deb package file and archive (.tar.gz) file | |
# will be stored. | |
INSTALL_PKG_FOLDER=save | |
# Name of the folder where downloaded source files will be stored, | |
# this directory and all contents will be removed after NGINX is | |
# successfully installed. | |
SRC_FOLDER=src_files | |
########################################################################## | |
# Constant strings DO NOT EDIT THESE VALUES | |
# | |
EXT=.tar.gz | |
EXT_DB=.mmdb | |
NGINX_PRE=nginx- | |
PCRE_PRE=pcre- | |
ZLIB_PRE=zlib- | |
OPENSSL_PRE=openssl- | |
GEOIP1_PRE=GeoLite2-City | |
GEOIP2_PRE=GeoLite2-Country | |
########################################################################## | |
# Computed Environment Variables DO NOT EDIT THESE VALUES | |
# | |
SRC_PATH=${DOWNLOAD_PATH}/${SRC_FOLDER} | |
INSTALL_PKG_PATH=${DOWNLOAD_PATH}/${INSTALL_PKG_FOLDER} | |
NGINX_SRC_PATH=${SRC_PATH}/${NGINX_PRE}${NGINX_VER} | |
PCRE_SRC_PATH=${SRC_PATH}/${PCRE_PRE}${PCRE_VER} | |
ZLIB_SRC_PATH=${SRC_PATH}/${ZLIB_PRE}${ZLIB_VER} | |
OPENSSL_SRC_PATH=${SRC_PATH}/${OPENSSL_PRE}${OPENSSL_VER} | |
NGINX_SRC_TAR=${NGINX_PRE}${NGINX_VER}${EXT} | |
PCRE_SRC_TAR=${PCRE_PRE}${PCRE_VER}${EXT} | |
ZLIB_SRC_TAR=${ZLIB_PRE}${ZLIB_VER}${EXT} | |
OPENSSL_SRC_TAR=${OPENSSL_PRE}${OPENSSL_VER}${EXT} | |
GEOIP1_DB_TAR=${GEOIP1_PRE}${EXT} | |
GEOIP2_DB_TAR=${GEOIP2_PRE}${EXT} | |
GEOIP1_DB_FOLDER=${GEOIP1_PRE}${GEOIP_VER} | |
GEOIP2_DB_FOLDER=${GEOIP2_PRE}${GEOIP_VER} | |
GEOIP1_DB_FILE=${GEOIP1_PRE}${EXT_DB} | |
GEOIP2_DB_FILE=${GEOIP2_PRE}${EXT_DB} | |
ALL_SRC_FILES_TAR=${NGINX_PRE}${NGINX_VER}-src_files${EXT} | |
########################################################################## | |
# BEGIN SCRIPT EXECUTION | |
# | |
# NOTE: If building NGINX on Amazon EC2 instance with ubuntu 16.04 or 17.10 | |
# use the following command which is commented out in line 166: | |
# "sudo apt update && sudo DEBIAN_FRONTEND=noninteractive apt upgrade -y" | |
# (and comment out line 165) | |
# | |
# if you call "sudo apt upgrade -y" without the noninteractive | |
# setting a prompt asking for a decision re: grub version conflict | |
# will cause the script to hang. If run as part of a packer template, | |
# the user will be unable to interact with the prompt and must cancel | |
# the script via Ctrl+C. | |
# | |
# I tested this with ubuntu versions 14.04, 16.04 and 17.10 with | |
# VM instances from 3 different vendors (Amazon EC2, VMWare Fusion, | |
# VirtualBox) and the issue only occurrs with EC2 instances running 16.04. | |
# It is unknown if this issue exists with older distributions or | |
# VM instances from other vendors. | |
# | |
########################################################################## | |
# Add Maxmind PPA to apt sources | |
sudo add-apt-repository ppa:maxmind/ppa -y | |
# Update OS - SEE NOTE ABOVE IF INSTALLING ON UBUNTU 16.04 or 17.10 ON AMAZON EC2 | |
sudo apt update && sudo apt upgrade -y | |
#sudo apt update && sudo DEBIAN_FRONTEND=noninteractive apt upgrade -y | |
sudo apt autoremove -y | |
# Install build tools (gcc, g++, etc) | |
sudo apt install build-essential -y | |
# Install libraries required by GeoIP2 module to read MaxMind database files | |
sudo apt install libmaxminddb0 libmaxminddb-dev mmdb-bin -y | |
# Install checkinstall to create .deb package file | |
sudo apt install checkinstall -y | |
# Install Uncomplicated Firewall (UFW) since NGINX app profile | |
# is created after install and directory is assumed to exist | |
sudo apt install ufw -y | |
# Create a directory to store all the source files | |
sudo mkdir -p $SRC_PATH | |
cd $SRC_PATH | |
# Download and extract the source code for the latest version of NGINX | |
sudo wget http://nginx.org/download/$NGINX_SRC_TAR && \ | |
sudo tar xzf $NGINX_SRC_TAR | |
# PCRE, zlib and OpenSSL libraries are needed by various NGINX modules, | |
# download and extract the latest version of these as well | |
sudo wget https://downloads.sourceforge.net/project/pcre/pcre/${PCRE_VER}/${PCRE_SRC_TAR} && \ | |
sudo tar xzf $PCRE_SRC_TAR | |
sudo wget http://zlib.net/${ZLIB_SRC_TAR} && \ | |
sudo tar xzf $ZLIB_SRC_TAR | |
sudo wget https://www.openssl.org/source/${OPENSSL_SRC_TAR} && \ | |
sudo tar xzf $OPENSSL_SRC_TAR | |
# Download (third party) NGINX modules: cache purge and GeoIP2 | |
# The GeoIP module included with NGINX only works with v1 MaxMind database files | |
# V2 database files are far superior, see here for more info: | |
# https://dev.maxmind.com/geoip/geoip2/whats-new-in-geoip2/ | |
sudo git clone --recursive https://github.com/FRiCKLE/ngx_cache_purge.git | |
sudo git clone --recursive https://github.com/leev/ngx_http_geoip2_module.git | |
# Remove source code archive files and navigate to the NGINX source directory | |
sudo rm -rf *.tar.gz | |
cd $NGINX_SRC_PATH | |
# Choose the configuration options that are required for this build of NGINX: | |
sudo ./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=/var/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_SRC_PATH \ | |
--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_SRC_PATH \ | |
--with-pcre-jit \ | |
--with-zlib=$ZLIB_SRC_PATH \ | |
--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 \ | |
--add-module=../ngx_http_geoip2_module \ | |
--add-module=../ngx_cache_purge \ | |
--with-cc-opt='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' \ | |
--with-ld-opt='-Wl,-z,relro -Wl,--as-needed' | |
# Build nginx with the specified configuration | |
sudo make | |
# Create a .deb package (instead of running `sudo make install`) | |
sudo checkinstall --install=no -y | |
# Install the .deb package, this allows uninstall via apt-get | |
sudo dpkg -i nginx_${NGINX_VER}-1_amd64.deb | |
# Move the .deb package to a new folder since we are going to create an | |
# archive from the directory containing the downloaded source code files, | |
# which is our current working directory | |
sudo mkdir -p $INSTALL_PKG_PATH | |
sudo mv nginx_${NGINX_VER}-1_amd64.deb ${INSTALL_PKG_PATH}/nginx_${NGINX_VER}-1_amd64.deb | |
# Create an archive containing all the source files needed to build NGINX and | |
# compress the files using the .tar.gz format | |
cd $INSTALL_PKG_PATH | |
sudo tar -zcf $ALL_SRC_FILES_TAR $SRC_PATH | |
# Make both .deb package and source files archive executable by all users | |
sudo chmod 755 nginx*.* | |
# Create a directory at /var/lib/nginx to prevent the NGINX config | |
# file from failing verification in next command (sudo nginx -t) | |
sudo mkdir -p /var/lib/nginx | |
# Verify NGINX version and verify configuration options match what | |
# was specified with the ./configure command | |
echo | |
echo 'Verify NGINX version and config options below:' | |
echo | |
sudo nginx -t && sudo nginx -v && sudo nginx -V | |
# Create folders for nginx multiple virtual host config | |
cd /etc/nginx | |
sudo mkdir sites-available | |
sudo mkdir sites-enabled | |
# Create firewall app profile (UFW) for NGINX | |
# If provisioning an Amazon EC2 instance this does not need to be enabled | |
# if the same rule set is applied via security group | |
sudo touch nginx | |
echo '[Nginx HTTP]' | sudo tee -a nginx | |
echo 'title=Web Server (Nginx, HTTP)' | sudo tee -a nginx | |
echo 'description=Small, but very powerful and efficient web server' | sudo tee -a nginx | |
echo 'ports=80/tcp' | sudo tee -a nginx | |
echo | sudo tee -a nginx | |
echo '[Nginx HTTPS]' | sudo tee -a nginx | |
echo 'title=Web Server (Nginx, HTTPS)' | sudo tee -a nginx | |
echo 'description=Small, but very powerful and efficient web server' | sudo tee -a nginx | |
echo 'ports=443/tcp' | sudo tee -a nginx | |
echo | sudo tee -a nginx | |
echo '[Nginx Full]' | sudo tee -a nginx | |
echo 'title=Web Server (Nginx, HTTP + HTTPS)' | sudo tee -a nginx | |
echo 'description=Small, but very powerful and efficient web server' | sudo tee -a nginx | |
echo 'ports=80,443/tcp' | sudo tee -a nginx | |
# Move the file so UFW can read it. UFW is disabled by default | |
sudo mv nginx /etc/ufw/applications.d/nginx | |
# Create systemd unit file for NGINX | |
sudo touch nginx.service | |
echo '[Unit]' | sudo tee -a nginx.service | |
echo 'Description=A high performance web server and a reverse proxy server' | sudo tee -a nginx.service | |
echo 'After=network.target' | sudo tee -a nginx.service | |
echo | sudo tee -a nginx.service | |
echo '[Service]' | sudo tee -a nginx.service | |
echo 'Type=forking' | sudo tee -a nginx.service | |
echo 'PIDFile=/run/nginx.pid' | sudo tee -a nginx.service | |
echo $'ExecStartPre=/usr/sbin/nginx -t -q -g \'daemon on; master_process on;\'' | sudo tee -a nginx.service | |
echo $'ExecStart=/usr/sbin/nginx -g \'daemon on; master_process on;\'' | sudo tee -a nginx.service | |
echo $'ExecReload=/usr/sbin/nginx -g \'daemon on; master_process on;\' -s reload' | sudo tee -a nginx.service | |
echo 'ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid' | sudo tee -a nginx.service | |
echo 'TimeoutStopSec=5' | sudo tee -a nginx.service | |
echo 'KillMode=mixed' | sudo tee -a nginx.service | |
echo | sudo tee -a nginx.service | |
echo '[Install]' | sudo tee -a nginx.service | |
echo 'WantedBy=multi-user.target' | sudo tee -a nginx.service | |
# Move the file to correct location so NGINX can be started, | |
# stopped and reloaded with global commands | |
sudo mv nginx.service /etc/systemd/system/nginx.service | |
# Remove all source files | |
sudo rm -rf $SRC_PATH | |
# Start and enable NGINX service | |
sudo systemctl start nginx.service && sudo systemctl enable nginx.service | |
# Verify NGINX is running | |
sudo systemctl status nginx.service | |
# Reboot the server | |
sudo shutdown -r now | |
# Log in after the reboot is complete, and verify NGINX is running | |
# sudo systemctl status nginx.service |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment