Files
dokku/plugins/nginx-vhosts/internal-functions
Jose Diaz-Gonzalez ac56a5ffdd fix: check if nginx is running before reloading during an app deletion
The purpose of the reload is to remove nginx from being loaded. If nginx isn't running, then by definition the config is not loaded.

Closes #6832
2024-09-23 21:25:23 -04:00

678 lines
17 KiB
Bash
Executable File

#!/usr/bin/env bash
set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions"
fn-nginx-access-log-format() {
declare desc="get the configured access log format"
declare APP="$1"
fn-get-property --app "$APP" "access-log-format"
}
fn-nginx-computed-access-log-format() {
declare desc="get the computed access log format"
declare APP="$1"
fn-get-property --app "$APP" --computed "access-log-format"
}
fn-nginx-global-access-log-format() {
declare desc="get the global access log format"
declare APP="$1"
fn-get-property --app "$APP" --global "access-log-format"
}
fn-nginx-access-log-path() {
declare desc="get the configured access log path"
declare APP="$1"
fn-get-property --app "$APP" "access-log-path"
}
fn-nginx-computed-access-log-path() {
declare desc="get the computed access log path"
declare APP="$1"
fn-get-property --app "$APP" --computed "access-log-path"
}
fn-nginx-global-access-log-path() {
declare desc="get the global access log path"
declare APP="$1"
fn-get-property --app "$APP" --global "access-log-path"
}
fn-nginx-bind-address-ipv4() {
declare desc="get the configured ipv4 bind address"
declare APP="$1"
fn-get-property --app "$APP" "bind-address-ipv4"
}
fn-nginx-computed-bind-address-ipv4() {
declare desc="get the computed ipv4 bind address"
declare APP="$1"
fn-get-property --app "$APP" --computed "bind-address-ipv4"
}
fn-nginx-global-bind-address-ipv4() {
declare desc="get the global ipv4 bind address"
declare APP="$1"
fn-get-property --app "$APP" --global "bind-address-ipv4"
}
fn-nginx-bind-address-ipv6() {
declare desc="get the configured ipv6 bind address"
declare APP="$1"
fn-get-property --app "$APP" "bind-address-ipv6"
}
fn-nginx-computed-bind-address-ipv6() {
declare desc="get the computed ipv6 bind address"
declare APP="$1"
fn-get-property --app "$APP" --computed "bind-address-ipv6"
}
fn-nginx-global-bind-address-ipv6() {
declare desc="get the global ipv6 bind address"
declare APP="$1"
fn-get-property --app "$APP" --global "bind-address-ipv6"
}
fn-nginx-client-max-body-size() {
declare desc="get the configured client max body size"
declare APP="$1"
fn-get-property --app "$APP" "client-max-body-size"
}
fn-nginx-computed-client-max-body-size() {
declare desc="get the computed client max body size"
declare APP="$1"
fn-get-property --app "$APP" --computed "client-max-body-size"
}
fn-nginx-global-client-max-body-size() {
declare desc="get the global client max body size"
declare APP="$1"
fn-get-property --app "$APP" --global "client-max-body-size"
}
fn-nginx-disable-custom-config() {
declare desc="get the configured disable-custom-config value"
declare APP="$1"
fn-get-property --app "$APP" "disable-custom-config"
}
fn-nginx-computed-disable-custom-config() {
declare desc="get the computed disable-custom-config value"
declare APP="$1"
fn-get-property --app "$APP" --computed "disable-custom-config"
}
fn-nginx-global-disable-custom-config() {
declare desc="get the global disable-custom-config value"
declare APP="$1"
fn-get-property --app "$APP" --global "disable-custom-config"
}
fn-nginx-error-log-path() {
declare desc="get the configured error log path"
declare APP="$1"
fn-get-property --app "$APP" "error-log-path"
}
fn-nginx-computed-error-log-path() {
declare desc="get the computed error log path"
declare APP="$1"
fn-get-property --app "$APP" --computed "error-log-path"
}
fn-nginx-global-error-log-path() {
declare desc="get the global error log path"
declare APP="$1"
fn-get-property --app "$APP" --global "error-log-path"
}
fn-nginx-hsts-include-subdomains() {
declare APP="$1"
fn-get-property --app "$APP" "hsts-include-subdomains"
}
fn-nginx-computed-hsts-include-subdomains() {
declare APP="$1"
fn-get-property --app "$APP" --computed "hsts-include-subdomains"
}
fn-nginx-global-hsts-include-subdomains() {
declare APP="$1"
fn-get-property --app "$APP" --global "hsts-include-subdomains"
}
fn-nginx-hsts-max-age() {
declare APP="$1"
fn-get-property --app "$APP" "hsts-max-age"
}
fn-nginx-computed-hsts-max-age() {
declare APP="$1"
fn-get-property --app "$APP" --computed "hsts-max-age"
}
fn-nginx-global-hsts-max-age() {
declare APP="$1"
fn-get-property --app "$APP" --global "hsts-max-age"
}
fn-nginx-hsts-preload() {
declare APP="$1"
fn-get-property --app "$APP" "hsts-preload"
}
fn-nginx-computed-hsts-preload() {
declare APP="$1"
fn-get-property --app "$APP" --computed "hsts-preload"
}
fn-nginx-global-hsts-preload() {
declare APP="$1"
fn-get-property --app "$APP" --global "hsts-preload"
}
fn-nginx-hsts() {
declare APP="$1"
fn-get-property --app "$APP" "hsts"
}
fn-nginx-computed-hsts() {
declare APP="$1"
fn-get-property --app "$APP" --computed "hsts"
}
fn-nginx-global-hsts() {
declare APP="$1"
fn-get-property --app "$APP" --global "hsts"
}
fn-nginx-vhosts-last-visited-at() {
declare APP="$1"
local LOG_PATH=$(fn-nginx-access-log-path "$APP")
if [[ "$LOG_PATH" != "off" ]] && [[ "$LOG_PATH" != "/dev/null" ]] && [[ -f "$LOG_PATH" ]]; then
stat -c %Y "$LOG_PATH"
fi
}
fn-nginx-log-root() {
declare desc="get the nginx log root"
local NGINX_LOG_ROOT="/var/log/nginx"
fn-nginx-vhosts-uses-openresty && NGINX_LOG_ROOT="/var/log/openresty"
echo "$NGINX_LOG_ROOT"
}
fn-nginx-nginx-conf-sigil-path() {
declare APP="$1"
fn-get-property --app "$APP" "nginx-conf-sigil-path"
}
fn-nginx-computed-nginx-conf-sigil-path() {
declare APP="$1"
fn-get-property --computed --app "$APP" "nginx-conf-sigil-path"
}
fn-nginx-global-nginx-conf-sigil-path() {
declare APP="$1"
fn-get-property --global "nginx-conf-sigil-path"
}
fn-nginx-proxy-buffer-size() {
declare desc="get the configured proxy buffer size"
declare APP="$1"
fn-get-property --app "$APP" "proxy-buffer-size"
}
fn-nginx-computed-proxy-buffer-size() {
declare desc="get the computed proxy buffer size"
declare APP="$1"
fn-get-property --app "$APP" --computed "proxy-buffer-size"
}
fn-nginx-global-proxy-buffer-size() {
declare desc="get the global proxy buffer size"
declare APP="$1"
fn-get-property --app "$APP" --global "proxy-buffer-size"
}
fn-nginx-proxy-buffering() {
declare desc="get the configured proxy buffering"
declare APP="$1"
fn-get-property --app "$APP" "proxy-buffering"
}
fn-nginx-computed-proxy-buffering() {
declare desc="get the computed proxy buffering"
declare APP="$1"
fn-get-property --app "$APP" --computed "proxy-buffering"
}
fn-nginx-global-proxy-buffering() {
declare desc="get the global proxy buffering"
declare APP="$1"
fn-get-property --app "$APP" --global "proxy-buffering"
}
fn-nginx-proxy-buffers() {
declare desc="get the configured proxy buffers"
declare APP="$1"
fn-get-property --app "$APP" "proxy-buffers"
}
fn-nginx-computed-proxy-buffers() {
declare desc="get the computed proxy buffers"
declare APP="$1"
fn-get-property --app "$APP" --computed "proxy-buffers"
}
fn-nginx-global-proxy-buffers() {
declare desc="get the global proxy buffers"
declare APP="$1"
fn-get-property --app "$APP" --global "proxy-buffers"
}
fn-nginx-proxy-busy-buffers-size() {
declare desc="get the configured proxy busy buffers size"
declare APP="$1"
fn-get-property --app "$APP" "proxy-busy-buffers-size"
}
fn-nginx-computed-proxy-busy-buffers-size() {
declare desc="get the computed proxy busy buffers size"
declare APP="$1"
fn-get-property --app "$APP" --computed "proxy-busy-buffers-size"
}
fn-nginx-global-proxy-busy-buffers-size() {
declare desc="get the global proxy busy buffers size"
declare APP="$1"
fn-get-property --app "$APP" --global "proxy-busy-buffers-size"
}
fn-nginx-proxy-read-timeout() {
declare desc="get the configured proxy read timeout"
declare APP="$1"
fn-get-property --app "$APP" "proxy-read-timeout"
}
fn-nginx-computed-proxy-read-timeout() {
declare desc="get the computed proxy read timeout"
declare APP="$1"
fn-get-property --app "$APP" --computed "proxy-read-timeout"
}
fn-nginx-global-proxy-read-timeout() {
declare desc="get the global proxy read timeout"
declare APP="$1"
fn-get-property --app "$APP" --global "proxy-read-timeout"
}
fn-nginx-underscore-in-headers() {
declare desc="get the configured underscore in headers value"
declare APP="$1"
fn-get-property --app "$APP" "underscore-in-headers"
}
fn-nginx-computed-underscore-in-headers() {
declare desc="get the computed underscore in headers value"
declare APP="$1"
fn-get-property --app "$APP" --computed "underscore-in-headers"
}
fn-nginx-global-underscore-in-headers() {
declare desc="get the global underscore in headers value"
declare APP="$1"
fn-get-property --app "$APP" --global "underscore-in-headers"
}
fn-nginx-x-forwarded-for-value() {
declare desc="get the configured x-forwarded-for value"
declare APP="$1"
fn-get-property --app "$APP" "x-forwarded-for-value"
}
fn-nginx-computed-x-forwarded-for-value() {
declare desc="get the computed x-forwarded-for value"
declare APP="$1"
fn-get-property --app "$APP" --computed "x-forwarded-for-value"
}
fn-nginx-global-x-forwarded-for-value() {
declare desc="get the global x-forwarded-for value"
declare APP="$1"
fn-get-property --app "$APP" --global "x-forwarded-for-value"
}
fn-nginx-x-forwarded-port-value() {
declare desc="get the configured x-forwarded-port value"
declare APP="$1"
fn-get-property --app "$APP" "x-forwarded-port-value"
}
fn-nginx-computed-x-forwarded-port-value() {
declare desc="get the computed x-forwarded-port value"
declare APP="$1"
fn-get-property --app "$APP" --computed "x-forwarded-port-value"
}
fn-nginx-global-x-forwarded-port-value() {
declare desc="get the global x-forwarded-port value"
declare APP="$1"
fn-get-property --app "$APP" --global "x-forwarded-port-value"
}
fn-nginx-x-forwarded-proto-value() {
declare desc="get the configured x-forwarded-proto value"
declare APP="$1"
fn-get-property --app "$APP" "x-forwarded-proto-value"
}
fn-nginx-computed-x-forwarded-proto-value() {
declare desc="get the computed x-forwarded-proto value"
declare APP="$1"
fn-get-property --app "$APP" --computed "x-forwarded-proto-value"
}
fn-nginx-global-x-forwarded-proto-value() {
declare desc="get the global x-forwarded-proto value"
declare APP="$1"
fn-get-property --app "$APP" --global "x-forwarded-proto-value"
}
fn-nginx-x-forwarded-ssl() {
declare desc="get the configured x-forwarded-ssl value"
declare APP="$1"
fn-get-property --app "$APP" "x-forwarded-ssl"
}
fn-nginx-computed-x-forwarded-ssl() {
declare desc="get the computed x-forwarded-ssl value"
declare APP="$1"
fn-get-property --app "$APP" --computed "x-forwarded-ssl"
}
fn-nginx-global-x-forwarded-ssl() {
declare desc="get the global x-forwarded-ssl value"
declare APP="$1"
fn-get-property --app "$APP" --global "x-forwarded-ssl"
}
fn-nginx-vhosts-manage-hsts() {
declare APP="$1" SSL_ENABLED="$2"
local HSTS="$(fn-nginx-computed-hsts "$APP")"
local HSTS_INCLUDE_SUBDOMAINS="$(fn-nginx-computed-hsts-include-subdomains "$APP")"
local HSTS_MAX_AGE="$(fn-nginx-computed-hsts-max-age "$APP")"
local HSTS_PRELOAD="$(fn-nginx-computed-hsts-preload "$APP")"
local NGINX_HSTS_CONF="$DOKKU_ROOT/$APP/nginx.conf.d/hsts.conf"
local HSTS_TEMPLATE="$PLUGIN_AVAILABLE_PATH/nginx-vhosts/templates/hsts.conf.sigil"
local NGINX_TEMPLATE_SOURCE="built-in"
local is_custom_hsts_template=false
CUSTOM_HSTS_TEMPLATE="$(plugn trigger nginx-app-template-source "$APP" "hsts-config")"
if [[ -n "$CUSTOM_HSTS_TEMPLATE" ]]; then
is_custom_hsts_template=true
NGINX_TEMPLATE_SOURCE="plugin-supplied"
HSTS_TEMPLATE="$CUSTOM_HSTS_TEMPLATE"
fi
if [[ "$HSTS" == "false" ]] || [[ "$SSL_ENABLED" != "true" ]]; then
rm -rf "$NGINX_HSTS_CONF"
return
fi
dokku_log_verbose_quiet "Enabling HSTS (using $NGINX_TEMPLATE_SOURCE template)"
local HSTS_HEADERS=""
if [[ -n "$HSTS_MAX_AGE" ]]; then
HSTS_HEADERS="max-age=$HSTS_MAX_AGE"
fi
if [[ "$HSTS_INCLUDE_SUBDOMAINS" == "true" ]]; then
HSTS_HEADERS+="; includeSubdomains"
fi
if [[ "$HSTS_PRELOAD" == "true" ]]; then
HSTS_HEADERS+="; preload"
fi
mkdir -p "$DOKKU_ROOT/$APP/nginx.conf.d"
sigil -f "$HSTS_TEMPLATE" HSTS_HEADERS="$HSTS_HEADERS" | cat -s >"$NGINX_HSTS_CONF"
}
fn-nginx-vhosts-uses-openresty() {
declare desc="returns whether openresty is in use or not"
if [[ -x /usr/bin/openresty ]]; then
return
fi
return 1
}
fn-nginx-vhosts-nginx-location() {
declare desc="check that nginx is at the expected location and return it"
local NGINX_LOCATION
NGINX_LOCATION=$(command -v nginx 2>/dev/null)
if [[ -z "$NGINX_LOCATION" ]]; then
NGINX_LOCATION="/usr/sbin/nginx"
fi
if fn-nginx-vhosts-uses-openresty; then
NGINX_LOCATION="/usr/bin/openresty"
fi
if [[ ! -x "$NGINX_LOCATION" ]]; then
dokku_log_fail "Could not find nginx binary in \$PATH or at '${NGINX_LOCATION}'."
fi
echo "$NGINX_LOCATION"
}
fn-nginx-vhosts-nginx-is-running() {
declare desc="check if nginx is running"
local NGINX_INIT_NAME
NGINX_INIT_NAME=nginx
if fn-nginx-vhosts-uses-openresty; then
NGINX_INIT_NAME=openresty
fi
case "$DOKKU_DISTRO" in
debian | raspbian)
if [[ -x "$systemctl_path" ]]; then
if sudo "$systemctl_path" is-active --quiet "$NGINX_INIT_NAME"; then
return 0
fi
else
dokku_log_warn "Checking $NGINX_INIT_NAME status is not possible for init.d managed services"
return 0
fi
;;
ubuntu)
# support docker-based installations
if [[ "$DOKKU_INIT_SYSTEM" == "sv" ]]; then
if sudo /usr/bin/sv status $NGINX_INIT_NAME | grep -q "^run:"; then
return 0
fi
elif [[ -x "$systemctl_path" ]]; then
if sudo "$systemctl_path" is-active --quiet "$NGINX_INIT_NAME"; then
return 0
fi
elif [[ -x /usr/bin/sv ]]; then
if sudo /usr/bin/sv status $NGINX_INIT_NAME | grep -q "^run:"; then
return 0
fi
else
dokku_log_warn "Checking $NGINX_INIT_NAME status is not possible for init.d managed services"
return 0
fi
;;
arch)
if sudo "$systemctl_path" is-active --quiet "$NGINX_INIT_NAME"; then
return 0
fi
;;
esac
return 1
}
fn-nginx-vhosts-nginx-init-cmd() {
declare desc="start nginx for given distros"
declare CMD="$1"
local NGINX_INIT_NAME
NGINX_INIT_NAME=nginx
if fn-nginx-vhosts-uses-openresty; then
NGINX_INIT_NAME=openresty
fi
local systemctl_path=/bin/systemctl
if [[ -x /usr/bin/systemctl ]]; then
systemctl_path=/usr/bin/systemctl
fi
case "$DOKKU_DISTRO" in
debian | raspbian)
if [[ -x "$systemctl_path" ]]; then
sudo "$systemctl_path" "$CMD" "$NGINX_INIT_NAME"
else
sudo /usr/sbin/invoke-rc.d "$NGINX_INIT_NAME" "$CMD"
fi
;;
ubuntu)
# support docker-based installations
if [[ "$DOKKU_INIT_SYSTEM" == "sv" ]]; then
sudo /usr/bin/sv "$CMD" "$NGINX_INIT_NAME"
elif [[ -x "$systemctl_path" ]]; then
sudo "$systemctl_path" "$CMD" "$NGINX_INIT_NAME"
elif [[ -x /usr/bin/sv ]]; then
sudo /usr/bin/sv "$CMD" "$NGINX_INIT_NAME"
elif [[ "$CMD" == "enable" ]] || [[ "$CMD" == "disable" ]]; then
dokku_log_warn "Running $CMD is not possible for init.d managed services"
else
sudo "/etc/init.d/$NGINX_INIT_NAME" "$CMD"
fi
;;
arch)
sudo "$systemctl_path" "$CMD" "$NGINX_INIT_NAME"
;;
esac
}
fn-get-property() {
declare desc="get a property from the nginx plugin"
"$PLUGIN_CORE_AVAILABLE_PATH/nginx-vhosts/nginx-property" "$@"
}
nginx_vhosts_validate_single_func() {
declare APP="$1" FLAG="$2"
local NGINX_CONF="$DOKKU_ROOT/$APP/nginx.conf"
if [[ ! -f "$NGINX_CONF" ]]; then
dokku_log_warn_quiet "No nginx config found for ${APP}"
return
fi
if nginx_vhosts_is_valid_nginx_config_func "$APP"; then
return
fi
dokku_log_warn "Failed to validate nginx config for ${APP}. Contents below..."
cat "$NGINX_CONF"
if [[ "$FLAG" == "--clean" ]]; then
nginx_vhosts_conf_clean_func "$APP"
fi
}
nginx_vhosts_is_valid_nginx_config_func() {
declare desc="checks if an app has a valid nginx config"
declare APP="$1"
local VALIDATE_TEMPLATE="$PLUGIN_AVAILABLE_PATH/nginx-vhosts/templates/validate.conf.sigil"
local TMP_OUTPUT=$(mktemp "/tmp/dokku-${DOKKU_PID}-${FUNCNAME[0]}.XXXXXX")
trap "rm -rf '$TMP_OUTPUT' >/dev/null" RETURN INT TERM EXIT
CUSTOM_VALIDATE_TEMPLATE="$(plugn trigger nginx-app-template-source "$APP" "validate-config")"
if [[ -n "$CUSTOM_VALIDATE_TEMPLATE" ]]; then
VALIDATE_TEMPLATE="$CUSTOM_VALIDATE_TEMPLATE"
fi
sigil -f "$VALIDATE_TEMPLATE" NGINX_CONF="$DOKKU_ROOT/$APP/nginx.conf" | cat -s >"$TMP_OUTPUT"
sudo "$NGINX_LOCATION" -t -c "$TMP_OUTPUT" 2>/dev/null
}
nginx_vhosts_conf_clean_func() {
declare APP="$1"
local NGINX_CONF="$DOKKU_ROOT/$APP/nginx.conf"
dokku_log_warn "Removing invalid nginx file"
rm -f "$NGINX_CONF"
}
nginx_clear_config() {
declare desc="Remove the nginx conf file"
declare APP="$1"
rm -f "$DOKKU_ROOT/$APP/nginx.conf"
suppress_output fn-nginx-vhosts-nginx-init-cmd "reload"
}