37 Commits

Author SHA1 Message Date
asif f7a6d924d9 feature(helpers): add exit codes to update script 2021-07-27 18:28:09 -06:00
asif 16f302c3fd struct(tools): checksum generator script 2021-07-27 17:08:55 -06:00
asif a6107f7e25 struct(helpers): set params file as template again
- prevents accidental overwrite of user params on updates
2021-07-27 16:17:04 -06:00
asif 03e0631964 style(helpers): reformat update script and bump version 2021-07-27 16:09:27 -06:00
asif 4d5f3fa809 refactor(helpers): echo docker run result code on exit 2021-07-27 16:04:31 -06:00
asif fb81443cba style(helpers): make comment header style consistent 2021-07-27 16:00:30 -06:00
asif 92c0217374 perf(helpers): import and check params-file only if running 2021-07-27 15:58:12 -06:00
asif 750ad05d06 refactor(helpers): change name of stop and remove parameter switch 2021-07-27 15:55:17 -06:00
asif 0db9675bc4 feature(helpers): add stop and remove commands 2021-07-27 15:53:17 -06:00
asif dd7ef19d88 refactor(helpers): update and notate return codes 2021-07-27 15:39:30 -06:00
asif 810cbd44b7 feature(helpers): add container status display 2021-07-27 15:26:53 -06:00
asif 2b583ad7e0 struct(dockerfile): change internal labels
- add internal name label to allow finding containers
- use new domain in private labels
2021-07-27 15:10:49 -06:00
asif 4a1c1e5153 refactor(helpers): set initial vars to null vs unset 2021-07-27 14:59:16 -06:00
asif 2b55ae11f4 refactor(helpers): change volume mount var name
- change from vmount to volumeMounts
2021-07-27 14:58:01 -06:00
asif 49fa74159b refactor(helpers): remove dhparams check
- container now auto-generates this file if needed
2021-07-27 14:41:32 -06:00
asif 3548d88b63 style(helpers): rename textBlock functions
- rename functions to camelCase
2021-07-27 14:37:57 -06:00
asif a1e2911dc0 docs(helpers): change help text for container name 2021-07-27 14:35:57 -06:00
asif a2b08d5a72 refactor(helpers): activate params file by default
- remove template concept, use live file with defaults
- easier implementation, no need to user to rename
- active by default, one source for behaviour
- allow IDE parsing from active file
2021-07-27 14:34:46 -06:00
asif 85ff24faaf refactor(helpers): update domain and path in update script 2021-07-26 02:23:45 -06:00
asif 2e2c93b2b1 feature(helpers): change docker run cmd
- add user specification so UID/GID always specified
- add container default values
2021-07-26 01:36:41 -06:00
asif e208d22664 style(helpers): reformat helper script 2021-07-26 01:30:35 -06:00
asif bc2a34ddd8 feature(helpers): allow specifying tag 2021-07-26 01:20:38 -06:00
asif a3c6656764 fix(helpers): rename shell var in helper script 2021-07-26 00:54:27 -06:00
asif b2582b9bad refactor(helpers): condense TLS section of helper script
Take advantage of container generating DHParams and remove redundant
docker run blocks
2021-07-26 00:49:51 -06:00
asif 1ee8b8bf03 refactor(helpers): remove dhparams mapping from params template 2021-07-26 00:32:48 -06:00
asif 8c5bbe8d9c refactor(helpers): update domain in helper script 2021-07-26 00:29:35 -06:00
asif 60f79fdd45 docs(config): update sites readme file 2021-07-26 00:23:23 -06:00
asif f1faf3fedf feature(generate-cert): allow create self-signed cert
- self-signed cert with a group-readable key and customizable hostname
2021-07-25 19:18:32 -06:00
asif 4ded854631 feature(entrypoint): generate missing dhparam file if needed 2021-07-25 16:00:16 -06:00
asif 8890e662b0 docs(dockerfile): update domain in labels 2021-07-25 15:42:18 -06:00
asif a4cebd5216 fix(dockerfile): remove quotes in maintainer tag 2021-07-25 15:39:36 -06:00
asif f6efb86f2a feature(dockerfile): specify NGINX version via build-arg
- build-arg for NGINX version
- add labels incorporating NGINX version and internal version
- add label to reference GIT commit for tagged release
2021-07-25 15:37:38 -06:00
asif e499b7982c struct(entrypoint): add planned exit codes 2021-07-25 15:13:31 -06:00
asif 1c608859e7 refactor(dockerfile): change healthcheck periods
- reduce interval and increase start-period
- format for clarity
2021-07-25 15:04:22 -06:00
asif 7ea21e2cc4 feature(dockerfile): allow separate UID and GID during build 2021-07-25 15:03:24 -06:00
asif d045d098d9 docs(dockerfile): add deprecated maintainer tag
Harbor still uses this for informational display
2021-07-25 15:02:54 -06:00
asif 287830ffe7 chore(dockerfile): bump internal and nginx version
- update nginx to current
- bump internal version in preparation for new features
2021-07-25 15:02:11 -06:00
10 changed files with 707 additions and 440 deletions
+9 -2
View File
@@ -2,11 +2,18 @@
<project version="4">
<component name="CommitMessageInspectionProfile">
<profile version="1.0">
<inspection_tool class="BodyLimit" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="BodyLimit" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="SubjectBodySeparation" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="SubjectLimit" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="SubjectLimit" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>
<component name="GitSharedSettings">
<option name="FORCE_PUSH_PROHIBITED_PATTERNS">
<list>
<option value="master main" />
</list>
</option>
</component>
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
+37 -16
View File
@@ -1,10 +1,17 @@
FROM nginx:mainline-alpine
#
# build AB-NGINX container (based on NGINX mainline)
#
# default uid for nginx user
ARG NGINX_VERSION=1.21.1
FROM nginx:${NGINX_VERSION}-alpine
ARG NGINX_VERSION
# default uid and gid for nginx user
ARG UID=8080
ARG GID=8080
# create nginx user
RUN addgroup --gid ${UID} www-docker \
RUN addgroup --gid ${GID} www-docker \
&& adduser \
-S \
-h /home/www-docker \
@@ -15,11 +22,13 @@ RUN addgroup --gid ${UID} www-docker \
www-docker
# add libcap, allow nginx to bind to ports <1024, extract fun error pages & create LetsEncrypt challenge directory outside webroot
RUN apk --no-cache add libcap \
RUN apk --update --no-cache add \
libcap \
openssl \
&& setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx \
&& cd /usr/share/nginx \
&& rm -rf html/* \
&& wget -O /tmp/errorpages.tar.gz https://git.asifbacchus.app/asif/fun-errorpages/archive/v1.0.tar.gz \
&& wget -O /tmp/errorpages.tar.gz https://git.asifbacchus.dev/asif/fun-errorpages/archive/v1.0.tar.gz \
&& tar -xzf /tmp/errorpages.tar.gz -C /tmp \
&& mv /tmp/fun-errorpages/errorpages ./ \
&& rm -rf /tmp/* \
@@ -28,22 +37,29 @@ RUN apk --no-cache add libcap \
&& mkdir /usr/share/nginx/letsencrypt
# health check
HEALTHCHECK --interval=60s --timeout=5s --start-period=30s --retries=3 \
HEALTHCHECK \
--interval=10s \
--timeout=5s \
--start-period=60s \
--retries=3 \
CMD curl --fail http://127.0.0.1:9000/nginx_status || exit 1
# standardized labels
LABEL author="Asif Bacchus <asif@bacchus.cloud>"
MAINTAINER Asif Bacchus <asif@bacchus.cloud>
LABEL maintainer="Asif Bacchus <asif@bacchus.cloud>"
LABEL dev.asifbacchus.docker.internalName="ab-nginx"
LABEL org.opencontainers.image.author="Asif Bacchus <asif@bacchus.cloud>"
LABEL org.opencontainers.image.url="https://git.asifbacchus.app/ab-docker/ab-nginx"
LABEL org.opencontainers.image.documentation="https://git.asifbacchus.app/ab-docker/ab-nginx/wiki"
LABEL org.opencontainers.image.source="https://git.asifbacchus.app/ab-docker/ab-nginx.git"
LABEL org.opencontainers.image.url="https://git.asifbacchus.dev/ab-docker/ab-nginx"
LABEL org.opencontainers.image.documentation="https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki"
LABEL org.opencontainers.image.source="https://git.asifbacchus.dev/ab-docker/ab-nginx.git"
LABEL org.opencontainers.image.vendor="NGINX"
LABEL org.opencontainers.image.title="ab-nginx"
LABEL org.opencontainers.image.description="NGINX-mainline-alpine with more logical file location layout and automatic SSL set up if certificates are provided."
# copy configuration files
COPY entrypoint.sh /entrypoint.sh
# copy configuration files and utility scripts
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
COPY generate-cert.sh /usr/local/bin/generate-cert
COPY selfsigned.cnf /etc/selfsigned.cnf
COPY config /etc/nginx/
COPY sites /etc/nginx/sites/
COPY webroot /usr/share/nginx/html/
@@ -59,7 +75,9 @@ RUN chown -R www-docker:www-docker /usr/share/nginx \
&& find /etc/nginx -type d -exec chmod 750 {} \; \
&& find /etc/nginx -type f -exec chmod 640 {} \; \
&& chown www-docker:www-docker /var/cache/nginx \
&& chown www-docker:www-docker /var/log/nginx
&& chown www-docker:www-docker /var/log/nginx \
&& chmod 644 /etc/selfsigned.cnf \
&& chmod 755 /usr/local/bin/generate-cert /usr/local/bin/entrypoint.sh
USER www-docker
WORKDIR /usr/share/nginx/html
@@ -73,7 +91,7 @@ ENV HSTS=FALSE
ENV TLS13_ONLY=FALSE
# entrypoint script
ENTRYPOINT [ "/entrypoint.sh" ]
ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ]
# run NGINX by default
STOPSIGNAL SIGQUIT
@@ -81,8 +99,11 @@ CMD [ "nginx", "-g", "daemon off;" ]
# add build date and version labels
ARG BUILD_DATE
LABEL org.opencontainers.image.version="1.19.9"
LABEL app.asifbacchus.docker.internalVersion="4.0-1.19.9"
ARG GIT_COMMIT
ARG INTERNAL_VERSION
LABEL org.opencontainers.image.revision=${GIT_COMMIT}
LABEL org.opencontainers.image.version=${NGINX_VERSION}
LABEL dev.asifbacchus.docker.internalVersion=${INTERNAL_VERSION}-${NGINX_VERSION}
LABEL org.opencontainers.image.created=${BUILD_DATE}
#EOF
+21 -2
View File
@@ -54,8 +54,20 @@ fi
if [ -f "/certs/fullchain.pem" ]; then
# activate SSL configuration as appropriate and only if certs exist
if [ "$TLS13_ONLY" = 'FALSE' ]; then
if [ -f "/certs/fullchain.pem" ] && [ -f "/certs/privkey.pem" ] && [ -f "/certs/chain.pem" ] && [ -f "/certs/dhparam.pem" ]; then
if [ -f "/certs/fullchain.pem" ] && [ -f "/certs/privkey.pem" ] && [ -f "/certs/chain.pem" ]; then
printf "Certificates found. Securing deployment using TLS 1.2\n"
# check for dhparam file and generate, if necessary
if ! [ -f "/certs/dhparam.pem" ]; then
printf "Diffie-Hellman Parameters not found... generating (using Digital Signature Algorithm instead of Diffie-Hellman)...\n"
if ! openssl dhparam -dsaparam -out /certs/dhparam.pem 4096; then
printf "\n\nUnable to generate 'dhparam.pem'. Is your '/certs' directory writable by this container?\n"
printf "TLS version 1.2 requires DHParams (or DSAParams) in order to function securely. Exiting.\n\n"
exit 101
fi
printf "\nDSA-Params generated successfully\n"
fi
# activate shared SSL configuration file
if [ -f "/etc/nginx/ssl-config/mozIntermediate_ssl.conf.disabled" ]; then
mv /etc/nginx/ssl-config/mozIntermediate_ssl.conf.disabled \
@@ -123,4 +135,11 @@ fi
printf "\nSetup complete...Container ready...\n"
exec "$@"
#EOF
# exit return codes
# 10x certificate generation errors
# 101 unable to generate DSA-parameters
# 102 unable to generate private key
# 103 unable to generate self-signed certificate
#EOF
+48
View File
@@ -0,0 +1,48 @@
#!/bin/sh
#
# generate a self-signed certificate
#
# check for null hostname
if [ -z "$1" ]; then
printf "\nPlease supply a hostname for the generated certificate as a parameter to this script. Exiting.\n\n"
exit 1
fi
# update openssl configuration file
sed -e "s/{CERT_HOSTNAME}/$1/" /etc/selfsigned.cnf > /tmp/selfsigned.cnf
printf "\nGenerating self-signed certificate for '%s':\n" "$1"
# create placeholder files to set permissions
if ! touch /certs/fullchain.pem && chmod 644 /certs/fullchain.pem; then
printf "\nUnable to write to '/certs', is it mounted writable by this container?\n\n"
exit 2
fi
touch /certs/privkey.pem && chmod 640 /certs/privkey.pem
# generate certificate
if ! openssl req -new -x509 -days 365 -nodes -out /certs/fullchain.pem -keyout /certs/privkey.pem -config /tmp/selfsigned.cnf; then
printf "\nUnable to generate certificate. Is the '/certs' directory writable by this container?\n\n"
exit 3
fi
\cp /certs/fullchain.pem /certs/chain.pem
# print user notification
printf "\n\nA self-signed certificate has been generated and saved in the location mounted to '/certs' in this container.\n"
printf "The certificate and private key are PEM formatted with names 'fullchain.pem' and 'privkey.pem', respectively.\n"
printf "Remember to import 'fullchain.pem' to the trusted store on any client machines or you will get warnings.\n\n"
# exit gracefully
exit 0
#
# exit codes
# 0: normal exit, no errors
# 1: invalid or missing parameters
# 2: unable to write to certs directory
# 3: unable to generate certificate
#EOF
+16
View File
@@ -0,0 +1,16 @@
default_bits = 4096
default_md = sha256
distinguished_name = dn
req_extensions = san
x509_extensions = san
prompt = no
[dn]
organizationName = AB-NGINX Webserver
CN = {CERT_HOSTNAME}
[san]
subjectAltName = @alt_names
[alt_names]
DNS.1 = {CERT_HOSTNAME}
+28
View File
@@ -0,0 +1,28 @@
#!/bin/sh
#
# generate checksums from provided path suitable for use by 'update.sh'
#
# check for missing path to helper files, otherwise strip trailing slash
if [ -z "$1" ]; then
printf "\nPlease supply path to helper files. Exiting.\n\n"
exit 1
fi
srcDir="${1%/}"
# verify path exists and is accessible
if ! [ -d "$srcDir" ]; then
printf "\nUnable to find or read supplied path to helper files. Exiting.\n\n"
exit 1
fi
# generate checksum file
\rm -f "${srcDir}/checksums.sha256"
find "${srcDir}/" -type f -exec sha256sum {} + >>"${srcDir}/checksums.sha256"
sed -i "s+$srcDir/++g" "${srcDir}/checksums.sha256"
# exit gracefully
exit 0
#EOF
+41 -22
View File
@@ -6,6 +6,23 @@
###
#
# Container options
#
# Specify a particular tag to 'version pin' the ab-nginx container.
TAG=latest
# Specify a runtime UID and GID for the container user. This is useful to
# ensure the container can read and/or write to locations on the host or
# has access to files shared between members of a container stack.
# REQUIRED: NO
# DEFAULT: NGINX_UID=8080, NGINX_GID=8080
# VALID OPTIONS: any permissible and available UID/GID value
NGINX_UID=8080
NGINX_GID=8080
#
# Network options
#
@@ -16,7 +33,7 @@
# REQUIRED: NO
# DEFAULT: nginx_network
# VALID OPTIONS: network names acceptable to the docker engine
#NETWORK=nginx_network
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
@@ -24,7 +41,7 @@
# REQUIRED: NO
# DEFAULT: '172.31.254.0/24'
# VALID OPTIONS: subnet in CIDR format
#SUBNET='172.31.254.0/24'
SUBNET='172.31.254.0/24'
#
@@ -38,7 +55,7 @@
# REQUIRED: NO
# DEFAULT: Etc/UTC
# VALID OPTIONS: IANA time zones in TZ format
#TZ=Etc/UTC
TZ=Etc/UTC
#
@@ -55,7 +72,8 @@
#
# REQUIRED: YES, if using SSL and default server-blocks
# DEFAULT: "_"
#HOSTNAMES="domain.tld www.domain.tld server.domain.tld alt.domain.tld"
# EXAMPLE: HOSTNAMES="domain.tld www.domain.tld server.domain.tld alt.domain.tld"
HOSTNAMES="_"
# Ports to listen on:
# If you need to use ports other than HTTP=80 and HTTPS=443, remember to set up
@@ -65,8 +83,8 @@
# you use here.
# REQUIRED: NO
# DEFAULTS: 80 and 443, respectively
#HTTP_PORT=80
#HTTPS_PORT=443
HTTP_PORT=80
HTTPS_PORT=443
# Access logging (global preference):
# Unless overridden in a server/location block, access logging will be handled
@@ -74,7 +92,7 @@
# REQUIRED: NO
# DEFAULT: OFF
# VALID OPTIONS: 'ON' or 'OFF'
#ACCESS_LOG=OFF
ACCESS_LOG=OFF
#
@@ -89,7 +107,7 @@
# Only files with a ".conf" extension will be loaded! If you want to disable a
# file, simply change its extension (i.e. '.conf.disabled').
#
# REMEMBER: Your configuration files must be readable by UID 8080!
# REMEMBER: Your configuration files must be readable by the container UID/GID!
CONFIG_DIR=$(pwd)/config
# Specify a directory containing your NGINX server-block configurations (if any)
@@ -103,7 +121,7 @@ CONFIG_DIR=$(pwd)/config
# Only files with a ".conf" extension will be loaded! If you want to disable a
# file, simply change its extension (i.e. '.conf.disabled').
#
# REMEMBER: Your server-block files must be readable by UID 8080!
# REMEMBER: Your server-block files must be readable by the container UID/GID!
SERVERS_DIR=$(pwd)/sites
# Specify a directory containing 'snippets' of NGINX code you want/need to
@@ -114,11 +132,11 @@ SERVERS_DIR=$(pwd)/sites
# instead of having to type the same thing many times.
# This is totally optional! Comment this variable to disable it.
# REMEMBER: Your snippets must be readable by UID 8080!
# REMEMBER: Your snippets must be readable by the container UID/GID!
SNIPPETS_DIR=$(pwd)/snippets
# Specify a directory with the content you want to serve.
# REMEMBER: This directory must be readable by UID 8080!
# REMEMBER: This directory must be readable by the container UID/GID!
WEBROOT_DIR=/var/www
@@ -131,26 +149,27 @@ WEBROOT_DIR=/var/www
# REQUIRED: NO
# DEFAULT: FALSE
# VALID OPTIONS: 'TRUE', 'FALSE'
#HSTS=FALSE
HSTS=FALSE
# TLS 1.3 mode:
# 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
TLS13_ONLY=FALSE
#
# Certificate files
#
# If you are mounting symlinks 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.
# the target is resolved!
#
# REMEMBER: ALL files must be readble by UID 8080!
#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
# REMEMBER: ALL files must be readable by container UID/GID!
# EXAMPLES:
# 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
SSL_CERT=""
SSL_KEY=""
SSL_CHAIN=""
#EOF
#EOF
+288 -212
View File
@@ -4,120 +4,239 @@
# 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)
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
cyan=''
err=''
magenta=''
norm=''
yellow=''
width=80
fi
### parameter defaults
shell=false
#
# parameter defaults
doShell=false
doStatus=false
doStop=false
removeStopped=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
CONFIG_DIR=""
SERVERS_DIR=""
WEBROOT_DIR=""
volumeMounts=""
stopErr=0
removeErr=0
#
# functions
checkExist() {
if [ "$1" = 'file' ]; then
if [ ! -f "$2" ]; then
printf "%s\nCannot find file: '$2'. Exiting.\n%s" "$err" "$norm"
exit 3
if [ "$1" = 'file' ]; then
if [ ! -f "$2" ]; then
printf "%s\nCannot find file: '$2'. Exiting.\n%s" "$err" "$norm"
exit 1
fi
elif [ "$1" = 'dir' ]; then
if [ ! -d "$2" ]; then
printf "%s\nCannot find directory: '$2'. Exiting.\n$%s" "$err" "$norm"
exit 1
fi
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
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 typing lengthy commands when working with the ab-nginx container."
textblock "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. If you specified certificates, nginx will serve over SSL by default."
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 (optional) 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
# header and description
printf "\n%s" "$magenta"
printf '%.0s-' $(seq "$width")
printf "\n%s" "$norm"
textBlock "This is a simple helper script so you can avoid typing lengthy commands when working with the ab-nginx container."
textBlock "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
# explanatory text
textBlock "If you run the script with no parameters, it will execute the container 'normally': Run in detached mode with nginx automatically launched. If you specified certificates, nginx will serve over SSL by default."
textBlock "Note: Containers (except shell) are always set to restart 'unless-stopped'. You must remove them manually if desired."
printf "%s" "$magenta"
newline
# parameters
textBlock "The script has the following (optional) parameters:"
textBlockParam 'parameter in cyan' 'default in yellow'
newline
textBlockParam '-n|--name' 'ab-nginx'
textBlock "Set the name of the container, otherwise the default will be used."
newline
textBlockParam '-s|--shell' 'off: run in detached mode'
textBlock "Enter the container using an interactive ASH/BusyBox 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."
newline
textBlockParam '--status'
textBlock "Run a search for all AB-NGINX containers and display their name and status."
newline
textBlockParam '--stop'
textBlock "Stops the container specified by the '--name' parameter or with the default name 'ab-nginx'."
newline
textBlockParam '--remove | --stop-remove'
textBlock "Stops and removes the container specified by the '--name' parameter or with the default name 'ab-nginx'."
# footer
newline
printf "%s" "$yellow"
textBlock"More information can be found at: https://git.asifbacchus.dev/ab-docker/ab-nginx/wiki"
printf "\n%s" "$magenta"
printf '%.0s-' $(seq "$width")
printf "\n%s" "$norm"
exit 0
}
newline() {
printf "\n"
printf "\n"
}
textblock() {
printf "%s\n" "$1" | fold -w "$width" -s
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
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
#
# 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
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
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 3
fi
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
doShell=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
;;
--status)
# find containers and check their status
doStatus=true
;;
--stop)
# stop named container
doStop=true
;;
--remove | --stop-remove)
# stop and remove named container
doStop=true
removeStopped=true
;;
*)
printf "%s\nUnknown option: %s\n" "$err" "$1"
printf "Use '--help' for valid options.\n\n%s" "$norm"
exit 1
;;
esac
shift
done
#
# status check
if [ "$doStatus" = "true" ]; then
printf "\nFound the following AB-NGINX containers:\n"
docker ps -a --filter "label=dev.asifbacchus.docker.internalName=ab-nginx"
printf "\n"
exit 0
fi
#
# stop container
if [ "$doStop" = "true" ]; then
printf "\nStopping container '%s'... " "$container_name"
# ensure container exists
if ! docker inspect "$container_name" >/dev/null 2>&1; then
printf "[ERROR]: No container with that name found.\n\n"
exit 11
fi
# stop and/or remove container
if ! docker stop "$container_name" >/dev/null 2>&1; then stopErr=1; fi
if [ "$removeStopped" = "true" ] && [ "$stopErr" -eq 0 ]; then
if ! docker rm "$container_name" >/dev/null 2>&1; then removeErr=1; fi
fi
# update status message
if [ "$stopErr" -eq 1 ]; then
printf "[ERROR]: Unable to stop container. Please try removing it manually.\n\n"
exit 12
fi
if [ "$removeErr" -eq 1 ]; then
printf "[STOPPED]\n"
printf "[ERROR]: Unable to remove container. Please try removing it manually.\n\n"
exit 13
fi
if [ "$removeStopped" = "true" ]; then
printf "[REMOVED]\n\n"
else
printf "[STOPPED]\n\n"
fi
exit 0
fi
#
# run container
# does the params file exist?
checkExist 'file' './ab-nginx.params'
# read .params file
# shellcheck source=ab-nginx.params.template
. "./ab-nginx.params"
# fix case of TLS13_ONLY var
if [ "$TLS13_ONLY" ]; then
TLS13_ONLY=$(printf "%s" "$TLS13_ONLY" | tr "[:lower:]" "[:upper:]")
TLS13_ONLY=$(printf "%s" "$TLS13_ONLY" | tr "[:lower:]" "[:upper:]")
fi
# check for certs if using SSL
@@ -125,175 +244,132 @@ 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"
checkExist 'dir' "$CONFIG_DIR"
fi
# check if specified server-block directory exists
if [ "$SERVERS_DIR" ]; then
checkExist 'dir' "$SERVERS_DIR"
checkExist 'dir' "$SERVERS_DIR"
fi
# check if specified webroot directory exists
if [ "$WEBROOT_DIR" ]; then
checkExist 'dir' "$WEBROOT_DIR"
checkExist 'dir' "$WEBROOT_DIR"
fi
# set up volume mounts
if [ "$CONFIG_DIR" ]; then
vmount="$vmount -v $CONFIG_DIR:/etc/nginx/config"
volumeMounts="${volumeMounts} -v $CONFIG_DIR:/etc/nginx/config"
fi
if [ "$SERVERS_DIR" ]; then
vmount="$vmount -v $SERVERS_DIR:/etc/nginx/sites"
volumeMounts="${volumeMounts} -v $SERVERS_DIR:/etc/nginx/sites"
fi
if [ "$SNIPPETS_DIR" ]; then
vmount="$vmount -v $SNIPPETS_DIR:/etc/nginx/snippets"
volumeMounts="${volumeMounts} -v $SNIPPETS_DIR:/etc/nginx/snippets"
fi
if [ "$WEBROOT_DIR" ]; then
vmount="$vmount -v $WEBROOT_DIR:/usr/share/nginx/html"
volumeMounts="${volumeMounts} -v $WEBROOT_DIR:/usr/share/nginx/html"
fi
# trim leading whitespace
vmount=${vmount##[[:space:]]}
volumeMounts=${volumeMounts##[[: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}
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
if [ "$doShell" = 'true' ]; then
# exec shell
printf "%s\nRunning SHELL on %s...%s\n" "$cyan" "$container_name" "$norm"
# shellcheck disable=SC2086
docker run --rm -it --name "${container_name}" \
--env-file ab-nginx.params \
--user="${NGINX_UID:-8080}:${NGINX_GID:-8080}" \
-e SERVER_NAMES="$HOSTNAMES" \
${volumeMounts} \
--network=${NETWORK} \
-p ${HTTP_PORT}:80 \
docker.asifbacchus.dev/nginx/ab-nginx:latest /bin/sh
else
# exec normally
printf "%s\nRunning NGINX on %s...%s\n" "$cyan" "$container_name" "$norm"
# shellcheck disable=SC2086
docker run -d --name "${container_name}" \
--env-file ab-nginx.params \
--user="${NGINX_UID:-8080}:${NGINX_GID:-8080}" \
-e SERVER_NAMES="$HOSTNAMES" \
${volumeMounts} \
--network=${NETWORK} \
-p ${HTTP_PORT}:80 \
--restart unless-stopped \
docker.asifbacchus.dev/nginx/ab-nginx:${TAG:-latest}
fi
# run with TLS
else
if [ "$doShell" = 'true' ]; then
if [ "$TLS13_ONLY" = 'FALSE' ]; then
printf "%s\nRunning SHELL on %s (TLS 1.2)...%s\n" "$cyan" "$container_name" "$norm"
else
printf "%s\nRunning SHELL on %s (TLS 1.3)...%s\n" "$cyan" "$container_name" "$norm"
fi
# shellcheck disable=SC2086
docker run --rm -it --name "${container_name}" \
--env-file ab-nginx.params \
--user="${NGINX_UID:-8080}:${NGINX_GID:-8080}" \
-e SERVER_NAMES="$HOSTNAMES" \
${volumeMounts} \
--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.dev/nginx/ab-nginx:${TAG:-latest} /bin/sh
else
if [ "$TLS13_ONLY" = 'FALSE' ]; then
printf "%s\nRunning NGINX on %s (TLS 1.2)...%s\n" "$cyan" "$container_name" "$norm"
else
printf "%s\nRunning NGINX on %s (TLS 1.3)...%s\n" "$cyan" "$container_name" "$norm"
fi
# shellcheck disable=SC2086
docker run -d --name "${container_name}" \
--env-file ab-nginx.params \
--user="${NGINX_UID:-8080}:${NGINX_GID:-8080}" \
-e SERVER_NAMES="$HOSTNAMES" \
${volumeMounts} \
--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.dev/nginx/ab-nginx:${TAG:-latest}
fi
fi
### exit gracefully
exit 0
#
# exit with code from docker
exit "$?"
#
# exit return codes
# 0: normal exit, no errors
# 1: missing or invalid parameter
# 2: cannot find docker
# 3: incorrect permissions to access docker
# 1x: operation errors
# 11 no container found with specified name
# 12 unable to stop container
# 13 unable to remove container
# other refer to docker exit codes
#EOF
+4 -4
View File
@@ -1,11 +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.
- this bind-mount will override the default server configurations
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,
- 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
- If you don't want to use this directory, you can bind-mount any other
directory you want to '/etc/nginx/sites/'
+215 -182
View File
@@ -1,83 +1,87 @@
#!/bin/sh
### update script for ab-nginx container and utility scripts
# version 2.0.0
# script by Asif Bacchus
###
#
# update script for ab-nginx container and utility scripts
# version 2.1.0
# script by Asif Bacchus
#
### functions
#
# functions
errMsg() {
printf "\n%s%s%s\n\n" "$err" "$1" "$norm"
exit 1
printf "\n%s%s%s\n\n" "$err" "$1" "$norm"
[ -n "$2" ] && exit "$2" || exit 1
}
errNotify() {
printf "%s[ERROR]%s\n" "$err" "$norm"
printf "%s[ERROR]%s\n" "$err" "$norm"
}
okMsg() {
printf "%s%s%s\n\n" "$ok" "$1" "$norm"
printf "%s%s%s\n\n" "$ok" "$1" "$norm"
}
okNotify() {
printf "%s[OK]%s\n" "$ok" "$norm"
printf "%s[OK]%s\n" "$ok" "$norm"
}
scriptHelp() {
textNewline
textblock "Update ${containerName} container and helper script files"
textblock "${bold}Usage: ${localScriptName} [parameters]${norm}"
textNewline
textblock "If run with no parameters, the script will update both the container and the helper script files, including this update script."
textblockHeader " parameters "
textblockParam "-h|-?|--help" "Display this help screen."
textblockParam "-c|--container|--container-only" "Update the docker container only."
textblockParam "-s|--scripts|--scripts-only" "Update the helper scripts (including this update script) only."
textNewline
exit 0
textNewline
textBlock "Update ${containerName} container and helper script files"
textBlock "${bold}Usage: ${localScriptName} [parameters]${norm}"
textNewline
textBlock "If run with no parameters, the script will update both the container and the helper script files, including this update script."
textBlockHeader " parameters "
textBlockParam "-h|-?|--help" "Display this help screen."
textBlockParam "-c|--container|--container-only" "Update the docker container only."
textBlockParam "-s|--scripts|--scripts-only" "Update the helper scripts (including this update script) only."
textNewline
exit 0
}
textblock() {
printf "%s\n" "$1" | fold -w "$width" -s
textBlock() {
printf "%s\n" "$1" | fold -w "$width" -s
}
textblockHeader() {
printf "\n%s***%s***%s\n" "$header" "$1" "$norm"
textBlockHeader() {
printf "\n%s***%s***%s\n" "$header" "$1" "$norm"
}
textblockParam() {
printf "%s%-35s%s%s\n" "$info" "$1" "$2" "$norm"
textBlockParam() {
printf "%s%-35s%s%s\n" "$info" "$1" "$2" "$norm"
}
textNewline() {
printf "\n"
printf "\n"
}
### text formatting presets
#
# text formatting presets
if command -v tput >/dev/null 2>&1; then
bold=$(tput bold)
err=$(tput bold)$(tput setaf 1)
info=$(tput bold)$(tput setaf 6)
header=$(tput bold)$(tput setaf 5)
norm=$(tput sgr0)
ok=$(tput sgr0)$(tput setaf 2)
warn=$(tput bold)$(tput setaf 3)
width=$(tput cols)
bold=$(tput bold)
err=$(tput bold)$(tput setaf 1)
info=$(tput bold)$(tput setaf 6)
header=$(tput bold)$(tput setaf 5)
norm=$(tput sgr0)
ok=$(tput sgr0)$(tput setaf 2)
warn=$(tput bold)$(tput setaf 3)
width=$(tput cols)
else
bold=''
err=''
info=''
header=''
norm=''
ok=''
warn=''
width=80
bold=''
err=''
info=''
header=''
norm=''
ok=''
warn=''
width=80
fi
### pre-requisites
#
# 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."
errMsg "Sorry, this script requires that 'wget' is installed in order to download updates. Exiting."
fi
# zero counters
@@ -90,8 +94,8 @@ updateSuccess=0
# reference constants
dockerNamespace='nginx'
containerName='ab-nginx'
containerUpdatePath="docker.asifbacchus.app/$dockerNamespace/$containerName:latest"
server="https://asifbacchus.app/updates/docker/$dockerNamespace/$containerName/"
containerUpdatePath="docker.asifbacchus.dev/$dockerNamespace/$containerName:latest"
server="https://asifbacchus.dev/public/docker/$dockerNamespace/$containerName/"
checksumFilename='checksums.sha256'
# operation triggers
@@ -102,149 +106,178 @@ doScriptUpdate=1
localScriptName="$(basename "$0")"
repoScriptName='update.sh'
### process startup parameters
#
# process startup parameters
while [ $# -gt 0 ]; do
case "$1" in
-h | -\? | --help)
# display inline help
scriptHelp
;;
-s | --scripts | --scripts-only)
# update scripts only, skip docker container update
doDockerUpdate=0
;;
-c | --container | --container-only)
# update docker container only, skip script update
doScriptUpdate=0
;;
*)
printf "%s\nUnknown option: %s\n" "$err" "$1"
printf "%sUse '--help' for valid options%s\n\n" "$info" "$norm"
exit 1
;;
esac
shift
case "$1" in
-h | -\? | --help)
# display inline help
scriptHelp
;;
-s | --scripts | --scripts-only)
# update scripts only, skip docker container update
doDockerUpdate=0
;;
-c | --container | --container-only)
# update docker container only, skip script update
doScriptUpdate=0
;;
*)
printf "%s\nUnknown option: %s\n" "$err" "$1"
printf "%sUse '--help' for valid options%s\n\n" "$info" "$norm"
exit 1
;;
esac
shift
done
### update container
#
# update container
if [ "$doDockerUpdate" -eq 1 ]; then
# 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
printf "%s\n*** Updating %s container ***\n\n%s" "$info" "$containerName" "$norm"
if ! docker pull "$containerUpdatePath"; then
errMsg "There was an error updating the container. Try again later."
else
okMsg "Container updated!"
fi
fi
### update scripts
if [ "$doScriptUpdate" -eq 1 ]; then
printf "%s*** Updating %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
# 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." 2
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"
# 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." 2
fi
fi
else
printf "[NONE]\n"
fi
done <"$checksumFilename"
printf "%s\n*** Updating %s container ***\n\n%s" "$info" "$containerName" "$norm"
if ! docker pull "$containerUpdatePath"; then
errMsg "There was an error updating the container. Try again later." 31
else
okMsg "Container updated!"
fi
fi
### display results
#
# update scripts
if [ "$doScriptUpdate" -eq 1 ]; then
printf "\n%s*** Results ***%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"
printf "%s*** Updating %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." 41
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." 42
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." 42
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"
fi
exit 0
#
# display results
if [ "$doScriptUpdate" -eq 1 ]; then
printf "\n%s*** Results ***%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"
fi
#
# exit
if [ "$downloadFailed" -gt 0 ]; then
exit 43
elif [ "$updateFailed" -gt 0 ]; then
exit 44
else
exit 0
fi
# this is a trap for mis-coding... should never get an exit code 99!
exit 99
#
# exit return codes
# 0: normal exit, no errors
# 1: missing or invalid parameter
# 2: docker not found or no docker permissions
# 31: unable to update docker container
# 4x: helper files errors
# 41: unable to download checksums
# 42: update script: unable to download or bad checksum
# 43: update helpers: unable to download
# 44: update helpers: bad checksum, no update
# 99: coding mistake trap -- this return code should never happen!
#EOF