Merge pull request #3369 from dokku/3162-nginx-validate
Pull invalid nginx configuration when the nginx configs fail to validate
This commit is contained in:
@@ -6,6 +6,67 @@ Dokku uses nginx as its server for routing requests to specific applications. By
|
||||
nginx:access-logs <app> [-t] # Show the nginx access logs for an application (-t follows)
|
||||
nginx:build-config <app> # (Re)builds nginx config for given app
|
||||
nginx:error-logs <app> [-t] # Show the nginx error logs for an application (-t follows)
|
||||
nginx:validate [<app>] [--clean] # Validates and optionally cleans up invalid nginx configurations
|
||||
```
|
||||
|
||||
## Checking access logs
|
||||
|
||||
You may check nginx access logs via the `nginx:access-logs` command. This assumes that app access logs are being stored in `/var/log/nginx/$APP-access.log`, as is the default in the generated `nginx.conf`.
|
||||
|
||||
```shell
|
||||
dokku nginx:access-logs node-js-app
|
||||
```
|
||||
|
||||
You may also follow the logs by specifying the `-t` flag.
|
||||
|
||||
```shell
|
||||
dokku nginx:access-logs node-js-app -t
|
||||
```
|
||||
|
||||
## Checking error logs
|
||||
|
||||
You may check nginx error logs via the `nginx:access-logs` command. This assumes that app error logs are being stored in `/var/log/nginx/$APP-error.log`, as is the default in the generated `nginx.conf`.
|
||||
|
||||
```shell
|
||||
dokku nginx:error-logs node-js-app
|
||||
```
|
||||
|
||||
You may also follow the logs by specifying the `-t` flag.
|
||||
|
||||
```shell
|
||||
dokku nginx:error-logs node-js-app -t
|
||||
```
|
||||
|
||||
## Regenerating nginx config
|
||||
|
||||
In certain cases, your app nginx configs may drift from the correct config for your app. You may regenerate the config at any point via the `nginx:build-config` command. This may fail if there are no current web listeners for your app.
|
||||
|
||||
```shell
|
||||
dokku nginx:build-config node-js-app
|
||||
```
|
||||
|
||||
## Validating nginx configs
|
||||
|
||||
It may be desired to validate an nginx config outside of the deployment process. To do so, run the `nginx:validate` command. With no arguments, this will validate all app nginx configs, one at a time. A minimal wrapper nginx config is generated for each app's nginx config, upon which `nginx -t` will be run.
|
||||
|
||||
```shell
|
||||
dokku nginx:validate
|
||||
```
|
||||
|
||||
As app nginx configs are actually executed within a shared context, it is possible for an individual config to be invalid when being validated standalone but _also_ be valid within the global server context. As such, the exit code for the `nginx:validate` command is the exit code of `nginx -t` against the server's real nginx config.
|
||||
|
||||
The `nginx:validate` command also takes an optional `--clean` flag. If specified, invalid nginx configs will be removed.
|
||||
|
||||
> Warning: Invalid app nginx config's will be removed _even if_ the config is valid in the global server context.
|
||||
|
||||
```shell
|
||||
dokku nginx:validate --clean
|
||||
```
|
||||
|
||||
The `--clean` flag may also be specified for a given app:
|
||||
|
||||
```shell
|
||||
dokku nginx:validate node-js-app --clean
|
||||
```
|
||||
|
||||
## Customizing the nginx configuration
|
||||
|
||||
@@ -67,7 +67,7 @@ dokku/node-js-app v1 936a42f25901 About a minute ago
|
||||
|
||||
Finally, you can also deploy a local image using the `tags:deploy` command. When specifying a tag that is not `latest`, the released image will be retagged as the `latest` image tag for the app.
|
||||
|
||||
> Warning: For images based on herokuish, using the `tags:deploy` subcommand will reset environment variables written into the image, causing a retag to occur. This will - on average - add two extra layers to your deployed image. Note that this does not affect dockerfile-based images, which are the majority of images deployed via the `tags` command.
|
||||
> Warning: For images based on herokuish, using the `tags:deploy` command will reset environment variables written into the image, causing a retag to occur. This will - on average - add two extra layers to your deployed image. Note that this does not affect dockerfile-based images, which are the majority of images deployed via the `tags` command.
|
||||
|
||||
```shell
|
||||
dokku tags:deploy node-js-app v1
|
||||
|
||||
@@ -37,7 +37,7 @@ dokku ps node-js-app
|
||||
|
||||
> New as of 0.13.0
|
||||
|
||||
A common administrative task to perform is calling `docker inspect` on the containers that are running for an application. This can be an error-prone task to perform, and may also reveal sensitive environment variables if not done correctly. Dokku provides a wrapper around this command via the `ps:inspect` subcommand:
|
||||
A common administrative task to perform is calling `docker inspect` on the containers that are running for an application. This can be an error-prone task to perform, and may also reveal sensitive environment variables if not done correctly. Dokku provides a wrapper around this command via the `ps:inspect` command:
|
||||
|
||||
```shell
|
||||
dokku ps:inspect node-js-app
|
||||
|
||||
@@ -6,6 +6,7 @@ source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
||||
source "$PLUGIN_AVAILABLE_PATH/domains/functions"
|
||||
source "$PLUGIN_AVAILABLE_PATH/proxy/functions"
|
||||
source "$PLUGIN_AVAILABLE_PATH/ps/functions"
|
||||
source "$PLUGIN_AVAILABLE_PATH/nginx-vhosts/internal-functions"
|
||||
|
||||
get_nginx_location() {
|
||||
declare desc="check that nginx is at the expected location and return it"
|
||||
@@ -25,26 +26,45 @@ get_nginx_location() {
|
||||
|
||||
validate_nginx() {
|
||||
declare desc="validate entire nginx config"
|
||||
local NGINX_LOCATION
|
||||
declare APP="${1:-}" FLAG="${2:-}"
|
||||
local NGINX_LOCATION EXIT_CODE
|
||||
NGINX_LOCATION=$(get_nginx_location)
|
||||
if [[ -z "$NGINX_LOCATION" ]]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
if [[ "$APP" == "--clean" ]]; then
|
||||
APP=""
|
||||
FLAG="--clean"
|
||||
fi
|
||||
|
||||
set +e
|
||||
sudo "$NGINX_LOCATION" -t > /dev/null 2>&1
|
||||
local exit_code=$?
|
||||
EXIT_CODE=$?
|
||||
set -e
|
||||
if [[ "$exit_code" -ne "0" ]]; then
|
||||
sudo "$NGINX_LOCATION" -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"
|
||||
if [[ "$EXIT_CODE" -eq "0" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -n "$APP" ]]; then
|
||||
nginx_vhosts_validate_single_func "$APP" "$FLAG"
|
||||
else
|
||||
for app in $(dokku_apps); do
|
||||
nginx_vhosts_validate_single_func "$app" "$FLAG"
|
||||
done
|
||||
fi
|
||||
|
||||
set +e
|
||||
sudo "$NGINX_LOCATION" -t > /dev/null 2>&1
|
||||
EXIT_CODE=$?
|
||||
set -e
|
||||
if [[ "$EXIT_CODE" -eq "0" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
|
||||
sudo "$NGINX_LOCATION" -t
|
||||
exit $?
|
||||
}
|
||||
|
||||
restart_nginx() {
|
||||
@@ -320,7 +340,7 @@ nginx_build_config() {
|
||||
PROXY_PORT_MAP=$(echo "$PROXY_PORT_MAP" | xargs) # trailing spaces mess up default template
|
||||
|
||||
eval "$(config_export app "$APP")"
|
||||
local SIGIL_PARAMS=(-f $NGINX_TEMPLATE APP="$APP" DOKKU_ROOT="$DOKKU_ROOT"
|
||||
local SIGIL_PARAMS=(-f "$NGINX_TEMPLATE" APP="$APP" DOKKU_ROOT="$DOKKU_ROOT"
|
||||
NOSSL_SERVER_NAME="$NOSSL_SERVER_NAME"
|
||||
DOKKU_APP_LISTENERS="$DOKKU_APP_LISTENERS"
|
||||
DOKKU_LIB_ROOT="$DOKKU_LIB_ROOT"
|
||||
|
||||
@@ -5,23 +5,23 @@ source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
||||
|
||||
case "$DOKKU_DISTRO" in
|
||||
debian)
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:/usr/sbin/invoke-rc.d nginx reload, /usr/sbin/nginx -t" > /etc/sudoers.d/dokku-nginx
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:/usr/sbin/invoke-rc.d nginx reload, /usr/sbin/nginx -t, /usr/sbin/nginx -t -c *" > /etc/sudoers.d/dokku-nginx
|
||||
;;
|
||||
|
||||
ubuntu)
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:/etc/init.d/nginx reload, /usr/sbin/nginx -t" > /etc/sudoers.d/dokku-nginx
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:/etc/init.d/nginx reload, /usr/sbin/nginx -t, /usr/sbin/nginx -t -c *" > /etc/sudoers.d/dokku-nginx
|
||||
;;
|
||||
|
||||
opensuse)
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:/sbin/service nginx reload, /usr/sbin/nginx -t" > /etc/sudoers.d/dokku-nginx
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:/sbin/service nginx reload, /usr/sbin/nginx -t, /usr/sbin/nginx -t -c *" > /etc/sudoers.d/dokku-nginx
|
||||
;;
|
||||
|
||||
arch)
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:/usr/bin/systemctl reload nginx, /usr/sbin/nginx -t" > /etc/sudoers.d/dokku-nginx
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:/usr/bin/systemctl reload nginx, /usr/sbin/nginx -t, /usr/sbin/nginx -t -c *" > /etc/sudoers.d/dokku-nginx
|
||||
;;
|
||||
|
||||
centos|rhel)
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:/usr/bin/systemctl reload nginx, /usr/sbin/nginx -t" > /etc/sudoers.d/dokku-nginx
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:/usr/bin/systemctl reload nginx, /usr/sbin/nginx -t, /usr/sbin/nginx -t -c *" > /etc/sudoers.d/dokku-nginx
|
||||
echo "Defaults:dokku !requiretty" >> /etc/sudoers.d/dokku-nginx
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1,12 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
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/${FUNCNAME[0]}.XXXX")
|
||||
trap 'rm -rf "$TMP_OUTPUT" > /dev/null' RETURN INT TERM EXIT
|
||||
|
||||
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_vhosts_help_content_func() {
|
||||
declare desc="return nginx plugin help content"
|
||||
cat<<help_content
|
||||
nginx:build-config <app>, (Re)builds nginx config for given app
|
||||
nginx:access-logs <app> [-t], Show the nginx access logs for an application (-t follows)
|
||||
nginx:error-logs <app> [-t], Show the nginx error logs for an application (-t follows)
|
||||
nginx:validate [<app>] [--clean], Validates and optionally cleans up invalid nginx configurations
|
||||
help_content
|
||||
}
|
||||
|
||||
|
||||
13
plugins/nginx-vhosts/subcommands/validate
Executable file
13
plugins/nginx-vhosts/subcommands/validate
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
||||
source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
||||
source "$PLUGIN_AVAILABLE_PATH/nginx-vhosts/functions"
|
||||
|
||||
nginx_validate_cmd() {
|
||||
declare desc="validates and optionally cleans up invalid nginx configurations"
|
||||
declare cmd="nginx:validate" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1
|
||||
validate_nginx "$@"
|
||||
}
|
||||
|
||||
nginx_validate_cmd "$@"
|
||||
2
plugins/nginx-vhosts/templates/validate.conf.sigil
Normal file
2
plugins/nginx-vhosts/templates/validate.conf.sigil
Normal file
@@ -0,0 +1,2 @@
|
||||
events { worker_connections 768; }
|
||||
http { include {{ $.NGINX_CONF }}; }
|
||||
@@ -106,3 +106,50 @@ assert_error_log() {
|
||||
echo "status: $status"
|
||||
assert_failure
|
||||
}
|
||||
|
||||
@test "(nginx-vhosts) nginx:validate" {
|
||||
deploy_app
|
||||
run /bin/bash -c "dokku nginx:validate"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku nginx:validate $TEST_APP"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
echo "invalid config" > "/home/dokku/${TEST_APP}/nginx.conf"
|
||||
|
||||
run /bin/bash -c "dokku nginx:validate"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_failure
|
||||
|
||||
run /bin/bash -c "dokku nginx:validate $TEST_APP"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_failure
|
||||
|
||||
run /bin/bash -c "dokku nginx:validate --clean"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku nginx:validate"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
echo "invalid config" > "/home/dokku/${TEST_APP}/nginx.conf"
|
||||
|
||||
run /bin/bash -c "dokku nginx:validate $TEST_APP --clean"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
run /bin/bash -c "dokku nginx:validate"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user