diff --git a/README.install-brotli b/README.install-brotli index f7ec6d9..83a326a 100644 --- a/README.install-brotli +++ b/README.install-brotli @@ -2,14 +2,15 @@ # Build dynamic Nginx module Brotli # ========== -# Download ngx_brotli -# -cd /usr/local/src -git clone https://github.com/google/ngx_brotli.git +backup_date="$(date +%Y-%m-%d-%H%M)" -# download (clone) also submodules +builddir=/usr/local/src/nginx +mkdir -p /usr/local/src/nginx +cd "${builddir}" + +# Install needed development packages if not yet installed in the system # -git submodule update --init --recursive +apt -y install git libpcre3 libpcre3-dev zlib1g zlib1g-dev openssl libssl-dev # Find installed version of nginx @@ -18,55 +19,101 @@ git submodule update --init --recursive # # output like: # -# nginx version: nginx/1.14.2 - - -# Download nginx version 1.14.2 +# nginx version: nginx/1.18.0 # -cd /usr/local/src/nginx -wget https://nginx.org/download/nginx-1.14.2.tar.gz +# For automated detection of currently installed NGINX version (not to be used +# for auto-updating, see hooks in post), use: +# +ngver=$(nginx -v 2>&1 | grep -o '[0-9\.]*') + +# 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. +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') + + +# To automatically select 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 '!! missing modules directory, exiting...'; exit 1; } + + +# --- +# Download and unpack NGINX +# --- +[ -d "nginx-${ngver}" ] && mv "nginx-${ngver}" "nginx-${ngver}.${backup_date}" +wget https://nginx.org/download/nginx-${ngver}.tar.gz # Umpack nginx souce code archive -gunzip < nginx-1.14.2.tar.gz | tar -xf - +gunzip < nginx-${ngver}.tar.gz | tar -xf - -cd nginx-1.14.2/ +# Remove Downloadwed archive +rm nginx-${ngver}.tar.gz -# Configure nginx including dynamic brotli module -# -# From output of 'nginx -V' keep configure arguments, +# --- +# Download, initialize, and make Brotli dynamic modules +# --- +cd /usr/local/src +[ -d "ngx_brotli" ] && mv ngx_brotli ngx_brotli.${backup_date} +git clone https://github.com/google/ngx_brotli.git -# remove *all* flaggs like +cd ngx_brotli + +# download (clone) also submodules # -# --add-dynamic-module= -# -# add -# -# --add-dynamic-module=/usr/local/src/ngx_brotli -# -./configure --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-tBUzFN/nginx-1.14.2=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --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-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_flv_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_secure_link_module --with-http_sub_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --add-dynamic-module=/usr/local/src/ngx_brotli +#git submodule update --init --recursive +git submodule update --init + + + +cd /usr/local/src/nginx/nginx-${ngver} + +if [[ -z "${confparams}" ]] ; then + nice -n 19 ionice -c 3 ./configure --with-compat --add-dynamic-module=/usr/local/src/ngx_brotli +else + nice -n 19 ionice -c 3 ./configure --add-dynamic-module=/usr/local/src/ngx_brotli ${confparams} +fi # Build modules # -make modules +nice -n 19 ionice -c 3 make modules -# Add and load the dynamic brotli modules to nginx service +# Replace Brotli in modules directory # -mkdir -p /etc/nginx/modules +[ -f "${moddir}/ngx_http_brotli_filter_module.so" ] && mv "${moddir}/ngx_http_brotli_filter_module.so" "${moddir}/ngx_http_brotli_filter_module.${backup_date}" +cp -a "/usr/local/src/nginx/nginx-${ngver}/objs/ngx_http_brotli_filter_module.so" \ + "${moddir}/ngx_http_brotli_filter_module.so" -cp -a /usr/local/src/nginx/nginx-1.14.2/objs/ngx_http_brotli_filter_module.so /etc/nginx/modules/ -cp -a /usr/local/src/nginx/nginx-1.14.2/objs/ngx_http_brotli_static_module.so /etc/nginx/modules/ + +[ -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}" +cp -a "/usr/local/src/nginx/nginx-${ngver}/objs//ngx_http_brotli_static_module.so" \ + "${moddir}/ngx_http_brotli_static_module.so" + +# 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 # cat < /etc/nginx/modules-available/http-brotli-filter-module.conf -load_module /etc/nginx/modules/ngx_http_brotli_filter_module.so; +load_module ${moddir}/ngx_http_brotli_filter_module.so; EOF cat < /etc/nginx/modules-available/http-brotli-static-module.conf -load_module /etc/nginx/modules/ngx_http_brotli_static_module.so; +load_module ${moddir}/ngx_http_brotli_static_module.so; EOF @@ -75,6 +122,22 @@ EOF ln -s ../modules-available/http-brotli-filter-module.conf /etc/nginx/modules-enabled/60-http-brotli-filter-module.conf ln -s ../modules-available/http-brotli-static-module.conf /etc/nginx/modules-enabled/60-http-brotli-static-module.conf + +# Configure Brotli +# +cat < /etc/nginx/conf.d/http-brotli.conf +## +# 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 + # Verify if all is fine # nginx -t diff --git a/mkbrotli.sh b/mkbrotli.sh new file mode 100755 index 0000000..a1ddc17 --- /dev/null +++ b/mkbrotli.sh @@ -0,0 +1,490 @@ +# ========== +# 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