Merge pull request #1476 from progrium/1123_mh-nginx-novhost

nginx proxy without VHOST
This commit is contained in:
Jose Diaz-Gonzalez
2015-09-19 17:54:26 -04:00
30 changed files with 459 additions and 284 deletions

View File

@@ -2,6 +2,14 @@
Dokku uses nginx as it's server for routing requests to specific applications. By default, access and error logs are written for each app to `/var/log/nginx/${APP}-access.log` and `/var/log/nginx/${APP}-error.log` respectively
```
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:disable <app> disable nginx for an application (forces container binding to external interface)
nginx:enable <app> enable nginx for an application
nginx:error-logs <app> [-t] Show the nginx error logs for an application (-t follows)
```
## TLS/SPDY support
Dokku provides easy TLS/SPDY support out of the box. This can be done app-by-app or for all subdomains at once. Note that whenever TLS support is enabled SPDY is also enabled.
@@ -166,13 +174,13 @@ You can also use the built-in `domains` plugin to handle:
### Disabling VHOSTS
If desired, it is possible to disable vhosts by setting the `NO_VHOST` environment variable:
If desired, it is possible to disable vhosts by setting the environment variable `NO_VHOST=1`:
```shell
dokku config:set myapp NO_VHOST=1
```
On subsequent deploys, the nginx virtualhost will be discarded. This is useful when deploying internal-facing services that should not be publicly routeable.
On subsequent deploys, the nginx virtualhost will be discarded. This is useful when deploying internal-facing services that should not be publicly routeable. As of 0.4.0, nginx will still be configured to proxy your app on some random high port. This allows internal services to maintain the same port between deployments. You may change this port by setting `DOKKU_NGINX_PORT` and/or `DOKKU_NGINX_SSL_PORT` (for services configured to use SSL.)
### Domains plugin

22
dokku
View File

@@ -80,6 +80,16 @@ case "$1" in
DOKKU_RESTART_LIMIT=$(dokku config:get $APP DOKKU_RESTART_LIMIT || echo 10)
DOKKU_RESTART_LIMIT=${DOKKU_RESTART_LIMIT:=10}
DOKKU_APP_SKIP_ALL_CHECKS=$(dokku config:get $APP DOKKU_SKIP_ALL_CHECKS || true)
DOKKU_APP_SKIP_DEFAULT_CHECKS=$(dokku config:get $APP DOKKU_SKIP_DEFAULT_CHECKS || true)
DOKKU_GLOBAL_SKIP_ALL_CHECKS=$(dokku config:get --global DOKKU_SKIP_ALL_CHECKS || true)
DOKKU_GLOBAL_SKIP_DEFAULT_CHECKS=$(dokku config:get --global DOKKU_SKIP_DEFAULT_CHECKS || true)
DOKKU_SKIP_ALL_CHECKS=${DOKKU_APP_SKIP_ALL_CHECKS:="$DOKKU_GLOBAL_SKIP_ALL_CHECKS"}
DOKKU_SKIP_DEFAULT_CHECKS=${DOKKU_APP_SKIP_DEFAULT_CHECKS:="$DOKKU_GLOBAL_SKIP_DEFAULT_CHECKS"}
DOKKU_DEFAULT_DOCKER_ARGS=$(: | plugn trigger docker-args-deploy $APP $IMAGE_TAG)
while read line || [[ -n "$line" ]]; do
TRIM=${line%#*}
PROC_TYPE=${TRIM%%=*}
@@ -93,9 +103,9 @@ case "$1" in
DOKKU_PORT_FILE="$DOKKU_ROOT/$APP/PORT.$PROC_TYPE.$CONTAINER_INDEX"
# start the app
DOCKER_ARGS=" -e DYNO='$PROC_TYPE.$CONTAINER_INDEX' "
DOCKER_ARGS="$DOKKU_DEFAULT_DOCKER_ARGS"
DOCKER_ARGS+=" -e DYNO='$PROC_TYPE.$CONTAINER_INDEX' "
DOCKER_ARGS+=" --restart=on-failure:$DOKKU_RESTART_LIMIT"
DOCKER_ARGS+=$(: | plugn trigger docker-args-deploy $APP $IMAGE_TAG)
[[ "$DOKKU_TRACE" ]] && DOCKER_ARGS+=" -e TRACE=true "
BIND_EXTERNAL=$(plugn trigger bind-external-ip $APP)
@@ -127,14 +137,6 @@ case "$1" in
kill -9 $$
}
DOKKU_APP_SKIP_ALL_CHECKS=$(dokku config:get $APP DOKKU_SKIP_ALL_CHECKS || true)
DOKKU_APP_SKIP_DEFAULT_CHECKS=$(dokku config:get $APP DOKKU_SKIP_DEFAULT_CHECKS || true)
DOKKU_GLOBAL_SKIP_ALL_CHECKS=$(dokku config:get --global DOKKU_SKIP_ALL_CHECKS || true)
DOKKU_GLOBAL_SKIP_DEFAULT_CHECKS=$(dokku config:get --global DOKKU_SKIP_DEFAULT_CHECKS || true)
DOKKU_SKIP_ALL_CHECKS=${DOKKU_APP_SKIP_ALL_CHECKS:="$DOKKU_GLOBAL_SKIP_ALL_CHECKS"}
DOKKU_SKIP_DEFAULT_CHECKS=${DOKKU_APP_SKIP_DEFAULT_CHECKS:="$DOKKU_GLOBAL_SKIP_DEFAULT_CHECKS"}
# run checks first, then post-deploy hooks, which switches Nginx traffic
if [[ "$DOKKU_SKIP_ALL_CHECKS" = "true" ]]; then
dokku_log_info1 "Skipping pre-flight checks"

View File

@@ -1,7 +1,9 @@
#!/usr/bin/env bash
[[ " build release trace delete ls logs run url urls version help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
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"
case "$1" in
build)
@@ -189,12 +191,22 @@ case "$1" in
SCHEME="https"
fi
if [[ -f "$DOKKU_ROOT/VHOST" ]] && [[ "$NO_VHOST" != "1" ]]; then
echo "$SCHEME://$(< "$DOKKU_ROOT/VHOST")"
else
if [[ "$(is_app_vhost_enabled $APP)" == "false" ]]; then
for PORT_FILE in $DOKKU_ROOT/$APP/PORT.*; do
echo "$SCHEME://$(< "$DOKKU_ROOT/HOSTNAME"):$(< "$PORT_FILE")"
echo "http://$(< "$DOKKU_ROOT/HOSTNAME"):$(< "$PORT_FILE") (container)"
done
DOKKU_NGINX_PORT=$(config_get $APP DOKKU_NGINX_PORT || true)
DOKKU_NGINX_SSL_PORT=$(config_get $APP DOKKU_NGINX_SSL_PORT || true)
if [[ -n "$DOKKU_NGINX_PORT" ]]; then
echo "http://$(< "$DOKKU_ROOT/HOSTNAME"):$DOKKU_NGINX_PORT (nginx)"
fi
if [[ -n "$DOKKU_NGINX_SSL_PORT" ]]; then
echo "https://$(< "$DOKKU_ROOT/HOSTNAME"):$DOKKU_NGINX_SSL_PORT (nginx-ssl)"
fi
else
echo "$SCHEME://$(< "$DOKKU_ROOT/VHOST")"
fi
;;

View File

@@ -1,9 +1,8 @@
#!/usr/bin/env bash
[[ " events events:on events:off events:list help events:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
PLUGIN_DIR="$(dirname $0)"
case "$1" in
events)
if [[ -f $DOKKU_EVENTS_LOGFILE ]]; then
@@ -27,6 +26,7 @@ case "$1" in
;;
events:list)
PLUGIN_DIR="$(dirname $0)"
if [[ "$DOKKU_EVENTS" ]]; then
logged="$(find $PLUGIN_DIR -type l -printf '%f ' | sort)"
dokku_col_log_info2_quiet "Events currently logged"

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env bash
[[ " apps apps:create apps:destroy help apps:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"

View File

@@ -1,10 +1,10 @@
#!/usr/bin/env bash
[[ " backup:export backup:import help backup:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
CURRENT_BACKUP_VERSION=1
case "$1" in
backup:export)
CURRENT_BACKUP_VERSION=1
OUTPUT_FILE="$2"
BACKUP_DIR="$DOKKU_ROOT"

View File

@@ -1,7 +1,9 @@
#!/usr/bin/env bash
[[ " certs:add certs:generate certs:info certs:remove certs:update help certs:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_AVAILABLE_PATH/certs/functions"
source "$PLUGIN_AVAILABLE_PATH/nginx-vhosts/functions"
is_tar_import() {
[[ -t 0 ]] && return 1
@@ -57,7 +59,7 @@ certs_set() {
mv "$KEY_FILE" "$DOKKU_ROOT/$APP/tls/server.key"
cd $DOKKU_ROOT
rm -rf $TEMP_DIR
dokku nginx:build-config $APP
nginx_build_config $APP
}
case "$1" in
@@ -84,7 +86,7 @@ case "$1" in
mkdir -p "$DOKKU_ROOT/$APP/tls"
dokku_log_info1 "Installing certificate and key..."
mv -f $TMP_WORK_DIR/server.key $TMP_WORK_DIR/server.crt $SSL_PATH
[[ -n "$DOMAIN" ]] && (dokku domains:add $APP $DOMAIN || dokku nginx:build-config $APP)
[[ -n "$DOMAIN" ]] && (dokku domains:add $APP $DOMAIN || nginx_build_config $APP)
dokku_log_info1 "The following is a certificate signing request that can be used"
dokku_log_info1 "to generate an 'officially' signed SSL certificate for $APP at $DOMAIN"
dokku_log_info1 "by a CA of your choosing."

View File

@@ -330,3 +330,15 @@ docker_cleanup() {
# shellcheck disable=SC2046
docker rmi $(docker images -f 'dangling=true' -q) &> /dev/null &
}
get_available_port() {
while true; do
local port=$(shuf -i 1025-65535 -n 1)
if ! nc -z 0.0.0.0 $port; then
echo $port
return 0
else
continue
fi
done
}

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env bash
[[ " config config:get config:set config:unset help config:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_AVAILABLE_PATH/config/functions"

View File

@@ -214,6 +214,7 @@ config_unset() {
ENV_TEMP=$(echo "${ENV_TEMP}" | sed "/^export $var=/ d")
config_write "$ENV_TEMP"
[[ "$var" == "NO_VHOST" ]] && config_set --no-restart $APP NO_VHOST=0 && DOKKU_CONFIG_RESTART=true
done
if [[ "$DOKKU_CONFIG_RESTART" == "true" ]]; then

View File

@@ -1,11 +1,8 @@
#!/usr/bin/env bash
[[ " docker-options docker-options:add docker-options:remove help docker-options:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
PHASES=(build deploy run)
FILE_PREFIX="DOCKER_OPTIONS_"
get_app() {
[[ -z $1 ]] && dokku_log_fail "Please specify an app to run the command on"
verify_app_name "$1"
@@ -25,17 +22,19 @@ get_phases() {
verify_phase() {
local phase
for phase in "${PHASES[@]}"; do
local phases=(build deploy run)
for phase in "${phases[@]}"; do
if [[ "$phase" = "$1" ]]; then
return 0
fi
done
dokku_log_fail "Phase(s) must be one of [${PHASES[@]}]"
dokku_log_fail "Phase(s) must be one of [${phases[@]}]"
}
get_phase_file_path() {
local phase=$1
phase_file_path="${DOKKU_ROOT}/${APP}/${FILE_PREFIX}${phase^^}"
local prefix="DOCKER_OPTIONS_"
phase_file_path="${DOKKU_ROOT}/${APP}/${prefix}${phase^^}"
}
create_phase_file_if_required() {
@@ -53,7 +52,8 @@ display_phase_options() {
}
display_all_phases_options() {
for phase in "${PHASES[@]}"; do
local phases=(build deploy run)
for phase in "${phases[@]}"; do
get_phase_file_path $phase
if [[ -s $phase_file_path ]]; then
display_phase_options $phase $phase_file_path
@@ -139,7 +139,7 @@ case "$1" in
;;
# Display usage help
help)
help | docker-options:help)
cat<<EOF
docker-options <app>, Display apps docker options for all phases
docker-options <app> <phase(s)>, Display apps docker options for phase (comma separated phase list)

View File

@@ -1,28 +1,9 @@
#!/usr/bin/env bash
[[ " domains domains:setup domains:add domains:clear domains:remove help domains:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_AVAILABLE_PATH/config/functions"
source "$PLUGIN_AVAILABLE_PATH/domains/functions"
RE_IPV4="([0-9]{1,3}[\.]){3}[0-9]{1,3}"
RE_IPV6="([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|" # TEST: 1:2:3:4:5:6:7:8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,7}:|" # TEST: 1:: 1:2:3:4:5:6:7::
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|" # TEST: 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|" # TEST: 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|" # TEST: 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|" # TEST: 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|" # TEST: 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8
RE_IPV6="${RE_IPV6}[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|" # TEST: 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8
RE_IPV6="${RE_IPV6}:((:[0-9a-fA-F]{1,4}){1,7}|:)|" # TEST: ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::
RE_IPV6="${RE_IPV6}fe08:(:[0-9a-fA-F]{1,4}){2,2}%[0-9a-zA-Z]{1,}|" # TEST: fe08::7:8%eth0 fe08::7:8%1 (link-local IPv6 addresses with zone index)
RE_IPV6="${RE_IPV6}::(ffff(:0{1,4}){0,1}:){0,1}${RE_IPV4}|" # TEST: ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,4}:${RE_IPV4}" # TEST: 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33
# Ensure the ip address continues to the end of the line
# Fixes using a wildcard dns service such as xip.io which allows for *.<ip address>.xip.io
RE_IPV4="${RE_IPV4}\$"
RE_IPV6="${RE_IPV6}\$"
source "$PLUGIN_AVAILABLE_PATH/nginx-vhosts/functions"
case "$1" in
domains)
@@ -43,6 +24,7 @@ case "$1" in
[[ -z $2 ]] && dokku_log_fail "Please specify an app to run the command on"
verify_app_name "$2"
APP="$2"; VHOST_PATH="$DOKKU_ROOT/$APP/VHOST"
RE_IPV4="$(get_ipv4_regex)"; RE_IPV6="$(get_ipv6_regex)"
if [[ ! -f $VHOST_PATH ]]; then
if [[ -f "$DOKKU_ROOT/VHOST" ]]; then
@@ -52,7 +34,7 @@ case "$1" in
fi
if [[ "$VHOST" =~ $RE_IPV4 ]] || [[ "$VHOST" =~ $RE_IPV6 ]]; then
dokku_log_info2 "unsupported vhost config found. disabling vhost support"
config_set --no-restart $APP NO_VHOST=1
disable_app_vhost $APP --no-restart $APP
else
if [[ -f "$DOKKU_ROOT/VHOST" ]]; then
dokku_log_info1 "Creating new $VHOST_PATH..."
@@ -94,7 +76,7 @@ case "$1" in
echo "$DOMAIN" >> "$DOKKU_ROOT/$APP/VHOST"
done
# we need to restart the app to make sure we're binding to the appropriate network interface
dokku nginx:build-config $APP
nginx_build_config $APP
plugn trigger post-domains-update $APP
for DOMAIN in "$@"; do
dokku_log_info1 "Added $DOMAIN to $APP"

View File

@@ -3,6 +3,9 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
get_app_domains() {
local APP=$1; verify_app_name $APP
cat "$DOKKU_ROOT/$APP/VHOST"
local APP=$1; local APP_VHOST_FILE="$DOKKU_ROOT/$APP/VHOST"
verify_app_name $APP
if [[ -f "$APP_VHOST_FILE" ]];then
cat "$APP_VHOST_FILE"
fi
}

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env bash
[[ " enter help enter:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"

View File

@@ -1,41 +1,13 @@
#!/usr/bin/env bash
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_AVAILABLE_PATH/config/functions"
source "$PLUGIN_AVAILABLE_PATH/nginx-vhosts/functions"
APP="$1"
NO_VHOST=$(config_get $APP NO_VHOST || true)
RE_IPV4="([0-9]{1,3}[\.]){3}[0-9]{1,3}"
RE_IPV6="([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|" # TEST: 1:2:3:4:5:6:7:8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,7}:|" # TEST: 1:: 1:2:3:4:5:6:7::
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|" # TEST: 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|" # TEST: 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|" # TEST: 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|" # TEST: 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|" # TEST: 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8
RE_IPV6="${RE_IPV6}[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|" # TEST: 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8
RE_IPV6="${RE_IPV6}:((:[0-9a-fA-F]{1,4}){1,7}|:)|" # TEST: ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::
RE_IPV6="${RE_IPV6}fe08:(:[0-9a-fA-F]{1,4}){2,2}%[0-9a-zA-Z]{1,}|" # TEST: fe08::7:8%eth0 fe08::7:8%1 (link-local IPv6 addresses with zone index)
RE_IPV6="${RE_IPV6}::(ffff(:0{1,4}){0,1}:){0,1}${RE_IPV4}|" # TEST: ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,4}:${RE_IPV4}" # TEST: 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33
# Ensure the ip address continues to the end of the line
# Fixes using a wildcard dns service such as xip.io which allows for *.<ip address>.xip.io
RE_IPV4="${RE_IPV4}\$"
RE_IPV6="${RE_IPV6}\$"
[[ -f "$DOKKU_ROOT/VHOST" ]] && GLOBAL_VHOST=$(< "$DOKKU_ROOT/VHOST")
if [[ -n "$NO_VHOST" ]]; then
if [[ "$(is_app_vhost_enabled $APP)" == "false" ]]; then
echo true # bind to external ip. VHOST is disabled
elif [[ "$GLOBAL_VHOST" =~ $RE_IPV4 ]] || [[ "$GLOBAL_VHOST" =~ $RE_IPV6 ]]; then
echo true # bind to external ip. GLOBAL_VHOST is somehow an IPv4 or IPv6 address
elif [[ -z "$GLOBAL_VHOST" ]] && [[ ! -f "$DOKKU_ROOT/$APP/VHOST" ]]; then
echo true # bind to external ip. no GLOBAL_VHOST and no app vhost
elif [[ -f "$DOKKU_ROOT/$APP/VHOST" ]]; then
echo false # bind to docker ip. this app has a vhost defined
elif [[ "$(is_global_vhost_enabled $APP)" == "false" ]] && [[ ! -f "$DOKKU_ROOT/$APP/VHOST" ]]; then
echo true # bind to external ip. no global vhost or global vhost is an ip
else
echo false
fi

View File

@@ -1,168 +1,17 @@
#!/usr/bin/env bash
[[ " nginx:build-config nginx:access-logs nginx:error-logs nginx:disable nginx:enable help nginx:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
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"
validate_nginx () {
set +e
sudo /usr/sbin/nginx -t > /dev/null 2>&1
exit_code=$?
set -e
if [[ "$exit_code" -ne "0" ]]; then
sudo /usr/sbin/nginx -t
exit "$exit_code"
fi
}
restart_nginx () {
case "$DOKKU_DISTRO" in
ubuntu)
sudo /etc/init.d/nginx reload > /dev/null
;;
opensuse)
sudo /sbin/service nginx reload > /dev/null
;;
esac
}
source "$PLUGIN_AVAILABLE_PATH/nginx-vhosts/functions"
case "$1" in
nginx:build-config)
APP="$2"; DOKKU_APP_LISTEN_PORT="$3"; DOKKU_APP_LISTEN_IP="${4}"
verify_app_name "$APP"
VHOST_PATH="$DOKKU_ROOT/$APP/VHOST"
URLS_PATH="$DOKKU_ROOT/$APP/URLS"
WILDCARD_SSL_PATH="$DOKKU_ROOT/tls"
APP_SSL_PATH="$DOKKU_ROOT/$APP/tls"
APP_NGINX_TEMPLATE="$DOKKU_ROOT/$APP/nginx.conf.template"
APP="$2"; DOKKU_APP_LISTEN_PORT="$3"; DOKKU_APP_LISTEN_IP="$4"
if [[ -z "$DOKKU_APP_LISTEN_PORT" ]] && [[ -z "$DOKKU_APP_LISTEN_IP" ]]; then
shopt -s nullglob
for DOKKU_APP_IP_FILE in $DOKKU_ROOT/$APP/IP.web.*; do
DOKKU_APP_PORT_FILE=$(echo $DOKKU_APP_IP_FILE | sed -e "s:IP:PORT:g")
DOKKU_APP_LISTENER_IP=$(< $DOKKU_APP_IP_FILE)
DOKKU_APP_LISTENER_PORT=$(< $DOKKU_APP_PORT_FILE)
nginx_build_config $APP $DOKKU_APP_LISTEN_PORT $DOKKU_APP_LISTEN_IP
DOKKU_APP_LISTENERS+=" "
DOKKU_APP_LISTENERS+="$DOKKU_APP_LISTENER_IP:$DOKKU_APP_LISTENER_PORT"
DOKKU_APP_LISTENERS+=" "
done
shopt -u nullglob
fi
DOKKU_APP_CIDS=($(get_app_container_ids $APP))
docker cp "${DOKKU_APP_CIDS[0]}:/app/nginx.conf.template" "$DOKKU_ROOT/$APP/" 2> /dev/null || true
eval "$(config_export global)"
eval "$(config_export app $APP)"
[[ -f "$APP_NGINX_TEMPLATE" ]] && NGINX_TEMPLATE="$APP_NGINX_TEMPLATE" && NGINX_CUSTOM_TEMPLATE="true" && dokku_log_info1 'Overriding default nginx.conf with detected nginx.conf.template'
if [[ ! -n "$NO_VHOST" ]] && [[ -f "$DOKKU_ROOT/$APP/VHOST" ]]; then
NONSSL_VHOSTS=$(get_app_domains $APP)
if [[ -n "$(is_ssl_enabled $APP)" ]]; then
SSL_HOSTNAME=$(get_ssl_hostnames $APP)
[[ -n "$SSL_HOSTNAME" ]] && SSL_HOSTNAME_REGEX=$(echo "$SSL_HOSTNAME" | xargs | sed 's|\.|\\.|g' | sed 's/\*/\[^\.\]\*/g' | sed 's/ /|/g')
if (egrep -q "^${SSL_HOSTNAME_REGEX}$" $VHOST_PATH); then
SSL_INUSE=true
else
dokku_log_info1 "No matching configured domains for $APP found in SSL certificate. Your app will not be configured with an SSL endpoint"
dokku_log_info1 "Please add appropriate domains via the dokku domains command"
dokku_log_info1 "Configured domains for app:"
for domain in $(echo $NONSSL_VHOSTS| xargs); do
dokku_log_info2 "$domain"
done
dokku_log_info1 "Domains found in SSL certificate:"
for domain in $(echo $SSL_HOSTNAME | xargs); do
dokku_log_info2 "$domain"
done
fi
if [[ "$(is_ssl_enabled $APP)" == "app" ]]; then
SSL_DIRECTIVES=$(cat <<EOF
ssl_certificate $APP_SSL_PATH/server.crt;
ssl_certificate_key $APP_SSL_PATH/server.key;
EOF
)
elif [[ "$(is_ssl_enabled $APP)" == "global" ]]; then
SSL_DIRECTIVES=""
fi
fi
NGINX_CONF=$(mktemp -t "nginx.conf.XXXXXX")
SCHEME="http"
if [[ -n "$SSL_INUSE" ]]; then
SCHEME="https"
[[ -z "$NGINX_TEMPLATE" ]] && NGINX_TEMPLATE="$(dirname $0)/templates/nginx.ssl.conf.template"
SSL_VHOSTS=$(egrep "^${SSL_HOSTNAME_REGEX}$" $VHOST_PATH || true)
NONSSL_VHOSTS=$(egrep -v "^${SSL_HOSTNAME_REGEX}$" $VHOST_PATH || true)
while read line; do
[[ -z "$line" ]] && continue
dokku_log_info1 "Configuring SSL for $line..."
SSL_SERVER_NAME=$line
NOSSL_SERVER_NAME=$line
eval "cat <<< \"$(< $NGINX_TEMPLATE)\" >> $NGINX_CONF"
done <<< "$SSL_VHOSTS"
fi
if [[ -n "$NONSSL_VHOSTS" ]]; then
NOSSL_SERVER_NAME=$(echo $NONSSL_VHOSTS | tr '\n' ' ')
xargs -i echo "-----> Configuring {}..." <<< "$NONSSL_VHOSTS"
if [[ -n "$DOKKU_SSL_TERMINATED" ]] && [[ -z "$NGINX_CUSTOM_TEMPLATE" ]]; then
NGINX_TEMPLATE="$(dirname $0)/templates/nginx.conf.ssl_terminated.template"
elif [[ -z "$NGINX_CUSTOM_TEMPLATE" ]]; then
NGINX_TEMPLATE="$(dirname $0)/templates/nginx.conf.template"
fi
eval "cat <<< \"$(< $NGINX_TEMPLATE)\" >> $NGINX_CONF"
fi
if [[ -n "$DOKKU_APP_LISTEN_PORT" ]] && [[ -n "$DOKKU_APP_LISTEN_IP" ]]; then
echo "upstream $APP { server $DOKKU_APP_LISTEN_IP:$DOKKU_APP_LISTEN_PORT; }" >> $NGINX_CONF
elif [[ -n "$DOKKU_APP_LISTENERS" ]]; then
echo "upstream $APP { " >> $NGINX_CONF
for listener in $DOKKU_APP_LISTENERS; do
echo " server $listener;" >> $NGINX_CONF
done
echo "}" >> $NGINX_CONF
fi
dokku_log_info1 "Creating $SCHEME nginx.conf"
mv $NGINX_CONF "$DOKKU_ROOT/$APP/nginx.conf"
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
echo "# THIS FILE IS GENERATED BY DOKKU - DO NOT EDIT, YOUR CHANGES WILL BE OVERWRITTEN" > $URLS_PATH
xargs -i echo "https://{}" <<< "${SSL_VHOSTS}" >> $URLS_PATH
xargs -i echo "http://{}" <<< "${NONSSL_VHOSTS}" >> $URLS_PATH
else
if [[ -f "$DOKKU_ROOT/$APP/VHOST" ]]; then
dokku_log_info1 "VHOST support disabled, deleting $APP/VHOST"
rm "$DOKKU_ROOT/$APP/VHOST"
fi
if [[ -f "$DOKKU_ROOT/$APP/URLS" ]]; then
dokku_log_info1 "VHOST support disabled, deleting $APP/URLS"
rm "$DOKKU_ROOT/$APP/URLS"
fi
if [[ -f "$DOKKU_ROOT/$APP/nginx.conf" ]]; then
dokku_log_info1 "VHOST support disabled, deleting nginx.conf"
rm "$DOKKU_ROOT/$APP/nginx.conf"
if is_deployed "$APP"; then
dokku_log_info1 "VHOST support disabled, reloading nginx after nginx.conf deletion"
validate_nginx && restart_nginx
fi
fi
fi
;;
;;
nginx:access-logs|nginx:error-logs)
[[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1
@@ -180,18 +29,50 @@ EOF
fi
tail "$NGINX_LOGS_ARGS" "$NGINX_LOGS_PATH"
;;
;;
nginx:disable)
[[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1
verify_app_name "$2"
APP="$2"
if [[ "$(is_app_vhost_enabled $APP)" == "true" ]]; then
config_set --no-restart $APP DOKKU_NO_NGINX=1
disable_app_vhost $APP
elif [[ "$(is_app_nginx_enabled $APP)" == "true" ]]; then
config_set --no-restart $APP DOKKU_NO_NGINX=1
nginx_build_config $APP
else
dokku_log_info1 "nginx is already disable for app ($APP)"
fi
;;
nginx:enable)
[[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1
verify_app_name "$2"
APP="$2"
if [[ "$(is_app_nginx_enabled $APP)" == "true" ]]; then
config_unset --no-restart $APP DOKKU_NO_NGINX
unset DOKKU_NO_NGINX
nginx_build_config $APP
else
dokku_log_info1 "nginx is already enabled for app ($APP)"
fi
;;
help | nginx:help)
cat<<EOF
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:disable <app>, disable nginx for an application (forces container binding to external interface)
nginx:enable <app>, enable nginx for an application
EOF
;;
;;
*)
exit $DOKKU_NOT_IMPLEMENTED_EXIT
;;
;;
esac

293
plugins/nginx-vhosts/functions Executable file
View File

@@ -0,0 +1,293 @@
#!/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"
_ipv4_regex() {
echo "([0-9]{1,3}[\.]){3}[0-9]{1,3}"
}
_ipv6_regex() {
local RE_IPV4="$(_ipv4_regex)"
local RE_IPV6="([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|" # TEST: 1:2:3:4:5:6:7:8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,7}:|" # TEST: 1:: 1:2:3:4:5:6:7::
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|" # TEST: 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|" # TEST: 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|" # TEST: 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|" # TEST: 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|" # TEST: 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8
RE_IPV6="${RE_IPV6}[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|" # TEST: 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8
RE_IPV6="${RE_IPV6}:((:[0-9a-fA-F]{1,4}){1,7}|:)|" # TEST: ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::
RE_IPV6="${RE_IPV6}fe08:(:[0-9a-fA-F]{1,4}){2,2}%[0-9a-zA-Z]{1,}|" # TEST: fe08::7:8%eth0 fe08::7:8%1 (link-local IPv6 addresses with zone index)
RE_IPV6="${RE_IPV6}::(ffff(:0{1,4}){0,1}:){0,1}${RE_IPV4}|" # TEST: ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
RE_IPV6="${RE_IPV6}([0-9a-fA-F]{1,4}:){1,4}:${RE_IPV4}" # TEST: 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33
echo "$RE_IPV6"
}
get_ipv4_regex() {
local RE_IPV4="$(_ipv4_regex)"
# Ensure the ip address continues to the end of the line
# Fixes using a wildcard dns service such as xip.io which allows for *.<ip address>.xip.io
echo "${RE_IPV4}\$"
}
get_ipv6_regex() {
local RE_IPV6="$(_ipv4_regex)"
# Ensure the ip address continues to the end of the line
# Fixes using a wildcard dns service such as xip.io which allows for *.<ip address>.xip.io
echo "${RE_IPV6}\$"
}
is_app_nginx_enabled() {
local APP="$1"
verify_app_name "$APP"
local DOKKU_NO_NGINX=$(config_get $APP DOKKU_NO_NGINX)
if [[ -z "$DOKKU_NO_NGINX" ]]; then
echo true
else
echo false
fi
}
is_global_vhost_enabled() {
local GLOBAL_VHOST_FILE="$DOKKU_ROOT/VHOST"
local GLOBAL_VHOST_ENABLED=true
[[ -f "$GLOBAL_VHOST_FILE" ]] && local GLOBAL_VHOST=$(< "$GLOBAL_VHOST_FILE")
# Ensure the ip address continues to the end of the line
# Fixes using a wildcard dns service such as xip.io which allows for *.<ip address>.xip.io
local RE_IPV4="$(get_ipv4_regex)"
local RE_IPV6="$(get_ipv6_regex)"
if [[ -z "$GLOBAL_VHOST" ]] || [[ "$GLOBAL_VHOST" =~ $RE_IPV4 ]] || [[ "$GLOBAL_VHOST" =~ $RE_IPV6 ]]; then
local GLOBAL_VHOST_ENABLED=false
fi
echo $GLOBAL_VHOST_ENABLED
}
is_app_vhost_enabled() {
local APP=$1; local APP_VHOST_FILE="$DOKKU_ROOT/$APP/VHOST"
verify_app_name $APP
local NO_VHOST=$(config_get $APP NO_VHOST)
local APP_VHOST_ENABLED=true
if [[ "$NO_VHOST" == "1" ]]; then
local APP_VHOST_ENABLED=false
elif [[ -f "$DOKKU_ROOT/$APP/nginx.conf" ]] && [[ ! -f "$APP_VHOST_FILE" ]] && [[ "$NO_VHOST" != "0" ]]; then
local APP_VHOST_ENABLED=false
fi
echo $APP_VHOST_ENABLED
}
disable_app_vhost() {
local APP=$1; local APP_VHOST_FILE="$DOKKU_ROOT/$APP/VHOST"
verify_app_name $APP
if [[ -f "$DOKKU_ROOT/$APP/VHOST" ]]; then
dokku_log_info1 "VHOST support disabled, deleting $APP/VHOST"
rm "$DOKKU_ROOT/$APP/VHOST"
fi
if [[ -f "$DOKKU_ROOT/$APP/URLS" ]]; then
dokku_log_info1 "VHOST support disabled, deleting $APP/URLS"
rm "$DOKKU_ROOT/$APP/URLS"
fi
[[ "$2" == "--no-restart" ]] && local CONFIG_SET_ARGS=$2
config_set $CONFIG_SET_ARGS $APP NO_VHOST=1
}
validate_nginx() {
set +e
sudo /usr/sbin/nginx -t > /dev/null 2>&1
exit_code=$?
set -e
if [[ "$exit_code" -ne "0" ]]; then
sudo /usr/sbin/nginx -t
exit "$exit_code"
fi
}
restart_nginx() {
case "$DOKKU_DISTRO" in
ubuntu)
sudo /etc/init.d/nginx reload > /dev/null
;;
opensuse)
sudo /sbin/service nginx reload > /dev/null
;;
esac
}
nginx_build_config() {
local APP="$1"; local DOKKU_APP_LISTEN_PORT="$2"; local DOKKU_APP_LISTEN_IP="$3"
verify_app_name "$APP"
VHOST_PATH="$DOKKU_ROOT/$APP/VHOST"
URLS_PATH="$DOKKU_ROOT/$APP/URLS"
WILDCARD_SSL_PATH="$DOKKU_ROOT/tls"
APP_SSL_PATH="$DOKKU_ROOT/$APP/tls"
APP_NGINX_TEMPLATE="$DOKKU_ROOT/$APP/nginx.conf.template"
eval "$(config_export global)"
eval "$(config_export app $APP)"
if [[ ! -n "$DOKKU_NO_NGINX" ]]; then
if [[ -z "$DOKKU_APP_LISTEN_PORT" ]] && [[ -z "$DOKKU_APP_LISTEN_IP" ]]; then
shopt -s nullglob
for DOKKU_APP_IP_FILE in $DOKKU_ROOT/$APP/IP.web.*; do
DOKKU_APP_PORT_FILE=$(echo $DOKKU_APP_IP_FILE | sed -e "s:IP:PORT:g")
DOKKU_APP_LISTENER_IP=$(< $DOKKU_APP_IP_FILE)
DOKKU_APP_LISTENER_PORT=$(< $DOKKU_APP_PORT_FILE)
DOKKU_APP_LISTENERS+=" "
DOKKU_APP_LISTENERS+="$DOKKU_APP_LISTENER_IP:$DOKKU_APP_LISTENER_PORT"
DOKKU_APP_LISTENERS+=" "
done
shopt -u nullglob
fi
DOKKU_APP_CIDS=($(get_app_container_ids $APP))
docker cp "${DOKKU_APP_CIDS[0]}:/app/nginx.conf.template" "$DOKKU_ROOT/$APP/" 2> /dev/null || true
[[ -f "$APP_NGINX_TEMPLATE" ]] && NGINX_TEMPLATE="$APP_NGINX_TEMPLATE" && NGINX_CUSTOM_TEMPLATE="true" && dokku_log_info1 'Overriding default nginx.conf with detected nginx.conf.template'
NGINX_CONF=$(mktemp -t "nginx.conf.XXXXXX")
SCHEME="http"
# if the app has is not vhost enabled then, let's make sure we're cleaned up
[[ "$(is_app_vhost_enabled $APP)" == "false" ]] && disable_app_vhost $APP --no-restart
if [[ -z "$DOKKU_NGINX_PORT" ]]; then
if [[ "$(is_app_vhost_enabled $APP)" == "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}
else
NGINX_PORT=$DOKKU_NGINX_PORT
fi
NONSSL_VHOSTS=$(get_app_domains $APP)
if [[ -n "$(is_ssl_enabled $APP)" ]]; then
SSL_HOSTNAME=$(get_ssl_hostnames $APP)
SSL_INUSE=true
[[ -n "$SSL_HOSTNAME" ]] && 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:"
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
if [[ "$(is_ssl_enabled $APP)" == "app" ]]; then
SSL_DIRECTIVES=$(cat <<EOF
ssl_certificate $APP_SSL_PATH/server.crt;
ssl_certificate_key $APP_SSL_PATH/server.key;
EOF
)
elif [[ "$(is_ssl_enabled $APP)" == "global" ]]; then
SSL_DIRECTIVES=""
fi
fi
if [[ -n "$SSL_INUSE" ]]; then
SCHEME="https"
[[ -z "$NGINX_TEMPLATE" ]] && NGINX_TEMPLATE="$PLUGIN_AVAILABLE_PATH/nginx-vhosts/templates/nginx.ssl.conf.template"
if [[ "$(is_app_vhost_enabled $APP)" == "true" ]]; then
SSL_VHOSTS=$(egrep "^${SSL_HOSTNAME_REGEX}$" $VHOST_PATH || true)
else
SSL_VHOSTS=$(< $DOKKU_ROOT/HOSTNAME)
fi
NONSSL_VHOSTS=$(egrep -v "^${SSL_HOSTNAME_REGEX}$" $VHOST_PATH 2> /dev/null || true)
if [[ -z "$DOKKU_NGINX_SSL_PORT" ]]; then
if [[ "$(is_app_vhost_enabled $APP)" == "false" ]]; then
dokku_log_info1 "no nginx ssl port set. setting to random open high port"
local NGINX_SSL_PORT=$(get_available_port)
else
NGINX_SSL_PORT=443
fi
config_set --no-restart $APP DOKKU_NGINX_SSL_PORT=${NGINX_SSL_PORT}
else
local NGINX_SSL_PORT=$DOKKU_NGINX_SSL_PORT
fi
while read line; do
[[ -z "$line" ]] && continue
dokku_log_info1 "Configuring SSL for $line..."
SSL_SERVER_NAME=$line
NOSSL_SERVER_NAME=$line
eval "cat <<< \"$(< $NGINX_TEMPLATE)\" >> $NGINX_CONF"
done <<< "$SSL_VHOSTS"
fi
if [[ -n "$DOKKU_SSL_TERMINATED" ]] && [[ -z "$NGINX_CUSTOM_TEMPLATE" ]]; then
NGINX_TEMPLATE="$PLUGIN_AVAILABLE_PATH/nginx-vhosts/templates/nginx.conf.ssl_terminated.template"
elif [[ -z "$NGINX_CUSTOM_TEMPLATE" ]]; then
NGINX_TEMPLATE="$PLUGIN_AVAILABLE_PATH/nginx-vhosts/templates/nginx.conf.template"
fi
if [[ -n "$NONSSL_VHOSTS" ]]; then
NOSSL_SERVER_NAME=$(echo $NONSSL_VHOSTS | tr '\n' ' ')
xargs -i echo "-----> Configuring {}..." <<< "$NONSSL_VHOSTS"
fi
eval "cat <<< \"$(< $NGINX_TEMPLATE)\" >> $NGINX_CONF"
if [[ "$(is_app_vhost_enabled $APP)" == "false" ]] || ([[ -z "$NONSSL_VHOSTS" ]] && [[ -z "$SSL_VHOSTS" ]]); then
sed --in-place -n -e '/^.*server_name.*$/!p' $NGINX_CONF
fi
if [[ -n "$DOKKU_APP_LISTEN_PORT" ]] && [[ -n "$DOKKU_APP_LISTEN_IP" ]]; then
echo "upstream $APP { server $DOKKU_APP_LISTEN_IP:$DOKKU_APP_LISTEN_PORT; }" >> $NGINX_CONF
elif [[ -n "$DOKKU_APP_LISTENERS" ]]; then
echo "upstream $APP { " >> $NGINX_CONF
for listener in $DOKKU_APP_LISTENERS; do
echo " server $listener;" >> $NGINX_CONF
done
echo "}" >> $NGINX_CONF
fi
dokku_log_info1 "Creating $SCHEME nginx.conf"
mv $NGINX_CONF "$DOKKU_ROOT/$APP/nginx.conf"
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 [[ "$(is_app_vhost_enabled $APP)" == "true" ]]; then
echo "# THIS FILE IS GENERATED BY DOKKU - DO NOT EDIT, YOUR CHANGES WILL BE OVERWRITTEN" > $URLS_PATH
xargs -i echo "https://{}" <<< "${SSL_VHOSTS}" >> $URLS_PATH
xargs -i echo "http://{}" <<< "${NONSSL_VHOSTS}" >> $URLS_PATH
fi
else
# note because this clause is long. if $DOKKU_NO_NGINX 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
}

View File

@@ -1,17 +1,15 @@
#!/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"
APP="$1"
if [[ -f "$DOKKU_ROOT/$APP/IP.web.1" ]] && [[ -f "$DOKKU_ROOT/$APP/PORT.web.1" ]]; then
NO_VHOST=$(config_get $APP NO_VHOST || true)
if [[ -n "$NO_VHOST" ]]; then
dokku_log_info1 "NO_VHOST config detected"
if [[ "$(is_app_vhost_enabled $APP)" == "false" ]]; then
dokku_log_info1 "VHOST support disabled. Skipping domains setup"
elif [[ ! -f "$DOKKU_ROOT/$APP/VHOST" ]]; then
dokku domains:setup $APP
fi
dokku nginx:build-config $APP
nginx_build_config $APP
fi

View File

@@ -1,7 +1,8 @@
#!/usr/bin/env bash
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_AVAILABLE_PATH/nginx-vhosts/functions"
APP="$1"
dokku nginx:build-config $APP
nginx_build_config $APP

View File

@@ -1,8 +1,8 @@
# Nginx configuration when running behind a load balancer that terminates SSL
# connections (e.g. AWS ELB)
server {
listen [::]:80;
listen 80;
listen [::]:$NGINX_PORT;
listen $NGINX_PORT;
server_name $NOSSL_SERVER_NAME;
location / {
proxy_pass http://$APP;

View File

@@ -1,6 +1,6 @@
server {
listen [::]:80;
listen 80;
listen [::]:$NGINX_PORT;
listen $NGINX_PORT;
server_name $NOSSL_SERVER_NAME;
access_log /var/log/nginx/${APP}-access.log;
error_log /var/log/nginx/${APP}-error.log;

View File

@@ -1,22 +1,22 @@
server {
listen [::]:80;
listen 80;
listen [::]:$NGINX_PORT;
listen $NGINX_PORT;
server_name $NOSSL_SERVER_NAME;
access_log /var/log/nginx/${APP}-access.log;
error_log /var/log/nginx/${APP}-error.log;
return 301 https://\$host\$request_uri;
return 301 https://\$host:$NGINX_SSL_PORT\$request_uri;
}
server {
listen [::]:443 ssl spdy;
listen 443 ssl spdy;
listen [::]:$NGINX_SSL_PORT ssl spdy;
listen $NGINX_SSL_PORT ssl spdy;
server_name $SSL_SERVER_NAME;
access_log /var/log/nginx/${APP}-access.log;
error_log /var/log/nginx/${APP}-error.log;
$SSL_DIRECTIVES
keepalive_timeout 70;
add_header Alternate-Protocol 443:npn-spdy/2;
add_header Alternate-Protocol $NGINX_SSL_PORT:npn-spdy/2;
location / {
gzip on;

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env bash
[[ " plugin plugin:install plugin:install-dependencies plugin:update plugin:disable plugin:enable plugin:uninstall help plugin:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_AVAILABLE_PATH/plugin/functions"

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env bash
[[ " ps ps:start ps:stop ps:rebuild ps:rebuildall ps:restart ps:restartall ps:scale help ps:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_AVAILABLE_PATH/ps/functions"

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env bash
[[ " shell help shell:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
case "$1" in

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env bash
[[ " tags tags:create tags:deploy tags:destroy help tags:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_AVAILABLE_PATH/tags/functions"

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env bash
[[ " tar-from tar:from tar-in tar:in tar-build tar-build-locked help tar:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
@@ -57,7 +58,7 @@ case "$1" in
fi
;;
help)
help | tar:help)
cat && cat<<EOF
tar:in <app>, Reads an tarball containing the app from stdin
tar:from <app> <url>, Loads an app tarball from url.

View File

@@ -142,16 +142,6 @@ check_urls() {
check_urls http://www.test.app.dokku.me
}
@test "(core) dockerfile port exposure" {
deploy_app dockerfile
run bash -c "grep -A1 upstream $DOKKU_ROOT/$TEST_APP/nginx.conf | grep -q 3000"
echo "output: "$output
echo "status: "$status
assert_success
check_urls http://${TEST_APP}.dokku.me
}
@test "(core) port exposure (xip.io style hostnames)" {
echo "127.0.0.1.xip.io" > "$DOKKU_ROOT/VHOST"
deploy_app
@@ -164,6 +154,16 @@ check_urls() {
check_urls http://my-cool-guy-test-app.127.0.0.1.xip.io
}
@test "(core) dockerfile port exposure" {
deploy_app dockerfile
run bash -c "grep -A1 upstream $DOKKU_ROOT/$TEST_APP/nginx.conf | grep -q 3000"
echo "output: "$output
echo "status: "$status
assert_success
check_urls http://${TEST_APP}.dokku.me
}
@test "(core) port exposure (dockerfile raw port)" {
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
cat<<EOF > $DOCKERFILE

View File

@@ -18,7 +18,7 @@ teardown() {
assert_ssl_domain() {
local domain=$1
assert_app_domain "${domain}"
assert_http_redirect "http://${domain}" "https://${domain}/"
assert_http_redirect "http://${domain}" "https://${domain}:443/"
assert_http_success "https://${domain}"
}

View File

@@ -175,20 +175,20 @@ custom_ssl_nginx_template() {
[[ -z "$APP" ]] && APP="$TEST_APP"
cat<<EOF > $DOKKU_ROOT/$APP/nginx.conf.template
server {
listen [::]:80;
listen 80;
listen [::]:\$NGINX_PORT;
listen \$NGINX_PORT;
server_name \$NOSSL_SERVER_NAME;
return 301 https://\$SSL_SERVER_NAME\\\$request_uri;
return 301 https://\\\$host:\$NGINX_SSL_PORT\\\$request_uri;
}
server {
listen [::]:443 ssl spdy;
listen 443 ssl spdy;
listen [::]:\$NGINX_SSL_PORT ssl spdy;
listen \$NGINX_SSL_PORT ssl spdy;
server_name \$SSL_SERVER_NAME;
\$SSL_DIRECTIVES
keepalive_timeout 70;
add_header Alternate-Protocol 443:npn-spdy/2;
add_header Alternate-Protocol \$NGINX_SSL_PORT:npn-spdy/2;
location / {
proxy_pass http://\$APP;
proxy_http_version 1.1;
@@ -210,8 +210,8 @@ custom_nginx_template() {
[[ -z "$APP" ]] && APP="$TEST_APP"
cat<<EOF > $DOKKU_ROOT/$APP/nginx.conf.template
server {
listen [::]:80;
listen 80;
listen [::]:\$NGINX_PORT;
listen \$NGINX_PORT;
server_name \$NOSSL_SERVER_NAME;
location / {