diff --git a/dokku b/dokku index c6a1cb769..9680a8588 100755 --- a/dokku +++ b/dokku @@ -37,7 +37,7 @@ case "$1" in echo "-----> Deploying $APP ..." dokku deploy $APP echo "=====> Application deployed:" - echo " $(dokku url $APP)" + echo "$(dokku urls $APP | sed "s/^/ /")" echo ;; diff --git a/plugins/00_dokku-standard/commands b/plugins/00_dokku-standard/commands index eb32e8037..aaf493ddd 100755 --- a/plugins/00_dokku-standard/commands +++ b/plugins/00_dokku-standard/commands @@ -52,13 +52,26 @@ case "$1" in docker run -i -t $DOCKER_ARGS $IMAGE /exec "$@" ;; - url) + url | urls) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 [[ ! -d "$DOKKU_ROOT/$2" ]] && echo "App $2 does not exist" && exit 1 - APP="$2"; + APP="$2"; SCHEME="http"; SSL="$DOKKU_ROOT/$APP/tls" - if [[ -f "$DOKKU_ROOT/$APP/URL" ]]; then - echo $(< "$DOKKU_ROOT/$APP/URL") + if [[ -e "$SSL/server.crt" ]] && [[ -e "$SSL/server.key" ]]; then + SCHEME="https" + fi + + if [[ -f "$DOKKU_ROOT/$APP/VHOST" ]]; then + case "$1" in + url) + echo "$SCHEME://$(head -n1 "$DOKKU_ROOT/$APP/VHOST")" + ;; + urls) + for vhost in $(< "$DOKKU_ROOT/$APP/VHOST"); do + echo "$SCHEME://$vhost" + done + ;; + esac fi ;; @@ -73,7 +86,8 @@ case "$1" in cat && cat< [-t] Show the last logs for an application (-t follows) run Run a command in the environment of an application - url Show the URL for an application + url Show the first URL for an application (compatibility) + urls Show all URLs for an application version Print dokku's version EOF ;; diff --git a/plugins/domains/backup-export b/plugins/domains/backup-export new file mode 100755 index 000000000..e131dfbf9 --- /dev/null +++ b/plugins/domains/backup-export @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x + +shopt -s nullglob +VERSION="$1" +BASE_DIR="$2" + +cat; for i in $BASE_DIR/*/VHOST; do echo $i; done +cat; for i in $BASE_DIR/*/nginx.conf.template; do echo $i; done diff --git a/plugins/domains/backup-import b/plugins/domains/backup-import new file mode 100755 index 000000000..f16caaf8a --- /dev/null +++ b/plugins/domains/backup-import @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x + +shopt -s nullglob +VERSION="$1" +IMPORT_DIR="$2" +TARGET_DIR="$3" + +cd $IMPORT_DIR +for file in */VHOST; do + cp $file "$TARGET_DIR/$file" +done +for file in */nginx.conf.template; do + cp $file "$TARGET_DIR/$file" +done diff --git a/plugins/domains/commands b/plugins/domains/commands new file mode 100755 index 000000000..14c7b01a8 --- /dev/null +++ b/plugins/domains/commands @@ -0,0 +1,103 @@ +#!/usr/bin/env bash +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x + +case "$1" in + domains) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + [[ ! -d "$DOKKU_ROOT/$2" ]] && echo "App $2 does not exist" && exit 1 + APP="$2" + + dokku domains:setup $APP + echo "=== $APP Domain Names" + cat "$DOKKU_ROOT/$APP/VHOST" + ;; + + domains:setup) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + [[ ! -d "$DOKKU_ROOT/$2" ]] && echo "App $2 does not exist" && exit 1 + APP="$2"; VHOST_PATH="$DOKKU_ROOT/$APP/VHOST" + + if [[ ! -f $VHOST_PATH ]]; then + echo "-----> Creating new $VHOST_PATH..." + VHOST=$(< "$DOKKU_ROOT/VHOST") + SUBDOMAIN=${APP/%\.${VHOST}/} + hostname=$(: | pluginhook nginx-hostname $APP $SUBDOMAIN $VHOST) + if [[ ! -n $hostname ]]; then + if [[ "$APP" == *.* ]] && [[ "$SUBDOMAIN" == "$APP" ]]; then + hostname="${APP/\//-}" + else + hostname="${APP/\//-}.$VHOST" + fi + fi + + echo $hostname > $VHOST_PATH + fi + ;; + + domains:add) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + [[ ! -d "$DOKKU_ROOT/$2" ]] && echo "App $2 does not exist" && exit 1 + APP="$2" + + if [[ -z $3 ]]; then + echo "Usage: dokku $1 $APP DOMAIN" + echo "Must specify DOMAIN." + exit 1 + fi + + if [[ $(grep $3 "$DOKKU_ROOT/$APP/VHOST" > /dev/null 2>&1; echo $?) -eq 0 ]]; then + echo "$3 is already defined for $APP" + exit 1 + fi + + dokku domains:setup $APP + echo "$3" >> "$DOKKU_ROOT/$APP/VHOST" + pluginhook post-domains-update $APP + echo "-----> Added $3 to $APP" + + ;; + + domains:clear) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + [[ ! -d "$DOKKU_ROOT/$2" ]] && echo "App $2 does not exist" && exit 1 + APP="$2" + + rm -f "$DOKKU_ROOT/$APP/VHOST" + dokku domains:setup $APP + pluginhook post-domains-update $APP + echo "-----> Cleared domains in $APP" + + ;; + + domains:remove) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + [[ ! -d "$DOKKU_ROOT/$2" ]] && echo "App $2 does not exist" && exit 1 + APP="$2" + + if [[ -z $3 ]]; then + echo "Usage: dokku $1 $2 DOMAIN" + echo "Must specify DOMAIN." + exit 1 + fi + + dokku domains:setup $APP + sed -i "/^$3$/d" "$DOKKU_ROOT/$APP/VHOST" + pluginhook post-domains-update $APP + echo "-----> Removed $3 from $APP" + + ;; + + help | domains:help) + cat && cat< List custom domains for app + domains:add DOMAIN Add a custom domain to app + domains:clear Clear all custom domains for app + domains:remove DOMAIN Remove a custom domain from app +EOF + ;; + + *) + exit $DOKKU_NOT_IMPLEMENTED_EXIT + ;; + +esac diff --git a/plugins/domains/install b/plugins/domains/install new file mode 100755 index 000000000..18b7ae028 --- /dev/null +++ b/plugins/domains/install @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x + +for app in $(ls -d $DOKKU_ROOT/*/CONTAINER); do + APP=$(basename $(dirname $app)); + dokku domains:setup $APP +done diff --git a/plugins/nginx-vhosts/commands b/plugins/nginx-vhosts/commands index eb6719a23..c961bc5f0 100755 --- a/plugins/nginx-vhosts/commands +++ b/plugins/nginx-vhosts/commands @@ -1,7 +1,92 @@ #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +restart_nginx () { + case "$DOKKU_DISTRO" in + ubuntu) + sudo /etc/init.d/nginx reload > /dev/null + ;; + + opensuse) + sudo /sbin/service nginx reload > /dev/null + ;; + esac +} + case "$1" in + nginx:build-config) + APP="$2"; PORT="$3" + [[ -z "$PORT" ]] && PORT=$(< "$DOKKU_ROOT/$APP/PORT") + VHOST_PATH="$DOKKU_ROOT/$APP/VHOST" + WILDCARD_SSL="$DOKKU_ROOT/tls" + SSL="$DOKKU_ROOT/$APP/tls" + NONSSL_VHOSTS=`cat $VHOST_PATH` + + if [[ ! -n "$NO_VHOST" ]]; then + if [[ -e "$SSL/server.crt" ]] && [[ -e "$SSL/server.key" ]]; then + SSL_INUSE="$SSL" + SSL_DIRECTIVES=$(cat < Configuring SSL for $line..." + SSL_SERVER_NAME=$line + eval "cat <<< \"$(< $NGINX_CONF)\" >> $DOKKU_ROOT/$APP/nginx.conf" + done <<< "$SSL_VHOSTS" + fi + + APP_NGINX_TEMPLATE="$DOKKU_ROOT/$APP/nginx.conf.template" + if [[ -f $APP_NGINX_TEMPLATE ]]; then + echo "-----> Overriding default nginx.conf with detected nginx.conf.template" + NGINX_CONF=$APP_NGINX_TEMPLATE + fi + + cat $VHOST_PATH | xargs -i echo "-----> Configuring {}..." + # Include SSL_VHOSTS so we can redirect http to https on that hostname as well + NOSSL_SERVER_NAME=`echo $NONSSL_VHOSTS $SSL_VHOSTS| tr '\n' ' '` + + echo "-----> Creating $SCHEME nginx.conf" + echo "upstream $APP { server 127.0.0.1:$PORT; }" > $DOKKU_ROOT/$APP/nginx.conf + eval "cat <<< \"$(< $NGINX_CONF)\" >> $DOKKU_ROOT/$APP/nginx.conf" + + echo "-----> Running nginx-pre-reload" + pluginhook nginx-pre-reload $APP $PORT + + echo " Reloading nginx" + restart_nginx + else + if [[ -f "$DOKKU_ROOT/$APP/VHOST" ]]; then + echo "-----> NO_VHOST set, deleting $APP/VHOST" + rm "$DOKKU_ROOT/$APP/VHOST" + fi + if [[ -f "$DOKKU_ROOT/$APP/nginx.conf" ]]; then + echo "-----> NO_VHOST set, deleting nginx.conf" + rm "$DOKKU_ROOT/$APP/nginx.conf" + + echo "-----> NO_VHOST set, reloading nginx after nginx.conf deletion" + restart_nginx + fi + fi + ;; + nginx:import-ssl) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 [[ ! -d "$DOKKU_ROOT/$2" ]] && echo "App $2 does not exist" && exit 1 @@ -17,12 +102,15 @@ case "$1" in mkdir -p "$DOKKU_ROOT/$APP/tls" mv "$TEMP_DIR/server.crt" "$DOKKU_ROOT/$APP/tls/server.crt" mv "$TEMP_DIR/server.key" "$DOKKU_ROOT/$APP/tls/server.key" + cd $DOKKU_ROOT rm -rf $TEMP_DIR + dokku nginx:build-config $APP ;; help | nginx:help) cat && cat< Imports a tarball from stdin; should contain server.crt and server.key + nginx:build-config (Re)builds nginx config for given app EOF ;; diff --git a/plugins/nginx-vhosts/post-deploy b/plugins/nginx-vhosts/post-deploy index fe01ab77b..cdf81d452 100755 --- a/plugins/nginx-vhosts/post-deploy +++ b/plugins/nginx-vhosts/post-deploy @@ -2,134 +2,13 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x APP="$1"; PORT="$2" -WILDCARD_SSL="$DOKKU_ROOT/tls" -SSL="$DOKKU_ROOT/$APP/tls" -set +e -NO_VHOST=$(dokku config:get $APP NO_VHOST) -set -e +set +e; NO_VHOST=$(dokku config:get $APP NO_VHOST); set -e if [[ -n "$NO_VHOST" ]]; then echo "-----> NO_VHOST config detected" +elif [[ ! -f "$DOKKU_ROOT/$APP/VHOST" ]]; then + dokku domains:setup $APP fi -if [[ -f "$DOKKU_ROOT/VHOST" && ! -n "$NO_VHOST" ]]; then - VHOST=$(< "$DOKKU_ROOT/VHOST") - SUBDOMAIN=${APP/%\.${VHOST}/} - hostname=$(: | pluginhook nginx-hostname $APP $SUBDOMAIN $VHOST) - if [[ ! -n $hostname ]]; then - if [[ "$APP" == *.* ]] && [[ "$SUBDOMAIN" == "$APP" ]]; then - hostname="${APP/\//-}" - else - hostname="${APP/\//-}.$VHOST" - fi - fi - - if [[ -e "$SSL/server.crt" ]] && [[ -e "$SSL/server.key" ]]; then - SSL_INUSE="$SSL" - SSL_DIRECTIVES=$(cat < Creating ssl nginx.conf" - cat< $DOKKU_ROOT/$APP/nginx.conf -upstream $APP { server 127.0.0.1:$PORT; } -server { - listen [::]:80; - listen 80; - server_name $hostname; - return 301 https://\$host\$request_uri; -} - -server { - listen [::]:443 ssl spdy; - listen 443 ssl spdy; - server_name $hostname; -$SSL_DIRECTIVES - - keepalive_timeout 70; - add_header Alternate-Protocol 443:npn-spdy/2; - - location / { - proxy_pass http://$APP; - proxy_http_version 1.1; - proxy_set_header Upgrade \$http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host \$http_host; - proxy_set_header X-Forwarded-Proto \$scheme; - proxy_set_header X-Forwarded-For \$remote_addr; - proxy_set_header X-Forwarded-Port \$server_port; - proxy_set_header X-Request-Start \$msec; - } - include $DOKKU_ROOT/$APP/nginx.conf.d/*.conf; -} -EOF - - echo "https://$hostname" > "$DOKKU_ROOT/$APP/URL" - else - echo "-----> Creating non-ssl nginx.conf" - cat< $DOKKU_ROOT/$APP/nginx.conf -upstream $APP { server 127.0.0.1:$PORT; } -server { - listen [::]:80; - listen 80; - server_name $hostname; - location / { - proxy_pass http://$APP; - proxy_http_version 1.1; - proxy_set_header Upgrade \$http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host \$http_host; - proxy_set_header X-Forwarded-Proto \$scheme; - proxy_set_header X-Forwarded-For \$remote_addr; - proxy_set_header X-Forwarded-Port \$server_port; - proxy_set_header X-Request-Start \$msec; - } - include $DOKKU_ROOT/$APP/nginx.conf.d/*.conf; -} -EOF - - echo "http://$hostname" > "$DOKKU_ROOT/$APP/URL" - fi - - echo "-----> Running nginx-pre-reload" - pluginhook nginx-pre-reload $APP $PORT - - echo " Reloading nginx" - case "$DOKKU_DISTRO" in - ubuntu) - sudo /etc/init.d/nginx reload > /dev/null - ;; - - opensuse) - sudo /sbin/service nginx reload > /dev/null - ;; - esac -else - if [[ -f "$DOKKU_ROOT/$APP/URL" ]]; then - echo "------> NO_VHOST set, deleting $APP/URL" - rm "$DOKKU_ROOT/$APP/URL" - fi - if [[ -f "$DOKKU_ROOT/$APP/nginx.conf" ]]; then - echo "------> NO_VHOST set, deleting $APP/nginx.conf" - rm "$DOKKU_ROOT/$APP/nginx.conf" - echo "------> NO_VHOST set, reloading nginx after nginx.conf deletion" - case "$DOKKU_DISTRO" in - ubuntu) - sudo /etc/init.d/nginx reload > /dev/null - ;; - - opensuse) - sudo /sbin/service nginx reload > /dev/null - ;; - esac - sudo /etc/init.d/nginx reload > /dev/null - fi -fi +dokku nginx:build-config $APP $PORT diff --git a/plugins/nginx-vhosts/post-domains-update b/plugins/nginx-vhosts/post-domains-update new file mode 100755 index 000000000..e2bb35ebd --- /dev/null +++ b/plugins/nginx-vhosts/post-domains-update @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x + +APP="$1" + +dokku nginx:build-config $APP diff --git a/plugins/nginx-vhosts/templates/nginx.conf b/plugins/nginx-vhosts/templates/nginx.conf new file mode 100644 index 000000000..8ed426275 --- /dev/null +++ b/plugins/nginx-vhosts/templates/nginx.conf @@ -0,0 +1,17 @@ +server { + listen [::]:80; + listen 80; + server_name $NOSSL_SERVER_NAME; + location / { + proxy_pass http://$APP; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$http_host; + proxy_set_header X-Forwarded-Proto \$scheme; + proxy_set_header X-Forwarded-For \$remote_addr; + proxy_set_header X-Forwarded-Port \$server_port; + proxy_set_header X-Request-Start \$msec; + } + include $DOKKU_ROOT/$APP/nginx.conf.d/*.conf; +} diff --git a/plugins/nginx-vhosts/templates/nginx.ssl.conf b/plugins/nginx-vhosts/templates/nginx.ssl.conf new file mode 100644 index 000000000..5cde7484a --- /dev/null +++ b/plugins/nginx-vhosts/templates/nginx.ssl.conf @@ -0,0 +1,28 @@ +server { + listen [::]:80; + listen 80; + server_name $NOSSL_SERVER_NAME; + return 301 https://$SSL_SERVER_NAME\$request_uri; +} + +server { + listen [::]:443 ssl spdy; + listen 443 ssl spdy; + server_name $SSL_SERVER_NAME; +$SSL_DIRECTIVES + + keepalive_timeout 70; + add_header Alternate-Protocol 443:npn-spdy/2; + location / { + proxy_pass http://$APP; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$http_host; + proxy_set_header X-Forwarded-Proto \$scheme; + proxy_set_header X-Forwarded-For \$remote_addr; + proxy_set_header X-Forwarded-Port \$server_port; + proxy_set_header X-Request-Start \$msec; + } + include $DOKKU_ROOT/$APP/nginx.conf.d/*.conf; +}