#!/bin/bash
#
# setup-tunnel-vps.sh — installs frp server on a VPS to front an
# Ancient Holdings StoaChain node running behind CGNAT.
#
# What this does:
#   1. Downloads the frp v0.62.1 binaries (github.com/fatedier/frp).
#   2. Creates /etc/frp/frps.toml with a random auth token.
#   3. Writes a systemd unit so frps runs as a non-root `frp` user,
#      restarts on failure, comes back on reboot.
#   4. Opens UFW on the VPS for: 1789 (chainweb p2p), 1848 (chainweb
#      service), 22 (SSH forwarded to the home node), 7000 (frp
#      control channel).
#   5. Prints the auth token + instructions for the home-node step.
#
# What this does NOT do:
#   - Configure IONOS's cloud-level firewall. That's a separate
#     concern you handle in the IONOS control panel. This script only
#     configures the VPS's own UFW.
#   - Install certificates. chainweb-node's TLS cert lives on the
#     HOME node, not here — this script just tunnels raw TCP.
#   - Provision the VPS. You rent it first, then scp this script
#     over and run as root.
#
# Usage (on the VPS, as root):
#   wget https://ancientholdings.eu/scripts/setup-tunnel-vps.sh
#   chmod +x setup-tunnel-vps.sh
#   sudo ./setup-tunnel-vps.sh
#
# Tested on: Ubuntu 24.04 Noble, Ubuntu 22.04 Jammy. Should work
# on any recent Debian-family distro with systemd.

set -euo pipefail

if [ "$EUID" -ne 0 ]; then
  echo "[tunnel-vps] must run as root (or with sudo)" >&2
  exit 1
fi

FRP_VERSION="0.62.1"
FRP_ARCH="linux_amd64"
FRP_URL="https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_${FRP_ARCH}.tar.gz"
INSTALL_DIR="/usr/local/bin"
CONFIG_DIR="/etc/frp"
DATA_DIR="/var/lib/frp"
SERVICE_NAME="frps"

echo "[tunnel-vps] Ancient Holdings — StoaChain tunnel server installer"
echo "[tunnel-vps] frp version: ${FRP_VERSION}"
echo

# ----- 1. Download + install frp binary -----

echo "[tunnel-vps] downloading frp..."
cd /tmp
rm -rf frp-download
mkdir -p frp-download
cd frp-download
curl -fsSL "$FRP_URL" -o frp.tar.gz
tar xzf frp.tar.gz
cd "frp_${FRP_VERSION}_${FRP_ARCH}"
install -m 0755 frps "${INSTALL_DIR}/frps"
install -m 0755 frpc "${INSTALL_DIR}/frpc"   # keep both; harmless on a server
cd /tmp
rm -rf frp-download

# ----- 2. Create frp user + dirs -----

if ! id -u frp >/dev/null 2>&1; then
  useradd --system --no-create-home --shell /usr/sbin/nologin frp
  echo "[tunnel-vps] created system user 'frp'"
fi
mkdir -p "$CONFIG_DIR" "$DATA_DIR"
chown -R frp:frp "$DATA_DIR"
chmod 750 "$DATA_DIR"

# ----- 3. Generate auth token (or reuse existing) -----

TOKEN_FILE="${CONFIG_DIR}/.token"
if [ -f "$TOKEN_FILE" ]; then
  AUTH_TOKEN=$(cat "$TOKEN_FILE")
  echo "[tunnel-vps] reusing existing auth token from ${TOKEN_FILE}"
else
  AUTH_TOKEN=$(head -c 32 /dev/urandom | base64 | tr -d '=+/' | head -c 32)
  echo "$AUTH_TOKEN" > "$TOKEN_FILE"
  chmod 600 "$TOKEN_FILE"
  chown frp:frp "$TOKEN_FILE"
  echo "[tunnel-vps] generated new auth token in ${TOKEN_FILE}"
fi

# ----- 4. Write frps config -----

cat > "${CONFIG_DIR}/frps.toml" <<EOF
# Ancient Holdings — StoaChain tunnel server config.
# Generated by setup-tunnel-vps.sh on $(date -u +%FT%TZ).
#
# See docs: https://ancientholdings.eu/docs/vps-tunnel-setup

bindAddr = "0.0.0.0"
bindPort = 7000

# Authentication — the home node's frp client must present the
# same token in its config.
auth.method = "token"
auth.token = "${AUTH_TOKEN}"

# Allow the client to request privileged low ports (1789/1848/22)
# for its reverse-proxies.
allowPorts = [
  { start = 22, end = 22 },
  { start = 1789, end = 1789 },
  { start = 1848, end = 1848 },
]

# Dashboard (optional, off by default). Uncomment + set strong pwd
# if you want live tunnel visibility.
# webServer.addr = "127.0.0.1"
# webServer.port = 7500
# webServer.user = "admin"
# webServer.password = "CHANGE_ME"

transport.maxPoolCount = 10
log.to = "${DATA_DIR}/frps.log"
log.level = "info"
log.maxDays = 7
EOF
chown root:frp "${CONFIG_DIR}/frps.toml"
chmod 640 "${CONFIG_DIR}/frps.toml"
echo "[tunnel-vps] wrote ${CONFIG_DIR}/frps.toml"

# ----- 5. Systemd unit -----

cat > /etc/systemd/system/${SERVICE_NAME}.service <<EOF
[Unit]
Description=Ancient Holdings StoaChain tunnel server (frp)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=frp
Group=frp
ExecStart=${INSTALL_DIR}/frps -c ${CONFIG_DIR}/frps.toml
Restart=on-failure
RestartSec=5s
LimitNOFILE=65536

# Hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ReadWritePaths=${DATA_DIR}
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictNamespaces=true
# frp needs CAP_NET_BIND_SERVICE to bind low-port reverse proxies
# (22, 1789, 1848) on behalf of the home node.
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable "${SERVICE_NAME}" >/dev/null
systemctl restart "${SERVICE_NAME}"

# ----- 6. UFW — open the ports we tunnel + frp control -----

if command -v ufw >/dev/null 2>&1; then
  echo "[tunnel-vps] configuring UFW..."
  ufw allow 22/tcp comment 'SSH (tunneled to home node)' >/dev/null
  ufw allow 1789/tcp comment 'chainweb P2P (tunneled)' >/dev/null
  ufw allow 1848/tcp comment 'chainweb service API (tunneled)' >/dev/null
  ufw allow 7000/tcp comment 'frp control channel (from home node)' >/dev/null
  # Make sure ufw is actually active.
  if ! ufw status | grep -q "Status: active"; then
    echo "[tunnel-vps] UFW was inactive; enabling with SSH allowed..."
    ufw --force enable
  fi
  ufw status numbered | sed 's/^/[tunnel-vps]   /'
else
  echo "[tunnel-vps] UFW not installed; skipping firewall config."
  echo "[tunnel-vps] Install with: apt install ufw; then re-run this script."
fi

# ----- 7. Verify + print handoff info -----

sleep 2
if systemctl is-active --quiet "${SERVICE_NAME}"; then
  echo
  echo "=================================================================="
  echo "[tunnel-vps] ✓ frp server is running."
  echo "=================================================================="
  PUBLIC_IP=$(curl -fsSL https://ifconfig.me 2>/dev/null || echo "<unknown>")
  echo
  echo "Public IPv4 of this VPS:   ${PUBLIC_IP}"
  echo "frp control port:          7000/tcp"
  echo "Tunneled public ports:     22/tcp, 1789/tcp, 1848/tcp"
  echo
  echo "=================================================================="
  echo "AUTH TOKEN (needed by home-node setup script):"
  echo
  echo "    ${AUTH_TOKEN}"
  echo
  echo "Copy this entire token. You'll paste it when running"
  echo "setup-tunnel-node.sh on your home node."
  echo "=================================================================="
  echo
  echo "Next steps:"
  echo
  echo "1. In IONOS cloud panel, open inbound TCP 22, 1789, 1848, 7000"
  echo "   for this VPS. (The VPS's UFW is already configured, but"
  echo "   IONOS's cloud-level firewall is separate and takes priority.)"
  echo
  echo "2. Point your DuckDNS (or similar) hostname at ${PUBLIC_IP}."
  echo "   For DuckDNS: login, update the IP field, save."
  echo
  echo "3. On your HOME node (the one running chainweb-node), run:"
  echo "     wget https://ancientholdings.eu/scripts/setup-tunnel-node.sh"
  echo "     chmod +x setup-tunnel-node.sh"
  echo "     sudo ./setup-tunnel-node.sh ${PUBLIC_IP} ${AUTH_TOKEN}"
  echo
  echo "4. See https://ancientholdings.eu/docs/vps-tunnel-setup for the"
  echo "   full walkthrough and troubleshooting."
else
  echo "[tunnel-vps] ✗ frp server failed to start. Check:"
  echo "    systemctl status ${SERVICE_NAME}"
  echo "    journalctl -u ${SERVICE_NAME} -n 50"
  exit 1
fi
