it seems docker images --digests cloudron/sftp --format "{{.ID}} {{.Repository}}:{{.Tag}}@{{.Digest}}
broke at some point
186 lines
6.9 KiB
Bash
Executable File
186 lines
6.9 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# This script is run before the box code is switched. This means that we can
|
|
# put network related/curl downloads here. If the script fails, the old code
|
|
# will continue to run
|
|
|
|
set -eu -o pipefail
|
|
|
|
if [[ ${EUID} -ne 0 ]]; then
|
|
echo "This script should be run as root." > /dev/stderr
|
|
exit 1
|
|
fi
|
|
|
|
function log() {
|
|
echo -e "$(date +'%Y-%m-%dT%H:%M:%S')" "==> installer: $1"
|
|
}
|
|
|
|
apt_ready="no"
|
|
function prepare_apt_once() {
|
|
[[ "${apt_ready}" == "yes" ]] && return
|
|
|
|
log "Making sure apt is in a good state"
|
|
|
|
log "Waiting for all dpkg tasks to finish..."
|
|
while fuser /var/lib/dpkg/lock; do
|
|
sleep 1
|
|
done
|
|
|
|
# it's unclear what needs to be run first or whether both these command should be run. so keep trying both
|
|
for count in {1..3}; do
|
|
# alternative to apt-install -y --fix-missing ?
|
|
if ! dpkg --force-confold --configure -a; then
|
|
log "dpkg reconfigure failed (try $count)"
|
|
dpkg_configure="no"
|
|
else
|
|
dpkg_configure="yes"
|
|
fi
|
|
|
|
if ! apt update -y; then
|
|
log "apt update failed (try $count)"
|
|
apt_update="no"
|
|
else
|
|
apt_update="yes"
|
|
fi
|
|
|
|
[[ "${dpkg_configure}" == "yes" && "${apt_update}" == "yes" ]] && break
|
|
|
|
sleep 1
|
|
done
|
|
|
|
apt_ready="yes"
|
|
|
|
if [[ "${dpkg_configure}" == "yes" && "${apt_update}" == "yes" ]]; then
|
|
log "apt is ready"
|
|
else
|
|
log "apt is not ready but proceeding anyway"
|
|
fi
|
|
}
|
|
|
|
readonly user=yellowtent
|
|
readonly box_src_dir=/home/${user}/box
|
|
|
|
readonly curl="curl --fail --connect-timeout 20 --retry 10 --retry-delay 2 --max-time 2400"
|
|
readonly script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
readonly box_src_tmp_dir="$(realpath ${script_dir}/..)"
|
|
|
|
readonly ubuntu_version=$(lsb_release -rs)
|
|
readonly ubuntu_codename=$(lsb_release -cs)
|
|
|
|
readonly is_update=$(systemctl is-active -q box && echo "yes" || echo "no")
|
|
|
|
log "Updating from $(cat $box_src_dir/VERSION 2>/dev/null) to $(cat $box_src_tmp_dir/VERSION 2>/dev/null)"
|
|
|
|
if [[ "${ubuntu_version}" == "18.04" ]]; then
|
|
log "This Cloudron version requires atleast Ubuntu 20.04. Please upgrade following https://docs.cloudron.io/guides/upgrade-ubuntu-20/"
|
|
exit 2
|
|
fi
|
|
|
|
# https://docs.docker.com/engine/installation/linux/ubuntulinux/
|
|
readonly docker_version="23.0.6"
|
|
readonly containerd_version="1.6.21-1"
|
|
if ! which docker 2>/dev/null || [[ $(docker version --format {{.Client.Version}}) != "${docker_version}" ]]; then
|
|
log "installing/updating docker"
|
|
|
|
# create systemd drop-in file already to make sure images are with correct driver
|
|
mkdir -p /etc/systemd/system/docker.service.d
|
|
echo -e "[Service]\nExecStart=\nExecStart=/usr/bin/dockerd -H fd:// --log-driver=journald --exec-opt native.cgroupdriver=cgroupfs --storage-driver=overlay2 --experimental --ip6tables" > /etc/systemd/system/docker.service.d/cloudron.conf
|
|
|
|
# there are 3 packages for docker - containerd, CLI and the daemon (https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/)
|
|
$curl -sL "https://download.docker.com/linux/ubuntu/dists/${ubuntu_codename}/pool/stable/amd64/containerd.io_${containerd_version}_amd64.deb" -o /tmp/containerd.deb
|
|
$curl -sL "https://download.docker.com/linux/ubuntu/dists/${ubuntu_codename}/pool/stable/amd64/docker-ce-cli_${docker_version}-1~ubuntu.${ubuntu_version}~${ubuntu_codename}_amd64.deb" -o /tmp/docker-ce-cli.deb
|
|
$curl -sL "https://download.docker.com/linux/ubuntu/dists/${ubuntu_codename}/pool/stable/amd64/docker-ce_${docker_version}-1~ubuntu.${ubuntu_version}~${ubuntu_codename}_amd64.deb" -o /tmp/docker.deb
|
|
|
|
log "installing docker"
|
|
prepare_apt_once
|
|
apt install -y /tmp/containerd.deb /tmp/docker-ce-cli.deb /tmp/docker.deb
|
|
rm /tmp/containerd.deb /tmp/docker-ce-cli.deb /tmp/docker.deb
|
|
fi
|
|
|
|
# we want atleast nginx 1.14 for TLS v1.3 support. Ubuntu 20/22 already has nginx 1.18
|
|
# Ubuntu 18 OpenSSL does not have TLS v1.3 support, so we use the upstream nginx packages
|
|
readonly nginx_version=$(nginx -v 2>&1)
|
|
if [[ "${ubuntu_version}" == "20.04" ]]; then
|
|
if [[ "${nginx_version}" == *"Ubuntu"* ]]; then
|
|
log "switching nginx to ubuntu package"
|
|
prepare_apt_once
|
|
apt remove -y nginx
|
|
apt install -y nginx-full
|
|
fi
|
|
elif [[ "${ubuntu_version}" == "18.04" ]]; then
|
|
if [[ "${nginx_version}" != *"1.18."* ]]; then
|
|
log "installing/updating nginx 1.18"
|
|
$curl -sL http://nginx.org/packages/ubuntu/pool/nginx/n/nginx/nginx_1.18.0-2~${ubuntu_codename}_amd64.deb -o /tmp/nginx.deb
|
|
|
|
prepare_apt_once
|
|
|
|
# apt install with install deps (as opposed to dpkg -i)
|
|
apt install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --force-yes /tmp/nginx.deb
|
|
rm /tmp/nginx.deb
|
|
fi
|
|
fi
|
|
|
|
readonly old_node_version=16.18.1
|
|
readonly node_version=18.16.0
|
|
if ! which node 2>/dev/null || [[ "$(node --version)" != "v${node_version}" ]]; then
|
|
log "installing/updating node ${node_version}"
|
|
mkdir -p /usr/local/node-${node_version}
|
|
$curl -sL https://nodejs.org/dist/v${node_version}/node-v${node_version}-linux-x64.tar.gz -o /tmp/node.tar.gz
|
|
tar zxvf /tmp/node.tar.gz --strip-components=1 -C /usr/local/node-${node_version}
|
|
rm /tmp/node.tar.gz
|
|
ln -sf /usr/local/node-${node_version}/bin/node /usr/bin/node
|
|
ln -sf /usr/local/node-${node_version}/bin/npm /usr/bin/npm
|
|
rm -rf /usr/local/node-${old_node_version}
|
|
fi
|
|
|
|
# obsolete module
|
|
rm -rf /usr/local/cloudron-syslog
|
|
|
|
# note that rebuild requires the above node
|
|
for try in `seq 1 10`; do
|
|
# for reasons unknown, the dtrace package will fail. but rebuilding second time will work
|
|
|
|
# We need --unsafe-perm as we run as root and the folder is owned by root,
|
|
# however by default npm drops privileges for npm rebuild
|
|
# https://docs.npmjs.com/misc/config#unsafe-perm
|
|
if cd "${box_src_tmp_dir}" && npm rebuild --unsafe-perm; then break; fi
|
|
log "Failed to rebuild, trying again"
|
|
sleep 5
|
|
done
|
|
|
|
if [[ ${try} -eq 10 ]]; then
|
|
log "npm rebuild failed, giving up"
|
|
exit 4
|
|
fi
|
|
|
|
log "downloading new addon images"
|
|
images=$(node -e "const i = require('${box_src_tmp_dir}/src/infra_version.js'); console.log(Object.keys(i.images).map(x => i.images[x]).join(' '));")
|
|
|
|
log "\tPulling docker images: ${images}"
|
|
for image in ${images}; do
|
|
while ! docker pull "${image}"; do # this pulls the image using the sha256
|
|
log "Could not pull ${image}"
|
|
sleep 5
|
|
done
|
|
while ! docker pull "${image%@sha256:*}"; do # this will tag the image for readability
|
|
log "Could not pull ${image%@sha256:*}"
|
|
sleep 5
|
|
done
|
|
done
|
|
|
|
if [[ "${is_update}" == "yes" ]]; then
|
|
log "stop box service for update"
|
|
${box_src_dir}/setup/stop.sh
|
|
fi
|
|
|
|
# ensure we are not inside the source directory, which we will remove now
|
|
cd /root
|
|
|
|
log "switching the box code"
|
|
rm -rf "${box_src_dir}"
|
|
mv "${box_src_tmp_dir}" "${box_src_dir}"
|
|
chown -R "${user}:${user}" "${box_src_dir}"
|
|
|
|
log "calling box setup script"
|
|
"${box_src_dir}/setup/start.sh"
|