Files
petrolyst-infra/host/bootstrap.sh
T
Nasim SadatandClaude Opus 5.5 8405706ed8 Remove Trino: Superset reads fuel-db directly as fuel_ro (PD-14)
trino/ deleted; the role trino_ro becomes fuel_ro, its password read from a
secret file at connect time; dashboards' SQL and column list for PostgreSQL;
the Compose project is renamed petrolyst, with volumes pinned to their old
names. AGENTS.md points to the architecture context. Not deployed: the next
deploy needs README's one-time steps first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 10:57:18 +01:00

91 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# One-time host preparation for the petrolyst server (Ubuntu 24.04), run as root.
# Idempotent: re-running converges to the same state.
#
# bootstrap.sh
#
# Deploys are manual: a person runs them over root SSH, and root hands over to
# the deploy user (README, "Manual deploy"). There is no CI runner, so deploy
# has no SSH key of its own.
set -euo pipefail
die() { echo "ERROR: $*" >&2; exit 1; }
[ "$(id -u)" = 0 ] || die "run as root"
[ $# -eq 0 ] || die "bootstrap.sh takes no arguments (deploys are manual; there is no CI key)"
ROOT=/opt/petrolyst
echo "== packages and Docker (official apt repository)"
apt-get update -q
apt-get install -y -q ca-certificates curl rsync ufw
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
# shellcheck source=/dev/null
codename=$(. /etc/os-release && echo "$VERSION_CODENAME")
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $codename stable" \
>/etc/apt/sources.list.d/docker.list
apt-get update -q
apt-get install -y -q docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
daemon_json='{
"log-driver": "json-file",
"log-opts": { "max-size": "10m", "max-file": "3" },
"live-restore": true
}'
if [ "$(cat /etc/docker/daemon.json 2>/dev/null)" != "$daemon_json" ]; then
printf '%s\n' "$daemon_json" >/etc/docker/daemon.json
systemctl restart docker
fi
systemctl enable --now docker
echo "== swap (4 GB) for Superset and two Postgres in 7.8 GB"
if ! swapon --show=NAME --noheadings | grep -qx /swapfile; then
[ -e /swapfile ] || fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile >/dev/null
swapon /swapfile
fi
grep -q '^/swapfile ' /etc/fstab || echo '/swapfile none swap sw 0 0' >>/etc/fstab
echo 'vm.swappiness=10' >/etc/sysctl.d/99-petrolyst.conf
sysctl -q -p /etc/sysctl.d/99-petrolyst.conf
echo "== firewall: 22, 80, 443 only"
# Docker-published ports bypass ufw. Only Traefik publishes publicly; every
# other published port in the stacks binds to 127.0.0.1.
ufw default deny incoming >/dev/null
ufw default allow outgoing >/dev/null
for port in 22 80 443; do ufw allow "$port/tcp" >/dev/null; done
ufw --force enable >/dev/null
echo "== deploy user (runs deploy.sh; reached only through sudo from root)"
id deploy >/dev/null 2>&1 || useradd --create-home --shell /bin/bash deploy
usermod -aG docker deploy # docker access makes deploy root-equivalent, so it gets no SSH key
rm -f /home/deploy/.ssh/authorized_keys # the former CI key, if an earlier bootstrap installed it
echo "== SSH: keys only"
[ -s /root/.ssh/authorized_keys ] || die "root has no authorized_keys; refusing to turn off password login"
# 00- sorts before cloud-init's 50-cloud-init.conf, and sshd keeps the first
# value it reads, so these win over its PasswordAuthentication yes.
cat >/etc/ssh/sshd_config.d/00-petrolyst.conf <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
EOF
sshd -t
systemctl reload ssh
echo "== /opt/petrolyst"
install -d -o root -g root -m 0755 "$ROOT"
install -d -o deploy -g deploy -m 0755 "$ROOT/infra" "$ROOT/releases" "$ROOT/incoming" "$ROOT/state"
install -d -o deploy -g deploy -m 0750 "$ROOT/backups"
[ -e "$ROOT/deploy.lock" ] || install -o deploy -g deploy -m 0640 /dev/null "$ROOT/deploy.lock"
docker network inspect proxy >/dev/null 2>&1 || docker network create proxy >/dev/null
echo
echo "Done. Before closing this session, check from another terminal that"
echo " ssh petrolyst still logs you in as root, and"
echo " sshd -T | grep -E 'passwordauthentication|permitrootlogin' shows no / prohibit-password."
echo "Next: host/secrets-init.sh"