build(GIT): move helper scripts to own directory

This commit is contained in:
Asif Bacchus
2021-01-07 15:06:38 -07:00
parent d742bdf9ab
commit 7c0616afe1
12 changed files with 0 additions and 0 deletions
+107
View File
@@ -0,0 +1,107 @@
#####
# Parameters for use by ab-nginx convenience script
#
# If you are not using the 'ab-nginx.sh' script file to start the container,
# then you don't have to do anything with this file.
#####
### Network options
# If you want to specify a network to which this container should bind or one
# that should be created, then use this variable. If you don't know what this
# means or if you just want to use the default, leave this line/variable
# commented-out.
#NETWORK=nginx_network
# If you want to specify a particular IP subnet for the network to be created
# as per the above variable, specify it here. Again, if you don't know what
# this means, just leave this commented-out.
#SUBNET='172.31.254.0/24'
### Timezone
# This doesn't impact any functionality of the container, but it does make your
# logs easier to understand if they report the correct local time, right?
# (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
TZ=Area/Location
### NGINX options
# Hostnames to which this instance of NGINX should answer:
# By default, this is set to '_' meaning 'match anything'. However, that won't
# work if you're using SSL certificates! Multiple hostnames must be space
# delimited and "enclosed in quotes".
# This is NOT required if you are supplying your own server blocks via
# 'SERVERS_DIR'
HOSTNAMES="domain.tld www.domain.tld server.domain.tld alt.domain.tld"
# Ports to listen on:
# If you need to use ports other than HTTP=80 and HTTPS=443, remember to set up
# your server blocks accordingly! See 'test_secured.conf.disabled' in the
# container if you need help. If you're using the default configuration, the
# 'test blocks' automatically adjust for non-standard ports.
# If you want to use the defaults, either leave these lines as-is, comment them
# out or just delete them.
#HTTP_PORT=80
#HTTPS_PORT=443
# Access logging (global preference):
# Unless overridden in a server/location block, access logging will be handled
# according to this setting. Default is OFF. Choices are 'ON' or 'OFF'.
# Logs will be printed to the console so they are accessible via
# 'docker logs ...'
ACCESS_LOG=OFF
### Content files
# Whatever you specify here will replace the default files in the container
# with your content/configurations. You may comment any/all of the following
# lines to disable them use the container defaults.
# Specify a directory containing your NGINX configurations (if any)
# Remember that these will be all be applied in the HTTP configuration
# context.
# Only files with a ".conf" extension will be loaded! If you want to disable a
# file, simply change its extension (i.e. '.conf.disabled').
CONFIG_DIR=$(pwd)/config
# Specify a directory containing your NGINX server-block configurations (if any)
# If you are just serving static content from the 'webroot', you can use the
# hard-coded 'test blocks' in the container and specify a webroot with your
# files below.
# More likely, you will have your own server blocks. Remember, files are
# processed in order so consider starting file names with numbers
# (i.e. 00-first_server.conf, 05-second_server.conf)
# Only files with a ".conf" extension will be loaded! If you want to disable a
# file, simply change its extension (i.e. '.conf.disabled').
SERVERS_DIR=$(pwd)/sites
# Specify a directory containing 'snippets' of NGINX code you want/need to
# reference in various other configuration files. Pointers to additional SSL
# certificates for other hosted domains is a good example of this.
SNIPPETS_DIR=$(pwd)/snippets
# Specify a directory that contains files for your 'webroot'. This includes
# things like HTML, CSS, etc.
WEBROOT_DIR=/var/www
### SSL options:
# Enable HSTS only AFTER you've tested SSL implementation! Container sets the
# header to require SSL for 6 months! Subdomains are NOT included.
HSTS=FALSE
# If 'FALSE' (default), NGINX will accept both TLS 1.2 and 1.3 connections.
# If 'TRUE', only TLS 1.3 connections will be accepted.
TLS13_ONLY=FALSE
### Certificate files to be bind-mounted
# Remember, if you are mounting symlinks (like when using Let's Encrypt), you
# MUST specify the full path of the symlink so the target is resolved!
# DH (Diffie-Hellman Parameters file) is only required if using TLS 1.2
#SSL_CERT=/path/to/your/ssl-certificate/fullchain.pem
#SSL_KEY=/path/to/your/ssl-private-key/privkey.pem
#SSL_CHAIN=/path/to/your/ssl-certificate-chain/chain.pem
#DH=/path/to/your/diffie-hellman-parameters-file/dhparam.pem
#EOF
+299
View File
@@ -0,0 +1,299 @@
#!/bin/sh
#
### start ab-nginx container using params file variables
#
# text formatting presets
if command -v tput >/dev/null; then
cyan=$(tput bold)$(tput setaf 6)
err=$(tput bold)$(tput setaf 1)
magenta=$(tput sgr0)$(tput setaf 5)
norm=$(tput sgr0)
yellow=$(tput sgr0)$(tput setaf 3)
width=$(tput cols)
else
cyan=''
err=''
magenta=''
norm=''
yellow=''
width=80
fi
### parameter defaults
shell=false
container_name="ab-nginx"
NETWORK='nginx_network'
SUBNET='172.31.254.0/24'
HTTP_PORT=80
HTTPS_PORT=443
unset CONFIG_DIR
unset SERVERS_DIR
unset WEBROOT_DIR
unset vmount
### functions
checkExist() {
if [ "$1" = 'file' ]; then
if [ ! -f "$2" ]; then
printf "%s\nCannot find file: '$2'. Exiting.\n%s" "$err" "$norm"
exit 3
fi
elif [ "$1" = 'dir' ]; then
if [ ! -d "$2" ]; then
printf "%s\nCannot find directory: '$2'. Exiting.\n$%s" "$err" "$norm"
exit 3
fi
fi
return 0
}
scriptHelp() {
printf "\n%s%1000s\n" "$magenta" | tr " " "-" | cut -c -$width
printf "%s" "$norm"
textblock "This is a simple helper script so you can avoid lengthy typing when working with the nginx container. The script reads the contents of 'ab-nginx.params' and constructs various 'docker run' commands based on that file. The biggest time-saver is working with certificates. If they are specified in the params file, the script will automatically bind-mount them so nginx serves content via SSL by default."
newline
textblock "If you run the script with no parameters, it will execute the container 'normally': Run in detached mode with nginx automatically launched and logging to stdout. If you specified certificates, nginx will serve over SSL by default."
newline
textblock "Note: Containers (except shell) are always set to restart 'unless-stopped'. You must remove them manually if desired."
printf "%s" "$magenta"
newline
textblock "The script has the following parameters:"
textblockParam 'parameter in cyan' 'default in yellow'
newline
textblockParam '-n|--name' 'ab-nginx'
textblock "Change the name of the container. This is cosmetic and does not affect operation in any way."
newline
textblockParam '-s|--shell' 'off: run in detached mode'
textblock "Enter the container using an interactive POSIX shell. This happens after startup operations but *before* nginx is actually started. This is a great way to see configuration changes possibly stopping nginx from starting normally."
printf "%s" "$yellow"
newline
textblock "More information can be found at: https://git.asifbacchus.app/ab-docker/ab-nginx/wiki"
printf "%s%1000s\n" "$magenta" | tr " " "-" | cut -c -$width
exit 0
}
newline() {
printf "\n"
}
textblock() {
printf "%s\n" "$1" | fold -w "$width" -s
}
textblockParam() {
if [ -z "$2" ]; then
# no default
printf "%s%s%s\n" "$cyan" "$1" "$norm"
else
# default param provided
printf "%s%s %s(%s)%s\n" "$cyan" "$1" "$yellow" "$2" "$norm"
fi
}
### pre-requisite checks
# is docker installed?
if ! command -v docker > /dev/null; then
printf "%s\nCannot find docker... is it installed?\n%s" "$err" "$norm"
exit 2
fi
# is user root or in the docker group?
if [ ! "$(id -u)" -eq 0 ]; then
if ! id -Gn | grep docker >/dev/null; then
printf "%s\nYou must either be root or in the 'docker' group to run this script since you must be able to actually start the container! Exiting.\n$%s" "$err" "$norm"
exit 2
fi
fi
# does the params file exist?
checkExist 'file' './ab-nginx.params'
# read .params file
. "./ab-nginx.params"
# fix case of TLS13_ONLY var
if [ "$TLS13_ONLY" ]; then
TLS13_ONLY=$(printf "%s" "$TLS13_ONLY" | tr "[:lower:]" "[:upper:]")
fi
# check for certs if using SSL
if [ "$SSL_CERT" ]; then checkExist 'file' "$SSL_CERT"; fi
if [ "$SSL_KEY" ]; then checkExist 'file' "$SSL_KEY"; fi
if [ "$SSL_CHAIN" ]; then checkExist 'file' "$SSL_CHAIN"; fi
# check for DHparam if using TLS1.2
if [ "$SSL_CERT" ] && [ "$TLS13_ONLY" = 'FALSE' ]; then
if [ -z "$DH" ]; then
printf "%s\nA DHparam file must be specified when using TLS 1.2. Exiting.%s\n" "$err" "$norm"
exit 5
else
checkExist 'file' "$DH"
fi
fi
# check if specified config directory exists
if [ "$CONFIG_DIR" ]; then
checkExist 'dir' "$CONFIG_DIR"
fi
# check if specified server-block directory exists
if [ "$SERVERS_DIR" ]; then
checkExist 'dir' "$SERVERS_DIR"
fi
# check if specified webroot directory exists
if [ "$WEBROOT_DIR" ]; then
checkExist 'dir' "$WEBROOT_DIR"
fi
# set up volume mounts
if [ "$CONFIG_DIR" ]; then
vmount="$vmount -v $CONFIG_DIR:/etc/nginx/config"
fi
if [ "$SERVERS_DIR" ]; then
vmount="$vmount -v $SERVERS_DIR:/etc/nginx/sites"
fi
if [ "$SNIPPETS_DIR" ]; then
vmount="$vmount -v $SNIPPETS_DIR:/etc/nginx/snippets"
fi
if [ "$WEBROOT_DIR" ]; then
vmount="$vmount -v $WEBROOT_DIR:/usr/share/nginx/html"
fi
# trim leading whitespace
vmount=${vmount##[[:space:]]}
# handle null HOSTNAMES
if [ -z "$HOSTNAMES" ]; then HOSTNAMES="_"; fi
# process startup parameters
while [ $# -gt 0 ]; do
case "$1" in
-h | -\? | --help)
# display help
scriptHelp
exit 0
;;
-s | --shell)
# start shell instead of default CMD
shell=true
;;
-n | --name)
# container name
if [ -z "$2" ]; then
printf "%s\nNo container name specified. Exiting.\n%s" "$err" "$norm"
exit 1
fi
container_name="$2"
shift
;;
*)
printf "%s\nUnknown option: %s\n" "$err" "$1"
printf "Use '--help' for valid options.\n\n%s" "$norm"
exit 1
;;
esac
shift
done
# create network if it doesn't already exist
docker network inspect ${NETWORK} >/dev/null 2>&1 ||
docker network create \
--attachable \
--driver=bridge \
--subnet=${SUBNET} \
${NETWORK}
# run without TLS
if [ -z "$SSL_CERT" ]; then
if [ $shell = 'true' ]; then
# exec shell
printf "%s\nRunning SHELL on %s...%s\n" "$cyan" "$container_name" "$norm"
docker run --rm -it --name "${container_name}" \
--env-file ab-nginx.params \
-e SERVER_NAMES="$HOSTNAMES" \
$vmount \
--network=${NETWORK} \
-p ${HTTP_PORT}:80 \
docker.asifbacchus.app/nginx/ab-nginx:latest /bin/sh
else
# exec normally
printf "%s\nRunning NGINX on %s...%s\n" "$cyan" "$container_name" "$norm"
docker run -d --name "${container_name}" \
--env-file ab-nginx.params \
-e SERVER_NAMES="$HOSTNAMES" \
$vmount \
--network=${NETWORK} \
-p ${HTTP_PORT}:80 \
--restart unless-stopped \
docker.asifbacchus.app/nginx/ab-nginx:latest
fi
# run with TLS1.2
elif [ "$SSL_CERT" ] && [ "$TLS13_ONLY" = 'FALSE' ]; then
if [ $shell = 'true' ]; then
# exec shell
printf "%s\nRunning SHELL on %s (TLS 1.2)...%s\n" "$cyan" "$container_name" "$norm"
docker run --rm -it --name "${container_name}" \
--env-file ab-nginx.params \
-e SERVER_NAMES="$HOSTNAMES" \
$vmount \
--network=${NETWORK} \
-v "$SSL_CERT":/certs/fullchain.pem:ro \
-v "$SSL_KEY":/certs/privkey.pem:ro \
-v "$SSL_CHAIN":/certs/chain.pem:ro \
-v "$DH":/certs/dhparam.pem:ro \
-p ${HTTP_PORT}:80 -p ${HTTPS_PORT}:443 \
docker.asifbacchus.app/nginx/ab-nginx:latest /bin/sh
else
# exec normally
printf "%s\nRunning NGINX on %s (TLS 1.2)...%s\n" "$cyan" "$container_name" "$norm"
docker run -d --name "${container_name}" \
--env-file ab-nginx.params \
-e SERVER_NAMES="$HOSTNAMES" \
$vmount \
--network=${NETWORK} \
-v "$SSL_CERT":/certs/fullchain.pem:ro \
-v "$SSL_KEY":/certs/privkey.pem:ro \
-v "$SSL_CHAIN":/certs/chain.pem:ro \
-v "$DH":/certs/dhparam.pem:ro \
-p ${HTTP_PORT}:80 -p ${HTTPS_PORT}:443 \
--restart unless-stopped \
docker.asifbacchus.app/nginx/ab-nginx:latest
fi
# run with TLS1.3
elif [ "$SSL_CERT" ] && [ "$TLS13_ONLY" = 'TRUE' ]; then
if [ $shell = 'true' ]; then
# exec shell
printf "%s\nRunning SHELL on %s (TLS 1.3)...%s\n" "$cyan" "$container_name" "$norm"
docker run --rm -it --name "${container_name}" \
--env-file ab-nginx.params \
-e SERVER_NAMES="$HOSTNAMES" \
$vmount \
--network=${NETWORK} \
-v "$SSL_CERT":/certs/fullchain.pem:ro \
-v "$SSL_KEY":/certs/privkey.pem:ro \
-v "$SSL_CHAIN":/certs/chain.pem:ro \
-p ${HTTP_PORT}:80 -p ${HTTPS_PORT}:443 \
docker.asifbacchus.app/nginx/ab-nginx:latest /bin/sh
else
# exec normally
printf "%s\nRunning NGINX on %s (TLS 1.3)...%s\n" "$cyan" "$container_name" "$norm"
docker run -d --name "${container_name}" \
--env-file ab-nginx.params \
-e SERVER_NAMES="$HOSTNAMES" \
$vmount \
--network=${NETWORK} \
-v "$SSL_CERT":/certs/fullchain.pem:ro \
-v "$SSL_KEY":/certs/privkey.pem:ro \
-v "$SSL_CHAIN":/certs/chain.pem:ro \
-p ${HTTP_PORT}:80 -p ${HTTPS_PORT}:443 \
--restart unless-stopped \
docker.asifbacchus.app/nginx/ab-nginx:latest
fi
fi
### exit gracefully
exit 0
+4
View File
@@ -0,0 +1,4 @@
client_body_buffer_size 16k;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
client_max_body_size 10M;
+3
View File
@@ -0,0 +1,3 @@
resolver
1.1.1.1
1.0.0.1;
+14
View File
@@ -0,0 +1,14 @@
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json
application/ld+json application/manifest+json application/rss+xml
application/vnd.geo+json application/vnd.ms-fontobject
application/x-font-ttf application/x-web-app-manifest+json
application/xhtml+xml application/xml font/opentype image/bmp
image/svg+xml image/x-icon text/cache-manifest text/css text/plain
text/vcard text/vnd.rim.location.xloc text/vtt text/x-component
text/x-cross-domain-policy;
gzip_disable "MSIE [1-6]\.";
+9
View File
@@ -0,0 +1,9 @@
- Place all your configuration customization files in this directory
- feel free to edit the included recommended files
- files here override container settings
- Files here are placed in the HTTP configuration context
- ONLY files that end with '.conf' will be processed!
- if you want to keep a file for reference or disable it temporarily,
simply change the extension. I like using '.conf.disabled'.
- If you don't want to use this directory or these settings, you can bind-mount
any other directory you want to '/etc/nginx/config/'
+4
View File
@@ -0,0 +1,4 @@
sendfile on;
sendfile_max_chunk 1m;
tcp_nopush on;
tcp_nodelay on;
+8
View File
@@ -0,0 +1,8 @@
client_body_timeout 15s;
client_header_timeout 15s;
send_timeout 15s;
keepalive_timeout 65s;
reset_timedout_connection on;
proxy_connect_timeout 30s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
+11
View File
@@ -0,0 +1,11 @@
- Place all your server block configuration files in this directory
- This path should be bind-mounted to the container at:
'/etc/nginx/sites'
- this bind-mount will override the test pages included in the container by
default.
- All files should begin in the 'server' configuration context
- ONLY files that end with '.conf' will be processed!
- if you want to keep a file for reference or disable it temporarily,
simply change the extension. I like using '.conf.disabled'.
- If you don't want to use this directory, you can bind-mount any other
directory you want to '/etc/nginx/sites/'
+18
View File
@@ -0,0 +1,18 @@
# these are common security headers that you can easily add to locations or
# entire server blocks by including this file
# include /etc/nginx/snippets/headersSecurity.conf;
add_header Feature-Policy "geolocation 'self'";
add_header Referrer-Policy "same-origin" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options noopen;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-UA-Compatible "IE=edge";
add_header X-XSS-Protection "1; mode=block" always;
# prevent search engines from indexing sites on this server
# comment the line below if you are running public sites!
add_header X-Robots-Tag none;
+4
View File
@@ -0,0 +1,4 @@
- Place any configuration 'snippets' in this directory. You can then reference
these files in your server configuration, etc.
- This directory is a great place for supplemental SSL configuration if you
have one site that uses different certificates, for example
+184
View File
@@ -0,0 +1,184 @@
#!/bin/sh
### update script for ab-nginx container and utility scripts
# version 1.0.0
# script by Asif Bacchus
###
### functions
errMsg() {
printf "\n%s%s%s\n\n" "$err" "$1" "$norm"
exit 1
}
errNotify() {
printf "%s[ERROR]%s\n" "$err" "$norm"
}
okMsg() {
printf "%s%s%s\n\n" "$ok" "$1" "$norm"
}
okNotify() {
printf "%s[OK]%s\n" "$ok" "$norm"
}
### text formatting presets
if command -v tput >/dev/null 2>&1; then
err=$(tput bold)$(tput setaf 1)
info=$(tput bold)$(tput setaf 6)
norm=$(tput sgr0)
ok=$(tput sgr0)$(tput setaf 2)
warn=$(tput bold)$(tput setaf 3)
else
err=''
info=''
norm=''
ok=''
warn=''
fi
### pre-requisites
# check if wget is installed
if ! command -v wget >/dev/null 2>&1; then
errMsg "Sorry, this script requires that 'wget' is installed in order to download updates. Exiting."
fi
# check if docker is installed
if ! command -v docker >/dev/null 2>&1; then
errMsg "Sorry, it appears that docker is not installed on this machine! Exiting."
fi
# is user root or in the docker group?
if [ ! "$(id -u)" -eq 0 ]; then
if ! id -Gn | grep docker >/dev/null; then
errMsg "You must either be root or in the 'docker' group to pull container updates."
fi
fi
# zero counters
updatesAvailable=0
downloadFailed=0
downloadSuccess=0
updateFailed=0
updateSuccess=0
# reference constants
dockerNamespace='nginx'
containerName='ab-nginx'
containerUpdatePath="docker.asifbacchus.app/$dockerNamespace/$containerName:latest"
server="https://asifbacchus.app/updates/docker/$dockerNamespace/$containerName/"
checksumFilename='checksums.sha256'
# files to update
localScriptName="$(basename "$0")"
repoScriptName='update.sh'
### update container
printf "%s\n*** Updating %s container and service scripts ***\n\n%s" "$info" "$containerName" "$norm"
printf "Updating container:\n"
if ! docker pull "$containerUpdatePath"; then
errMsg "There was an error updating the container. Try again later."
else
okMsg "Container updated!"
fi
### update scripts
printf "%sUpdating %s service scripts%s\n" "$info" "$containerName" "$norm"
## download latest checksums
printf "Getting latest checksums... "
if ! wget --quiet --tries=3 --timeout=10 -N "${server}${checksumFilename}"; then
errNotify
errMsg "Unable to download checksums. Try again later."
else
okNotify
fi
## check for updates to this script
printf "Checking for updates to this script... "
repoScriptChecksum=$(grep "$repoScriptName" "$checksumFilename" | grep -o '^\S*')
localScriptChecksum=$(sha256sum "$localScriptName" | grep -o '^\S*')
if [ "$localScriptChecksum" = "$repoScriptChecksum" ]; then
printf "[NONE]\n"
else
printf "[AVAILABLE]\n"
printf "Getting updated script... "
# download updated script
if ! wget --quiet --tries=3 --timeout=10 -O "update.sh.tmp" "${server}${repoScriptName}"; then
errNotify
# delete failed download as necessary
rm -f ./update.sh.tmp 2>/dev/null
errMsg "Unable to download script update. Try again later."
else
# verify download
dlScriptChecksum=$(sha256sum "update.sh.tmp" | grep -o '^\S*')
if ! [ "$dlScriptChecksum" = "$repoScriptChecksum" ]; then
printf "[ERROR]\n"
# delete corrupt download as necessary
rm -f ./update.sh.tmp 2>/dev/null
errMsg "Checksum mismatch! Try again later."
else
okNotify
printf "\n%s*** This script has been updated. Please re-run it to load the updated version of this file. ***%s\n\n" "$warn" "$norm"
# overwrite this script with updated script
mv -f ./update.sh.tmp "$localScriptName"
fi
fi
fi
## update files
while IFS=' ' read -r field1 field2; do
printf "\nChecking '%s' for updates... " "$field2"
updateFilename="$field2"
repoFileChecksum="$field1"
if [ -f "$updateFilename" ]; then
localFileChecksum=$(sha256sum "$updateFilename" | grep -o '^\S*')
else
localFileChecksum=0
fi
# update file if necessary
if ! [ "$localFileChecksum" = "$repoFileChecksum" ]; then
printf "[AVAILABLE]\n"
updatesAvailable=$((updatesAvailable + 1))
# download update
printf "Downloading updated '%s'... " "$updateFilename"
if ! wget --quiet --tries=3 --timeout=10 -O "$updateFilename.tmp" "${server}${updateFilename}"; then
errNotify
downloadFailed=$((downloadFailed + 1))
# delete failed download file as necessary
rm -f "$updateFilename.tmp" 2>&1
else
okNotify
downloadSuccess=$((downloadSuccess + 1))
# verify download
printf "Verifying '%s'... " "$updateFilename"
localFileChecksum=$(sha256sum "$updateFilename.tmp" | grep -o '^\S*')
if ! [ "$localFileChecksum" = "$repoFileChecksum" ]; then
errNotify
updateFailed=$((updateFailed + 1))
# delete corrupted download file as necessary
rm -f "$updateFilename.tmp" 2>&1
else
okNotify
updateSuccess=$((updateSuccess + 1))
# overwrite old version of file
mv -f "$updateFilename.tmp" "$updateFilename"
fi
fi
else
printf "[NONE]\n"
fi
done <"$checksumFilename"
### display results
printf "\n%sResults:%s\n" "$info" "$norm"
printf "\tUpdates: %s available\n" "$updatesAvailable"
printf "\tDownloads: %s%s successful%s, %s%s failed%s\n" "$ok" "$downloadSuccess" "$norm" "$err" "$downloadFailed" "$norm"
printf "\tUpdates: %s%s applied%s, %s%s failed%s\n" "$ok" "$updateSuccess" "$norm" "$err" "$updateFailed" "$norm"
exit 0