#!/usr/bin/env bash
# SPDX-License-Identifier: AGPL-3.0-or-later
# Harden a fresh Ubuntu 24.04 VPS for running the pvtcoms oblivious relay.
# Idempotent where practical. Run as root on first login:  bash harden.sh
set -euo pipefail

RELAY_USER="${RELAY_USER:-pvtops}"

log() { printf '\033[1;34m[harden]\033[0m %s\n' "$*"; }
die() { printf '\033[1;31m[harden] %s\033[0m\n' "$*" >&2; exit 1; }

[ "$(id -u)" -eq 0 ] || die "run as root"

log "Updating packages…"
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get upgrade -y
apt-get install -y ufw fail2ban unattended-upgrades sudo curl ca-certificates

# --- Non-root sudo user with your SSH key -----------------------------------
if ! id "$RELAY_USER" &>/dev/null; then
  log "Creating sudo user '$RELAY_USER'…"
  adduser --disabled-password --gecos "" "$RELAY_USER"
  usermod -aG sudo "$RELAY_USER"
fi

# Passwordless sudo for the admin user. The account has NO password (key-only login), so the SSH key
# is the sole auth boundary — exactly how Ubuntu cloud images grant their default user sudo. Without
# this, 'sudo' would prompt for a non-existent password and lock out all key-based automation.
echo "$RELAY_USER ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/90-pvtcoms
chmod 440 /etc/sudoers.d/90-pvtcoms
visudo -cf /etc/sudoers.d/90-pvtcoms >/dev/null || die "sudoers drop-in invalid; aborting"

# Copy root's authorized_keys to the new user so you can log in as them with the SAME key.
if [ -f /root/.ssh/authorized_keys ]; then
  install -d -m 700 -o "$RELAY_USER" -g "$RELAY_USER" "/home/$RELAY_USER/.ssh"
  install -m 600 -o "$RELAY_USER" -g "$RELAY_USER" \
    /root/.ssh/authorized_keys "/home/$RELAY_USER/.ssh/authorized_keys"
  log "Copied SSH key to $RELAY_USER. TEST 'ssh $RELAY_USER@<ip>' BEFORE closing this session."
else
  log "WARNING: /root/.ssh/authorized_keys not found. Add your key for '$RELAY_USER' before"
  log "         disabling password login, or you will be locked out."
fi

# --- SSH hardening: key-only, no root login ---------------------------------
log "Hardening SSH (key-only, no root login)…"
SSHD_DROPIN=/etc/ssh/sshd_config.d/99-pvtcoms.conf
cat > "$SSHD_DROPIN" <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
MaxAuthTries 3
X11Forwarding no
AllowAgentForwarding no
EOF
# Validate config before restarting so a typo can't lock you out.
sshd -t && systemctl restart ssh || die "sshd config test failed; NOT restarting ssh"

# --- Firewall: deny all inbound except SSH ----------------------------------
# Relay is onion-only — Tor makes OUTBOUND connections to publish the service, so no inbound
# port is needed for the messenger at all. Only SSH is allowed in.
log "Configuring UFW (default deny inbound, allow SSH only)…"
ufw --force reset >/dev/null
ufw default deny incoming
ufw default allow outgoing
ufw allow OpenSSH
ufw --force enable
ufw status verbose || true

# --- fail2ban for SSH -------------------------------------------------------
log "Enabling fail2ban (sshd jail)…"
cat > /etc/fail2ban/jail.d/sshd.local <<'EOF'
[sshd]
enabled = true
maxretry = 3
bantime = 1h
findtime = 10m
EOF
systemctl enable --now fail2ban
systemctl restart fail2ban

# --- Automatic security updates ---------------------------------------------
log "Enabling unattended security upgrades…"
cat > /etc/apt/apt.conf.d/20auto-upgrades <<'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
EOF
systemctl enable --now unattended-upgrades || true

# --- Kernel/network sysctl hardening ----------------------------------------
log "Applying sysctl hardening…"
cat > /etc/sysctl.d/99-pvtcoms.conf <<'EOF'
# Ignore ICMP redirects / source routing, log martians
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.log_martians = 1
kernel.kptr_restrict = 2
kernel.dmesg_restrict = 1
EOF
sysctl --system >/dev/null

log "Done. NEXT:"
log "  1) Open a NEW terminal and confirm:  ssh $RELAY_USER@<this-ip>   (key login, sudo works)"
log "  2) Only after that works, run:        sudo bash setup-relay.sh"
log ""
log "NOTE on full-disk encryption (LUKS): most VPS providers can't add FDE post-install."
log "     For at-rest protection against host seizure, provision the VPS with LUKS at install"
log "     time if the provider offers it, or keep the relay's data dir on an encrypted volume."
