diff --git a/.gitmodules b/.gitmodules
index 987791ac9db5f..6cd704b370376 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -11,3 +11,6 @@
 [submodule "src/jemalloc"]
 	path = src/jemalloc
 	url = https://github.com/rust-lang/jemalloc.git
+[submodule "src/rust-installer"]
+	path = src/rust-installer
+	url = https://github.com/rust-lang/rust-installer
diff --git a/mk/dist.mk b/mk/dist.mk
index 00f6e8617391d..2db26f819dfdf 100644
--- a/mk/dist.mk
+++ b/mk/dist.mk
@@ -58,6 +58,7 @@ PKG_FILES := \
       rt                                       \
       rustllvm                                 \
       snapshots.txt                            \
+      rust-installer                           \
       test)                                    \
     $(PKG_GITMODULES)                          \
     $(filter-out config.stamp, \
@@ -209,33 +210,40 @@ distcheck-osx: dist-osx
 # Unix binary installer tarballs
 ######################################################################
 
+NON_INSTALLED_PREFIXES=COPYRIGHT,LICENSE-APACHE,LICENSE-MIT,README.md,doc
+
 define DEF_INSTALLER
 
 $$(eval $$(call DEF_PREPARE,dir-$(1)))
 
 dist-install-dir-$(1): PREPARE_HOST=$(1)
 dist-install-dir-$(1): PREPARE_TARGETS=$(2)
-dist-install-dir-$(1): PREPARE_DEST_DIR=tmp/dist/$$(PKG_NAME)-$(1)
+dist-install-dir-$(1): PREPARE_DEST_DIR=tmp/dist/$$(PKG_NAME)-$(1)-image
 dist-install-dir-$(1): PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD)
 dist-install-dir-$(1): PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD)
 dist-install-dir-$(1): PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD)
 dist-install-dir-$(1): PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD)
 dist-install-dir-$(1): PREPARE_CLEAN=true
 dist-install-dir-$(1): prepare-base-dir-$(1) docs compiler-docs
-	$$(Q)(cd $$(PREPARE_DEST_DIR)/ && find . -type f | sed 's/^\.\///') \
-      > tmp/dist/manifest-$(1).in
-	$$(Q)mv tmp/dist/manifest-$(1).in $$(PREPARE_DEST_DIR)/$$(CFG_LIBDIR_RELATIVE)/rustlib/manifest.in
-# Add remaining non-installed files
 	$$(Q)$$(PREPARE_MAN_CMD) $$(S)COPYRIGHT $$(PREPARE_DEST_DIR)
 	$$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-APACHE $$(PREPARE_DEST_DIR)
 	$$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-MIT $$(PREPARE_DEST_DIR)
 	$$(Q)$$(PREPARE_MAN_CMD) $$(S)README.md $$(PREPARE_DEST_DIR)
 	$$(Q)cp -r doc $$(PREPARE_DEST_DIR)
-	$$(Q)$$(PREPARE_BIN_CMD) $$(S)src/etc/install.sh $$(PREPARE_DEST_DIR)
 
 dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1)
 	@$(call E, build: $$@)
-	$$(Q)tar -czf dist/$$(PKG_NAME)-$(1).tar.gz -C tmp/dist $$(PKG_NAME)-$(1)
+	$$(Q)$$(S)src/rust-installer/gen-installer.sh \
+		--product-name=Rust \
+		--verify-bin=rustc \
+		--rel-manifest-dir=rustlib \
+		--success-message=Rust-is-ready-to-roll. \
+		--image-dir=tmp/dist/$$(PKG_NAME)-$(1)-image \
+		--work-dir=tmp/dist \
+		--output-dir=dist \
+		--non-installed-prefixes=$$(NON_INSTALLED_PREFIXES) \
+		--package-name=$$(PKG_NAME)-$(1)
+	$$(Q)rm -R tmp/dist/$$(PKG_NAME)-$(1)-image
 
 endef
 
diff --git a/mk/install.mk b/mk/install.mk
index 88b451f661af2..632df3c754b8d 100644
--- a/mk/install.mk
+++ b/mk/install.mk
@@ -25,7 +25,7 @@ endif
 # Remove tmp files because it's a decent amount of disk space
 	$(Q)rm -R tmp/dist
 
-prepare_install: dist-install-dir-$(CFG_BUILD) | tmp/empty_dir
+prepare_install: dist/$(PKG_NAME)-$(CFG_BUILD).tar.gz | tmp/empty_dir
 
 uninstall:
 ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
@@ -38,7 +38,7 @@ endif
 # Remove tmp files because it's a decent amount of disk space
 	$(Q)rm -R tmp/dist
 
-prepare_uninstall: dist-install-dir-$(CFG_BUILD) | tmp/empty_dir
+prepare_uninstall: dist/$(PKG_NAME)-$(CFG_BUILD).tar.gz | tmp/empty_dir
 
 .PHONY: install prepare_install uninstall prepare_uninstall
 
diff --git a/src/etc/install.sh b/src/etc/install.sh
deleted file mode 100644
index 8bc48fc7934e2..0000000000000
--- a/src/etc/install.sh
+++ /dev/null
@@ -1,519 +0,0 @@
-#!/bin/sh
-# Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-msg() {
-    echo "install: $1"
-}
-
-step_msg() {
-    msg
-    msg "$1"
-    msg
-}
-
-warn() {
-    echo "install: WARNING: $1"
-}
-
-err() {
-    echo "install: error: $1"
-    exit 1
-}
-
-need_ok() {
-    if [ $? -ne 0 ]
-    then
-        err "$1"
-    fi
-}
-
-need_cmd() {
-    if command -v $1 >/dev/null 2>&1
-    then msg "found $1"
-    else err "need $1"
-    fi
-}
-
-putvar() {
-    local T
-    eval T=\$$1
-    eval TLEN=\${#$1}
-    if [ $TLEN -gt 35 ]
-    then
-        printf "install: %-20s := %.35s ...\n" $1 "$T"
-    else
-        printf "install: %-20s := %s %s\n" $1 "$T" "$2"
-    fi
-}
-
-valopt() {
-    VAL_OPTIONS="$VAL_OPTIONS $1"
-
-    local OP=$1
-    local DEFAULT=$2
-    shift
-    shift
-    local DOC="$*"
-    if [ $HELP -eq 0 ]
-    then
-        local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_')
-        local V="CFG_${UOP}"
-        eval $V="$DEFAULT"
-        for arg in $CFG_ARGS
-        do
-            if echo "$arg" | grep -q -- "--$OP="
-            then
-                val=$(echo "$arg" | cut -f2 -d=)
-                eval $V=$val
-            fi
-        done
-        putvar $V
-    else
-        if [ -z "$DEFAULT" ]
-        then
-            DEFAULT="<none>"
-        fi
-        OP="${OP}=[${DEFAULT}]"
-        printf "    --%-30s %s\n" "$OP" "$DOC"
-    fi
-}
-
-opt() {
-    BOOL_OPTIONS="$BOOL_OPTIONS $1"
-
-    local OP=$1
-    local DEFAULT=$2
-    shift
-    shift
-    local DOC="$*"
-    local FLAG=""
-
-    if [ $DEFAULT -eq 0 ]
-    then
-        FLAG="enable"
-    else
-        FLAG="disable"
-        DOC="don't $DOC"
-    fi
-
-    if [ $HELP -eq 0 ]
-    then
-        for arg in $CFG_ARGS
-        do
-            if [ "$arg" = "--${FLAG}-${OP}" ]
-            then
-                OP=$(echo $OP | tr 'a-z-' 'A-Z_')
-                FLAG=$(echo $FLAG | tr 'a-z' 'A-Z')
-                local V="CFG_${FLAG}_${OP}"
-                eval $V=1
-                putvar $V
-            fi
-        done
-    else
-        if [ ! -z "$META" ]
-        then
-            OP="$OP=<$META>"
-        fi
-        printf "    --%-30s %s\n" "$FLAG-$OP" "$DOC"
-     fi
-}
-
-flag() {
-    BOOL_OPTIONS="$BOOL_OPTIONS $1"
-
-    local OP=$1
-    shift
-    local DOC="$*"
-
-    if [ $HELP -eq 0 ]
-    then
-        for arg in $CFG_ARGS
-        do
-            if [ "$arg" = "--${OP}" ]
-            then
-                OP=$(echo $OP | tr 'a-z-' 'A-Z_')
-                local V="CFG_${OP}"
-                eval $V=1
-                putvar $V
-            fi
-        done
-    else
-        if [ ! -z "$META" ]
-        then
-            OP="$OP=<$META>"
-        fi
-        printf "    --%-30s %s\n" "$OP" "$DOC"
-     fi
-}
-
-validate_opt () {
-    for arg in $CFG_ARGS
-    do
-        isArgValid=0
-        for option in $BOOL_OPTIONS
-        do
-            if test --disable-$option = $arg
-            then
-                isArgValid=1
-            fi
-            if test --enable-$option = $arg
-            then
-                isArgValid=1
-            fi
-            if test --$option = $arg
-            then
-                isArgValid=1
-            fi
-        done
-        for option in $VAL_OPTIONS
-        do
-            if echo "$arg" | grep -q -- "--$option="
-            then
-                isArgValid=1
-            fi
-        done
-        if [ "$arg" = "--help" ]
-        then
-            echo
-            echo "No more help available for Configure options,"
-            echo "check the Wiki or join our IRC channel"
-            break
-        else
-            if test $isArgValid -eq 0
-            then
-                err "Option '$arg' is not recognized"
-            fi
-        fi
-    done
-}
-
-absolutify() {
-    FILE_PATH="${1}"
-    FILE_PATH_DIRNAME="$(dirname ${FILE_PATH})"
-    FILE_PATH_BASENAME="$(basename ${FILE_PATH})"
-    FILE_ABS_PATH="$(cd ${FILE_PATH_DIRNAME} && pwd)"
-    FILE_PATH="${FILE_ABS_PATH}/${FILE_PATH_BASENAME}"
-    # This is the return value
-    ABSOLUTIFIED="${FILE_PATH}"
-}
-
-msg "looking for install programs"
-need_cmd mkdir
-need_cmd printf
-need_cmd cut
-need_cmd grep
-need_cmd uname
-need_cmd tr
-need_cmd sed
-
-CFG_SRC_DIR="$(cd $(dirname $0) && pwd)"
-CFG_SELF="$0"
-CFG_ARGS="$@"
-
-HELP=0
-if [ "$1" = "--help" ]
-then
-    HELP=1
-    shift
-    echo
-    echo "Usage: $CFG_SELF [options]"
-    echo
-    echo "Options:"
-    echo
-else
-    step_msg "processing $CFG_SELF args"
-fi
-
-# Check for mingw or cygwin in order to special case $CFG_LIBDIR_RELATIVE.
-# This logic is duplicated from configure in order to get the correct libdir
-# for Windows installs.
-CFG_OSTYPE=$(uname -s)
-
-case $CFG_OSTYPE in
-
-    MINGW32*)
-        CFG_OSTYPE=pc-mingw32
-        ;;
-
-    MINGW64*)
-        # msys2, MSYSTEM=MINGW64
-        CFG_OSTYPE=w64-mingw32
-        ;;
-
-# Thad's Cygwin identifers below
-
-#   Vista 32 bit
-    CYGWIN_NT-6.0)
-        CFG_OSTYPE=pc-mingw32
-        ;;
-
-#   Vista 64 bit
-    CYGWIN_NT-6.0-WOW64)
-        CFG_OSTYPE=w64-mingw32
-        ;;
-
-#   Win 7 32 bit
-    CYGWIN_NT-6.1)
-        CFG_OSTYPE=pc-mingw32
-        ;;
-
-#   Win 7 64 bit
-    CYGWIN_NT-6.1-WOW64)
-        CFG_OSTYPE=w64-mingw32
-        ;;
-esac
-
-OPTIONS=""
-BOOL_OPTIONS=""
-VAL_OPTIONS=""
-
-# On windows we just store the libraries in the bin directory because
-# there's no rpath. This is where the build system itself puts libraries;
-# --libdir is used to configure the installation directory.
-# FIXME: Thise needs to parameterized over target triples. Do it in platform.mk
-CFG_LIBDIR_RELATIVE=lib
-if [ "$CFG_OSTYPE" = "pc-mingw32" ] || [ "$CFG_OSTYPE" = "w64-mingw32" ]
-then
-    CFG_LIBDIR_RELATIVE=bin
-fi
-
-if [ "$CFG_OSTYPE" = "pc-mingw32" ] || [ "$CFG_OSTYPE" = "w64-mingw32" ]
-then
-    CFG_LD_PATH_VAR=PATH
-    CFG_OLD_LD_PATH_VAR=$PATH
-elif [ "$CFG_OSTYPE" = "Darwin" ]
-then
-    CFG_LD_PATH_VAR=DYLD_LIBRARY_PATH
-    CFG_OLD_LD_PATH_VAR=$DYLD_LIBRARY_PATH
-else
-    CFG_LD_PATH_VAR=LD_LIBRARY_PATH
-    CFG_OLD_LD_PATH_VAR=$LD_LIBRARY_PATH
-fi
-
-flag uninstall "only uninstall from the installation prefix"
-opt verify 1 "verify that the installed binaries run correctly"
-valopt prefix "/usr/local" "set installation prefix"
-# NB This is exactly the same definition as in `configure`.
-valopt libdir "${CFG_PREFIX}/${CFG_LIBDIR_RELATIVE}" "install libraries"
-case "$CFG_LIBDIR" in
-    "$CFG_PREFIX"/*) CAT_INC=2;;
-    "$CFG_PREFIX"*)  CAT_INC=1;;
-    *)
-        err "libdir must begin with the prefix. Use --prefix to set it accordingly.";;
-esac
-CFG_LIBDIR_RELATIVE=`echo ${CFG_LIBDIR} | cut -c$((${#CFG_PREFIX}+${CAT_INC}))-`
-
-valopt mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
-
-if [ $HELP -eq 1 ]
-then
-    echo
-    exit 0
-fi
-
-step_msg "validating $CFG_SELF args"
-validate_opt
-
-
-# OK, let's get installing ...
-
-# Sanity check: can we run the binaries?
-if [ -z "${CFG_DISABLE_VERIFY}" ]
-then
-    # Don't do this if uninstalling. Failure here won't help in any way.
-    if [ -z "${CFG_UNINSTALL}" ]
-    then
-        msg "verifying platform can run binaries"
-        export $CFG_LD_PATH_VAR="${CFG_SRC_DIR}/lib:$CFG_OLD_LD_PATH_VAR"
-        "${CFG_SRC_DIR}/bin/rustc" --version > /dev/null
-        if [ $? -ne 0 ]
-        then
-            err "can't execute rustc binary on this platform"
-        fi
-        export $CFG_LD_PATH_VAR=$CFG_OLD_LD_PATH_VAR
-    fi
-fi
-
-# Sanity check: can we can write to the destination?
-msg "verifying destination is writable"
-umask 022 && mkdir -p "${CFG_LIBDIR}"
-need_ok "can't write to destination. consider \`sudo\`."
-touch "${CFG_LIBDIR}/rust-install-probe" > /dev/null
-if [ $? -ne 0 ]
-then
-    err "can't write to destination. consider \`sudo\`."
-fi
-rm -f "${CFG_LIBDIR}/rust-install-probe"
-need_ok "failed to remove install probe"
-
-# Sanity check: don't install to the directory containing the installer.
-# That would surely cause chaos.
-msg "verifying destination is not the same as source"
-INSTALLER_DIR="$(cd $(dirname $0) && pwd)"
-PREFIX_DIR="$(cd ${CFG_PREFIX} && pwd)"
-if [ "${INSTALLER_DIR}" = "${PREFIX_DIR}" ]
-then
-    err "can't install to same directory as installer"
-fi
-
-# Using an absolute path to libdir in a few places so that the status
-# messages are consistently using absolute paths.
-absolutify "${CFG_LIBDIR}"
-ABS_LIBDIR="${ABSOLUTIFIED}"
-
-# The file name of the manifest we're going to create during install
-INSTALLED_MANIFEST="${ABS_LIBDIR}/rustlib/manifest"
-
-# First, uninstall from the installation prefix.
-# Errors are warnings - try to rm everything in the manifest even if some fail.
-if [ -f "${INSTALLED_MANIFEST}" ]
-then
-    # Iterate through installed manifest and remove files
-    while read p; do
-        # The installed manifest contains absolute paths
-        msg "removing $p"
-        if [ -f "$p" ]
-        then
-            rm -f "$p"
-            if [ $? -ne 0 ]
-            then
-                warn "failed to remove $p"
-            fi
-        else
-            warn "supposedly installed file $p does not exist!"
-        fi
-    done < "${INSTALLED_MANIFEST}"
-
-    # If we fail to remove rustlib below, then the installed manifest will
-    # still be full; the installed manifest needs to be empty before install.
-    msg "removing ${INSTALLED_MANIFEST}"
-    rm -f "${INSTALLED_MANIFEST}"
-    # For the above reason, this is a hard error
-    need_ok "failed to remove installed manifest"
-
-    # Remove 'rustlib' directory
-    msg "removing ${ABS_LIBDIR}/rustlib"
-    rm -Rf "${ABS_LIBDIR}/rustlib"
-    if [ $? -ne 0 ]
-    then
-        warn "failed to remove rustlib"
-    fi
-else
-    # There's no manifest. If we were asked to uninstall, then that's a problem.
-    if [ -n "${CFG_UNINSTALL}" ]
-    then
-        err "unable to find installation manifest at ${CFG_LIBDIR}/rustlib"
-    fi
-fi
-
-# If we're only uninstalling then exit
-if [ -n "${CFG_UNINSTALL}" ]
-then
-    echo
-    echo "    Rust is uninstalled. Have a nice day."
-    echo
-    exit 0
-fi
-
-# Create the installed manifest, which we will fill in with absolute file paths
-mkdir -p "${CFG_LIBDIR}/rustlib"
-need_ok "failed to create rustlib"
-touch "${INSTALLED_MANIFEST}"
-need_ok "failed to create installed manifest"
-
-# Now install, iterate through the new manifest and copy files
-while read p; do
-
-    # Decide the destination of the file
-    FILE_INSTALL_PATH="${CFG_PREFIX}/$p"
-
-    if echo "$p" | grep "^${CFG_LIBDIR_RELATIVE}/" > /dev/null
-    then
-        pp=`echo $p | sed "s%^${CFG_LIBDIR_RELATIVE}/%%"`
-        FILE_INSTALL_PATH="${CFG_LIBDIR}/$pp"
-    fi
-
-    if echo "$p" | grep "^share/man/" > /dev/null
-    then
-        pp=`echo $p | sed 's/^share\/man\///'`
-        FILE_INSTALL_PATH="${CFG_MANDIR}/$pp"
-    fi
-
-    # Make sure there's a directory for it
-    umask 022 && mkdir -p "$(dirname ${FILE_INSTALL_PATH})"
-    need_ok "directory creation failed"
-
-    # Make the path absolute so we can uninstall it later without
-    # starting from the installation cwd
-    absolutify "${FILE_INSTALL_PATH}"
-    FILE_INSTALL_PATH="${ABSOLUTIFIED}"
-
-    # Install the file
-    msg "${FILE_INSTALL_PATH}"
-    if echo "$p" | grep "^bin/" > /dev/null
-    then
-        install -m755 "${CFG_SRC_DIR}/$p" "${FILE_INSTALL_PATH}"
-    else
-        install -m644 "${CFG_SRC_DIR}/$p" "${FILE_INSTALL_PATH}"
-    fi
-    need_ok "file creation failed"
-
-    # Update the manifest
-    echo "${FILE_INSTALL_PATH}" >> "${INSTALLED_MANIFEST}"
-    need_ok "failed to update manifest"
-
-# The manifest lists all files to install
-done < "${CFG_SRC_DIR}/${CFG_LIBDIR_RELATIVE}/rustlib/manifest.in"
-
-# Run ldconfig to make dynamic libraries available to the linker
-if [ "$CFG_OSTYPE" = "Linux" ]
-    then
-    ldconfig
-    if [ $? -ne 0 ]
-    then
-        warn "failed to run ldconfig."
-        warn "this may happen when not installing as root and may be fine"
-    fi
-fi
-
-# Sanity check: can we run the installed binaries?
-#
-# As with the verification above, make sure the right LD_LIBRARY_PATH-equivalent
-# is in place. Try first without this variable, and if that fails try again with
-# the variable. If the second time tries, print a hopefully helpful message to
-# add something to the appropriate environment variable.
-if [ -z "${CFG_DISABLE_VERIFY}" ]
-then
-    msg "verifying installed binaries are executable"
-    "${CFG_PREFIX}/bin/rustc" --version 2> /dev/null 1> /dev/null
-    if [ $? -ne 0 ]
-    then
-        export $CFG_LD_PATH_VAR="${CFG_PREFIX}/lib:$CFG_OLD_LD_PATH_VAR"
-        "${CFG_PREFIX}/bin/rustc" --version > /dev/null
-        if [ $? -ne 0 ]
-        then
-            ERR="can't execute installed rustc binary. "
-            ERR="${ERR}installation may be broken. "
-            ERR="${ERR}if this is expected then rerun install.sh with \`--disable-verify\` "
-            ERR="${ERR}or \`make install\` with \`--disable-verify-install\`"
-            err "${ERR}"
-        else
-            echo
-            echo "    Note: please ensure '${CFG_PREFIX}/lib' is added to ${CFG_LD_PATH_VAR}"
-        fi
-    fi
-fi
-
-echo
-echo "    Rust is ready to roll."
-echo
-
-
diff --git a/src/rust-installer b/src/rust-installer
new file mode 160000
index 0000000000000..aed7347241606
--- /dev/null
+++ b/src/rust-installer
@@ -0,0 +1 @@
+Subproject commit aed73472416064642911af790b25d57c9390b6c7