2016-10-24 16:18:02 +02:00
|
|
|
#!/bin/bash
|
|
|
|
|
|
2016-10-25 12:00:54 -07:00
|
|
|
set -eu -o pipefail
|
2016-10-24 16:18:02 +02:00
|
|
|
|
2016-10-24 14:52:30 -07:00
|
|
|
# change this to a hash when we make a upgrade release
|
2016-10-25 14:01:35 +02:00
|
|
|
readonly LOG_FILE="/var/log/cloudron-setup.log"
|
2017-03-22 14:21:40 +01:00
|
|
|
readonly MINIMUM_DISK_SIZE_GB="18" # this is the size of "/" and required to fit in docker images 18 is a safe bet for different reporting on 20GB min
|
2017-03-13 13:05:59 -07:00
|
|
|
readonly MINIMUM_MEMORY="974" # this is mostly reported for 1GB main memory (DO 992, EC2 990, Linode 989, Serverdiscounter.com 974)
|
2017-01-02 18:02:40 +01:00
|
|
|
|
2017-02-16 17:32:44 -08:00
|
|
|
readonly curl="curl --fail --connect-timeout 20 --retry 10 --retry-delay 2 --max-time 2400"
|
|
|
|
|
|
2017-01-02 18:02:40 +01:00
|
|
|
# copied from cloudron-resize-fs.sh
|
2017-07-24 18:14:51 -07:00
|
|
|
readonly rootfs_type=$(LC_ALL=C df --output=fstype / | tail -n1)
|
2017-03-13 10:32:27 -07:00
|
|
|
readonly physical_memory=$(LC_ALL=C free -m | awk '/Mem:/ { print $2 }')
|
2017-03-27 13:51:34 +02:00
|
|
|
readonly disk_size_bytes=$(LC_ALL=C df --output=size / | tail -n1)
|
2017-03-22 14:21:40 +01:00
|
|
|
readonly disk_size_gb=$((${disk_size_bytes}/1024/1024))
|
2017-01-02 18:02:40 +01:00
|
|
|
|
2018-03-07 15:48:01 -08:00
|
|
|
readonly RED='\033[31m'
|
|
|
|
|
readonly GREEN='\033[32m'
|
|
|
|
|
readonly DONE='\033[m'
|
|
|
|
|
|
2017-01-02 18:02:40 +01:00
|
|
|
# verify the system has minimum requirements met
|
2017-07-24 18:14:51 -07:00
|
|
|
if [[ "${rootfs_type}" != "ext4" ]]; then
|
|
|
|
|
echo "Error: Cloudron requires '/' to be ext4" # see #364
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2017-01-02 18:02:40 +01:00
|
|
|
if [[ "${physical_memory}" -lt "${MINIMUM_MEMORY}" ]]; then
|
2017-01-03 14:27:01 -08:00
|
|
|
echo "Error: Cloudron requires atleast 1GB physical memory"
|
2017-01-02 18:02:40 +01:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [[ "${disk_size_gb}" -lt "${MINIMUM_DISK_SIZE_GB}" ]]; then
|
2017-03-27 13:51:34 +02:00
|
|
|
echo "Error: Cloudron requires atleast 20GB disk space (Disk space on / is ${disk_size_gb}GB)"
|
2017-01-02 18:02:40 +01:00
|
|
|
exit 1
|
|
|
|
|
fi
|
2016-10-24 14:52:30 -07:00
|
|
|
|
2018-07-30 10:08:00 -07:00
|
|
|
if systemctl -q is-active box; then
|
|
|
|
|
echo "Error: Cloudron is already installed. To reinstall, start afresh"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2016-12-26 11:37:50 -08:00
|
|
|
initBaseImage="true"
|
|
|
|
|
# provisioning data
|
2016-10-26 10:53:25 -07:00
|
|
|
provider=""
|
2017-04-13 15:20:33 -07:00
|
|
|
requestedVersion=""
|
2017-01-11 12:35:31 -08:00
|
|
|
apiServerOrigin="https://api.cloudron.io"
|
2017-06-08 10:30:23 -07:00
|
|
|
webServerOrigin="https://cloudron.io"
|
2017-02-01 14:06:18 -08:00
|
|
|
sourceTarballUrl=""
|
2017-02-07 12:42:32 +01:00
|
|
|
rebootServer="true"
|
2019-05-07 15:29:34 -07:00
|
|
|
license=""
|
2016-10-24 16:18:02 +02:00
|
|
|
|
2019-05-07 14:15:35 -07:00
|
|
|
args=$(getopt -o "" -l "help,skip-baseimage-init,provider:,version:,env:,skip-reboot,license:" -n "$0" -- "$@")
|
2016-10-24 16:18:02 +02:00
|
|
|
eval set -- "${args}"
|
|
|
|
|
|
|
|
|
|
while true; do
|
|
|
|
|
case "$1" in
|
2017-10-20 22:13:54 +02:00
|
|
|
--help) echo "See https://cloudron.io/documentation/installation/ on how to install Cloudron"; exit 0;;
|
2016-10-24 16:18:02 +02:00
|
|
|
--provider) provider="$2"; shift 2;;
|
2016-12-30 13:12:22 -08:00
|
|
|
--version) requestedVersion="$2"; shift 2;;
|
2017-01-10 20:19:39 -08:00
|
|
|
--env)
|
|
|
|
|
if [[ "$2" == "dev" ]]; then
|
2017-01-11 12:35:31 -08:00
|
|
|
apiServerOrigin="https://api.dev.cloudron.io"
|
2017-06-08 10:30:23 -07:00
|
|
|
webServerOrigin="https://dev.cloudron.io"
|
2017-01-10 20:19:39 -08:00
|
|
|
elif [[ "$2" == "staging" ]]; then
|
2017-01-11 12:35:31 -08:00
|
|
|
apiServerOrigin="https://api.staging.cloudron.io"
|
2017-06-08 10:30:23 -07:00
|
|
|
webServerOrigin="https://staging.cloudron.io"
|
2017-01-10 20:19:39 -08:00
|
|
|
fi
|
|
|
|
|
shift 2;;
|
2019-05-07 14:15:35 -07:00
|
|
|
--license) license="$2"; shift 2;;
|
2016-12-26 10:00:00 -08:00
|
|
|
--skip-baseimage-init) initBaseImage="false"; shift;;
|
2017-02-07 12:42:32 +01:00
|
|
|
--skip-reboot) rebootServer="false"; shift;;
|
2016-10-24 16:18:02 +02:00
|
|
|
--) break;;
|
|
|
|
|
*) echo "Unknown option $1"; exit 1;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
2018-03-09 10:37:18 -08:00
|
|
|
# Only --help works as non-root
|
|
|
|
|
if [[ ${EUID} -ne 0 ]]; then
|
|
|
|
|
echo "This script should be run as root." > /dev/stderr
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Only --help works with mismatched ubuntu
|
2018-10-05 10:27:34 -07:00
|
|
|
ubuntu_version=$(lsb_release -rs)
|
|
|
|
|
if [[ "${ubuntu_version}" != "16.04" && "${ubuntu_version}" != "18.04" ]]; then
|
|
|
|
|
echo "Cloudron requires Ubuntu 16.04 or 18.04" > /dev/stderr
|
2018-03-09 10:37:18 -08:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2018-10-25 11:31:39 -07:00
|
|
|
# Can only write after we have confirmed script has root access
|
|
|
|
|
echo "Running cloudron-setup with args : $@" > "${LOG_FILE}"
|
|
|
|
|
|
2016-12-27 13:36:02 -08:00
|
|
|
# validate arguments in the absence of data
|
2020-02-28 11:14:06 -08:00
|
|
|
readonly AVAILABLE_PROVIDERS="azure, caas, cloudscale, contabo, digitalocean, ec2, exoscale, gce, hetzner, interox, lightsail, linode, netcup, ovh, rosehosting, scaleway, skysilk, time4vps, upcloud, vultr or generic"
|
2018-01-30 19:08:06 -08:00
|
|
|
if [[ -z "${provider}" ]]; then
|
2019-07-29 20:54:41 +02:00
|
|
|
echo "--provider is required ($AVAILABLE_PROVIDERS)"
|
2018-01-30 19:08:06 -08:00
|
|
|
exit 1
|
|
|
|
|
elif [[ \
|
2019-12-11 12:56:30 -08:00
|
|
|
"${provider}" != "ami" && \
|
2018-01-30 19:08:06 -08:00
|
|
|
"${provider}" != "azure" && \
|
2019-12-17 16:42:25 +01:00
|
|
|
"${provider}" != "azure-image" && \
|
2018-02-17 10:27:39 -08:00
|
|
|
"${provider}" != "caas" && \
|
2018-01-30 19:08:06 -08:00
|
|
|
"${provider}" != "cloudscale" && \
|
2018-12-21 11:09:12 -08:00
|
|
|
"${provider}" != "contabo" && \
|
2018-01-30 19:08:06 -08:00
|
|
|
"${provider}" != "digitalocean" && \
|
2019-02-06 16:15:36 -08:00
|
|
|
"${provider}" != "digitalocean-mp" && \
|
2018-01-30 19:08:06 -08:00
|
|
|
"${provider}" != "ec2" && \
|
|
|
|
|
"${provider}" != "exoscale" && \
|
|
|
|
|
"${provider}" != "gce" && \
|
|
|
|
|
"${provider}" != "hetzner" && \
|
2019-08-14 14:47:08 +02:00
|
|
|
"${provider}" != "interox" && \
|
|
|
|
|
"${provider}" != "interox-image" && \
|
2018-01-30 19:08:06 -08:00
|
|
|
"${provider}" != "lightsail" && \
|
|
|
|
|
"${provider}" != "linode" && \
|
2020-03-05 11:25:39 -08:00
|
|
|
"${provider}" != "linode-oneclick" && \
|
2019-02-16 13:59:35 -08:00
|
|
|
"${provider}" != "linode-stackscript" && \
|
2018-12-04 09:51:40 +01:00
|
|
|
"${provider}" != "netcup" && \
|
2019-02-09 18:01:31 +01:00
|
|
|
"${provider}" != "netcup-image" && \
|
2018-01-30 19:08:06 -08:00
|
|
|
"${provider}" != "ovh" && \
|
|
|
|
|
"${provider}" != "rosehosting" && \
|
|
|
|
|
"${provider}" != "scaleway" && \
|
2019-09-11 09:14:04 -07:00
|
|
|
"${provider}" != "skysilk" && \
|
|
|
|
|
"${provider}" != "skysilk-image" && \
|
2019-07-29 20:54:41 +02:00
|
|
|
"${provider}" != "time4vps" && \
|
|
|
|
|
"${provider}" != "time4vps-image" && \
|
2019-04-11 15:41:34 +02:00
|
|
|
"${provider}" != "upcloud" && \
|
|
|
|
|
"${provider}" != "upcloud-image" && \
|
2018-01-30 19:08:06 -08:00
|
|
|
"${provider}" != "vultr" && \
|
|
|
|
|
"${provider}" != "generic" \
|
|
|
|
|
]]; then
|
2019-07-29 20:54:41 +02:00
|
|
|
echo "--provider must be one of: $AVAILABLE_PROVIDERS"
|
2018-01-30 19:08:06 -08:00
|
|
|
exit 1
|
|
|
|
|
fi
|
2016-10-26 10:53:25 -07:00
|
|
|
|
2016-10-25 15:28:26 +02:00
|
|
|
echo ""
|
2016-10-25 14:07:28 +02:00
|
|
|
echo "##############################################"
|
2017-04-13 15:20:33 -07:00
|
|
|
echo " Cloudron Setup (${requestedVersion:-latest})"
|
2016-10-25 14:07:28 +02:00
|
|
|
echo "##############################################"
|
|
|
|
|
echo ""
|
|
|
|
|
echo " Follow setup logs in a second terminal with:"
|
|
|
|
|
echo " $ tail -f ${LOG_FILE}"
|
|
|
|
|
echo ""
|
2018-03-08 10:50:18 -08:00
|
|
|
echo " Join us at https://forum.cloudron.io for any questions."
|
2016-12-22 13:28:04 -08:00
|
|
|
echo ""
|
2016-10-25 14:07:28 +02:00
|
|
|
|
2017-01-05 14:03:30 -08:00
|
|
|
if [[ "${initBaseImage}" == "true" ]]; then
|
2018-12-21 11:28:21 -08:00
|
|
|
echo "=> Installing software-properties-common"
|
2019-01-10 15:28:56 +01:00
|
|
|
if ! apt-get install -y software-properties-common &>> "${LOG_FILE}"; then
|
2018-12-21 11:28:21 -08:00
|
|
|
echo "Could not install software-properties-common (for add-apt-repository below). See ${LOG_FILE}"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2018-12-06 13:23:30 +01:00
|
|
|
echo "=> Ensure required apt sources"
|
|
|
|
|
if ! add-apt-repository universe &>> "${LOG_FILE}"; then
|
2018-12-06 09:32:02 -08:00
|
|
|
echo "Could not add required apt sources (for nginx-full). See ${LOG_FILE}"
|
2018-12-06 13:23:30 +01:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2017-02-12 20:48:36 +01:00
|
|
|
echo "=> Updating apt and installing script dependencies"
|
2017-01-05 14:03:30 -08:00
|
|
|
if ! apt-get update &>> "${LOG_FILE}"; then
|
2018-09-06 09:16:11 -07:00
|
|
|
echo "Could not update package repositories. See ${LOG_FILE}"
|
2017-01-05 14:03:30 -08:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2019-09-17 14:43:11 -07:00
|
|
|
if ! DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y install curl python3 ubuntu-standard -y &>> "${LOG_FILE}"; then
|
2018-09-06 09:16:11 -07:00
|
|
|
echo "Could not install setup dependencies (curl). See ${LOG_FILE}"
|
2017-01-05 14:03:30 -08:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
2016-10-25 13:05:24 -07:00
|
|
|
echo "=> Checking version"
|
2018-10-24 15:27:09 -07:00
|
|
|
if ! releaseJson=$($curl -s "${apiServerOrigin}/api/v1/releases?boxVersion=${requestedVersion}"); then
|
2018-01-31 20:14:31 -08:00
|
|
|
echo "Failed to get release information"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
2017-04-13 15:20:33 -07:00
|
|
|
|
2018-01-31 20:14:31 -08:00
|
|
|
if [[ "$requestedVersion" == "" ]]; then
|
|
|
|
|
version=$(echo "${releaseJson}" | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(obj["version"])')
|
|
|
|
|
else
|
|
|
|
|
version="${requestedVersion}"
|
|
|
|
|
fi
|
2017-04-13 15:20:33 -07:00
|
|
|
|
2018-01-31 20:14:31 -08:00
|
|
|
if ! sourceTarballUrl=$(echo "${releaseJson}" | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(obj["info"]["sourceTarballUrl"])'); then
|
|
|
|
|
echo "No source code for version '${requestedVersion:-latest}'"
|
|
|
|
|
exit 1
|
2016-10-25 13:05:24 -07:00
|
|
|
fi
|
|
|
|
|
|
2017-01-03 14:48:37 -08:00
|
|
|
echo "=> Downloading version ${version} ..."
|
2016-12-23 18:28:18 -08:00
|
|
|
box_src_tmp_dir=$(mktemp -dt box-src-XXXXXX)
|
|
|
|
|
|
2017-02-16 17:32:44 -08:00
|
|
|
if ! $curl -sL "${sourceTarballUrl}" | tar -zxf - -C "${box_src_tmp_dir}"; then
|
2016-12-23 18:28:18 -08:00
|
|
|
echo "Could not download source tarball. See ${LOG_FILE} for details"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
2017-01-03 14:48:37 -08:00
|
|
|
|
|
|
|
|
if [[ "${initBaseImage}" == "true" ]]; then
|
2017-01-19 09:58:31 -08:00
|
|
|
echo -n "=> Installing base dependencies and downloading docker images (this takes some time) ..."
|
2017-01-09 09:22:22 -08:00
|
|
|
if ! /bin/bash "${box_src_tmp_dir}/baseimage/initializeBaseUbuntuImage.sh" "${provider}" "../src" &>> "${LOG_FILE}"; then
|
2017-01-03 14:48:37 -08:00
|
|
|
echo "Init script failed. See ${LOG_FILE} for details"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
2017-01-19 09:58:31 -08:00
|
|
|
echo ""
|
2017-01-03 14:48:37 -08:00
|
|
|
fi
|
|
|
|
|
|
2020-02-07 09:15:12 -08:00
|
|
|
# NOTE: this install script only supports 4.2 and above
|
2017-01-03 14:48:37 -08:00
|
|
|
echo "=> Installing version ${version} (this takes some time) ..."
|
2019-04-25 19:38:24 -07:00
|
|
|
mkdir -p /etc/cloudron
|
2019-07-26 08:44:37 -07:00
|
|
|
echo "${provider}" > /etc/cloudron/PROVIDER
|
2018-10-26 09:49:52 -07:00
|
|
|
|
2019-05-07 16:48:40 -07:00
|
|
|
[[ -n "${license}" ]] && echo -n "$license" > /etc/cloudron/LICENSE
|
2019-05-07 14:15:35 -07:00
|
|
|
|
2019-04-25 19:38:24 -07:00
|
|
|
if ! /bin/bash "${box_src_tmp_dir}/scripts/installer.sh" &>> "${LOG_FILE}"; then
|
|
|
|
|
echo "Failed to install cloudron. See ${LOG_FILE} for details"
|
|
|
|
|
exit 1
|
2016-10-25 12:47:51 -07:00
|
|
|
fi
|
2016-10-25 11:27:58 +02:00
|
|
|
|
2019-07-26 22:35:44 -07:00
|
|
|
mysql -uroot -ppassword -e "REPLACE INTO box.settings (name, value) VALUES ('api_server_origin', '${apiServerOrigin}');" 2>/dev/null
|
|
|
|
|
mysql -uroot -ppassword -e "REPLACE INTO box.settings (name, value) VALUES ('web_server_origin', '${webServerOrigin}');" 2>/dev/null
|
2019-07-26 10:49:29 -07:00
|
|
|
|
2016-12-30 11:35:03 +01:00
|
|
|
echo -n "=> Waiting for cloudron to be ready (this takes some time) ..."
|
2016-10-24 14:52:30 -07:00
|
|
|
while true; do
|
|
|
|
|
echo -n "."
|
2017-02-16 17:32:44 -08:00
|
|
|
if status=$($curl -q -f "http://localhost:3000/api/v1/cloudron/status" 2>/dev/null); then
|
2018-01-30 19:08:06 -08:00
|
|
|
break # we are up and running
|
2016-10-24 14:52:30 -07:00
|
|
|
fi
|
|
|
|
|
sleep 10
|
|
|
|
|
done
|
|
|
|
|
|
2018-12-07 11:28:23 -08:00
|
|
|
echo -e "\n\n${GREEN}Visit https://<IP> and accept the self-signed certificate to finish setup.${DONE}\n"
|
2017-01-05 20:18:57 -08:00
|
|
|
|
2017-02-07 12:42:32 +01:00
|
|
|
if [[ "${rebootServer}" == "true" ]]; then
|
2018-12-07 10:41:13 -08:00
|
|
|
systemctl stop box mysql # sometimes mysql ends up having corrupt privilege tables
|
|
|
|
|
|
2018-12-14 15:01:28 -08:00
|
|
|
read -p "The server has to be rebooted to apply all the settings. Reboot now ? [Y/n] " yn
|
2018-12-07 10:41:13 -08:00
|
|
|
yn=${yn:-y}
|
|
|
|
|
case $yn in
|
|
|
|
|
[Yy]* ) systemctl reboot;;
|
|
|
|
|
* ) exit;;
|
|
|
|
|
esac
|
2017-02-07 12:42:32 +01:00
|
|
|
fi
|