From 0d4560177a34a99d9561b2274048defbde808f64 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Fri, 15 Jul 2016 02:51:31 -0400 Subject: [PATCH 1/5] Properly remap http port 80 mappings to https 443 when adding an ssl certificate Rather than removing all port mappings, we simply remap port 80 mappings to 443. The previous behavior would remove custom port mappings for all applications and reset them on any certificate change, preventing automation from plugins such as letsencrypt. While this behavior doesn't matter for buildpack deploys - which only expose a single port on container port 5000 - Dockerfile deploys would frequently be affected by such a change, requiring a remapping of all custom ports. This commit also standardizes on the method used to source the proxy functions --- plugins/certs/subcommands/add | 3 -- plugins/common/functions | 2 +- plugins/nginx-vhosts/post-certs-update | 7 ++- plugins/nginx-vhosts/proxy-disable | 2 +- plugins/nginx-vhosts/proxy-enable | 2 +- plugins/proxy/functions | 60 ++++++++++++++++++++++++++ plugins/proxy/subcommands/ports | 2 +- plugins/proxy/subcommands/ports-add | 11 +---- plugins/proxy/subcommands/ports-remove | 27 +++--------- 9 files changed, 77 insertions(+), 39 deletions(-) diff --git a/plugins/certs/subcommands/add b/plugins/certs/subcommands/add index 8a539233b..07601378c 100755 --- a/plugins/certs/subcommands/add +++ b/plugins/certs/subcommands/add @@ -38,7 +38,6 @@ certs_set() { if is_file_import "$CRT_FILE" "$KEY_FILE"; then # importing from file true - elif is_tar_import; then local CERTS_SET_TMP_WORK_DIR=$(mktemp -d "/tmp/dokku_certs_set.XXXX") pushd "$CERTS_SET_TMP_WORK_DIR" &> /dev/null @@ -64,10 +63,8 @@ certs_set() { else local KEY_FILE=$KEY_FILE_SEARCH fi - else dokku_log_fail "Tar archive containing server.crt and server.key expected on stdin" - fi mkdir -p "$APP_SSL_PATH" diff --git a/plugins/common/functions b/plugins/common/functions index 459f7c236..6d3a339eb 100755 --- a/plugins/common/functions +++ b/plugins/common/functions @@ -524,7 +524,7 @@ dokku_deploy_cmd() { local cmd="deploy" source "$PLUGIN_AVAILABLE_PATH/checks/functions" source "$PLUGIN_AVAILABLE_PATH/config/functions" - source "$PLUGIN_CORE_AVAILABLE_PATH/proxy/functions" + source "$PLUGIN_AVAILABLE_PATH/proxy/functions" [[ -z $1 ]] && dokku_log_fail "Please specify an app to deploy" local APP="$1"; local IMAGE_TAG="$2"; local IMAGE=$(get_deploying_app_image_name "$APP" "$IMAGE_TAG") diff --git a/plugins/nginx-vhosts/post-certs-update b/plugins/nginx-vhosts/post-certs-update index 22756ea18..3a391d7b5 100755 --- a/plugins/nginx-vhosts/post-certs-update +++ b/plugins/nginx-vhosts/post-certs-update @@ -20,7 +20,12 @@ nginx_post_certs_update() { config_unset --no-restart "$APP" DOKKU_NGINX_SSL_PORT fi if [[ "$DOKKU_PROXY_PORT_MAP" == *http:80:* ]]; then - config_unset --no-restart "$APP" DOKKU_PROXY_PORT_MAP + # shellcheck disable=SC2046 + remove_proxy_ports "$APP" $(filter_app_proxy_ports "$APP" "https" "443") + # shellcheck disable=SC2046 + for port_map in $(filter_app_proxy_ports "$APP" "http" "80"); do + add_proxy_ports "$APP" "https:443:$(cut -d ':' -f3 <<< "$port_map")" + done fi fi } diff --git a/plugins/nginx-vhosts/proxy-disable b/plugins/nginx-vhosts/proxy-disable index 512863078..681c860c2 100755 --- a/plugins/nginx-vhosts/proxy-disable +++ b/plugins/nginx-vhosts/proxy-disable @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" -source "$PLUGIN_CORE_AVAILABLE_PATH/proxy/functions" +source "$PLUGIN_AVAILABLE_PATH/proxy/functions" source "$PLUGIN_CORE_AVAILABLE_PATH/ps/functions" nginx_proxy_disable() { diff --git a/plugins/nginx-vhosts/proxy-enable b/plugins/nginx-vhosts/proxy-enable index a4fe26edd..366f94ed8 100755 --- a/plugins/nginx-vhosts/proxy-enable +++ b/plugins/nginx-vhosts/proxy-enable @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" -source "$PLUGIN_CORE_AVAILABLE_PATH/proxy/functions" +source "$PLUGIN_AVAILABLE_PATH/proxy/functions" source "$PLUGIN_CORE_AVAILABLE_PATH/ps/functions" nginx_proxy_enable() { diff --git a/plugins/proxy/functions b/plugins/proxy/functions index 010136719..d7d3b1a2f 100755 --- a/plugins/proxy/functions +++ b/plugins/proxy/functions @@ -40,3 +40,63 @@ list_app_proxy_ports() { dokku_log_fail "No port mappings configured for app ($APP)" fi } + +filter_app_proxy_ports() { + declare desc="list proxy port mappings for an app that start with a particular scheme and a host port" + local APP="$1"; verify_app_name "$APP" + local SCHEME="$2" HOST_PORT="$3" + local PROXY_PORT_MAP="$(config_get "$APP" DOKKU_PROXY_PORT_MAP || true)" + + if [[ -n "$PROXY_PORT_MAP" ]]; then + local port_map + for port_map in $PROXY_PORT_MAP; do + local scheme="$(cut -d ':' -f1 <<< "$port_map")" + local host_port="$(cut -d ':' -f2 <<< "$port_map")" + if [[ "$scheme" == "$SCHEME" ]] && [[ "$host_port" == "$HOST_PORT" ]]; then + echo "$port_map" + fi + done + fi +} + +add_proxy_ports() { + declare desc="add proxy port mappings from an app" + local APP="$1" + local PROXY_PORT_MAP="$(config_get "$APP" DOKKU_PROXY_PORT_MAP || true)" + shift 1 + + local INPUT_PORTS="$*" + if [[ -n "$INPUT_PORTS" ]]; then + PROXY_PORT_MAP="$(merge_dedupe_list "$PROXY_PORT_MAP $INPUT_PORTS" " ")" + config_set --no-restart "$APP" DOKKU_PROXY_PORT_MAP="$PROXY_PORT_MAP" + else + dokku proxy:help + dokku_log_fail "No port mapping specified. Exiting..." + fi +} + +remove_proxy_ports() { + declare desc="remove specific proxy port mappings from an app" + local APP="$1" + local PROXY_PORT_MAP="$(config_get "$APP" DOKKU_PROXY_PORT_MAP || true)" + local RE_PORT='^[0-9]+$' + shift 1 + + local INPUT_PORTS="$*" + local port + PROXY_PORT_MAP=" $PROXY_PORT_MAP " + for port in $INPUT_PORTS; do + if [[ "$port" =~ $RE_PORT ]]; then + PROXY_PORT_MAP="$(sed -r "s/[[:alnum:]]+:$port:[[:alnum:]]+//g" <<< "$PROXY_PORT_MAP")" + else + PROXY_PORT_MAP="$(sed -r "s/ $port / /g" <<< "$PROXY_PORT_MAP")" + fi + done + PROXY_PORT_MAP="$(echo "$PROXY_PORT_MAP" | xargs)" + PROXY_PORT_MAP="$(merge_dedupe_list "$PROXY_PORT_MAP" " ")" + if [[ -n "$PROXY_PORT_MAP" ]]; then + config_set --no-restart "$APP" DOKKU_PROXY_PORT_MAP="$PROXY_PORT_MAP" + else + config_unset --no-restart "$APP" DOKKU_PROXY_PORT_MAP + fi +} diff --git a/plugins/proxy/subcommands/ports b/plugins/proxy/subcommands/ports index 47a1a6cab..912f4b99f 100755 --- a/plugins/proxy/subcommands/ports +++ b/plugins/proxy/subcommands/ports @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" -source "$PLUGIN_CORE_AVAILABLE_PATH/proxy/functions" +source "$PLUGIN_AVAILABLE_PATH/proxy/functions" source "$PLUGIN_AVAILABLE_PATH/config/functions" proxy_ports_cmd() { diff --git a/plugins/proxy/subcommands/ports-add b/plugins/proxy/subcommands/ports-add index 911da22b2..ce7f8c226 100755 --- a/plugins/proxy/subcommands/ports-add +++ b/plugins/proxy/subcommands/ports-add @@ -2,22 +2,15 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" source "$PLUGIN_AVAILABLE_PATH/config/functions" +source "$PLUGIN_AVAILABLE_PATH/proxy/functions" proxy_ports_add_cmd() { declare desc="add proxy port mappings from an app" local cmd="proxy:add" local APP="$2"; verify_app_name "$APP" - local PROXY_PORT_MAP="$(config_get "$APP" DOKKU_PROXY_PORT_MAP || true)" shift 2 - local INPUT_PORTS="$*" - if [[ -n "$INPUT_PORTS" ]]; then - PROXY_PORT_MAP="$(merge_dedupe_list "$PROXY_PORT_MAP $INPUT_PORTS" " ")" - config_set --no-restart "$APP" DOKKU_PROXY_PORT_MAP="$PROXY_PORT_MAP" - else - dokku proxy:help - dokku_log_fail "No port mapping specified. Exiting..." - fi + add_proxy_ports "$APP" "$@" plugn trigger post-proxy-ports-update "$APP" "add" } diff --git a/plugins/proxy/subcommands/ports-remove b/plugins/proxy/subcommands/ports-remove index 0d73df5ca..267c86654 100755 --- a/plugins/proxy/subcommands/ports-remove +++ b/plugins/proxy/subcommands/ports-remove @@ -1,41 +1,24 @@ #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" -source "$PLUGIN_CORE_AVAILABLE_PATH/proxy/functions" +source "$PLUGIN_AVAILABLE_PATH/proxy/functions" source "$PLUGIN_AVAILABLE_PATH/config/functions" proxy_ports_remove_cmd() { declare desc="remove specific proxy port mappings from an app" local cmd="proxy:ports-remove" local APP="$2"; verify_app_name "$APP" - local PROXY_PORT_MAP="$(config_get "$APP" DOKKU_PROXY_PORT_MAP || true)" - local RE_PORT='^[0-9]+$' shift 2 local INPUT_PORTS="$*" - if [[ -n "$INPUT_PORTS" ]]; then - local port - PROXY_PORT_MAP=" $PROXY_PORT_MAP " - for port in $INPUT_PORTS; do - if [[ "$port" =~ $RE_PORT ]]; then - PROXY_PORT_MAP="$(sed -r "s/[[:alnum:]]+:$port:[[:alnum:]]+//g" <<< "$PROXY_PORT_MAP")" - else - PROXY_PORT_MAP="$(sed -r "s/ $port / /g" <<< "$PROXY_PORT_MAP")" - fi - done - PROXY_PORT_MAP="$(echo "$PROXY_PORT_MAP" | xargs)" - PROXY_PORT_MAP="$(merge_dedupe_list "$PROXY_PORT_MAP" " ")" - if [[ -n "$PROXY_PORT_MAP" ]]; then - config_set --no-restart "$APP" DOKKU_PROXY_PORT_MAP="$PROXY_PORT_MAP" - else - config_unset --no-restart "$APP" DOKKU_PROXY_PORT_MAP - fi - plugn trigger post-proxy-ports-update "$APP" "remove" - else + if [[ -z "$INPUT_PORTS" ]]; then dokku_log_warn "No port mapping specified. Please supply a valid configured host port" list_app_proxy_ports "$APP" dokku_log_fail "exiting..." fi + + remove_proxy_ports "$APP" "$@" + plugn trigger post-proxy-ports-update "$APP" "remove" } proxy_ports_remove_cmd "$@" From de550094dad8c2b429857dfdd48d563770d13504 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Sun, 17 Jul 2016 18:16:45 -0400 Subject: [PATCH 2/5] Standardize parenthesis usage for is_deployed --- plugins/nginx-vhosts/functions | 6 +++--- plugins/ps/functions | 2 +- plugins/ps/subcommands/rebuildall | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/nginx-vhosts/functions b/plugins/nginx-vhosts/functions index 11dba3d0a..6e4a0769b 100755 --- a/plugins/nginx-vhosts/functions +++ b/plugins/nginx-vhosts/functions @@ -267,7 +267,7 @@ nginx_build_config() { # echo "sigil ${SIGIL_PARAMS[@]}" sigil "${SIGIL_PARAMS[@]}" | cat -s > "$NGINX_CONF" - if is_deployed "$APP"; then + if (is_deployed "$APP"); then dokku_log_info1 "Creating $SCHEME nginx.conf" mv "$NGINX_CONF" "$DOKKU_ROOT/$APP/nginx.conf" else @@ -275,7 +275,7 @@ nginx_build_config() { rm -f "$NGINX_CONF" fi - if is_deployed "$APP"; then + 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" @@ -294,7 +294,7 @@ nginx_build_config() { dokku_log_info1 "deleting nginx.conf" rm "$DOKKU_ROOT/$APP/nginx.conf" - if is_deployed "$APP"; then + if (is_deployed "$APP"); then dokku_log_info1 "reloading nginx after nginx.conf deletion" validate_nginx && restart_nginx fi diff --git a/plugins/ps/functions b/plugins/ps/functions index 5a9949431..0e3bda1ee 100755 --- a/plugins/ps/functions +++ b/plugins/ps/functions @@ -135,7 +135,7 @@ ps_restart() { local APP="$1"; verify_app_name "$APP" local IMAGE_TAG=$(get_running_image_tag "$APP") - if is_deployed "$APP"; then + if (is_deployed "$APP"); then release_and_deploy "$APP" "$IMAGE_TAG" else echo "App $APP has not been deployed" diff --git a/plugins/ps/subcommands/rebuildall b/plugins/ps/subcommands/rebuildall index 7a903b3f0..06eff9311 100755 --- a/plugins/ps/subcommands/rebuildall +++ b/plugins/ps/subcommands/rebuildall @@ -7,7 +7,7 @@ ps_rebuildall_cmd() { declare desc="rebuilds all deployed apps via command line" local cmd="ps:rebuildall" for app in $(dokku_apps); do - is_deployed "$app" && ps_rebuild "$app" + (is_deployed "$app") && ps_rebuild "$app" done } From 372802f83420107dd8e1da026d6a094a78a89c2c Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Fri, 29 Jul 2016 01:52:19 -0400 Subject: [PATCH 3/5] Only remove https ports when removing a certificate --- plugins/nginx-vhosts/post-certs-remove | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/nginx-vhosts/post-certs-remove b/plugins/nginx-vhosts/post-certs-remove index fded1290a..ff6518d33 100755 --- a/plugins/nginx-vhosts/post-certs-remove +++ b/plugins/nginx-vhosts/post-certs-remove @@ -9,7 +9,10 @@ nginx_post_certs_remove() { local trigger="nginx_post_certs_remove" local APP="$1" if [[ "$(get_app_proxy_type "$APP")" == "nginx" ]]; then - config_unset --no-restart "$APP" DOKKU_NGINX_PORT DOKKU_NGINX_SSL_PORT DOKKU_PROXY_PORT_MAP + config_unset --no-restart "$APP" DOKKU_NGINX_SSL_PORT + + # shellcheck disable=SC2046 + remove_proxy_ports "$APP" $(filter_app_proxy_ports "$APP" "https" "443") fi } From b3b1f12e6939c97fc8d9c6a6fe0b6ec485f4f213 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Fri, 29 Jul 2016 02:32:24 -0400 Subject: [PATCH 4/5] Clarify documentation surrounding port management for domain and ssl configuration When configuring domains/ssl certificates, the port mappings for an application may be automatically set. This can cause issues for applications which will use non-standard ports - ie. for Dockerfile deploys. [ci skip] --- docs/configuration/domains.md | 2 ++ docs/configuration/ssl.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/configuration/domains.md b/docs/configuration/domains.md index 9c83b64c4..de066357c 100644 --- a/docs/configuration/domains.md +++ b/docs/configuration/domains.md @@ -12,6 +12,8 @@ domains:remove DOMAIN # Remove a domain from app domains:set-global # Set global domain name ``` +> Adding a domain before deploying an application will result in port mappings being set. This may cause issues for applications that use non-standard ports, as those will not be automatically detected. Please refer to the [proxy documentation](/dokku/advanced-usage/proxy-management/) for information as to how to reconfigure the mappings. + ## Customizing hostnames Applications typically have the following structure for their hostname: diff --git a/docs/configuration/ssl.md b/docs/configuration/ssl.md index 9a5cfc18c..fc354f92d 100644 --- a/docs/configuration/ssl.md +++ b/docs/configuration/ssl.md @@ -17,6 +17,8 @@ certs:update CRT KEY # Update an SSL Endpoint on an app. Can dokku nginx:import-ssl < certs.tar ``` +> Adding an ssl certificate before deploying an application will result in port mappings being updated. This may cause issues for applications that use non-standard ports, as those may not be automatically detected. Please refer to the [proxy documentation](/dokku/advanced-usage/proxy-management/) for information as to how to reconfigure the mappings. + ## Per-application certificate management Dokku provides built-in support for managing SSL certificates on a per-application basis. SSL is managed via nginx outside of application containers, and as such can be updated on-the-fly without rebuilding containers. At this time, applications only support a single SSL certificate at a time. To support multiple domains for a single application, wildcard certificate usage is encouraged. From 9dfeb16329b9889b057fe0d02e4e50c356f72cc0 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Fri, 29 Jul 2016 02:32:41 -0400 Subject: [PATCH 5/5] Minor doc changes [ci skip] --- docs/configuration/ssl.md | 3 --- docs/template.html | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/configuration/ssl.md b/docs/configuration/ssl.md index fc354f92d..888be0688 100644 --- a/docs/configuration/ssl.md +++ b/docs/configuration/ssl.md @@ -98,9 +98,6 @@ server { access_log /var/log/nginx/{{ .APP }}-access.log; error_log /var/log/nginx/{{ .APP }}-error.log; - # set a custom header for requests - add_header X-Served-By www-ec2-01; - location / { proxy_pass http://{{ .APP }}; proxy_http_version 1.1; diff --git a/docs/template.html b/docs/template.html index 8af9b7ba7..1a314e772 100644 --- a/docs/template.html +++ b/docs/template.html @@ -160,7 +160,7 @@ Docker Container Options Event Logs Persistent Storage - Proxy Management + Proxy and Port Management Repository Management Community Contributions