All of these commands should execute against the image that is in use versus the "latest" that dokku provides the system with.
304 lines
12 KiB
Bash
Executable File
304 lines
12 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
|
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
|
source "$PLUGIN_AVAILABLE_PATH/certs/functions"
|
|
source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
|
source "$PLUGIN_AVAILABLE_PATH/domains/functions"
|
|
source "$PLUGIN_AVAILABLE_PATH/ps/functions"
|
|
|
|
validate_nginx() {
|
|
declare desc="validate entire nginx config"
|
|
set +e
|
|
sudo /usr/sbin/nginx -t > /dev/null 2>&1
|
|
local exit_code=$?
|
|
set -e
|
|
if [[ "$exit_code" -ne "0" ]]; then
|
|
sudo /usr/sbin/nginx -t
|
|
shopt -s nullglob
|
|
local conf_file
|
|
for conf_file in $DOKKU_ROOT/*/nginx.conf; do
|
|
dokku_log_verbose "validate_nginx failed. contents of $conf_file below..."
|
|
cat "$conf_file"
|
|
done
|
|
exit "$exit_code"
|
|
fi
|
|
}
|
|
|
|
restart_nginx() {
|
|
declare desc="restart nginx for given distros"
|
|
case "$DOKKU_DISTRO" in
|
|
debian)
|
|
sudo /usr/sbin/invoke-rc.d nginx reload > /dev/null
|
|
;;
|
|
|
|
ubuntu)
|
|
sudo /etc/init.d/nginx reload > /dev/null
|
|
;;
|
|
|
|
opensuse)
|
|
sudo /sbin/service nginx reload > /dev/null
|
|
;;
|
|
|
|
arch)
|
|
sudo /usr/bin/systemctl reload nginx
|
|
;;
|
|
esac
|
|
}
|
|
|
|
nginx_logs() {
|
|
declare desc="display app nginx logs"
|
|
local APP="$2"; verify_app_name "$APP"
|
|
local NGINX_LOGS_TYPE=${1#nginx:}
|
|
local NGINX_LOGS_TYPE=${NGINX_LOGS_TYPE%-logs}
|
|
local NGINX_LOGS_PATH="/var/log/nginx/$APP-$NGINX_LOGS_TYPE.log"
|
|
|
|
if [[ $3 == "-t" ]]; then
|
|
local NGINX_LOGS_ARGS="-F"
|
|
else
|
|
local NGINX_LOGS_ARGS="-n 20"
|
|
fi
|
|
|
|
tail "$NGINX_LOGS_ARGS" "$NGINX_LOGS_PATH"
|
|
}
|
|
|
|
configure_nginx_ports() {
|
|
declare desc="configure nginx listening ports"
|
|
local APP=$1; verify_app_name "$APP"
|
|
local RAW_TCP_PORTS="$(get_app_raw_tcp_ports "$APP")"
|
|
local DOKKU_NGINX_PORT=$(config_get "$APP" DOKKU_NGINX_PORT)
|
|
local DOKKU_NGINX_SSL_PORT=$(config_get "$APP" DOKKU_NGINX_SSL_PORT)
|
|
local DOKKU_PROXY_PORT_MAP=$(config_get "$APP" DOKKU_PROXY_PORT_MAP)
|
|
local IS_APP_VHOST_ENABLED="$(is_app_vhost_enabled "$APP")"
|
|
local UPSTREAM_PORT="5000"
|
|
|
|
if [[ -z "$DOKKU_NGINX_PORT" ]] && [[ -z "$RAW_TCP_PORTS" ]]; then
|
|
if [[ "$IS_APP_VHOST_ENABLED" == "false" ]]; then
|
|
dokku_log_info1 "no nginx port set. setting to random open high port"
|
|
local NGINX_PORT=$(get_available_port)
|
|
else
|
|
local NGINX_PORT=80
|
|
fi
|
|
config_set --no-restart "$APP" DOKKU_NGINX_PORT="$NGINX_PORT"
|
|
fi
|
|
if [[ -z "$DOKKU_NGINX_SSL_PORT" ]]; then
|
|
if (is_ssl_enabled "$APP") && [[ -z "$RAW_TCP_PORTS" ]]; then
|
|
if [[ "$IS_APP_VHOST_ENABLED" == "false" ]]; then
|
|
dokku_log_info1 "no nginx ssl port set. setting to random open high port"
|
|
local NGINX_SSL_PORT=$(get_available_port)
|
|
else
|
|
local NGINX_SSL_PORT=443
|
|
fi
|
|
config_set --no-restart "$APP" DOKKU_NGINX_SSL_PORT="$NGINX_SSL_PORT"
|
|
fi
|
|
fi
|
|
if [[ -z "$DOKKU_PROXY_PORT_MAP" ]]; then
|
|
if [[ -n "$RAW_TCP_PORTS" ]]; then
|
|
local RAW_TCP_PORT
|
|
for RAW_TCP_PORT in $RAW_TCP_PORTS; do
|
|
local PROXY_PORT_MAP+=" http:${RAW_TCP_PORT}:${RAW_TCP_PORT} "
|
|
done
|
|
else
|
|
local NGINX_PORT=${NGINX_PORT:-$DOKKU_NGINX_PORT}
|
|
local NGINX_SSL_PORT=${NGINX_SSL_PORT:-$DOKKU_NGINX_SSL_PORT}
|
|
[[ -f "$DOKKU_ROOT/$APP/PORT.web.1" ]] && local UPSTREAM_PORT="$(< "$DOKKU_ROOT/$APP/PORT.web.1")"
|
|
if [[ -n "$NGINX_PORT" ]] && [[ -n "$NGINX_SSL_PORT" ]]; then
|
|
local PROXY_PORT_MAP+=" http:${NGINX_PORT}:$UPSTREAM_PORT https:${NGINX_SSL_PORT}:$UPSTREAM_PORT "
|
|
elif [[ -n "$NGINX_PORT" ]]; then
|
|
local PROXY_PORT_MAP+=" http:${NGINX_PORT}:$UPSTREAM_PORT "
|
|
fi
|
|
fi
|
|
if [[ -n "$PROXY_PORT_MAP" ]]; then
|
|
local PROXY_PORT_MAP="$(echo "$PROXY_PORT_MAP" | xargs)"
|
|
local PROXY_PORT_MAP+=" $(merge_dedupe_list "$(remove_val_from_list "$PORT_MAP" "$DOKKU_PROXY_PORT_MAP" " ")" " ") "
|
|
config_set --no-restart "$APP" DOKKU_PROXY_PORT_MAP="$PROXY_PORT_MAP"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
validate_ssl_domains() {
|
|
declare desc="check configured domains against SSL cert contents and show warning if mismatched"
|
|
local APP=$1; verify_app_name "$APP"
|
|
local SSL_HOSTNAME=$(get_ssl_hostnames "$APP")
|
|
local SSL_HOSTNAME_REGEX=$(echo "$SSL_HOSTNAME" | xargs | sed 's|\.|\\.|g' | sed 's/\*/\[^\.\]\*/g' | sed 's/ /|/g')
|
|
|
|
if ! (egrep -q "^${SSL_HOSTNAME_REGEX}$" "$VHOST_PATH" &> /dev/null); then
|
|
dokku_log_info1 "No matching configured domains for $APP found in SSL certificate. Your app will show as insecure in a browser if accessed via SSL"
|
|
dokku_log_info1 "Please add appropriate domains via the dokku domains command"
|
|
[[ -n "$NONSSL_VHOSTS" ]] && dokku_log_info1 "Configured domains for app:"
|
|
local domain
|
|
for domain in $(echo "$NONSSL_VHOSTS"| xargs); do
|
|
dokku_log_info2 "$domain"
|
|
done
|
|
[[ -n "$SSL_HOSTNAME" ]] && dokku_log_info1 "Domains found in SSL certificate:"
|
|
for domain in $(echo "$SSL_HOSTNAME" | xargs); do
|
|
dokku_log_info2 "$domain"
|
|
done
|
|
fi
|
|
}
|
|
|
|
get_custom_nginx_template() {
|
|
declare desc="attempts to copy custom nginx template from app image"
|
|
local APP="$1"; verify_app_name "$APP"
|
|
local DESTINATION="$2"
|
|
local IMAGE_TAG="$(get_running_image_tag "$APP")"
|
|
local IMAGE=$(get_deploying_app_image_name "$APP" "$IMAGE_TAG")
|
|
local NGINX_TEMPLATE_NAME="nginx.conf.sigil"
|
|
|
|
copy_from_image "$IMAGE" "$NGINX_TEMPLATE_NAME" "$DESTINATION" 2>/dev/null || true
|
|
}
|
|
|
|
is_spdy_enabled() {
|
|
declare desc="detects whether the installed nginx version has spdy or http2 support"
|
|
local NGINX_VERSION="$1"
|
|
local MAJOR_VERSION MINOR_VERSION PATCH_VERSION
|
|
local HAS_SUPPORT=true
|
|
|
|
if ! which nginx > /dev/null 2>&1; then
|
|
echo $HAS_SUPPORT
|
|
return
|
|
fi
|
|
|
|
MAJOR_VERSION=$(echo "$NGINX_VERSION" | awk '{split($0,a,"."); print a[1]}')
|
|
MINOR_VERSION=$(echo "$NGINX_VERSION" | awk '{split($0,a,"."); print a[2]}')
|
|
PATCH_VERSION=$(echo "$NGINX_VERSION" | awk '{split($0,a,"."); print a[3]}')
|
|
if [[ "$MAJOR_VERSION" -ge "2" ]]; then
|
|
HAS_SUPPORT=false
|
|
elif [[ "$MAJOR_VERSION" -eq "1" ]]; then
|
|
if [[ "$MINOR_VERSION" -ge "10" ]]; then
|
|
HAS_SUPPORT=false
|
|
elif [[ "$MINOR_VERSION" -ge "9" ]] && [[ "$PATCH_VERSION" -ge "5" ]]; then
|
|
HAS_SUPPORT=false
|
|
fi
|
|
fi
|
|
|
|
echo $HAS_SUPPORT
|
|
}
|
|
|
|
nginx_build_config() {
|
|
declare desc="build nginx config to proxy app containers using sigil"
|
|
local APP="$1"; verify_app_name "$APP"
|
|
local DOKKU_APP_LISTEN_PORT="$2"; local DOKKU_APP_LISTEN_IP="$3"
|
|
local VHOST_PATH="$DOKKU_ROOT/$APP/VHOST"; local URLS_PATH="$DOKKU_ROOT/$APP/URLS"
|
|
local NGINX_TEMPLATE_NAME="nginx.conf.sigil"
|
|
local DEFAULT_NGINX_TEMPLATE="$PLUGIN_AVAILABLE_PATH/nginx-vhosts/templates/$NGINX_TEMPLATE_NAME"
|
|
local NGINX_TEMPLATE="$DEFAULT_NGINX_TEMPLATE"; local SCHEME=http
|
|
local NGINX_TEMPLATE_SOURCE="built-in"; local APP_SSL_PATH="$DOKKU_ROOT/$APP/tls"
|
|
local RAW_TCP_PORTS="$(get_app_raw_tcp_ports "$APP")"
|
|
|
|
local DOKKU_DISABLE_PROXY=$(config_get "$APP" DOKKU_DISABLE_PROXY)
|
|
local IS_APP_VHOST_ENABLED=$(is_app_vhost_enabled "$APP")
|
|
|
|
if [[ -z "$DOKKU_DISABLE_PROXY" ]]; then
|
|
if [[ -z "$DOKKU_APP_LISTEN_PORT" ]] && [[ -z "$DOKKU_APP_LISTEN_IP" ]]; then
|
|
shopt -s nullglob
|
|
local DOKKU_APP_IP_FILE
|
|
for DOKKU_APP_IP_FILE in $DOKKU_ROOT/$APP/IP.web.*; do
|
|
local DOKKU_APP_PORT_FILE="${DOKKU_APP_IP_FILE//IP/PORT}"
|
|
local DOKKU_APP_LISTENER_IP=$(< "$DOKKU_APP_IP_FILE")
|
|
local DOKKU_APP_LISTENER_PORT=$(< "$DOKKU_APP_PORT_FILE")
|
|
local DOKKU_APP_LISTENERS+="$DOKKU_APP_LISTENER_IP:$DOKKU_APP_LISTENER_PORT "
|
|
done
|
|
local DOKKU_APP_LISTENERS="$(echo "$DOKKU_APP_LISTENERS" | xargs)"
|
|
shopt -u nullglob
|
|
elif [[ -n "$DOKKU_APP_LISTEN_PORT" ]] && [[ -n "$DOKKU_APP_LISTEN_IP" ]]; then
|
|
local PASSED_LISTEN_IP_PORT=true
|
|
fi
|
|
|
|
# setup nginx listen ports
|
|
configure_nginx_ports "$APP"
|
|
local NGINX_PORT=$(config_get "$APP" DOKKU_NGINX_PORT)
|
|
local NGINX_SSL_PORT=$(config_get "$APP" DOKKU_NGINX_SSL_PORT)
|
|
local PROXY_PORT_MAP=$(config_get "$APP" DOKKU_PROXY_PORT_MAP)
|
|
|
|
local PORT_MAP
|
|
for PORT_MAP in $PROXY_PORT_MAP; do
|
|
local PROXY_UPSTREAM_PORT="$(awk -F ':' '{ print $3 }' <<< "$PORT_MAP")"
|
|
if [[ "$(is_val_in_list "$PROXY_UPSTREAM_PORT" "$PROXY_UPSTREAM_PORTS" " ")" == "false" ]]; then
|
|
local PROXY_UPSTREAM_PORTS+="$PROXY_UPSTREAM_PORT "
|
|
fi
|
|
done
|
|
local PROXY_UPSTREAM_PORTS="$(echo "$PROXY_UPSTREAM_PORTS" | xargs)"
|
|
|
|
local NGINX_BUILD_CONFIG_TMP_WORK_DIR=$(mktemp -d /tmp/dokku_nginx_template.XXXXX)
|
|
local NGINX_CONF=$(mktemp --tmpdir="${NGINX_BUILD_CONFIG_TMP_WORK_DIR}" "nginx.conf.XXXXXX")
|
|
local CUSTOM_NGINX_TEMPLATE="$NGINX_BUILD_CONFIG_TMP_WORK_DIR/$NGINX_TEMPLATE_NAME"
|
|
# shellcheck disable=SC2086
|
|
trap 'rm -rf $NGINX_CONF $NGINX_BUILD_CONFIG_TMP_WORK_DIR > /dev/null' RETURN INT TERM EXIT
|
|
|
|
get_custom_nginx_template "$APP" "$CUSTOM_NGINX_TEMPLATE"
|
|
if [[ -f "$CUSTOM_NGINX_TEMPLATE" ]]; then
|
|
dokku_log_info1 'Overriding default nginx.conf with detected nginx.conf.sigil'
|
|
local NGINX_TEMPLATE="$CUSTOM_NGINX_TEMPLATE"
|
|
local NGINX_TEMPLATE_SOURCE="app-supplied"
|
|
fi
|
|
|
|
local NONSSL_VHOSTS=$(get_app_domains "$APP")
|
|
local NOSSL_SERVER_NAME=$(echo "$NONSSL_VHOSTS" | xargs)
|
|
if is_ssl_enabled "$APP"; then
|
|
local SSL_INUSE=true; local SCHEME=https
|
|
validate_ssl_domains "$APP"
|
|
local SSL_HOSTNAME=$(get_ssl_hostnames "$APP")
|
|
local SSL_HOSTNAME_REGEX=$(echo "$SSL_HOSTNAME" | xargs | sed 's|\.|\\.|g' | sed 's/\*/\[^\.\]\*/g' | sed 's/ /|/g')
|
|
|
|
if [[ "$IS_APP_VHOST_ENABLED" == "true" ]]; then
|
|
local SSL_VHOSTS=$(egrep "^${SSL_HOSTNAME_REGEX}$" "$VHOST_PATH" || true)
|
|
else
|
|
local SSL_VHOSTS=$(< "$DOKKU_ROOT/HOSTNAME")
|
|
fi
|
|
local SSL_SERVER_NAME=$(echo "$SSL_VHOSTS" | xargs)
|
|
fi
|
|
|
|
local NGINX_VERSION="$(nginx -v 2>&1 | cut -d'/' -f 2)"
|
|
local SPDY_SUPPORTED="$(is_spdy_enabled "$NGINX_VERSION")"
|
|
|
|
eval "$(config_export app "$APP")"
|
|
local SIGIL_PARAMS=(-f $NGINX_TEMPLATE APP="$APP" DOKKU_ROOT="$DOKKU_ROOT"
|
|
NOSSL_SERVER_NAME="$NOSSL_SERVER_NAME"
|
|
DOKKU_APP_LISTENERS="$DOKKU_APP_LISTENERS"
|
|
PASSED_LISTEN_IP_PORT="$PASSED_LISTEN_IP_PORT"
|
|
SPDY_SUPPORTED="$SPDY_SUPPORTED"
|
|
DOKKU_APP_LISTEN_PORT="$DOKKU_APP_LISTEN_PORT" DOKKU_APP_LISTEN_IP="$DOKKU_APP_LISTEN_IP"
|
|
APP_SSL_PATH="$APP_SSL_PATH" SSL_INUSE="$SSL_INUSE" SSL_SERVER_NAME="$SSL_SERVER_NAME"
|
|
NGINX_PORT="$NGINX_PORT" NGINX_SSL_PORT="$NGINX_SSL_PORT" RAW_TCP_PORTS="$RAW_TCP_PORTS"
|
|
PROXY_PORT_MAP="$PROXY_PORT_MAP" PROXY_UPSTREAM_PORTS="$PROXY_UPSTREAM_PORTS")
|
|
|
|
# execute sigil template processing
|
|
xargs -i echo "-----> Configuring {}...(using $NGINX_TEMPLATE_SOURCE template)" <<< "$(echo "${SSL_VHOSTS}" "${NONSSL_VHOSTS}" | tr ' ' '\n' | sort -u)"
|
|
# echo "sigil ${SIGIL_PARAMS[@]}"
|
|
sigil "${SIGIL_PARAMS[@]}" | cat -s > "$NGINX_CONF"
|
|
|
|
if is_deployed "$APP"; then
|
|
dokku_log_info1 "Creating $SCHEME nginx.conf"
|
|
mv "$NGINX_CONF" "$DOKKU_ROOT/$APP/nginx.conf"
|
|
else
|
|
dokku_log_info1 "App $APP has not been deployed. Skipping nginx config creation"
|
|
rm -f "$NGINX_CONF"
|
|
fi
|
|
|
|
if is_deployed "$APP"; then
|
|
dokku_log_info1 "Running nginx-pre-reload"
|
|
plugn trigger nginx-pre-reload "$APP" "$DOKKU_APP_LISTEN_PORT" "$DOKKU_APP_LISTEN_IP"
|
|
|
|
dokku_log_verbose "Reloading nginx"
|
|
validate_nginx && restart_nginx
|
|
fi
|
|
|
|
if ([[ -n "$NONSSL_VHOSTS" ]] || [[ -n "$SSL_VHOSTS" ]]) && [[ "$IS_APP_VHOST_ENABLED" == "true" ]]; then
|
|
echo "# THIS FILE IS GENERATED BY DOKKU - DO NOT EDIT, YOUR CHANGES WILL BE OVERWRITTEN" > "$URLS_PATH"
|
|
xargs -i echo "$SCHEME://{}" <<< "$(echo "${SSL_VHOSTS}" "${NONSSL_VHOSTS}" | tr ' ' '\n' | sort -u)" >> "$URLS_PATH"
|
|
fi
|
|
else
|
|
# note because this clause is long. if $DOKKU_DISABLE_PROXY is set:
|
|
dokku_log_info1 "nginx support is disabled for app ($APP)."
|
|
if [[ -f "$DOKKU_ROOT/$APP/nginx.conf" ]]; then
|
|
dokku_log_info1 "deleting nginx.conf"
|
|
rm "$DOKKU_ROOT/$APP/nginx.conf"
|
|
|
|
if is_deployed "$APP"; then
|
|
dokku_log_info1 "reloading nginx after nginx.conf deletion"
|
|
validate_nginx && restart_nginx
|
|
fi
|
|
fi
|
|
fi
|
|
}
|