117 lines
4.6 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
if [[ ${EUID} -ne 0 ]]; then
echo "This installer must run as root" >&2
exit 1
fi
SOURCE_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
MYSQL_ENV=/opt/cangku/shared/mysql.env
SERVICE_ENV=/etc/cangku-bootstrap/service.env
test -f "${MYSQL_ENV}"
test -f "${SOURCE_DIR}/bootstrap_service.py"
apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq python3-venv openssl certbot >/dev/null
if ! getent passwd cangku-bootstrap >/dev/null; then
useradd --system --home-dir /var/lib/cangku-bootstrap --create-home --shell /usr/sbin/nologin cangku-bootstrap
fi
if ! getent passwd cangku-tunnel >/dev/null; then
useradd --system --home-dir /var/lib/cangku-tunnel --create-home --shell /bin/bash cangku-tunnel
fi
passwd -d cangku-tunnel >/dev/null 2>&1
install -d -m 0755 /opt/cangku-bootstrap/app
install -d -m 0700 -o cangku-bootstrap -g cangku-bootstrap /var/lib/cangku-bootstrap
install -d -m 0750 -o root -g cangku-bootstrap /etc/cangku-bootstrap
install -m 0755 "${SOURCE_DIR}/bootstrap_service.py" /opt/cangku-bootstrap/app/bootstrap_service.py
install -m 0750 "${SOURCE_DIR}/cangku-bootstrapctl" /usr/local/sbin/cangku-bootstrapctl
if [[ ! -x /opt/cangku-bootstrap/venv/bin/python ]]; then
python3 -m venv /opt/cangku-bootstrap/venv
fi
/opt/cangku-bootstrap/venv/bin/pip install --disable-pip-version-check -q -r "${SOURCE_DIR}/requirements.txt"
if [[ ! -f /var/lib/cangku-bootstrap/ssh_user_ca ]]; then
sudo -u cangku-bootstrap ssh-keygen -q -t ed25519 -N '' -C cangku-bootstrap-user-ca -f /var/lib/cangku-bootstrap/ssh_user_ca
fi
chmod 0600 /var/lib/cangku-bootstrap/ssh_user_ca
chmod 0644 /var/lib/cangku-bootstrap/ssh_user_ca.pub
install -d -m 0700 -o cangku-tunnel -g cangku-tunnel /var/lib/cangku-tunnel/.ssh
{
printf 'cert-authority,principals="cangku-tunnel" '
cat /var/lib/cangku-bootstrap/ssh_user_ca.pub
} > /var/lib/cangku-tunnel/.ssh/authorized_keys
chown cangku-tunnel:cangku-tunnel /var/lib/cangku-tunnel/.ssh/authorized_keys
chmod 0600 /var/lib/cangku-tunnel/.ssh/authorized_keys
install -m 0644 "${SOURCE_DIR}/sshd-cangku-tunnel.conf" /etc/ssh/sshd_config.d/60-cangku-tunnel.conf
sshd -t
systemctl reload ssh
if [[ ! -f "${SERVICE_ENV}" ]]; then
provisioner_password=$(openssl rand -hex 32)
token_pepper=$(openssl rand -hex 32)
umask 0077
{
printf 'BOOTSTRAP_BIND_HOST=127.0.0.1\n'
printf 'BOOTSTRAP_PORT=4092\n'
printf 'BOOTSTRAP_STATE_DB=/var/lib/cangku-bootstrap/state.sqlite3\n'
printf 'BOOTSTRAP_TOKEN_PEPPER=%s\n' "${token_pepper}"
printf 'BOOTSTRAP_MYSQL_HOST=127.0.0.1\n'
printf 'BOOTSTRAP_MYSQL_PORT=3307\n'
printf 'BOOTSTRAP_MYSQL_DATABASE=cangku_system\n'
printf 'BOOTSTRAP_MYSQL_USER=cangku_bootstrap\n'
printf 'BOOTSTRAP_MYSQL_PASSWORD=%s\n' "${provisioner_password}"
printf 'BOOTSTRAP_SSH_CA_KEY=/var/lib/cangku-bootstrap/ssh_user_ca\n'
printf 'BOOTSTRAP_SSH_HOST_KEY=/etc/ssh/ssh_host_ed25519_key.pub\n'
printf 'BOOTSTRAP_SSH_HOST=103.236.66.132\n'
printf 'BOOTSTRAP_SSH_PORT=22\n'
printf 'BOOTSTRAP_SSH_USER=cangku-tunnel\n'
printf 'BOOTSTRAP_REMOTE_DB_HOST=127.0.0.1\n'
printf 'BOOTSTRAP_REMOTE_DB_PORT=3307\n'
printf 'BOOTSTRAP_CERT_DAYS=30\n'
} > "${SERVICE_ENV}"
chown root:cangku-bootstrap "${SERVICE_ENV}"
chmod 0640 "${SERVICE_ENV}"
else
provisioner_password=$(sed -n 's/^BOOTSTRAP_MYSQL_PASSWORD=//p' "${SERVICE_ENV}")
fi
set -a
source "${MYSQL_ENV}"
set +a
docker exec -i -e MYSQL_PWD="${MYSQL_ROOT_PASSWORD}" cangku-mysql mysql -uroot <<EOF
CREATE USER IF NOT EXISTS 'cangku_bootstrap'@'%' IDENTIFIED BY '${provisioner_password}';
ALTER USER 'cangku_bootstrap'@'%' IDENTIFIED BY '${provisioner_password}';
GRANT CREATE USER ON *.* TO 'cangku_bootstrap'@'%';
GRANT ALL PRIVILEGES ON cangku_system.* TO 'cangku_bootstrap'@'%' WITH GRANT OPTION;
EOF
unset MYSQL_ROOT_PASSWORD MYSQL_PASSWORD provisioner_password token_pepper
install -m 0644 "${SOURCE_DIR}/cangku-bootstrap.service" /etc/systemd/system/cangku-bootstrap.service
test -f /etc/letsencrypt/live/ck.yydd.ai/fullchain.pem
install -m 0644 "${SOURCE_DIR}/nginx-bootstrap.conf" /etc/nginx/sites-available/cangku-bootstrap
ln -sfn /etc/nginx/sites-available/cangku-bootstrap /etc/nginx/sites-enabled/cangku-bootstrap
nginx -t
systemctl daemon-reload
systemctl enable --now cangku-bootstrap
systemctl enable --now certbot.timer
ufw allow 80/tcp comment 'HTTP and ACME' >/dev/null
ufw allow 443/tcp comment 'HTTPS' >/dev/null
systemctl reload nginx
for _ in {1..20}; do
if curl --silent --show-error --fail https://ck.yydd.ai/health >/dev/null; then
exit 0
fi
sleep 0.5
done
journalctl -u cangku-bootstrap -n 50 --no-pager >&2
exit 1