diff --git a/setup/container.sh b/setup/container.sh deleted file mode 100755 index fae3de5f2..000000000 --- a/setup/container.sh +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/bash - -set -eu -o pipefail - -# This file can be used in Dockerfile - -readonly USER=yellowtent - -readonly USER_DATA_FILE="/root/user_data.img" -readonly USER_DATA_DIR="/home/yellowtent/data" - -readonly container_files="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/container" - -readonly CONFIG_DIR="/home/yellowtent/configs" -readonly DATA_DIR="/home/yellowtent/data" -readonly provider="${1:-generic}" - -sed -e 's/^#NTP=/NTP=0.ubuntu.pool.ntp.org 1.ubuntu.pool.ntp.org 2.ubuntu.pool.ntp.org 3.ubuntu.pool.ntp.org/' -i /etc/systemd/timesyncd.conf -timedatectl set-ntp 1 -timedatectl set-timezone UTC - -echo "==> Setting up firewall" -iptables -t filter -N CLOUDRON || true -iptables -t filter -F CLOUDRON # empty any existing rules - -# NOTE: keep these in sync with src/apps.js validatePortBindings -# allow ssh, http, https, ping, dns -iptables -t filter -I CLOUDRON -m state --state RELATED,ESTABLISHED -j ACCEPT -# caas has ssh on port 202 -if [[ "${provider}" == "caas" ]]; then - iptables -A CLOUDRON -p tcp -m tcp -m multiport --dports 25,80,202,443,587,993,4190 -j ACCEPT -else - iptables -A CLOUDRON -p tcp -m tcp -m multiport --dports 25,80,22,443,587,993,4190 -j ACCEPT -fi -iptables -t filter -A CLOUDRON -p icmp --icmp-type echo-request -j ACCEPT -iptables -t filter -A CLOUDRON -p icmp --icmp-type echo-reply -j ACCEPT -iptables -t filter -A CLOUDRON -p udp --sport 53 -j ACCEPT -iptables -t filter -A CLOUDRON -s 172.18.0.0/16 -j ACCEPT # required to accept any connections from apps to our IP: -iptables -t filter -A CLOUDRON -i lo -j ACCEPT # required for localhost connections (mysql) - -# log dropped incoming. keep this at the end of all the rules -iptables -t filter -A CLOUDRON -m limit --limit 2/min -j LOG --log-prefix "IPTables Packet Dropped: " --log-level 7 -iptables -t filter -A CLOUDRON -j DROP - -if ! iptables -t filter -C INPUT -j CLOUDRON 2>/dev/null; then - iptables -t filter -I INPUT -j CLOUDRON -fi - -# so it gets restored across reboot -mkdir -p /etc/iptables && iptables-save > /etc/iptables/rules.v4 - -echo "==> Configuring docker" -cp "${container_files}/docker-cloudron-app.apparmor" /etc/apparmor.d/docker-cloudron-app -systemctl restart apparmor - -usermod yellowtent -a -G docker -sed -e 's,^ExecStart=.*$,ExecStart=/usr/bin/docker daemon -H fd:// --log-driver=journald --exec-opt native.cgroupdriver=cgroupfs,' -i /lib/systemd/system/docker.service -systemctl enable docker -systemctl restart docker - -# caas has ssh on port 202 and we disable password login -if [[ "${provider}" == "caas" ]]; then - # https://stackoverflow.com/questions/4348166/using-with-sed on why ? must be escaped - sed -e 's/^#\?PermitRootLogin .*/PermitRootLogin without-password/g' \ - -e 's/^#\?PermitEmptyPasswords .*/PermitEmptyPasswords no/g' \ - -e 's/^#\?PasswordAuthentication .*/PasswordAuthentication no/g' \ - -e 's/^#\?Port .*/Port 202/g' \ - -i /etc/ssh/sshd_config - - # required so we can connect to this machine since port 22 is blocked by iptables by now - systemctl reload sshd -fi - -echo "==> Setup btrfs data" -if ! grep -q loop.ko /lib/modules/`uname -r`/modules.builtin; then - # on scaleway loop is not built-in - echo "loop" >> /etc/modules - modprobe loop -fi - -if [[ ! -d "${USER_DATA_DIR}" ]]; then - truncate -s "8192m" "${USER_DATA_FILE}" # 8gb start (this will get resized dynamically by cloudron-system-setup.service) - mkfs.btrfs -L UserDataHome "${USER_DATA_FILE}" - mkdir -p "${USER_DATA_DIR}" - mount -t btrfs -o loop,nosuid "${USER_DATA_FILE}" ${USER_DATA_DIR} -fi - -echo "==> Configuring journald" -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 - -# Give user access to system logs -usermod -a -G systemd-journal yellowtent -mkdir -p /var/log/journal # in some images, this directory is not created making system log to /run/systemd instead -chown root:systemd-journal /var/log/journal -systemctl restart systemd-journald -setfacl -n -m u:yellowtent:r /var/log/journal/*/system.journal - -echo "==> Creating config directory" -rm -rf "${CONFIG_DIR}" && mkdir "${CONFIG_DIR}" -chown yellowtent:yellowtent "${CONFIG_DIR}" - -echo "==> Adding systemd services" -cp -r "${container_files}/systemd/." /etc/systemd/system/ -systemctl daemon-reload -systemctl enable cloudron.target -systemctl enable iptables-restore -systemctl enable cloudron-system-setup - -rm -rf /etc/collectd -ln -sfF "${DATA_DIR}/collectd" /etc/collectd -systemctl restart collectd - -echo "==> Configuring system" -rm -f /etc/sudoers.d/yellowtent -cp "${container_files}/sudoers" /etc/sudoers.d/yellowtent - -# For logrotate -systemctl enable cron - -# DO uses Google nameservers by default. This causes RBL queries to fail (host 2.0.0.127.zen.spamhaus.org) -# We do not use dnsmasq because it is not a recursive resolver and defaults to the value in the interfaces file (which is Google DNS!) -systemctl enable unbound - -# link nginx config to system config -unlink /etc/nginx 2>/dev/null || rm -rf /etc/nginx -ln -s "${DATA_DIR}/nginx" /etc/nginx - -cp "${container_files}/mysql.cnf" /etc/mysql/mysql.cnf - diff --git a/setup/start.sh b/setup/start.sh index 889191619..532488371 100755 --- a/setup/start.sh +++ b/setup/start.sh @@ -5,6 +5,7 @@ set -eu -o pipefail echo "==== Cloudron Start ====" readonly USER="yellowtent" +readonly DATA_FILE="/root/user_data.img" readonly BOX_SRC_DIR="/home/${USER}/box" readonly DATA_DIR="/home/${USER}/data" readonly CONFIG_DIR="/home/${USER}/configs" @@ -32,7 +33,124 @@ set_progress() { } set_progress "1" "Create container" -$script_dir/container.sh "${arg_provider}" +sed -e 's/^#NTP=/NTP=0.ubuntu.pool.ntp.org 1.ubuntu.pool.ntp.org 2.ubuntu.pool.ntp.org 3.ubuntu.pool.ntp.org/' -i /etc/systemd/timesyncd.conf +timedatectl set-ntp 1 +timedatectl set-timezone UTC + +echo "==> Setting up firewall" +iptables -t filter -N CLOUDRON || true +iptables -t filter -F CLOUDRON # empty any existing rules + +# NOTE: keep these in sync with src/apps.js validatePortBindings +# allow ssh, http, https, ping, dns +iptables -t filter -I CLOUDRON -m state --state RELATED,ESTABLISHED -j ACCEPT +# caas has ssh on port 202 +if [[ "${arg_provider}" == "caas" ]]; then + iptables -A CLOUDRON -p tcp -m tcp -m multiport --dports 25,80,202,443,587,993,4190 -j ACCEPT +else + iptables -A CLOUDRON -p tcp -m tcp -m multiport --dports 25,80,22,443,587,993,4190 -j ACCEPT +fi +iptables -t filter -A CLOUDRON -p icmp --icmp-type echo-request -j ACCEPT +iptables -t filter -A CLOUDRON -p icmp --icmp-type echo-reply -j ACCEPT +iptables -t filter -A CLOUDRON -p udp --sport 53 -j ACCEPT +iptables -t filter -A CLOUDRON -s 172.18.0.0/16 -j ACCEPT # required to accept any connections from apps to our IP: +iptables -t filter -A CLOUDRON -i lo -j ACCEPT # required for localhost connections (mysql) + +# log dropped incoming. keep this at the end of all the rules +iptables -t filter -A CLOUDRON -m limit --limit 2/min -j LOG --log-prefix "IPTables Packet Dropped: " --log-level 7 +iptables -t filter -A CLOUDRON -j DROP + +if ! iptables -t filter -C INPUT -j CLOUDRON 2>/dev/null; then + iptables -t filter -I INPUT -j CLOUDRON +fi + +# so it gets restored across reboot +mkdir -p /etc/iptables && iptables-save > /etc/iptables/rules.v4 + +echo "==> Configuring docker" +cp "${script_dir}/start/docker-cloudron-app.apparmor" /etc/apparmor.d/docker-cloudron-app +systemctl restart apparmor + +usermod yellowtent -a -G docker +sed -e 's,^ExecStart=.*$,ExecStart=/usr/bin/docker daemon -H fd:// --log-driver=journald --exec-opt native.cgroupdriver=cgroupfs,' -i /lib/systemd/system/docker.service +systemctl enable docker +systemctl restart docker + +# caas has ssh on port 202 and we disable password login +if [[ "${arg_provider}" == "caas" ]]; then + # https://stackoverflow.com/questions/4348166/using-with-sed on why ? must be escaped + sed -e 's/^#\?PermitRootLogin .*/PermitRootLogin without-password/g' \ + -e 's/^#\?PermitEmptyPasswords .*/PermitEmptyPasswords no/g' \ + -e 's/^#\?PasswordAuthentication .*/PasswordAuthentication no/g' \ + -e 's/^#\?Port .*/Port 202/g' \ + -i /etc/ssh/sshd_config + + # required so we can connect to this machine since port 22 is blocked by iptables by now + systemctl reload sshd +fi + +echo "==> Setup btrfs data" +if ! grep -q loop.ko /lib/modules/`uname -r`/modules.builtin; then + # on scaleway loop is not built-in + echo "loop" >> /etc/modules + modprobe loop +fi + +if [[ ! -d "${DATA_DIR}" ]]; then + truncate -s "8192m" "${DATA_FILE}" # 8gb start (this will get resized dynamically by cloudron-system-setup.service) + mkfs.btrfs -L UserDataHome "${DATA_FILE}" + mkdir -p "${DATA_DIR}" + mount -t btrfs -o loop,nosuid "${DATA_FILE}" ${DATA_DIR} +fi + +echo "==> Configuring journald" +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 + +# Give user access to system logs +usermod -a -G systemd-journal yellowtent +mkdir -p /var/log/journal # in some images, this directory is not created making system log to /run/systemd instead +chown root:systemd-journal /var/log/journal +systemctl restart systemd-journald +setfacl -n -m u:yellowtent:r /var/log/journal/*/system.journal + +echo "==> Creating config directory" +rm -rf "${CONFIG_DIR}" && mkdir "${CONFIG_DIR}" +chown yellowtent:yellowtent "${CONFIG_DIR}" + +echo "==> Adding systemd services" +cp -r "${script_dir}/start/systemd/." /etc/systemd/system/ +systemctl daemon-reload +systemctl enable cloudron.target +systemctl enable iptables-restore +systemctl enable cloudron-system-setup + +rm -rf /etc/collectd +ln -sfF "${DATA_DIR}/collectd" /etc/collectd +systemctl restart collectd + +echo "==> Configuring system" +rm -f /etc/sudoers.d/yellowtent +cp "${script_dir}/start/sudoers" /etc/sudoers.d/yellowtent + +# For logrotate +systemctl enable cron + +# DO uses Google nameservers by default. This causes RBL queries to fail (host 2.0.0.127.zen.spamhaus.org) +# We do not use dnsmasq because it is not a recursive resolver and defaults to the value in the interfaces file (which is Google DNS!) +systemctl enable unbound + +# link nginx config to system config +unlink /etc/nginx 2>/dev/null || rm -rf /etc/nginx +ln -s "${DATA_DIR}/nginx" /etc/nginx + +cp "${script_dir}/start/mysql.cnf" /etc/mysql/mysql.cnf set_progress "5" "Adjust system settings" hostnamectl set-hostname "${arg_fqdn}" diff --git a/setup/container/cloudron-system-setup.sh b/setup/start/cloudron-system-setup.sh similarity index 100% rename from setup/container/cloudron-system-setup.sh rename to setup/start/cloudron-system-setup.sh diff --git a/setup/container/docker-cloudron-app.apparmor b/setup/start/docker-cloudron-app.apparmor similarity index 100% rename from setup/container/docker-cloudron-app.apparmor rename to setup/start/docker-cloudron-app.apparmor diff --git a/setup/container/mysql.cnf b/setup/start/mysql.cnf similarity index 100% rename from setup/container/mysql.cnf rename to setup/start/mysql.cnf diff --git a/setup/container/sudoers b/setup/start/sudoers similarity index 100% rename from setup/container/sudoers rename to setup/start/sudoers diff --git a/setup/container/systemd/box.service b/setup/start/systemd/box.service similarity index 100% rename from setup/container/systemd/box.service rename to setup/start/systemd/box.service diff --git a/setup/container/systemd/cloudron-system-setup.service b/setup/start/systemd/cloudron-system-setup.service similarity index 84% rename from setup/container/systemd/cloudron-system-setup.service rename to setup/start/systemd/cloudron-system-setup.service index 201e6aadb..d626609ba 100644 --- a/setup/container/systemd/cloudron-system-setup.service +++ b/setup/start/systemd/cloudron-system-setup.service @@ -9,7 +9,7 @@ After=cloud-init.service [Service] Type=oneshot -ExecStart="/home/yellowtent/box/setup/container/cloudron-system-setup.sh" +ExecStart="/home/yellowtent/box/setup/start/cloudron-system-setup.sh" RemainAfterExit=yes [Install] diff --git a/setup/container/systemd/cloudron.target b/setup/start/systemd/cloudron.target similarity index 100% rename from setup/container/systemd/cloudron.target rename to setup/start/systemd/cloudron.target diff --git a/setup/container/systemd/crashnotifier@.service b/setup/start/systemd/crashnotifier@.service similarity index 100% rename from setup/container/systemd/crashnotifier@.service rename to setup/start/systemd/crashnotifier@.service diff --git a/setup/container/systemd/iptables-restore.service b/setup/start/systemd/iptables-restore.service similarity index 100% rename from setup/container/systemd/iptables-restore.service rename to setup/start/systemd/iptables-restore.service