This is then in sync with selfhosting and ensures the init startup sequence is in order, since the setup on its own creates unit files which should run prior to services already running. This hopefully fixes the mysql disconnect issues.
246 lines
8.4 KiB
Bash
Executable File
246 lines
8.4 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -eu -o pipefail
|
|
|
|
if [[ ${EUID} -ne 0 ]]; then
|
|
echo "This script should be run as root." > /dev/stderr
|
|
exit 1
|
|
fi
|
|
|
|
if [[ $(lsb_release -rs) != "16.04" ]]; then
|
|
echo "Cloudron requires Ubuntu 16.04" > /dev/stderr
|
|
exit 1
|
|
fi
|
|
|
|
# change this to a hash when we make a upgrade release
|
|
readonly LOG_FILE="/var/log/cloudron-setup.log"
|
|
readonly MINIMUM_DISK_SIZE_GB="19" # this is the size of "/" and required to fit in docker images 19 is a safe bet for different reporting on 20GB min
|
|
readonly MINIMUM_MEMORY="990" # this is mostly reported for 1GB main memory (DO 992, EC2 990)
|
|
|
|
# copied from cloudron-resize-fs.sh
|
|
readonly physical_memory=$(free -m | awk '/Mem:/ { print $2 }')
|
|
readonly disk_device="$(for d in $(find /dev -type b); do [ "$(mountpoint -d /)" = "$(mountpoint -x $d)" ] && echo $d && break; done)"
|
|
readonly disk_size_bytes=$(fdisk -l ${disk_device} | grep "Disk ${disk_device}" | awk '{ printf $5 }')
|
|
readonly disk_size_gb=$((${disk_size_bytes}/1024/1024/1024))
|
|
|
|
# verify the system has minimum requirements met
|
|
if [[ "${physical_memory}" -lt "${MINIMUM_MEMORY}" ]]; then
|
|
echo "Error: Cloudron requires atleast 1GB physical memory"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "${disk_size_gb}" -lt "${MINIMUM_DISK_SIZE_GB}" ]]; then
|
|
echo "Error: Cloudron requires atleast 20GB disk space (Disk space on ${disk_device} is ${disk_size_gb}GB)"
|
|
exit 1
|
|
fi
|
|
|
|
initBaseImage="true"
|
|
# provisioning data
|
|
domain=""
|
|
provider=""
|
|
encryptionKey=""
|
|
restoreUrl=""
|
|
dnsProvider="manual"
|
|
tlsProvider="le-prod"
|
|
versionsUrl="https://s3.amazonaws.com/prod-cloudron-releases/versions.json"
|
|
requestedVersion="latest"
|
|
apiServerOrigin="https://api.cloudron.io"
|
|
dataJson=""
|
|
prerelease=false
|
|
sourceTarballUrl=""
|
|
|
|
args=$(getopt -o "" -l "domain:,help,skip-baseimage-init,data:,provider:,encryption-key:,restore-url:,tls-provider:,version:,versions-url:,api-server:,dns-provider:,env:,prerelease,source-url:" -n "$0" -- "$@")
|
|
eval set -- "${args}"
|
|
|
|
while true; do
|
|
case "$1" in
|
|
--domain) domain="$2"; shift 2;;
|
|
--help) echo "See https://cloudron.io/references/selfhosting.html on how to install Cloudron"; exit 0;;
|
|
--provider) provider="$2"; shift 2;;
|
|
--encryption-key) encryptionKey="$2"; shift 2;;
|
|
--restore-url) restoreUrl="$2"; shift 2;;
|
|
--tls-provider) tlsProvider="$2"; shift 2;;
|
|
--dns-provider) dnsProvider="$2"; shift 2;;
|
|
--version) requestedVersion="$2"; shift 2;;
|
|
--env)
|
|
if [[ "$2" == "dev" ]]; then
|
|
apiServerOrigin="https://api.dev.cloudron.io"
|
|
versionsUrl="https://s3.amazonaws.com/dev-cloudron-releases/versions.json"
|
|
tlsProvider="le-staging"
|
|
prerelease="true"
|
|
elif [[ "$2" == "staging" ]]; then
|
|
apiServerOrigin="https://api.staging.cloudron.io"
|
|
versionsUrl="https://s3.amazonaws.com/staging-cloudron-releases/versions.json"
|
|
tlsProvider="le-staging"
|
|
prerelease="true"
|
|
fi
|
|
shift 2;;
|
|
--versions-url) versionsUrl="$2"; shift 2;;
|
|
--api-server) apiServerOrigin="$2"; shift 2;;
|
|
--skip-baseimage-init) initBaseImage="false"; shift;;
|
|
--data) dataJson="$2"; shift 2;;
|
|
--prerelease) prerelease="true"; shift;;
|
|
--source-url) sourceTarballUrl="$2"; version="0.0.1+custom"; shift 2;;
|
|
--) break;;
|
|
*) echo "Unknown option $1"; exit 1;;
|
|
esac
|
|
done
|
|
|
|
# validate arguments in the absence of data
|
|
if [[ -z "${dataJson}" ]]; then
|
|
if [[ -z "${provider}" ]]; then
|
|
echo "--provider is required (generic, scaleway, ec2, digitalocean)"
|
|
exit 1
|
|
elif [[ \
|
|
"${provider}" != "generic" && \
|
|
"${provider}" != "scaleway" && \
|
|
"${provider}" != "ec2" && \
|
|
"${provider}" != "digitalocean" \
|
|
]]; then
|
|
echo "--provider must be one of: generic, scaleway, ec2, digitalocean"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "${tlsProvider}" != "fallback" && "${tlsProvider}" != "le-prod" && "${tlsProvider}" != "le-staging" ]]; then
|
|
echo "--tls-provider must be one of: le-prod, le-staging, fallback"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -z "${dnsProvider}" ]]; then
|
|
echo "--dns-provider is required (noop, manual)"
|
|
exit 1
|
|
elif [[ "${dnsProvider}" != "noop" && "${dnsProvider}" != "manual" ]]; then
|
|
echo "--dns-provider must be one of : manual, noop"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "##############################################"
|
|
echo " Cloudron Setup (${requestedVersion}) "
|
|
echo "##############################################"
|
|
echo ""
|
|
echo " Follow setup logs in a second terminal with:"
|
|
echo " $ tail -f ${LOG_FILE}"
|
|
echo ""
|
|
echo " Join us at https://chat.cloudron.io for any questions."
|
|
echo ""
|
|
|
|
if [[ "${initBaseImage}" == "true" ]]; then
|
|
echo "=> Updating apt and installing script dependancies"
|
|
if ! apt-get update &>> "${LOG_FILE}"; then
|
|
echo "Could not update package repositories"
|
|
exit 1
|
|
fi
|
|
|
|
if ! apt-get install curl python3 ubuntu-standard -y &>> "${LOG_FILE}"; then
|
|
echo "Could not install setup dependencies (curl)"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo "=> Checking version"
|
|
if [[ "${sourceTarballUrl}" == "" ]]; then
|
|
releaseJson=$(curl -s "${versionsUrl}")
|
|
if [[ "$requestedVersion" == "latest" ]]; then
|
|
pre=$([[ "${prerelease}" == "true" ]] && echo "null" || echo "-pre")
|
|
version=$(echo "${releaseJson}" | python3 -c "import json,sys,collections;obj=json.load(sys.stdin, object_pairs_hook=collections.OrderedDict);latest=list(v for v in obj if '${pre}' not in v)[-1];print(latest)")
|
|
else
|
|
version="${requestedVersion}"
|
|
fi
|
|
if ! sourceTarballUrl=$(echo "${releaseJson}" | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(obj[sys.argv[1]]["sourceTarballUrl"])' "${version}"); then
|
|
echo "No source code for version ${requestedVersion}"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Build data
|
|
if [[ -z "${dataJson}" ]]; then
|
|
if [[ -z "${restoreUrl}" ]]; then
|
|
data=$(cat <<EOF
|
|
{
|
|
"boxVersionsUrl": "${versionsUrl}",
|
|
"fqdn": "${domain}",
|
|
"provider": "${provider}",
|
|
"apiServerOrigin": "${apiServerOrigin}",
|
|
"tlsConfig": {
|
|
"provider": "${tlsProvider}"
|
|
},
|
|
"dnsConfig": {
|
|
"provider": "${dnsProvider}"
|
|
},
|
|
"backupConfig" : {
|
|
"provider": "filesystem",
|
|
"backupFolder": "/var/backups",
|
|
"key": "${encryptionKey}"
|
|
},
|
|
"updateConfig": {
|
|
"prerelease": ${prerelease}
|
|
},
|
|
"version": "${version}"
|
|
}
|
|
EOF
|
|
)
|
|
else
|
|
data=$(cat <<EOF
|
|
{
|
|
"boxVersionsUrl": "${versionsUrl}",
|
|
"fqdn": "${domain}",
|
|
"provider": "${provider}",
|
|
"apiServerOrigin": "${apiServerOrigin}",
|
|
"restore": {
|
|
"url": "${restoreUrl}",
|
|
"key": "${encryptionKey}"
|
|
},
|
|
"version": "${version}"
|
|
}
|
|
EOF
|
|
)
|
|
fi
|
|
else
|
|
data="${dataJson}"
|
|
fi
|
|
|
|
echo "=> Downloading version ${version} ..."
|
|
box_src_tmp_dir=$(mktemp -dt box-src-XXXXXX)
|
|
|
|
if ! curl -sL "${sourceTarballUrl}" | tar -zxf - -C "${box_src_tmp_dir}"; then
|
|
echo "Could not download source tarball. See ${LOG_FILE} for details"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "${initBaseImage}" == "true" ]]; then
|
|
echo -n "=> Installing base dependencies and downloading docker images (this takes some time) ..."
|
|
if ! /bin/bash "${box_src_tmp_dir}/baseimage/initializeBaseUbuntuImage.sh" "${provider}" "../src" &>> "${LOG_FILE}"; then
|
|
echo "Init script failed. See ${LOG_FILE} for details"
|
|
exit 1
|
|
fi
|
|
echo ""
|
|
fi
|
|
|
|
echo "=> Installing version ${version} (this takes some time) ..."
|
|
if ! /bin/bash "${box_src_tmp_dir}/scripts/installer.sh" --data "${data}" &>> "${LOG_FILE}"; then
|
|
echo "Failed to install cloudron. See ${LOG_FILE} for details"
|
|
exit 1
|
|
fi
|
|
|
|
echo -n "=> Waiting for cloudron to be ready (this takes some time) ..."
|
|
while true; do
|
|
echo -n "."
|
|
if status=$(curl -q -f "http://localhost:3000/api/v1/cloudron/status" 2>/dev/null); then
|
|
[[ -z "$domain" ]] && break # with no domain, we are up and running
|
|
[[ "$status" == *"\"tls\": true"* ]] && break # with a domain, wait for the cert
|
|
fi
|
|
sleep 10
|
|
done
|
|
|
|
echo -e "\n\nRebooting this server now to let bootloader changes take effect.\n"
|
|
|
|
if [[ -n "${domain}" ]]; then
|
|
echo -e "Visit https://my.${domain} to finish setup once the server has rebooted.\n"
|
|
else
|
|
echo -e "Visit https://<IP> to finish setup once the server has rebooted.\n"
|
|
fi
|
|
|
|
systemctl reboot
|