diff --git a/bin/aws-eb-docker/Dockerfile b/bin/aws-eb-docker/Dockerfile
deleted file mode 100644
index d05f07de0d9b0feeb47338605cc8b8242d7239bd..0000000000000000000000000000000000000000
--- a/bin/aws-eb-docker/Dockerfile
+++ /dev/null
@@ -1,6 +0,0 @@
-# Example Dockerfile for creating Docker images which includes an H2 database
-# (./h2dump.db) from which to initialize the Metabase database. It can be used
-# to create Docker images for Elastic Beanstalk apps.
-FROM metabase/metabase
-
-COPY ./h2dump.db /app/initial.mv.db
diff --git a/bin/aws-eb-docker/Dockerrun.aws.json.template b/bin/aws-eb-docker/Dockerrun.aws.json.template
deleted file mode 100644
index 37a8ac0bf37e25d69bab892a055a09aee3973e8b..0000000000000000000000000000000000000000
--- a/bin/aws-eb-docker/Dockerrun.aws.json.template
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "AWSEBDockerrunVersion": "1",
-  "Image": {
-    "Name": "metabase/@@MB_REPOSITORY@@:@@MB_TAG@@",
-    "Update": "true"
-  },
-  "Ports": [
-    {
-      "ContainerPort": "3000"
-    }
-  ],
-  "Logging": "/var/log/metabase"
-}
diff --git a/bin/aws-eb-docker/build-eb-version.sh b/bin/aws-eb-docker/build-eb-version.sh
deleted file mode 100755
index 39747d79a6194c1b981857d0b8b7dd87c08e56be..0000000000000000000000000000000000000000
--- a/bin/aws-eb-docker/build-eb-version.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-BASEDIR=$(dirname $0)
-source "$BASEDIR/functions"
-
-MB_TAG=$1
-if [ -z $MB_TAG ]; then
-    echo "usage: $0 <release-name> <docker-repository>"
-    exit 1
-fi
-
-MB_DOCKER_REPOSITORY=$2
-if [ -z $MB_DOCKER_REPOSITORY ]; then
-    echo "usage: $0 <release-name> <docker-repository>"
-    exit 1
-fi
-
-
-make_eb_version ${MB_TAG} ${MB_DOCKER_REPOSITORY}
diff --git a/bin/aws-eb-docker/cloudformation-elasticbeanstalk.json.template b/bin/aws-eb-docker/cloudformation-elasticbeanstalk.json.template
deleted file mode 100644
index bc64e84b3e4871fad60e9aab3e129c614ab27b0b..0000000000000000000000000000000000000000
--- a/bin/aws-eb-docker/cloudformation-elasticbeanstalk.json.template
+++ /dev/null
@@ -1,149 +0,0 @@
-{
-    "AWSTemplateFormatVersion": "2010-09-09",
-    "Description": "Deploys Metabase by creating an ElasticBeanstalk application in an contained in a CloudFormation stack.",
-    "Parameters": {
-        "MetabaseVersion": {
-            "Description": "Metabase Version",
-            "Type": "String",
-            "Default": "@@MB_TAG@@"
-        },
-        "KeyName": {
-            "Description": "Name of an existing EC2 KeyPair to enable SSH access to the AWS Elastic Beanstalk instance",
-            "Type": "AWS::EC2::KeyPair::KeyName"
-        },
-        "instanceType": {
-            "Description": "The Type of EC2 instance to use for running Metabase",
-            "Type": "String",
-            "Default": "t2.small"
-        },
-        "VPCid": {
-            "Description": "The VPC to use for running Metabase",
-            "Type": "AWS::EC2::VPC::Id"
-        },
-        "Subnets": {
-            "Description": "The VPC subnet(s) to use for running Metabase",
-            "Type": "List<AWS::EC2::Subnet::Id>"
-        }
-    },
-    "Resources": {
-        "metabaseApplication": {
-            "Type": "AWS::ElasticBeanstalk::Application",
-            "Properties": {
-                "Description": "Metabase Application",
-                "ApplicationVersions": [
-                    {
-                        "VersionLabel": {
-                            "Ref": "MetabaseVersion"
-                        },
-                        "Description": "Metabase Application Version",
-                        "SourceBundle": {
-                            "S3Bucket": "downloads.metabase.com",
-                            "S3Key": {
-                                "Fn::Join": [
-                                    "/",
-                                    [
-                                        {
-                                            "Ref": "MetabaseVersion"
-                                        },
-                                        "metabase-aws-eb.zip"
-                                    ]
-                                ]
-                            }
-                        }
-                    }
-                ],
-                "ConfigurationTemplates": [
-                    {
-                        "TemplateName": "MetabaseConfiguration",
-                        "Description": "Metabase Application Configuration",
-                        "SolutionStackName": "64bit Amazon Linux 2017.03 v2.7.0 running Docker 17.03.1-ce",
-                        "OptionSettings": [
-                            {
-                                "Namespace": "aws:autoscaling:launchconfiguration",
-                                "OptionName": "EC2KeyName",
-                                "Value": {
-                                    "Ref": "KeyName"
-                                }
-                            },
-                            {
-                                "Namespace": "aws:rds:dbinstance",
-                                "OptionName": "DBEngine",
-                                "Value": "postgres"
-                            },
-                            {
-                                "Namespace": "aws:rds:dbinstance",
-                                "OptionName": "DBAllocatedStorage",
-                                "Value": "10"
-                            },
-                            {
-                                "Namespace": "aws:rds:dbinstance",
-                                "OptionName": "DBInstanceClass",
-                                "Value": "db.t2.small"
-                            },
-                            {
-                                "Namespace": "aws:rds:dbinstance",
-                                "OptionName": "MultiAZDatabase",
-                                "Value": "false"
-                            },
-                            {
-                                "Namespace": "aws:rds:dbinstance",
-                                "OptionName": "DBDeletionPolicy",
-                                "Value": "Snapshot"
-                            },
-                            {
-                                "Namespace": "aws:autoscaling:launchconfiguration",
-                                "OptionName": "InstanceType",
-                                "Value": {
-                                    "Ref": "instanceType"
-                                }
-                            },
-                            {
-                                "Namespace": "aws:ec2:vpc",
-                                "OptionName": "VPCId",
-                                "Value": {
-                                    "Ref": "VPCid"
-                                }
-                            },
-                            {
-                                "Namespace": "aws:ec2:vpc",
-                                "OptionName": "Subnets",
-                                "Value": {
-                                    "Fn::Join": [
-                                        ",",
-                                        {
-                                            "Ref": "Subnets"
-                                        }
-                                    ]
-                                }
-                            }
-                        ]
-                    }
-                ]
-            }
-        },
-        "metabaseEnvironment": {
-            "Type": "AWS::ElasticBeanstalk::Environment",
-            "Properties": {
-                "ApplicationName": {
-                    "Ref": "metabaseApplication"
-                },
-                "Description": "AWS Elastic Beanstalk Environment for Metabase",
-                "TemplateName": "MetabaseConfiguration",
-                "VersionLabel": {
-                    "Ref": "MetabaseVersion"
-                }
-            }
-        }
-    },
-    "Outputs": {
-        "URL": {
-            "Description": "Metabase URL",
-            "Value": {
-                "Fn::GetAtt": [
-                    "metabaseEnvironment",
-                    "EndpointURL"
-                ]
-            }
-        }
-    }
-}
diff --git a/bin/aws-eb-docker/deploy-eb-version.sh b/bin/aws-eb-docker/deploy-eb-version.sh
deleted file mode 100755
index f8b5b2b81aaa60aa5ff1930c1ef85043949127e6..0000000000000000000000000000000000000000
--- a/bin/aws-eb-docker/deploy-eb-version.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash
-
-BASEDIR=$(dirname $0)
-source "$BASEDIR/functions"
-
-MB_TAG=$1
-if [ -z $MB_TAG ]; then
-    echo "usage: $0 <release-name> <docker-repository> <eb-environment>"
-    exit 1
-fi
-
-MB_DOCKER_REPOSITORY=$2
-if [ -z $MB_DOCKER_REPOSITORY ]; then
-    echo "usage: $0 <release-name> <docker-repository> <eb-environment>"
-    exit 1
-fi
-
-EB_ENVIRONMENT=$3
-if [ -z $EB_ENVIRONMENT ]; then
-    echo "usage: $0 <release-name> <docker-repository> <eb-environment>"
-    exit 1
-fi
-
-if [ -z "$AWS_DEFAULT_PROFILE" ]; then
-    echo "You must set the AWS_DEFAULT_PROFILE environment variable in order to deploy to AWS!"
-    exit 1
-fi
-
-
-make_eb_version ${MB_TAG} ${MB_DOCKER_REPOSITORY}
-upload_eb_version ${MB_TAG}
-create_eb_version ${MB_TAG}
-deploy_version ${MB_TAG} ${EB_ENVIRONMENT}
diff --git a/bin/aws-eb-docker/functions b/bin/aws-eb-docker/functions
deleted file mode 100644
index deb0bb26719ce04ef27ebde0367e45d91a66889d..0000000000000000000000000000000000000000
--- a/bin/aws-eb-docker/functions
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/bin/bash
-set -eo pipefail
-
-BASEDIR=$(dirname $0)
-CURRENTDIR=$PWD
-PROJECT_ROOT=$(cd ${BASEDIR}/..; pwd)
-
-ARTIFACTS_S3BUCKET=${S3BUCKET:=metabase-artifacts}
-
-
-export LANG=en_US.UTF-8
-export LANGUAGE=$LANG
-export LC_ALL=$LANG
-
-CF_TEMPLATE=cloudformation-elasticbeanstalk.json
-CF_TEMPLATE_PATH=/tmp/$CF_TEMPLATE
-S3_CF_TEMPLATE_PATH=s3://$ARTIFACTS_S3BUCKET/eb/$CF_TEMPLATE
-
-make_eb_version() {
-    MB_TAG=$1
-    MB_DOCKER_REPOSITORY=$2
-
-    $(which locale) | $(which sort) || true
-
-    if [[ -z $MB_TAG ]]; then
-        echo "release name not provided!"
-        exit 1
-    fi
-
-    if [[ -z $MB_DOCKER_REPOSITORY ]]; then
-        echo "docker repository name not provided!"
-        exit 1
-    fi
-
-    RELEASE_FILE="/tmp/${MB_TAG}.zip"
-
-    echo "Building Elastic Beanstalk app version for Metabase using Docker Image: metabase/${MB_DOCKER_REPOSITORY}:${MB_TAG}"
-
-    # dynamically insert our MB version into the EB config file
-    sed "s/@@MB_REPOSITORY@@/${MB_DOCKER_REPOSITORY}/" < ${BASEDIR}/Dockerrun.aws.json.template > ${BASEDIR}/Dockerrun.aws.json.tmp
-    sed "s/@@MB_TAG@@/${MB_TAG}/" < ${BASEDIR}/Dockerrun.aws.json.tmp > ${BASEDIR}/Dockerrun.aws.json
-
-    # set the default version in the cloudformation template from the template-template (yo dawg i heard you like templates ;)
-    sed "s/@@MB_TAG@@/${MB_TAG}/" < ${BASEDIR}/$CF_TEMPLATE.template > $CF_TEMPLATE_PATH
-
-    # create our EB zip file
-    cd $BASEDIR; zip -r ${RELEASE_FILE} .ebextensions Dockerrun.aws.json; cd $CURRENTDIR
-
-    # clean up the temporary Dockerrun.aws.json file we created
-    rm ${BASEDIR}/Dockerrun.aws.json.tmp
-    rm ${BASEDIR}/Dockerrun.aws.json
-}
-
-upload_eb_version() {
-    MB_TAG=$1
-
-    $(which locale) | $(which sort) || true
-
-    if [[ -z $MB_TAG ]]; then
-        echo "release name not provided!"
-        exit 1
-    fi
-
-    echo "uploading /tmp/${MB_TAG}.zip -> $ARTIFACTS_S3BUCKET/eb/"
-    aws s3 cp /tmp/${MB_TAG}.zip s3://$ARTIFACTS_S3BUCKET/eb/${MB_TAG}.zip
-
-    echo "uploading $CF_TEMPLATE_PATH -> $S3_CF_TEMPLATE_PATH"
-    aws s3 cp $CF_TEMPLATE_PATH $S3_CF_TEMPLATE_PATH
-
-}
-
-create_eb_version() {
-    EB_APPLICATION=Metabase
-    MB_TAG=$1
-
-    $(which locale) | $(which sort) || true
-
-    if [[ -z $MB_TAG ]]; then
-        echo "release name not provided!"
-        exit 1
-    fi
-
-    echo "Creating app version in EB"
-    aws elasticbeanstalk create-application-version --no-auto-create-application --region us-east-1 --application-name ${EB_APPLICATION} --version-label ${MB_TAG} --source-bundle S3Bucket="${ARTIFACTS_S3BUCKET}",S3Key="eb/${MB_TAG}.zip"
-}
-
-deploy_version() {
-    MB_TAG=$1
-    EB_ENVIRONMENT=$2
-
-    $(which locale) | $(which sort) || true
-
-    if [[ -z $MB_TAG ]]; then
-        echo "release name not provided!"
-        exit 1
-    fi
-
-    if [[ -z $EB_ENVIRONMENT ]]; then
-        echo "beanstalk environment not provided!"
-        exit 1
-    fi
-
-    aws elasticbeanstalk update-environment --region us-east-1 --environment-name ${EB_ENVIRONMENT} --version-label ${MB_TAG}
-}
diff --git a/bin/aws-eb-docker/launch-aws-eb.html.template b/bin/aws-eb-docker/launch-aws-eb.html.template
deleted file mode 100644
index d27cdabb411284554efc1cdba1f89f99fcd0500a..0000000000000000000000000000000000000000
--- a/bin/aws-eb-docker/launch-aws-eb.html.template
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Redirecting...</title>
-<link rel=canonical href="https://console.aws.amazon.com/elasticbeanstalk/home?region=us-east-1#/newApplication?applicationName=Metabase&tierName=WebServer&platform=Docker&sourceBundleUrl=https%3A%2F%2Fdownloads.metabase.com.s3.amazonaws.com%2F@@MB_TAG@@%2Fmetabase-aws-eb.zip&instanceType=t2.small&withRds=true&rdsDBEngine=postgres&rdsDBAllocatedStorage=10&rdsDBInstanceClass=db.t2.small&rdsMultiAZDatabase=false&rdsDBDeletionPolicy=Snapshot">
-<meta http-equiv=refresh content="0; url=https://console.aws.amazon.com/elasticbeanstalk/home?region=us-east-1#/newApplication?applicationName=Metabase&tierName=WebServer&platform=Docker&sourceBundleUrl=https%3A%2F%2Fdownloads.metabase.com.s3.amazonaws.com%2F@@MB_TAG@@%2Fmetabase-aws-eb.zip&instanceType=t2.small&withRds=true&rdsDBEngine=postgres&rdsDBAllocatedStorage=10&rdsDBInstanceClass=db.t2.small&rdsMultiAZDatabase=false&rdsDBDeletionPolicy=Snapshot">
-<h1>Redirecting...</h1>
-<a href="https://console.aws.amazon.com/elasticbeanstalk/home?region=us-east-1#/newApplication?applicationName=Metabase&tierName=WebServer&platform=Docker&sourceBundleUrl=https%3A%2F%2Fdownloads.metabase.com.s3.amazonaws.com%2F@@MB_TAG@@%2Fmetabase-aws-eb.zip&instanceType=t2.small&withRds=true&rdsDBEngine=postgres&rdsDBAllocatedStorage=10&rdsDBInstanceClass=db.t2.small&rdsMultiAZDatabase=false&rdsDBDeletionPolicy=Snapshot">Click here if you are not redirected.</a>
-<script>location='https://console.aws.amazon.com/elasticbeanstalk/home?region=us-east-1#/newApplication?applicationName=Metabase&tierName=WebServer&platform=Docker&sourceBundleUrl=https%3A%2F%2Fdownloads.metabase.com.s3.amazonaws.com%2F@@MB_TAG@@%2Fmetabase-aws-eb.zip&instanceType=t2.small&withRds=true&rdsDBEngine=postgres&rdsDBAllocatedStorage=10&rdsDBInstanceClass=db.t2.small&rdsMultiAZDatabase=false&rdsDBDeletionPolicy=Snapshot'</script>
diff --git a/bin/aws-eb-docker/release-eb-version.sh b/bin/aws-eb-docker/release-eb-version.sh
deleted file mode 100755
index 93d561fff12838620ac7650bb5dc8afa36434c17..0000000000000000000000000000000000000000
--- a/bin/aws-eb-docker/release-eb-version.sh
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/bash
-
-BASEDIR=$(dirname $0)
-CURRENTDIR=$PWD
-
-if [ "$MB_EDITION" = "ENTERPRISE" ]; then
-    DOCKERHUB_REPO=metabase-enterprise
-else
-    DOCKERHUB_REPO=metabase
-fi
-
-S3_BUCKET=downloads.metabase.com
-
-
-# parse any cmd line arguments
-MB_TAG=$1
-if [ -z $MB_TAG ]; then
-    echo "usage: $0 <release-name> [--publish]"
-    exit 1
-fi
-
-if [ -z "$AWS_DEFAULT_PROFILE" ]; then
-    echo "In order to publish an Elastic Beanstalk version to S3 you must set the AWS_DEFAULT_PROFILE environment variable"
-    exit 1
-fi
-
-# TODO: improve this (hard coding)
-EB_FILE=/tmp/${MB_TAG}.zip
-EB_LAUNCH_FILE=launch-aws-eb.html
-
-if [ "$MB_EDITION" = "ENTERPRISE" ]; then
-    S3_FILE=s3://${S3_BUCKET}/enterprise/${MB_TAG}/metabase-aws-eb.zip
-    S3_LAUNCH_FILE=s3://${S3_BUCKET}/enterprise/${MB_TAG}/${EB_LAUNCH_FILE}
-else
-    S3_FILE=s3://${S3_BUCKET}/${MB_TAG}/metabase-aws-eb.zip
-    S3_LAUNCH_FILE=s3://${S3_BUCKET}/${MB_TAG}/${EB_LAUNCH_FILE}
-fi
-
-# make the release file
-${BASEDIR}/build-eb-version.sh ${MB_TAG} ${DOCKERHUB_REPO}
-
-# dynamically insert our MB version into the EB launch file
-sed "s/@@MB_TAG@@/${MB_TAG}/" < ${BASEDIR}/${EB_LAUNCH_FILE}.template > ${BASEDIR}/${EB_LAUNCH_FILE}
-
-
-echo "Publishing EB files to S3 at ${S3_FILE} and ${S3_LAUNCH_FILE}"
-
-# s3 put
-aws s3 cp ${EB_FILE} ${S3_FILE}
-aws s3 cp ${BASEDIR}/${EB_LAUNCH_FILE} ${S3_LAUNCH_FILE}
-
-# TODO: quick check to see that we succeeded
-
-# clean up the temporary EB launch file we created
-rm ${BASEDIR}/${EB_LAUNCH_FILE}
-
-echo "Done"
diff --git a/bin/metabuild_common/core.clj b/bin/metabuild_common/core.clj
index 4f40bd1e0165fb6fabde5b9143fee00976ee7c9b..c55aa1e36edd7ebe6d855722044f7348094a51b8 100644
--- a/bin/metabuild_common/core.clj
+++ b/bin/metabuild_common/core.clj
@@ -35,6 +35,7 @@
   copy-file!
   create-directory-unless-exists!
   delete-file!
+  delete-file-if-exists!
   file-exists?
   filename
   find-files]
diff --git a/bin/metabuild_common/files.clj b/bin/metabuild_common/files.clj
index 4dfd72e954b0d11c84427ed2baa32728b586b5d5..007831ec61ae1d11817b00f829de3d2a44f4edcc 100644
--- a/bin/metabuild_common/files.clj
+++ b/bin/metabuild_common/files.clj
@@ -23,15 +23,17 @@
   (str filename))
 
 (defn create-directory-unless-exists! [^String dir]
-  (when-not (file-exists? dir)
-    (steps/step (format "Creating directory %s..." dir)
-      (.mkdirs (File. dir))))
+  (steps/step (format "Create directory %s if it does not exist" dir)
+    (if (file-exists? dir)
+      (out/announce "%s already exists." dir)
+      (steps/step (format "Create directory %s" dir)
+        (.mkdirs (File. dir)))))
   dir)
 
-(defn delete-file!
+(defn delete-file-if-exists!
   "Delete a file or directory (recursively) if it exists."
   ([^String filename]
-   (steps/step (format "Deleting %s..." filename)
+   (steps/step (format "Delete %s if exists" filename)
      (if (file-exists? filename)
        (let [file (File. filename)]
          (if (.isDirectory file)
@@ -42,7 +44,13 @@
      (assert (not (file-exists? filename)))))
 
   ([file & more]
-   (dorun (map delete-file! (cons file more)))))
+   (dorun (map delete-file-if-exists! (cons file more)))))
+
+(defn ^:deprecated delete-file!
+  "Alias for `delete-file-if-exists!`. Here for backwards compatibility. Prefer `delete-file-if-exists!` going
+  forward."
+  [& args]
+  (apply delete-file-if-exists! args))
 
 (defn copy-file!
   "Copy a `source` file (or directory, recursively) to `dest`."
diff --git a/bin/release/release/check_prereqs.clj b/bin/release/release/check_prereqs.clj
index dfb95839f68de6add3aa37bc1a553cc01f43b1c3..dfb9b292bf8e913ac97d683a1dad65d858e21e6b 100644
--- a/bin/release/release/check_prereqs.clj
+++ b/bin/release/release/check_prereqs.clj
@@ -4,7 +4,7 @@
             [metabuild-common.core :as u]))
 
 (def ^:private required-commands
-  ["git" "node" "yarn" "aws" "docker" "java" "wget" "shasum" "gettext"])
+  ["git" "node" "yarn" "aws" "docker" "java" "wget" "shasum" "gettext" "zip"])
 
 (defn- check-for-required-commands []
   (u/step "Verify required external commands are available"
diff --git a/bin/release/release/common.clj b/bin/release/release/common.clj
index dfe84527c919e0bc8017a937f284bb571e768001..62bdd257eabd2f409e94ccce84322c9d63572676 100644
--- a/bin/release/release/common.clj
+++ b/bin/release/release/common.clj
@@ -7,12 +7,14 @@
 (assert (str/ends-with? (env/env :user-dir) "/bin/release")
         "Please run release.clj from the `release` directory e.g. `cd bin/release; clojure -m release`")
 
+(def cloudfront-distribution-id "E35CJLWZIZVG7K")
+
 (def ^String root-directory
   "e.g. /Users/cam/metabase"
-  (.. (File. (env/env :user-dir)) getParentFile getParent))
+  (.. (File. ^String (env/env :user-dir)) getParentFile getParent))
 
 (def ^String uberjar-path
-  (str root-directory "/target/uberjar/metabase.jar"))
+  (u/filename root-directory "target" "uberjar" "metabase.jar"))
 
 (defonce ^:private build-options
   (atom nil))
@@ -83,10 +85,10 @@
 
 (defn artifact-download-url
   "Public-facing URL where you can download the artifact after it has been uploaded."
-  ([filename]
+  (^String [filename]
    (artifact-download-url (version) filename))
 
-  ([version filename]
+  (^String [version filename]
    (format "https://%s/%s/%s"
            (downloads-url)
            (if (= version "latest") "latest" (str "v" version))
@@ -107,5 +109,31 @@
   []
   "metabase/metabase")
 
-(defn docker-tag []
+(defn docker-tag
+  "The complete image name + tag e.g. \"metabase/metabase:v0.37.0\""
+  []
   (format "%s:v%s" (docker-image-name) (version)))
+
+(defn s3-artifact-path
+  "S3 path excluding the protocol and bucket e.g. `/enterprise/v1.37.0.2/metabase.jar`"
+  ([filename]
+   (s3-artifact-path (version) filename))
+
+  ([version filename]
+   (str
+    (when (= (edition) :ee)
+      "/enterprise")
+    (format "/%s/%s"
+            (if (= version "latest") "latest" (str "v" version))
+            filename))))
+
+(defn s3-artifact-url
+  "S3 path including protocol and bucket e.g. `s3://downloads.metabase.com/enterprise/v1.37.0.2/metabase.jar`"
+  ([filename]
+   (s3-artifact-url (version) filename))
+
+  ([version filename]
+   (s3-artifact-url "downloads.metabase.com" version filename))
+
+  ([s3-bucket version filename]
+   (format "s3://%s%s" s3-bucket (s3-artifact-path version filename))))
diff --git a/bin/release/release/common/upload.clj b/bin/release/release/common/upload.clj
new file mode 100644
index 0000000000000000000000000000000000000000..024874034d7826edf92f0b6169ecf26a49ecdb32
--- /dev/null
+++ b/bin/release/release/common/upload.clj
@@ -0,0 +1,12 @@
+(ns release.common.upload
+  (:require [release.common :as c]))
+
+(defn upload-artifact!
+  "Upload an artifact to downloads.metabase.com and create a CloudFront invalidation."
+  ([source-file filename]
+   (upload-artifact! source-file (c/version) filename))
+
+  ([source-file version filename]
+   (u/step (format "Upload %s to %s" source-file (c/artifact-download-url version filename))
+     (u/s3-copy! (u/assert-file-exists source-file) (c/s3-artifact-url version filename))
+     (u/create-cloudfront-invalidation! c/cloudfront-distribution-id (c/s3-artifact-path version filename)))))
diff --git a/bin/release/release/docker.clj b/bin/release/release/docker.clj
index 253651744c4492b9c347075b16ad1f08a5dcbb4f..d91a162a24ed13f2458698e5cebffd0b5aa49893 100644
--- a/bin/release/release/docker.clj
+++ b/bin/release/release/docker.clj
@@ -10,6 +10,7 @@
 
 (defn- validate-docker-image []
   (u/step "Validate Docker image"
+    (u/announce "TODO")
     ;;   image="$1"
     ;;   docker pull "$image" > /dev/null
     ;;   docker_hash=$(docker run --rm "$image" version | grep -Eo 'hash [0-9a-f]+' | awk '{ print $2 }')
diff --git a/bin/release/release/draft_release.clj b/bin/release/release/draft_release.clj
index 25ca68c0d2cf0edabcf58bc1a3a87f47b8d719c4..7d68badb59d7218bf97bfd6771a114d46d5f8499 100644
--- a/bin/release/release/draft_release.clj
+++ b/bin/release/release/draft_release.clj
@@ -17,7 +17,7 @@
   (u/step "Generate draft changelog"
     (let [pre-release?                           (c/pre-release-version?)
           {bugs :bug, enhancements :enhancement} (group-by github/issue-type (github/milestone-issues))]
-      (stencil/render-file (u/assert-file-exists "release-template.md")
+      (stencil/render-file (u/assert-file-exists "release/draft_release/release-template.md")
                            {:enhancements enhancements
                             :bug-fixes    bugs
                             :docker-tag   (c/docker-tag)
diff --git a/bin/release/release-template.md b/bin/release/release/draft_release/release-template.md
similarity index 100%
rename from bin/release/release-template.md
rename to bin/release/release/draft_release/release-template.md
diff --git a/bin/release/release/elastic_beanstalk.clj b/bin/release/release/elastic_beanstalk.clj
index 7dee73eb50bb91aa297c493e194dc179143bbe87..ae365299e258355eff7d209d5eb378c6879749b4 100644
--- a/bin/release/release/elastic_beanstalk.clj
+++ b/bin/release/release/elastic_beanstalk.clj
@@ -1,16 +1,106 @@
 (ns release.elastic-beanstalk
   "Code related to building and publishing Elastic Beanstalk artifacts."
-  (:require [metabuild-common.core :as u]
+  (:require [cheshire.core :as json]
+            [clojure.core.cache :as cache]
+            [metabuild-common.core :as u]
             [release.common :as c]
-            [release.common.http :as common.http]))
+            [release.common
+             [http :as common.http]
+             [upload :as upload]]
+            [stencil loader
+             [core :as stencil]]))
+
+;; Disable caching of our template files for easier REPL debugging, we're only rendering them once anyways
+(stencil.loader/set-cache (cache/ttl-cache-factory {} :ttl 0))
+
+;; create a ZIP file with the contents
+;; metabase-aws-eb.zip
+;; ├─ Dockerrun.aws.json
+;; ├─ .ebextensions/
+;;    ├─ 01_metabase.config
+;;    ├─ metabase_config/
+;;       ├─ (a bunch of other stuff)
+
+(def ^:private eb-extensions-source
+  "Source location of the .ebextensions directory"
+  (u/assert-file-exists (u/filename c/root-directory "bin" "release" "release" "elastic_beanstalk" ".ebextensions")))
+
+(def ^:private archive-temp-dir
+  "Path where we'll put the contents of the ZIP file before we create it."
+  "/tmp/metabase-aws-eb")
+
+(def ^:private archive-path   "/tmp/metabase-aws-eb.zip")
+(def ^:private html-file-path "/tmp/launch-aws-eb.html")
+
+(defn- validate-json-docker-tag []
+  (u/step (format "Check that Dockerrun.aws.json Docker tag is %s" (c/docker-tag))
+    (u/step "Download archive"
+      (u/delete-file-if-exists! archive-path)
+      (u/sh {:quiet? true} "wget" "--quiet" "--no-cache" "--output-document" archive-path
+            (c/artifact-download-url "metabase-aws-eb.zip")))
+    (u/step "Unzip archive"
+      (u/delete-file-if-exists! archive-temp-dir)
+      (u/sh "unzip" (u/assert-file-exists archive-path) "-d" archive-temp-dir))
+    (u/step "Validate JSON file"
+      (let [json (-> (u/assert-file-exists (u/filename (u/assert-file-exists archive-temp-dir) "Dockerrun.aws.json"))
+                     slurp
+                     (json/parse-string true))
+            tag  (get-in json [:Image :Name])]
+        (u/announce "Docker tag is %s" tag)
+        (when-not (= tag (c/docker-tag))
+          (throw (ex-info "Incorrect Docker tag." {:expected (c/docker-tag)
+                                                   :actual   tag
+                                                   :json     json})))))))
 
 (defn- validate-elastic-beanstalk-artifacts []
   (u/step "Validate Elastic Beanstalk artifacts"
     (common.http/check-url-exists (c/artifact-download-url "launch-aws-eb.html"))
-    (common.http/check-url-exists (c/artifact-download-url "metabase-aws-eb.zip"))))
+    (common.http/check-url-exists (c/artifact-download-url "metabase-aws-eb.zip"))
+    (validate-json-docker-tag)
+    (u/announce "Artifacts validated.")))
+
+(defn- dockerrun-json-content []
+  {:AWSEBDockerrunVersion "1"
+   :Image                 {:Name   (c/docker-tag)
+                           :Update "true"}
+   :Ports                 [{:ContainerPort "3000"}]
+   :Logging               "/var/log/metabase"})
+
+(defn- create-archive! []
+  (u/step (format "Create metabase-aws-eb.zip for Docker image %s" (c/docker-tag))
+    (u/step "Create temp dir"
+      (u/delete-file-if-exists! archive-temp-dir)
+      (u/create-directory-unless-exists! archive-temp-dir))
+    (u/step "Generate Dockerrun.aws.json"
+      (spit (u/filename archive-temp-dir "Dockerrun.aws.json")
+            (json/generate-string (dockerrun-json-content) {:pretty true})))
+    (u/step "Copy .ebextensions"
+      (u/copy-file! eb-extensions-source (u/filename archive-temp-dir ".ebextensions")))
+    (u/step "Create metabase-aws-eb.zip"
+      (u/delete-file-if-exists! archive-path)
+      (u/sh {:dir archive-temp-dir} "zip" "--recurse-paths" archive-path ".")
+      (u/assert-file-exists archive-path))))
+
+(defn- create-html-file! []
+  (u/step (format "Create launch-aws-eb.html for Docker image %s" (c/docker-tag))
+    (u/delete-file-if-exists! html-file-path)
+    (spit html-file-path
+          (stencil/render-file (u/assert-file-exists "release/elastic_beanstalk/launch-aws-eb.html.template")
+                               {:url (java.net.URLEncoder/encode (c/artifact-download-url "metabase-aws-eb.zip")
+                                                                 "UTF-8")}))
+    (u/assert-file-exists html-file-path)))
+
+(defn- upload-artifacts! []
+  (u/step "Upload Elastic Beanstalk artifacts"
+    (u/step "Upload metabase-aws-eb.zip"
+      (upload/upload-artifact! archive-path "metabase-aws-eb.zip"))
+    (u/step "Upload launch-aws-eb.html"
+      (upload/upload-artifact! html-file-path "launch-aws-eb.html"))))
 
 ;; TODO -- we should merge the EB build logic into this script, it's still an ancient bash script
 (defn publish-elastic-beanstalk-artifacts! []
   (u/step "Create and publish Elastic Beanstalk artifacts"
-    (u/sh {:dir c/root-directory} "./bin/aws-eb-docker/release-eb-version.sh" (str "v" (c/version))))
+    (create-archive!)
+    (create-html-file!)
+    (upload-artifacts!))
   (validate-elastic-beanstalk-artifacts))
diff --git a/bin/aws-eb-docker/.ebextensions/01_metabase.config b/bin/release/release/elastic_beanstalk/.ebextensions/01_metabase.config
similarity index 100%
rename from bin/aws-eb-docker/.ebextensions/01_metabase.config
rename to bin/release/release/elastic_beanstalk/.ebextensions/01_metabase.config
diff --git a/bin/aws-eb-docker/.ebextensions/metabase_config/metabase-setup.sh b/bin/release/release/elastic_beanstalk/.ebextensions/metabase_config/metabase-setup.sh
similarity index 100%
rename from bin/aws-eb-docker/.ebextensions/metabase_config/metabase-setup.sh
rename to bin/release/release/elastic_beanstalk/.ebextensions/metabase_config/metabase-setup.sh
diff --git a/bin/aws-eb-docker/.ebextensions/metabase_config/nginx/log_x_real_ip.conf b/bin/release/release/elastic_beanstalk/.ebextensions/metabase_config/nginx/log_x_real_ip.conf
similarity index 100%
rename from bin/aws-eb-docker/.ebextensions/metabase_config/nginx/log_x_real_ip.conf
rename to bin/release/release/elastic_beanstalk/.ebextensions/metabase_config/nginx/log_x_real_ip.conf
diff --git a/bin/aws-eb-docker/.ebextensions/metabase_config/papertrail/log_files.yml b/bin/release/release/elastic_beanstalk/.ebextensions/metabase_config/papertrail/log_files.yml
similarity index 100%
rename from bin/aws-eb-docker/.ebextensions/metabase_config/papertrail/log_files.yml
rename to bin/release/release/elastic_beanstalk/.ebextensions/metabase_config/papertrail/log_files.yml
diff --git a/bin/aws-eb-docker/.ebextensions/metabase_config/papertrail/remote_syslog b/bin/release/release/elastic_beanstalk/.ebextensions/metabase_config/papertrail/remote_syslog
similarity index 100%
rename from bin/aws-eb-docker/.ebextensions/metabase_config/papertrail/remote_syslog
rename to bin/release/release/elastic_beanstalk/.ebextensions/metabase_config/papertrail/remote_syslog
diff --git a/bin/release/release/elastic_beanstalk/launch-aws-eb.html.template b/bin/release/release/elastic_beanstalk/launch-aws-eb.html.template
new file mode 100644
index 0000000000000000000000000000000000000000..361c0181dc2da1d37d51bd149a74c4f239165405
--- /dev/null
+++ b/bin/release/release/elastic_beanstalk/launch-aws-eb.html.template
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Redirecting...</title>
+<link
+    rel="canonical"
+    href="https://console.aws.amazon.com/elasticbeanstalk/home?region=us-east-1#/newApplication?applicationName=Metabase&tierName=WebServer&platform=Docker&sourceBundleUrl={{url}}&instanceType=t2.small&withRds=true&rdsDBEngine=postgres&rdsDBAllocatedStorage=10&rdsDBInstanceClass=db.t2.small&rdsMultiAZDatabase=false&rdsDBDeletionPolicy=Snapshot"
+    />
+<meta
+    http-equiv="refresh"
+    content="0; url=https://console.aws.amazon.com/elasticbeanstalk/home?region=us-east-1#/newApplication?applicationName=Metabase&tierName=WebServer&platform=Docker&sourceBundleUrl={{url}}&instanceType=t2.small&withRds=true&rdsDBEngine=postgres&rdsDBAllocatedStorage=10&rdsDBInstanceClass=db.t2.small&rdsMultiAZDatabase=false&rdsDBDeletionPolicy=Snapshot"
+    />
+<h1>Redirecting...</h1>
+<a
+    href="https://console.aws.amazon.com/elasticbeanstalk/home?region=us-east-1#/newApplication?applicationName=Metabase&tierName=WebServer&platform=Docker&sourceBundleUrl={{url}}&instanceType=t2.small&withRds=true&rdsDBEngine=postgres&rdsDBAllocatedStorage=10&rdsDBInstanceClass=db.t2.small&rdsMultiAZDatabase=false&rdsDBDeletionPolicy=Snapshot"
+    >
+Click here if you are not redirected.
+</a>
+<script>
+    location =
+        "https://console.aws.amazon.com/elasticbeanstalk/home?region=us-east-1#/newApplication?applicationName=Metabase&tierName=WebServer&platform=Docker&sourceBundleUrl={{url}}&instanceType=t2.small&withRds=true&rdsDBEngine=postgres&rdsDBAllocatedStorage=10&rdsDBInstanceClass=db.t2.small&rdsMultiAZDatabase=false&rdsDBDeletionPolicy=Snapshot";
+</script>
diff --git a/bin/release/release/set_build_options.clj b/bin/release/release/set_build_options.clj
index f166d506a829f933f7717256c3a85add6c1b1ab8..dcc013bc0654a9fdd2b366a51bc961789b4ab6d5 100644
--- a/bin/release/release/set_build_options.clj
+++ b/bin/release/release/set_build_options.clj
@@ -7,11 +7,10 @@
                            (u/sh "git" "symbolic-ref" "--short" "HEAD"))]
     (loop []
       (let [version (u/read-line-with-prompt "What version are we building (e.g. 0.36.0)?")
-            branch  (u/read-line-with-prompt "What branch are we building from?" :default current-branch)
-            edition (case (u/letter-options-prompt "Is this a [C]ommunity Edition release or an [E]nterprise Edition release?"
-                                                   [:c :e])
-                      :c :ce
-                      :e :ee)]
+            branch  current-branch
+            edition (case (first (c/version))
+                      \0 :ce
+                      \1 :ee)]
         (if-not (u/yes-or-no-prompt (format "Building %s version %s from branch %s. Is this correct?"
                                             (pr-str edition) (pr-str version) (pr-str branch)))
           (do
diff --git a/bin/release/release/uberjar.clj b/bin/release/release/uberjar.clj
index 1a41f27cb8dc3f7047c316664624f3c91fdad1eb..39f28d957a62c6db9f7180fcf11d1d7708424630 100644
--- a/bin/release/release/uberjar.clj
+++ b/bin/release/release/uberjar.clj
@@ -6,33 +6,12 @@
             [release.common :as c]
             [release.common
              [hash :as hash]
-             [http :as common.http]]))
-
-(def ^:private cloudfront-distribution-id
-  "E35CJLWZIZVG7K")
+             [http :as common.http]
+             [upload :as upload]]))
 
 (def ^:private bin-version-file
   (str c/root-directory "/bin/version"))
 
-(defn- s3-artifact-path
-  ([filename]
-   (s3-artifact-path (c/version) filename))
-
-  ([version filename]
-   (str
-    (when (= (c/edition) :ee)
-      "/enterprise")
-    (format "/%s/%s"
-            (if (= version "latest") "latest" (str "v" version))
-            filename))))
-
-(defn- s3-artifact-url
-  ([filename]
-   (s3-artifact-url (c/version) filename))
-
-  ([version filename]
-   (format "s3://downloads.metabase.com%s" (s3-artifact-path version filename))))
-
 (defn- update-version-info! []
   (u/step (format "Update %s if needed" (u/assert-file-exists bin-version-file))
     (u/step "Update version in bin/version"
@@ -86,10 +65,8 @@
 (defn upload-uberjar! []
   (u/step "Upload uberjar and validate"
     (u/step (format "Upload uberjar to %s" (c/artifact-download-url "metabase.jar"))
-      (u/s3-copy! (u/assert-file-exists c/uberjar-path) (s3-artifact-url "metabase.jar"))
-      (u/create-cloudfront-invalidation! cloudfront-distribution-id (s3-artifact-path "metabase.jar")))
+      (upload/upload-artifact! c/uberjar-path "metabase.jar"))
     (when (= (c/edition) :ee)
       (u/step (format "Upload uberjar to %s" (c/artifact-download-url "latest" "metabase.jar"))
-        (u/s3-copy! (u/assert-file-exists c/uberjar-path) (s3-artifact-url "latest" "metabase.jar"))
-        (u/create-cloudfront-invalidation! cloudfront-distribution-id (s3-artifact-path "latest" "metabase.jar"))))
+        (upload/upload-artifact! c/uberjar-path "latest" "metabase.jar")))
     (validate-uberjar)))
diff --git a/docs/operations-guide/running-metabase-on-elastic-beanstalk-old.md b/docs/operations-guide/running-metabase-on-elastic-beanstalk-old.md
index 31974e4a3d90414546cd5254b52694c441211d1f..54cfa000a43fa9c98f930f4da93cee11433a3fd6 100644
--- a/docs/operations-guide/running-metabase-on-elastic-beanstalk-old.md
+++ b/docs/operations-guide/running-metabase-on-elastic-beanstalk-old.md
@@ -58,7 +58,9 @@ The application version describes the exact binary you wish to deploy to your El
 Metabase provides a pre-built AWS Elastic Beanstalk application version which can be linked to directly.
 Simply enter the following url in the `S3 URL` textbox:
 
-https://s3.amazonaws.com/downloads.metabase.com/{{ site.latest_version }}/metabase-aws-eb.zip
+```
+https://s3.amazonaws.com/downloads.metabase.com/{{site.latest_version}}/metabase-aws-eb.zip
+```
 
 Leave all the settings under Deployment Limits on their defaults.  These settings won't impact Metabase.