#!/usr/bin/env bash
# Bootstrap a fresh Ubuntu 24.04 droplet into the house shape. Stream E, task E4.
#
# Run ONCE from the dev server, as root over SSH, on a droplet that has nothing on it:
#     ssh root@<ip> bash -s < deploy/bootstrap-droplet.sh
# Idempotent: every step checks before it changes. What it does, and why:
#   - a non-root user `deploy` (sudo, key-only) so root never logs in again;
#   - sshd: keys only, no passwords, no root once `deploy` works (second pass);
#   - unattended security upgrades, NO automatic reboot: a reboot killed an overnight
#     collection on 11 Sep; deploy/reboot-required-check.sh emails rian when one is due;
#   - Docker CE + compose plugin from Docker's own repository, json-file log rotation;
#   - a 2 GB swap file (Vite builds are the memory hog, not runtime);
#   - Tailscale installed but NOT joined: `tailscale up` needs rian's browser, not a key in chat;
#   - /srv/apps/<project> owned by deploy, mirroring the dev server's layout.
# No host firewall here on purpose: the DigitalOcean cloud firewall is the perimeter, and
# Docker manages its own iptables chains. The sidecar's DOCKER-USER rule is a separate,
# owner-approved step (running list `do-sidecar-firewall-rule`).
set -euo pipefail

PROJECT="${PROJECT:-dutyfreeprofessor}"
DEPLOY_USER="${DEPLOY_USER:-deploy}"
export DEBIAN_FRONTEND=noninteractive

log() { printf '\n== %s\n' "$*"; }

log "timezone UTC"
timedatectl set-timezone UTC

log "base packages"
apt-get update -q
apt-get install -y -q ca-certificates curl gnupg unattended-upgrades apt-listchanges rsync git python3

log "user ${DEPLOY_USER} (sudo, keys copied from root)"
if ! id -u "$DEPLOY_USER" >/dev/null 2>&1; then
  adduser --disabled-password --gecos "" "$DEPLOY_USER"
fi
usermod -aG sudo "$DEPLOY_USER"
install -d -m 700 -o "$DEPLOY_USER" -g "$DEPLOY_USER" "/home/$DEPLOY_USER/.ssh"
install -m 600 -o "$DEPLOY_USER" -g "$DEPLOY_USER" /root/.ssh/authorized_keys "/home/$DEPLOY_USER/.ssh/authorized_keys"
# Passwordless sudo for the deploy user: the account is key-only and reachable only over
# Tailscale once step two of sshd lands, and an unattended deploy cannot type a password.
echo "$DEPLOY_USER ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/90-$DEPLOY_USER"
chmod 440 "/etc/sudoers.d/90-$DEPLOY_USER"

log "sshd: keys only"
install -d /etc/ssh/sshd_config.d
cat > /etc/ssh/sshd_config.d/10-house.conf << 'SSHD'
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password
X11Forwarding no
MaxAuthTries 4
SSHD
sshd -t && systemctl reload ssh

log "unattended upgrades"
cat > /etc/apt/apt.conf.d/20auto-upgrades << 'APT'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
APT
cat > /etc/apt/apt.conf.d/52house-unattended << 'APT'
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "false";
APT

log "docker (Docker's repository)"
if ! command -v docker >/dev/null 2>&1; then
  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
  . /etc/os-release
  echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu ${VERSION_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
fi
if [ ! -f /etc/docker/daemon.json ]; then
  cat > /etc/docker/daemon.json << 'DOCKER'
{
  "log-driver": "json-file",
  "log-opts": { "max-size": "20m", "max-file": "5" }
}
DOCKER
  systemctl restart docker
fi
usermod -aG docker "$DEPLOY_USER"   # the deploy user IS the operator on this box (no gateway here yet)

log "swap 2G"
if ! swapon --show | grep -q /swapfile; then
  fallocate -l 2G /swapfile
  chmod 600 /swapfile
  mkswap /swapfile
  swapon /swapfile
  grep -q '^/swapfile' /etc/fstab || echo '/swapfile none swap sw 0 0' >> /etc/fstab
fi
grep -q '^vm.swappiness' /etc/sysctl.d/90-house.conf 2>/dev/null || echo 'vm.swappiness=10' >> /etc/sysctl.d/90-house.conf
sysctl -q -p /etc/sysctl.d/90-house.conf

log "tailscale (installed, not joined)"
if ! command -v tailscale >/dev/null 2>&1; then
  curl -fsSL https://tailscale.com/install.sh | sh
fi

log "project directory"
install -d -m 750 -o "$DEPLOY_USER" -g "$DEPLOY_USER" "/srv/apps/$PROJECT"
install -d -m 750 -o "$DEPLOY_USER" -g "$DEPLOY_USER" "/srv/caddy"

log "done"
echo "user=$DEPLOY_USER docker=$(docker --version) compose=$(docker compose version --short) swap=$(swapon --show --noheadings | awk '{print $3}') tailscale=$(tailscale version | head -1)"
echo "next: ssh ${DEPLOY_USER}@<ip> 'sudo tailscale up' and open the login URL it prints; then set PermitRootLogin no."
