2015-07-20 00:09:47 -07:00
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
set -eu -o pipefail
|
|
|
|
|
|
2018-10-26 10:13:27 -07:00
|
|
|
# This script is run after the box code is switched. This means that this script
|
|
|
|
|
# should pretty much always succeed. No network logic/download code here.
|
|
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
function log() {
|
|
|
|
|
echo -e "$(date +'%Y-%m-%dT%H:%M:%S')" "==> start: $1"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log "Cloudron Start"
|
2015-07-20 00:09:47 -07:00
|
|
|
|
|
|
|
|
readonly USER="yellowtent"
|
2017-01-24 10:09:05 -08:00
|
|
|
readonly HOME_DIR="/home/${USER}"
|
|
|
|
|
readonly BOX_SRC_DIR="${HOME_DIR}/box"
|
2021-06-17 11:37:00 -07:00
|
|
|
readonly PLATFORM_DATA_DIR="${HOME_DIR}/platformdata"
|
|
|
|
|
readonly APPS_DATA_DIR="${HOME_DIR}/appsdata"
|
2021-09-26 18:37:04 -07:00
|
|
|
readonly BOX_DATA_DIR="${HOME_DIR}/boxdata/box"
|
2021-06-17 11:37:00 -07:00
|
|
|
readonly MAIL_DATA_DIR="${HOME_DIR}/boxdata/mail"
|
2015-07-20 00:09:47 -07:00
|
|
|
|
2016-12-29 14:21:08 -08:00
|
|
|
readonly script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
2018-12-10 15:36:00 -08:00
|
|
|
readonly json="$(realpath ${script_dir}/../node_modules/.bin/json)"
|
2019-01-17 09:20:31 -08:00
|
|
|
readonly ubuntu_version=$(lsb_release -rs)
|
2015-07-20 00:09:47 -07:00
|
|
|
|
2018-12-26 19:42:45 -08:00
|
|
|
cp -f "${script_dir}/../scripts/cloudron-support" /usr/bin/cloudron-support
|
2020-11-18 22:03:57 +01:00
|
|
|
cp -f "${script_dir}/../scripts/cloudron-translation-update" /usr/bin/cloudron-translation-update
|
2018-12-26 19:42:45 -08:00
|
|
|
|
2020-04-29 21:55:21 -07:00
|
|
|
# this needs to match the cloudron/base:2.0.0 gid
|
|
|
|
|
if ! getent group media; then
|
|
|
|
|
addgroup --gid 500 --system media
|
|
|
|
|
fi
|
|
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Configuring docker"
|
2016-12-29 12:01:59 -08:00
|
|
|
cp "${script_dir}/start/docker-cloudron-app.apparmor" /etc/apparmor.d/docker-cloudron-app
|
2017-01-10 18:15:10 -08:00
|
|
|
systemctl enable apparmor
|
2016-12-29 12:01:59 -08:00
|
|
|
systemctl restart apparmor
|
|
|
|
|
|
2017-01-24 10:32:32 -08:00
|
|
|
usermod ${USER} -a -G docker
|
2016-12-29 12:01:59 -08:00
|
|
|
|
2022-02-09 17:47:48 -08:00
|
|
|
if ! grep -q ip6tables /etc/systemd/system/docker.service.d/cloudron.conf; then
|
|
|
|
|
log "Adding ip6tables flag to docker" # https://github.com/moby/moby/pull/41622
|
|
|
|
|
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
|
|
|
|
|
systemctl daemon-reload
|
|
|
|
|
systemctl restart docker
|
|
|
|
|
fi
|
|
|
|
|
|
2017-03-30 13:45:57 +02:00
|
|
|
mkdir -p "${BOX_DATA_DIR}"
|
2017-03-29 16:09:49 +02:00
|
|
|
mkdir -p "${APPS_DATA_DIR}"
|
2021-10-15 15:02:54 +02:00
|
|
|
mkdir -p "${MAIL_DATA_DIR}"
|
2017-03-29 16:09:49 +02:00
|
|
|
|
2016-12-29 14:35:48 -08:00
|
|
|
# keep these in sync with paths.js
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Ensuring directories"
|
2017-03-30 13:45:57 +02:00
|
|
|
|
2021-03-23 10:48:13 -07:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/graphite"
|
2017-03-29 15:51:53 +02:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/mysql"
|
|
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/postgresql"
|
|
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/mongodb"
|
2018-09-18 12:28:03 -07:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/redis"
|
2021-10-11 19:51:29 -07:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/addons/mail/banner" \
|
|
|
|
|
"${PLATFORM_DATA_DIR}/addons/mail/dkim"
|
2017-08-11 22:05:31 +02:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/logrotate.d"
|
2017-03-29 15:51:53 +02:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/acme"
|
2017-09-26 16:31:08 -07:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/backup"
|
2019-03-01 14:40:28 -08:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/logs/backup" \
|
|
|
|
|
"${PLATFORM_DATA_DIR}/logs/updater" \
|
|
|
|
|
"${PLATFORM_DATA_DIR}/logs/tasks" \
|
2020-02-18 20:34:13 -08:00
|
|
|
"${PLATFORM_DATA_DIR}/logs/crash" \
|
|
|
|
|
"${PLATFORM_DATA_DIR}/logs/collectd"
|
2018-08-01 15:38:40 -07:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/update"
|
2021-05-02 23:28:41 -07:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/sftp/ssh" # sftp keys
|
2021-05-04 15:21:38 -07:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/firewall"
|
2022-03-29 20:13:41 -07:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/sshfs"
|
2022-03-29 20:57:09 -07:00
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/cifs"
|
2017-03-29 15:51:53 +02:00
|
|
|
|
2017-04-20 15:41:25 +02:00
|
|
|
# ensure backups folder exists and is writeable
|
|
|
|
|
mkdir -p /var/backups
|
|
|
|
|
chmod 777 /var/backups
|
|
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Configuring journald"
|
2016-12-29 12:01:59 -08:00
|
|
|
sed -e "s/^#SystemMaxUse=.*$/SystemMaxUse=100M/" \
|
|
|
|
|
-e "s/^#ForwardToSyslog=.*$/ForwardToSyslog=no/" \
|
|
|
|
|
-i /etc/systemd/journald.conf
|
|
|
|
|
|
|
|
|
|
# When rotating logs, systemd kills journald too soon sometimes
|
|
|
|
|
# See https://github.com/systemd/systemd/issues/1353 (this is upstream default)
|
|
|
|
|
sed -e "s/^WatchdogSec=.*$/WatchdogSec=3min/" \
|
|
|
|
|
-i /lib/systemd/system/systemd-journald.service
|
|
|
|
|
|
2021-09-28 19:20:21 -07:00
|
|
|
usermod -a -G systemd-journal ${USER} # Give user access to system logs
|
|
|
|
|
if [[ ! -d /var/log/journal ]]; then # in some images, this directory is not created making system log to /run/systemd instead
|
|
|
|
|
mkdir -p /var/log/journal
|
|
|
|
|
chown root:systemd-journal /var/log/journal
|
|
|
|
|
chmod g+s /var/log/journal # sticky bit for group propagation
|
|
|
|
|
fi
|
2017-01-23 11:01:02 +01:00
|
|
|
systemctl daemon-reload
|
2016-12-29 12:01:59 -08:00
|
|
|
systemctl restart systemd-journald
|
|
|
|
|
|
2020-06-15 17:12:37 +02:00
|
|
|
# Give user access to nginx logs (uses adm group)
|
|
|
|
|
usermod -a -G adm ${USER}
|
|
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Setting up unbound"
|
2019-11-13 14:48:56 -08:00
|
|
|
cp -f "${script_dir}/start/unbound.conf" /etc/unbound/unbound.conf.d/cloudron-network.conf
|
2017-09-03 17:48:25 -07:00
|
|
|
# update the root anchor after a out-of-disk-space situation (see #269)
|
|
|
|
|
unbound-anchor -a /var/lib/unbound/root.key
|
2017-01-23 10:14:18 +01:00
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Adding systemd services"
|
2016-12-29 12:01:59 -08:00
|
|
|
cp -r "${script_dir}/start/systemd/." /etc/systemd/system/
|
2019-01-17 09:20:31 -08:00
|
|
|
[[ "${ubuntu_version}" == "16.04" ]] && sed -e 's/MemoryMax/MemoryLimit/g' -i /etc/systemd/system/box.service
|
2021-06-04 09:40:37 -07:00
|
|
|
[[ "${ubuntu_version}" == "16.04" ]] && sed -e 's/Type=notify/Type=simple/g' -i /etc/systemd/system/unbound.service
|
2016-12-29 12:01:59 -08:00
|
|
|
systemctl daemon-reload
|
2020-11-18 11:43:28 -08:00
|
|
|
systemctl enable --now cloudron-syslog
|
2020-11-25 10:02:43 -08:00
|
|
|
systemctl enable unbound
|
2020-08-01 20:00:20 -07:00
|
|
|
systemctl enable box
|
2017-03-29 02:18:38 -07:00
|
|
|
systemctl enable cloudron-firewall
|
2020-11-28 10:17:13 -08:00
|
|
|
systemctl enable --now cloudron-disable-thp
|
2017-03-29 02:18:38 -07:00
|
|
|
|
2022-02-09 17:47:48 -08:00
|
|
|
# update firewall rules. this must be done after docker created it's rules
|
2017-03-29 02:18:38 -07:00
|
|
|
systemctl restart cloudron-firewall
|
2016-12-29 12:01:59 -08:00
|
|
|
|
|
|
|
|
# For logrotate
|
2016-12-29 14:21:08 -08:00
|
|
|
systemctl enable --now cron
|
2016-12-29 12:01:59 -08:00
|
|
|
|
2020-11-25 10:02:43 -08:00
|
|
|
# ensure unbound runs
|
|
|
|
|
systemctl restart unbound
|
2016-12-29 14:21:08 -08:00
|
|
|
|
2018-06-06 11:37:00 +02:00
|
|
|
# ensure cloudron-syslog runs
|
|
|
|
|
systemctl restart cloudron-syslog
|
|
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Configuring sudoers"
|
2022-03-30 14:27:39 -07:00
|
|
|
rm -f /etc/sudoers.d/${USER} /etc/sudoers.d/cloudron
|
|
|
|
|
cp "${script_dir}/start/sudoers" /etc/sudoers.d/cloudron
|
2016-12-29 14:21:08 -08:00
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Configuring collectd"
|
2022-10-10 19:52:29 +02:00
|
|
|
rm -rf /etc/collectd /var/log/collectd.log "${PLATFORM_DATA_DIR}/collectd/collectd.conf.d"
|
2017-03-29 15:51:53 +02:00
|
|
|
ln -sfF "${PLATFORM_DATA_DIR}/collectd" /etc/collectd
|
2017-08-10 19:41:55 -07:00
|
|
|
cp "${script_dir}/start/collectd/collectd.conf" "${PLATFORM_DATA_DIR}/collectd/collectd.conf"
|
2016-12-29 14:21:08 -08:00
|
|
|
systemctl restart collectd
|
2016-12-29 12:01:59 -08:00
|
|
|
|
2022-02-09 12:17:42 -08:00
|
|
|
log "Configuring sysctl"
|
|
|
|
|
# If privacy extensions are not disabled on server, this breaks IPv6 detection
|
|
|
|
|
# https://bugs.launchpad.net/ubuntu/+source/procps/+bug/1068756
|
|
|
|
|
if [[ ! -f /etc/sysctl.d/99-cloudimg-ipv6.conf ]]; then
|
|
|
|
|
echo "==> Disable temporary address (IPv6)"
|
|
|
|
|
echo -e "# See https://bugs.launchpad.net/ubuntu/+source/procps/+bug/1068756\nnet.ipv6.conf.all.use_tempaddr = 0\nnet.ipv6.conf.default.use_tempaddr = 0\n\n" > /etc/sysctl.d/99-cloudimg-ipv6.conf
|
|
|
|
|
sysctl -p
|
|
|
|
|
fi
|
|
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Configuring logrotate"
|
2017-08-11 22:05:31 +02:00
|
|
|
if ! grep -q "^include ${PLATFORM_DATA_DIR}/logrotate.d" /etc/logrotate.conf; then
|
|
|
|
|
echo -e "\ninclude ${PLATFORM_DATA_DIR}/logrotate.d\n" >> /etc/logrotate.conf
|
|
|
|
|
fi
|
2019-03-01 14:40:28 -08:00
|
|
|
cp "${script_dir}/start/logrotate/"* "${PLATFORM_DATA_DIR}/logrotate.d/"
|
2019-03-18 22:05:35 -07:00
|
|
|
|
|
|
|
|
# logrotate files have to be owned by root, this is here to fixup existing installations where we were resetting the owner to yellowtent
|
2019-03-01 14:40:28 -08:00
|
|
|
chown root:root "${PLATFORM_DATA_DIR}/logrotate.d/"
|
2017-08-11 22:05:31 +02:00
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Adding motd message for admins"
|
2017-08-10 12:10:37 -07:00
|
|
|
cp "${script_dir}/start/cloudron-motd" /etc/update-motd.d/92-cloudron
|
|
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Configuring nginx"
|
2016-12-29 12:01:59 -08:00
|
|
|
# link nginx config to system config
|
|
|
|
|
unlink /etc/nginx 2>/dev/null || rm -rf /etc/nginx
|
2017-03-29 15:51:53 +02:00
|
|
|
ln -s "${PLATFORM_DATA_DIR}/nginx" /etc/nginx
|
|
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/nginx/applications"
|
|
|
|
|
mkdir -p "${PLATFORM_DATA_DIR}/nginx/cert"
|
|
|
|
|
cp "${script_dir}/start/nginx/nginx.conf" "${PLATFORM_DATA_DIR}/nginx/nginx.conf"
|
|
|
|
|
cp "${script_dir}/start/nginx/mime.types" "${PLATFORM_DATA_DIR}/nginx/mime.types"
|
2017-03-13 13:52:16 -07:00
|
|
|
if ! grep -q "^Restart=" /etc/systemd/system/multi-user.target.wants/nginx.service; then
|
2017-01-25 12:04:02 -08:00
|
|
|
# default nginx service file does not restart on crash
|
|
|
|
|
echo -e "\n[Service]\nRestart=always\n" >> /etc/systemd/system/multi-user.target.wants/nginx.service
|
|
|
|
|
fi
|
2020-05-25 15:22:01 -07:00
|
|
|
|
|
|
|
|
# worker_rlimit_nofile in nginx config can be max this number
|
|
|
|
|
mkdir -p /etc/systemd/system/nginx.service.d
|
2022-03-30 11:10:00 -07:00
|
|
|
if ! grep -q "^LimitNOFILE=" /etc/systemd/system/nginx.service.d/cloudron.conf 2>/dev/null; then
|
2020-05-25 15:22:01 -07:00
|
|
|
echo -e "[Service]\nLimitNOFILE=16384\n" > /etc/systemd/system/nginx.service.d/cloudron.conf
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
systemctl daemon-reload
|
2017-01-25 12:04:02 -08:00
|
|
|
systemctl start nginx
|
2016-12-29 12:01:59 -08:00
|
|
|
|
2015-08-13 15:16:01 -07:00
|
|
|
# restart mysql to make sure it has latest config
|
2017-02-07 22:45:54 -08:00
|
|
|
if [[ ! -f /etc/mysql/mysql.cnf ]] || ! diff -q "${script_dir}/start/mysql.cnf" /etc/mysql/mysql.cnf >/dev/null; then
|
|
|
|
|
# wait for all running mysql jobs
|
2021-02-26 09:48:43 -08:00
|
|
|
cp "${script_dir}/start/mysql.cnf" /etc/mysql/mysql.cnf
|
2017-02-07 22:45:54 -08:00
|
|
|
while true; do
|
|
|
|
|
if ! systemctl list-jobs | grep mysql; then break; fi
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Waiting for mysql jobs..."
|
2017-02-07 22:45:54 -08:00
|
|
|
sleep 1
|
|
|
|
|
done
|
2021-03-02 23:22:04 -08:00
|
|
|
log "Stopping mysql"
|
|
|
|
|
systemctl stop mysql
|
|
|
|
|
while mysqladmin ping 2>/dev/null; do
|
|
|
|
|
log "Waiting for mysql to stop..."
|
2017-10-30 16:14:20 -07:00
|
|
|
sleep 1
|
|
|
|
|
done
|
2017-02-07 22:45:54 -08:00
|
|
|
fi
|
2015-08-13 15:16:01 -07:00
|
|
|
|
2021-03-02 23:22:04 -08:00
|
|
|
# the start/stop of mysql is separate to make sure it got reloaded with latest config and it's up and running before we start the new box code
|
|
|
|
|
# when using 'system restart mysql', it seems to restart much later and the box code loses connection during platform startup (dangerous!)
|
|
|
|
|
log "Starting mysql"
|
|
|
|
|
systemctl start mysql
|
|
|
|
|
while ! mysqladmin ping 2>/dev/null; do
|
|
|
|
|
log "Waiting for mysql to start..."
|
|
|
|
|
sleep 1
|
|
|
|
|
done
|
|
|
|
|
|
2015-07-20 00:09:47 -07:00
|
|
|
readonly mysql_root_password="password"
|
|
|
|
|
mysqladmin -u root -ppassword password password # reset default root password
|
2022-04-27 15:45:53 -07:00
|
|
|
readonly mysqlVersion=$(mysql -NB -u root -p${mysql_root_password} -e 'SELECT VERSION()' 2>/dev/null)
|
|
|
|
|
if [[ "${mysqlVersion}" == "8.0."* ]]; then
|
2020-09-15 23:25:40 -07:00
|
|
|
# mysql 8 added a new caching_sha2_password scheme which mysqljs does not support
|
|
|
|
|
mysql -u root -p${mysql_root_password} -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '${mysql_root_password}';"
|
|
|
|
|
fi
|
2015-07-20 00:09:47 -07:00
|
|
|
mysql -u root -p${mysql_root_password} -e 'CREATE DATABASE IF NOT EXISTS box'
|
|
|
|
|
|
2020-05-17 21:50:50 -07:00
|
|
|
# set HOME explicity, because it's not set when the installer calls it. this is done because
|
|
|
|
|
# paths.js uses this env var and some of the migrate code requires box code
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Migrating data"
|
2019-09-25 10:17:02 -07:00
|
|
|
cd "${BOX_SRC_DIR}"
|
2020-05-17 21:50:50 -07:00
|
|
|
if ! HOME=${HOME_DIR} BOX_ENV=cloudron DATABASE_URL=mysql://root:${mysql_root_password}@127.0.0.1/box "${BOX_SRC_DIR}/node_modules/.bin/db-migrate" up; then
|
2021-03-02 23:05:41 -08:00
|
|
|
log "DB migration failed"
|
2019-09-25 10:17:02 -07:00
|
|
|
exit 1
|
|
|
|
|
fi
|
2015-07-20 00:09:47 -07:00
|
|
|
|
2019-07-26 14:55:36 -07:00
|
|
|
rm -f /etc/cloudron/cloudron.conf
|
|
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Changing ownership"
|
2021-05-07 20:20:10 -07:00
|
|
|
# note, change ownership after db migrate. this allow db migrate to move files around as root and then we can fix it up here
|
2018-11-07 15:21:12 -08:00
|
|
|
# be careful of what is chown'ed here. subdirs like mysql,redis etc are owned by the containers and will stop working if perms change
|
2018-12-14 15:40:25 -08:00
|
|
|
chown -R "${USER}" /etc/cloudron
|
2022-03-29 20:57:09 -07:00
|
|
|
chown "${USER}:${USER}" -R "${PLATFORM_DATA_DIR}/nginx" "${PLATFORM_DATA_DIR}/collectd" "${PLATFORM_DATA_DIR}/addons" "${PLATFORM_DATA_DIR}/acme" "${PLATFORM_DATA_DIR}/backup" "${PLATFORM_DATA_DIR}/logs" "${PLATFORM_DATA_DIR}/update" "${PLATFORM_DATA_DIR}/sftp" "${PLATFORM_DATA_DIR}/firewall" "${PLATFORM_DATA_DIR}/sshfs" "${PLATFORM_DATA_DIR}/cifs"
|
2017-03-29 15:51:53 +02:00
|
|
|
chown "${USER}:${USER}" "${PLATFORM_DATA_DIR}/INFRA_VERSION" 2>/dev/null || true
|
|
|
|
|
chown "${USER}:${USER}" "${PLATFORM_DATA_DIR}"
|
2018-09-13 13:55:49 -07:00
|
|
|
chown "${USER}:${USER}" "${APPS_DATA_DIR}"
|
2016-12-29 14:35:48 -08:00
|
|
|
|
2021-09-26 18:37:04 -07:00
|
|
|
chown "${USER}:${USER}" -R "${BOX_DATA_DIR}"
|
|
|
|
|
# do not chown the boxdata/mail directory entirely; dovecot gets upset
|
2021-06-17 11:37:00 -07:00
|
|
|
chown "${USER}:${USER}" "${MAIL_DATA_DIR}"
|
2017-10-16 21:41:48 -07:00
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Starting Cloudron"
|
2020-08-01 20:00:20 -07:00
|
|
|
systemctl start box
|
2015-07-20 00:09:47 -07:00
|
|
|
|
2015-09-07 11:18:44 -07:00
|
|
|
sleep 2 # give systemd sometime to start the processes
|
2015-07-20 00:09:47 -07:00
|
|
|
|
2021-03-02 23:05:41 -08:00
|
|
|
log "Almost done"
|