It's all very complicated. Approach 1: Simple move unbound to not listen on 0.0.0.0 and only the internal ones. However, docker has no way to bind only to the "public" interface. Approach 2: Move the internal unbound to some other port. This required a PR for haraka - https://github.com/haraka/Haraka/pull/2863 . This works and we use systemd-resolved by default. However, it turns out systemd-resolved with hog the lo and thus docker cannot bind again to port 53. Approach 3: Get rid of systemd-resolved and try to put the dns server list in /etc/resolv.conf. This is surprisingly hard because the DNS listing can come from DHCP or netplan or wherever. We can hardcode some public DNS servers but this seems not a good idea for privacy. Approach 4: So maybe we don't move the unbound away to different port after all. However, all the work for approach 2 is done and it's quite nice that the default resolver is used with the default dns server of the network (probably a caching server + also maybe has some home network firewalled dns). So, the final solution is to bind to the make docker bind to the IP explicity. It's unclear what will happen if the IP changes, maybe it needs a restart.
157 lines
5.8 KiB
Bash
Executable File
157 lines
5.8 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
|
|
|
|
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 box && echo "yes" || echo "no")
|
|
|
|
echo "==> installer: Updating from $(cat $box_src_dir/VERSION) to $(cat $box_src_tmp_dir/VERSION) <=="
|
|
|
|
echo "==> installer: updating docker"
|
|
|
|
if [[ $(docker version --format {{.Client.Version}}) != "19.03.12" ]]; then
|
|
# there are 3 packages for docker - containerd, CLI and the daemon
|
|
curl -sL "https://download.docker.com/linux/ubuntu/dists/${ubuntu_codename}/pool/stable/amd64/containerd.io_1.2.13-2_amd64.deb" -o /tmp/containerd.deb
|
|
curl -sL "https://download.docker.com/linux/ubuntu/dists/${ubuntu_codename}/pool/stable/amd64/docker-ce-cli_19.03.12~3-0~ubuntu-${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_19.03.12~3-0~ubuntu-${ubuntu_codename}_amd64.deb" -o /tmp/docker.deb
|
|
|
|
echo "==> installer: Waiting for all dpkg tasks to finish..."
|
|
while fuser /var/lib/dpkg/lock; do
|
|
sleep 1
|
|
done
|
|
|
|
while ! dpkg --force-confold --configure -a; do
|
|
echo "==> installer: Failed to fix packages. Retry"
|
|
sleep 1
|
|
done
|
|
|
|
# the latest docker might need newer packages
|
|
while ! apt update -y; do
|
|
echo "==> installer: Failed to update packages. Retry"
|
|
sleep 1
|
|
done
|
|
|
|
while ! apt install -y /tmp/containerd.deb /tmp/docker-ce-cli.deb /tmp/docker.deb; do
|
|
echo "==> installer: Failed to install docker. Retry"
|
|
sleep 1
|
|
done
|
|
|
|
rm /tmp/containerd.deb /tmp/docker-ce-cli.deb /tmp/docker.deb
|
|
fi
|
|
|
|
readonly nginx_version=$(nginx -v 2>&1)
|
|
if [[ "${nginx_version}" != *"1.18."* ]]; then
|
|
echo "==> installer: installing nginx 1.18"
|
|
curl -sL http://nginx.org/packages/ubuntu/pool/nginx/n/nginx/nginx_1.18.0-1~${ubuntu_codename}_amd64.deb -o /tmp/nginx.deb
|
|
# 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
|
|
|
|
if ! which ipset; then
|
|
echo "==> installer: installing ipset"
|
|
apt install -y ipset
|
|
fi
|
|
|
|
# Only used for the cloudron-translation-update script
|
|
if ! which unzip; then
|
|
echo "==> installer: installing unzip"
|
|
apt install -y unzip
|
|
fi
|
|
|
|
echo "==> installer: updating node"
|
|
if [[ "$(node --version)" != "v10.18.1" ]]; then
|
|
mkdir -p /usr/local/node-10.18.1
|
|
$curl -sL https://nodejs.org/dist/v10.18.1/node-v10.18.1-linux-x64.tar.gz | tar zxvf - --strip-components=1 -C /usr/local/node-10.18.1
|
|
ln -sf /usr/local/node-10.18.1/bin/node /usr/bin/node
|
|
ln -sf /usr/local/node-10.18.1/bin/npm /usr/bin/npm
|
|
rm -rf /usr/local/node-10.15.1
|
|
fi
|
|
|
|
# this is here (and not in updater.js) because 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
|
|
echo "==> installer: Failed to rebuild, trying again"
|
|
sleep 5
|
|
done
|
|
|
|
if [[ ${try} -eq 10 ]]; then
|
|
echo "==> installer: npm rebuild failed, giving up"
|
|
exit 4
|
|
fi
|
|
|
|
echo "==> installer: downloading new addon images"
|
|
images=$(node -e "var i = require('${box_src_tmp_dir}/src/infra_version.js'); console.log(i.baseImages.map(function (x) { return x.tag; }).join(' '), Object.keys(i.images).map(function (x) { return i.images[x].tag; }).join(' '));")
|
|
|
|
echo -e "\tPulling docker images: ${images}"
|
|
for image in ${images}; do
|
|
if ! docker pull "${image}"; then # this pulls the image using the sha256
|
|
echo "==> installer: Could not pull ${image}"
|
|
exit 5
|
|
fi
|
|
if ! docker pull "${image%@sha256:*}"; then # this will tag the image for readability
|
|
echo "==> installer: Could not pull ${image%@sha256:*}"
|
|
exit 6
|
|
fi
|
|
done
|
|
|
|
echo "==> installer: update cloudron-syslog"
|
|
CLOUDRON_SYSLOG_DIR=/usr/local/cloudron-syslog
|
|
CLOUDRON_SYSLOG="${CLOUDRON_SYSLOG_DIR}/bin/cloudron-syslog"
|
|
CLOUDRON_SYSLOG_VERSION="1.0.3"
|
|
while [[ ! -f "${CLOUDRON_SYSLOG}" || "$(${CLOUDRON_SYSLOG} --version)" != ${CLOUDRON_SYSLOG_VERSION} ]]; do
|
|
rm -rf "${CLOUDRON_SYSLOG_DIR}"
|
|
mkdir -p "${CLOUDRON_SYSLOG_DIR}"
|
|
if npm install --unsafe-perm -g --prefix "${CLOUDRON_SYSLOG_DIR}" cloudron-syslog@${CLOUDRON_SYSLOG_VERSION}; then break; fi
|
|
echo "===> installer: Failed to install cloudron-syslog, trying again"
|
|
sleep 5
|
|
done
|
|
|
|
if ! id "${user}" 2>/dev/null; then
|
|
useradd "${user}" -m
|
|
fi
|
|
|
|
if which resolvconf; then
|
|
echo "==> installer: uninstall resolvconf"
|
|
apt remove -y resolvconf
|
|
fi
|
|
|
|
if [[ "${is_update}" == "yes" ]]; then
|
|
echo "==> installer: 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
|
|
|
|
echo "==> installer: switching the box code"
|
|
rm -rf "${box_src_dir}"
|
|
mv "${box_src_tmp_dir}" "${box_src_dir}"
|
|
chown -R "${user}:${user}" "${box_src_dir}"
|
|
|
|
echo "==> installer: calling box setup script"
|
|
"${box_src_dir}/setup/start.sh"
|