# ========== # Build dynamic Nginx module Brotli # ========== script_name="$(basename $(realpath $0))" working_dir="$(dirname $(realpath $0))" conf_file="${working_dir}/conf/${script_name%%.*}.conf" LOCK_DIR="/tmp/$(basename $0).$$.LOCK" log_file="${LOCK_DIR}/${script_name%%.*}.log" backup_date="$(date +%Y-%m-%d-%H%M)" needed_debian_packages="git libpcre3 libpcre3-dev zlib1g zlib1g-dev openssl libssl-dev" builddir=/usr/local/src/nginx mkdir -p /usr/local/src/nginx cd "${builddir}" clean_up() { # Perform program exit housekeeping rm -rf "$LOCK_DIR" blank_line exit $1 } echononl(){ if $terminal ; then echo X\\c > /tmp/shprompt$$ if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then echo -e -n " $*\\c" 1>&2 else echo -e -n " $*" 1>&2 fi rm /tmp/shprompt$$ fi } fatal(){ echo "" if $terminal ; then echo -e " [ \033[31m\033[1mFatal\033[m ] $*" else echo -e " [ Fatal ] $*" fi echo "" if $terminal ; then echo -e " \033[1mScript terminated\033[m.." else echo -e " Script terminated.." fi echo "" rm -rf $LOCK_DIR exit 1 } error (){ echo "" if $terminal ; then echo -e " [ \033[31m\033[1mError\033[m ] $*" else echo " [ Error ] $*" fi echo "" } warn (){ if $LOGGING || $terminal ; then echo "" if $terminal ; then echo -e " [ \033[33m\033[1mWarn\033[m ] $*" else echo " [ Warn ] $*" fi echo "" fi } info (){ if $LOGGING || $terminal ; then echo "" if $terminal ; then echo -e " [ \033[32m\033[1mInfo\033[m ] $*" else echo " [ Info ] $*" fi echo "" fi } ok (){ if $LOGGING || $terminal ; then echo "" if $terminal ; then echo -e " [ \033[32m\033[1mOk\033[m ] $*" else echo " [ Ok ] $*" fi echo "" fi } echo_done() { if $terminal ; then echo -e "\033[75G[ \033[32mdone\033[m ]" fi } echo_ok() { if $terminal ; then echo -e "\033[75G[ \033[32mok\033[m ]" fi } echo_warn() { if $terminal ; then echo -e "\033[75G[ \033[33mwarn\033[m ]" fi } echo_failed(){ if $terminal ; then echo -e "\033[75G[ \033[1;31mfailed\033[m ]" fi } echo_skipped() { if $terminal ; then echo -e "\033[75G[ \033[90m\033[1mskipped\033[m ]" fi } echo_wait(){ if $terminal ; then echo -en "\033[75G[ \033[5m\033[1m...\033[m ]" fi } trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters echo -n "$var" } blank_line() { if $terminal ; then echo "" fi } # ---------- # - Jobhandling # ---------- # - Run 'clean_up' for signals SIGHUP SIGINT SIGTERM # - trap clean_up SIGHUP SIGINT SIGTERM # - Create lock directory '$LOCK_DIR" # mkdir "$LOCK_DIR" # ---------- # - Some checks .. # ---------- # - Running in a terminal? # - if [[ -t 1 ]] ; then terminal=true else terminal=false fi blank_line # Install needed development packages if not yet installed in the system # echononl "Install needed debian packages if not yet installed in the system" DEBIAN_FRONTEND=noninteractive apt -y install $needed_debian_packages > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi # Find installed version of nginx # # nginx -v # # output like: # # nginx version: nginx/1.18.0 # # For automated detection of currently installed NGINX version (not to be used # for auto-updating, see hooks in post), use: # echononl "Detection of currently installed NGINX version" ngver=$(nginx -v 2>&1 | grep -o '[0-9\.]*') if [[ $? -eq 0 ]] ; then echo_done else echo_failed fi # Get configure parameters of installed NGINX. Not needed if NGINX was configured '--with-compat'. # Uncomment one of the lines below if the script sucessfully builds modules but NGINX throws # a "not binary compatible" error. # echononl "Get configure parameters of installed NGINX" confparams=$(nginx -V 2>&1 | grep -o -- '--prefix='.* | sed -e 's/ --add-dynamic-module=[^[:space:]]*//g') [[ -z "${confparams}" ]] && confparams=$(nginx -V 2>&1 | grep -o -- '--[^with]'.* \ | sed -e 's/ --add-dynamic-module=[^[:space:]]*//g') [[ -z "${confparams}" ]] && confparams=$(nginx -V 2>&1 | grep -- '--' | sed "s/.*' //" \ | sed -e 's/ --add-dynamic-module=[^[:space:]]*//g') [[ -z "${confparams}" ]] && confparams=$(nginx -V 2>&1 | grep -o -- "--prefix='.*'$" \ | sed -e 's/ --add-dynamic-module=[^[:space:]]*//g') echo_done # To automatically select NGINX modules directory: # echononl "Detect NGINX modules directory" [ -d /usr/share/nginx/modules ] && moddir=/usr/share/nginx/modules [ -d $(nginx -V 2>&1 | grep -o 'prefix=[^ ]*' | sed 's/prefix=//')/modules ] && moddir="$(nginx -V 2>&1 | grep -o 'prefix=[^ ]*' | sed 's/prefix=//')/modules" [ -d $(nginx -V 2>&1 | grep -o 'modules-path=[^ ]*' | sed 's/modules-path=//') ] && moddir="$(nginx -V 2>&1 | grep -o 'modules-path=[^ ]*' | sed 's/modules-path=//')" [ "${moddir}" ] || { echo_failed ; error '!! missing modules directory, exiting...'; clean_up 1; } && echo_done blank_line # --- # Download and unpack NGINX # --- [ -d "nginx-${ngver}" ] && mv "nginx-${ngver}" "nginx-${ngver}.${backup_date}" echononl "Download NGINX.." wget https://nginx.org/download/nginx-${ngver}.tar.gz 2> $log_file if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi # Unpack nginx souce code archive echononl "Unpack nginx souce code archive" gunzip < nginx-${ngver}.tar.gz | tar -xf - 2> $log_file if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi # Remove Downloadwed archive # echononl "Remove Downloadwed archive" rm nginx-${ngver}.tar.gz > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi blank_line # --- # Download, initialize, and make Brotli dynamic modules # --- cd /usr/local/src [ -d "ngx_brotli" ] && mv ngx_brotli ngx_brotli.${backup_date} echononl "Clone git repositoty \033[1mngx_brotli\033[m" git clone https://github.com/google/ngx_brotli.git 2> $log_file if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi cd ngx_brotli # download (clone) also submodules # #git submodule update --init --recursive echononl "Download (clone) also submodules" git submodule update --init > $log_file 2>&1 3>&1 if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi cd /usr/local/src/nginx/nginx-${ngver} echononl "Configure NGINX version \033[1m${ngver}\033[m" if [[ -z "${confparams}" ]] ; then nice -n 19 ionice -c 3 ./configure --with-compat --add-dynamic-module=/usr/local/src/ngx_brotli > $log_file 2>&1 else nice -n 19 ionice -c 3 ./configure --add-dynamic-module=/usr/local/src/ngx_brotli ${confparams} > $log_file 2>&1 fi if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi # Build modules # echononl "Build modules" nice -n 19 ionice -c 3 make modules > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi # Replace Brotli in modules directory # echononl "Replace/Add Brotli Filter module in modules directory" [ -f "${moddir}/ngx_http_brotli_filter_module.so" ] && mv "${moddir}/ngx_http_brotli_filter_module.so" "${moddir}/ngx_http_brotli_filter_module.${backup_date}" > $log_file 2>&1 cp -a "/usr/local/src/nginx/nginx-${ngver}/objs/ngx_http_brotli_filter_module.so" \ "${moddir}/ngx_http_brotli_filter_module.so" >> $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi echononl "Replace/Add Brotli Static module in modules directory" [ -f "${moddir}/ngx_http_brotli_static_module.so" ] && mv "${moddir}/ngx_http_brotli_static_module.so" "${moddir}/ngx_http_brotli_static_module.so.${backup_date}" > $log_file 2>&1 cp -a "/usr/local/src/nginx/nginx-${ngver}/objs//ngx_http_brotli_static_module.so" \ "${moddir}/ngx_http_brotli_static_module.so" >> $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi # cp objs/*.so "${moddir}/" chmod 644 "${moddir}/ngx_http_brotli_filter_module.so" chmod 644 "${moddir}/ngx_http_brotli_static_module.so" # Create load_module statements for the two brotli modules # _failed=false echononl "Create load_module statements for the two brotli modules" cat < /etc/nginx/modules-available/http-brotli-filter-module.conf 2> $log_file load_module ${moddir}/ngx_http_brotli_filter_module.so; EOF if [[ $? -ne 0 ]] ; then _failed=true fi cat < /etc/nginx/modules-available/http-brotli-static-module.conf 2>> $log_file load_module ${moddir}/ngx_http_brotli_static_module.so; EOF if [[ $? -ne 0 ]] ; then _failed=true fi if $_failed ; then echo_failed error "$(cat $log_file)" else echo_done fi # Eanable Modules # [[ -h "/etc/nginx/modules-enabled/60-http-brotli-filter-module.conf" ]] \ && rm "/etc/nginx/modules-enabled/60-http-brotli-filter-module.conf" [[ -h "/etc/nginx/modules-enabled/60-http-brotli-static-module.conf" ]] \ && rm "/etc/nginx/modules-enabled/60-http-brotli-static-module.conf" echononl "Enable module Brotli Filter.." ln -s ../modules-available/http-brotli-filter-module.conf \ /etc/nginx/modules-enabled/60-http-brotli-filter-module.conf > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi echononl "Enable module Brotli Static.." ln -s ../modules-available/http-brotli-static-module.conf \ /etc/nginx/modules-enabled/60-http-brotli-static-module.conf > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi # Configure Brotli # echononl "Configure Brotli" cat < /etc/nginx/conf.d/http-brotli.conf 2> $log_file ## # Brotli Settings ## brotli on; brotli_comp_level 6; brotli_static on; brotli_types text/xml image/svg+xml application/x-font-ttf image/vnd.microsoft.icon application/x-font-opentype application/json font/eot application/vnd.ms-fontobject application/javascript font/otf application/xml application/xhtml+xml text/javascript application/x-javascript text/plain application/x-font-truetype application/xml+rss image/x-icon font/opentype text/css image/x-win-bitmap; # brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; EOF if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi # Verify if all is fine # echononl "Verify if all is fine" nginx -t > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi # Restart Nginx webservice # echononl "Restart Nginx webservice.." systemctl restart nginx.service > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat $log_file)" fi clean_up 0