#!/bin/sh # configuration web_root_path="/service/html" cert_root_path="/service/ssl" temp_path="/service/temp" nginx_pid="/tmp/nginx.pid" server_retries=10 log_file="" # leave empty for stdout # variables domain_file="$temp_path/domains.txt" certs_updated="$cert_root_path/.updated" certs_daemon_pid=-1 #functions function log() { local time=$(date +%F_%T) local prefix="LOG" case $1 in ERR | ERROR) prefix="ERR" shift ;; WAR | WARNING) prefix="WAR" shift ;; esac local func=$1; shift # remove any \n #local text=$(echo "$@"| tr '\n' '#' | sed 's|#|\\n |g') case "$log_file" in "") echo "[$time]:[$prefix]:[$0][$func]: $@" 2>&1 ;; *) echo "[$time]:[$prefix]:[$0][$func]: $@" >> $log_file ;; esac } function sleep_wait() { # waiting on sleep to be able to handle SIGTERM sleep $1 & wait $! } function exit_handler() { # TODO: because nginx is started in foreground and replaces # the shell via exec, this handler is never called, however as there # is no cleanup for the certs_daemon it doesn't really matter if [ $certs_daemon_pid -gt 0 ] ; then log exit_handler "stopping certs_daemon" kill -SIGTERM $certs_daemon_pid fi log exit_handler "shutting down nginx" nginx -s quit log exit_handler "container shutting down" exit } trap "exit_handler" SIGINT trap "exit_handler" SIGTERM function var_to_file() { local var=$1 local file=$2 log var_to_file "ENV VAR -> [$file]: $var" echo -e "$var" > $file } function env_domain_file() { log env_domain_file "ENV DOMAINS: $DOMAINS" echo -e "$DOMAINS" > $1 } function read_file() { local func=$1 local file=$2 local result=0 while read -r line || [[ -n "$line" ]]; do # skip empty lines if READ_EMPTY_LINES is not set [ -z ${READ_EMPTY_LINES+x} ] && [ "${#line}" -lt 1 ] && continue log read_file "LINE: $line" log read_file "FUNC START [$func]" if $func $line; then log read_file "FUNC END [$func]" else result=1 log ERROR read_file "FUNC END [$func]" fi done < "$file" return $result } function cert_exists() { local domain=$1 local cert_path="$cert_root_path/$domain" [ -f "$cert_path/fullchain.pem" ] } function certs_daemon() { ( # wait for nginx to start while [ ! -f "$nginx_pid" ]; do log certs_daemon "Waiting for nginx to start" sleep_wait 1 done # wait for inital cert update while [ ! -f "$certs_updated" ]; do log certs_daemon "Waiting for initial cert update" sleep_wait 1 done # reload nginx nginx -s reload # cert watcher loop while inotifywait -e attrib "$certs_updated"; do log certs_daemon "Certs updated, reloading nginx" nginx -s reload done ) & certs_daemon_pid=$! } function nginx_handler() { local retries=0 # start the daemon (it forks itself) certs_daemon # wait for certs to exist before starting nginx # just have nginx crash after n retries (default 10) while ! read_file cert_exists "$domain_file" && [ "$retries" -lt "$server_retries" ]; do log nginx_handler "Waiting for certs to be created" retries=$(( retries+1 )) sleep_wait 1 done # starting nginx in foreground log nginx_handler "Starting nginx in foreground" exec nginx -g "daemon off;" } function main() { log main "Starting nginx container" # TODO: load domains from nginx.conf env_domain_file "$domain_file" nginx_handler } main $@