210 lines
6.7 KiB
Bash
Executable File
210 lines
6.7 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
|
|
|
|
# change this to a hash when we make a upgrade release
|
|
readonly LOG_FILE="/var/log/cloudron-setup.log"
|
|
readonly MINIMUM_DISK_SIZE_GB="20" # this is the size of "/" and required to fit in docker images
|
|
readonly MINIMUM_MEMORY="992" # this is mostly reported for 1GB main memory due to 1000 vs 1024
|
|
|
|
# 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_gb=$(fdisk -l ${disk_device} | grep "Disk ${disk_device}" | awk '{ printf "%.0f", $3 }')
|
|
|
|
# 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"
|
|
apiServer="https://api.cloudron.io"
|
|
dataJson=""
|
|
|
|
args=$(getopt -o "" -l "domain:,help,skip-baseimage-init,data:,provider:,encryption-key:,restore-url:,tls-provider:,version:,versions-url:,api-server:,dns-provider:" -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;;
|
|
--versions-url) versionsUrl="$2"; shift 2;;
|
|
--api-server) apiServer="$2"; shift 2;;
|
|
--skip-baseimage-init) initBaseImage="false"; shift;;
|
|
--data) dataJson="$2"; 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 [[ -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 "The server will reboot at the end to complete the setup."
|
|
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"
|
|
releaseJson=$(curl -s "${versionsUrl}")
|
|
if [[ "$requestedVersion" == "latest" ]]; then
|
|
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
|
|
|
|
# Build data
|
|
if [[ -z "${dataJson}" ]]; then
|
|
if [[ -z "${restoreUrl}" ]]; then
|
|
data=$(cat <<EOF
|
|
{
|
|
"boxVersionsUrl": "${versionsUrl}",
|
|
"fqdn": "${domain}",
|
|
"provider": "${provider}",
|
|
"apiServerOrigin": "${apiServer}",
|
|
"tlsConfig": {
|
|
"provider": "${tlsProvider}"
|
|
},
|
|
"dnsConfig": {
|
|
"provider": "${dnsProvider}"
|
|
},
|
|
"backupConfig" : {
|
|
"provider": "filesystem",
|
|
"backupFolder": "/var/backups",
|
|
"key": "${encryptionKey}"
|
|
},
|
|
"version": "${version}"
|
|
}
|
|
EOF
|
|
)
|
|
else
|
|
data=$(cat <<EOF
|
|
{
|
|
"boxVersionsUrl": "${versionsUrl}",
|
|
"fqdn": "${domain}",
|
|
"provider": "${provider}",
|
|
"apiServerOrigin": "${apiServer}",
|
|
"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 "=> Installing base dependencies (this takes some time) ..."
|
|
if ! /bin/bash "${box_src_tmp_dir}/baseimage/initializeBaseUbuntuImage.sh" "${provider}" &>> "${LOG_FILE}"; then
|
|
echo "Init script failed. See ${LOG_FILE} for details"
|
|
exit 1
|
|
fi
|
|
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 journalctl -u box -a | grep "platformReady: " >/dev/null; then
|
|
break
|
|
fi
|
|
sleep 10
|
|
done
|
|
|
|
if [[ "${initBaseImage}" == "true" ]]; then
|
|
echo -e "\n\nRebooting this server now to let bootloader changes take effect.\n"
|
|
systemctl reboot
|
|
fi
|
|
|
|
echo -e "Visit https://my.${domain} to finish setup once the server has rebooted.\n"
|
|
|