Unverified Commit f5a76cf8 authored by Lemon-miaow's avatar Lemon-miaow
Browse files

fix(deploy): make demo-up a thin wrapper — bootstrap is the one origin for the game stack (#63)

demo-up.sh grew its own image lane in July, before bootstrap could build the
game stack. The copy has since drifted from the installer it duplicates: it
pinned Paper 1.21.8 while bootstrap derives one version from the Limbo login
gate (both hops of a login must speak one protocol), it never built
felis-velocity.jar (a proxy without it silently routes nothing), it imported
images under local tags the [velocity] wiring no longer points at, and it left
the docker daemon running.

It now runs deploy/bootstrap.sh (unless SKIP_BOOTSTRAP=1), checks that the
earlier run really left the full stack behind, and hands over to 'felis setup'
— so a half-installed base is a clear error instead of a proxy that accepts
logins and routes nowhere.

Verified on the VM: healthy base passes to the handoff (exit 0); a hidden
felis-velocity.jar dies naming the jar and the remedy (exit 1, jar restored).
parent 1184d6b7
Loading
Loading
Loading
Loading
+25 −91
Changes for deploy/demo-up.sh: 25 added lines, 91 removed lines.
Original line number Diff line number Diff line
#!/bin/bash
# demo-up.sh — one-shot Felis demo bring-up.
#
# Collapses the four manual steps (bootstrap -> build/import limbo+lobby images ->
# edit felis.toml -> felis setup) into a single command:
#
#     sudo bash deploy/demo-up.sh
#
# It ends by exec'ing the interactive `felis setup` TUI (create the Owner account) —
# that human step is the only thing this script cannot do for you.
# Every piece a demo box needs — base platform (k3s + felis + docker + cloudflared +
# control plane), the limbo/lobby/paper images, the felis-velocity proxy plugin, and
# the [velocity] wiring in felis.host.toml — is built by deploy/bootstrap.sh. This
# wrapper adds only the one step the installer cannot do: the interactive
# `felis setup` TUI that creates the Owner account.
#
# Image source, in order of preference:
#   1. Prebuilt tars at deploy/images/felis-limbo.tar + felis-lobby.tar (imported as-is).
#   2. Otherwise built on this host with docker, resolving the LOOHP/Limbo CI jar and
#      the latest stable Paper jar automatically. Override any of:
#        LIMBO_JAR_URL LIMBO_SCHEM_URL LIMBO_VERSION PAPER_JAR_URL PAPER_JAR_SHA256
#        PAPER_MC_VERSION
# It used to rebuild the game images here with its own copy of that logic, written
# before bootstrap grew the job. The copy drifted: it pinned Paper 1.21.8 while the
# installer derives one version from the Limbo login gate (both hops of a login must
# speak one protocol), never built felis-velocity.jar (so the proxy it wired had
# nowhere to route), and left docker running. The installer is the single origin.
#
# Toggles: SKIP_BOOTSTRAP=1 (base already up), SKIP_SETUP=1 (stop before the TUI).
# Toggles: SKIP_BOOTSTRAP=1 (base + game stack already installed by a full bootstrap),
#          SKIP_SETUP=1 (stop before the TUI).
set -Eeuo pipefail

SRC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
STATE_DIR=/etc/felis
HOST_TOML="$STATE_DIR/felis.host.toml"
IMG_DIR="$SRC_DIR/deploy/images"
LIMBO_IMAGE="felis-limbo:demo"
LOBBY_IMAGE="felis-lobby:demo"
PLUGIN_JAR=/opt/felis/velocity/plugins/felis-velocity.jar
K3S=/usr/local/bin/k3s
FELIS=/usr/local/bin/felis

@@ -33,11 +31,11 @@ die() { printf '\033[1;31mERROR: %s\033[0m\n' "$*" >&2; exit 1; }

[ "$(id -u)" -eq 0 ] || die "run as root (sudo bash deploy/demo-up.sh)"

# 1. base platform (k3s + felis + docker + cloudflared + control plane) ----------
# 1. base platform + full game stack (deploy/bootstrap.sh) -----------------------
if [ "${SKIP_BOOTSTRAP:-0}" = 1 ]; then
  log "SKIP_BOOTSTRAP=1 — assuming the base platform is already up"
else
  log "bringing up the base platform (deploy/bootstrap.sh)"
  log "bringing up the base platform and the game stack (deploy/bootstrap.sh)"
  bash "$SRC_DIR/deploy/bootstrap.sh"
fi

@@ -46,83 +44,19 @@ command -v "$K3S" >/dev/null 2>&1 || K3S=k3s
command -v "$K3S"   >/dev/null 2>&1 || die "k3s not found — did bootstrap complete?"
command -v "$FELIS" >/dev/null 2>&1 || die "felis not found — did bootstrap complete?"

# 2. get the two game images into k3s containerd --------------------------------
if [ -f "$IMG_DIR/felis-limbo.tar" ] && [ -f "$IMG_DIR/felis-lobby.tar" ]; then
  log "importing prebuilt image tars from $IMG_DIR"
  "$K3S" ctr images import "$IMG_DIR/felis-limbo.tar"
  "$K3S" ctr images import "$IMG_DIR/felis-lobby.tar"
  # Optional: the plain-Paper recommended base, if a tar was staged for it.
  [ -f "$IMG_DIR/felis-paper.tar" ] && "$K3S" ctr images import "$IMG_DIR/felis-paper.tar"
else
  log "no prebuilt tars in $IMG_DIR — building on this host with docker"
  command -v docker >/dev/null 2>&1 || die "docker not found; cannot build images"

  rel=$(curl -fsSL --max-time 30 "https://ci.loohpjames.com/job/Limbo/lastSuccessfulBuild/api/json" \
          | grep -oE 'target/Limbo-[0-9][^"]+\.jar' | head -1) || true
  : "${LIMBO_JAR_URL:=https://ci.loohpjames.com/job/Limbo/lastSuccessfulBuild/artifact/$rel}"
  : "${LIMBO_SCHEM_URL:=https://ci.loohpjames.com/job/Limbo/lastSuccessfulBuild/artifact/spawn.schem}"
  : "${LIMBO_VERSION:=$(basename "$rel" | sed -E 's/^Limbo-//; s/\.jar$//; s/-[0-9]+\.[0-9]+$//')}"
  [ -n "$rel" ] || [ -n "${LIMBO_JAR_URL##*artifact/}" ] || die "could not resolve the Limbo jar; set LIMBO_JAR_URL"
  log "building $LIMBO_IMAGE (Limbo $LIMBO_VERSION)"
  docker build -f "$SRC_DIR/deploy/limbo/Dockerfile" \
    --build-arg LIMBO_JAR_URL="$LIMBO_JAR_URL" \
    --build-arg LIMBO_SCHEM_URL="$LIMBO_SCHEM_URL" \
    --build-arg LIMBO_VERSION="$LIMBO_VERSION" \
    -t "$LIMBO_IMAGE" "$SRC_DIR"
  docker save "$LIMBO_IMAGE" | "$K3S" ctr images import -

  : "${PAPER_MC_VERSION:=1.21.8}"
  : "${PAPER_JAR_URL:=$(curl -fsSL --max-time 30 "https://fill.papermc.io/v3/projects/paper/versions/${PAPER_MC_VERSION}/builds/latest" | grep -oE 'https://fill-data\.papermc\.io/[^"]+\.jar' | head -1)}"
  [ -n "$PAPER_JAR_URL" ] || die "could not resolve the Paper jar; set PAPER_JAR_URL"
  # Both Dockerfiles require the jar's digest. The fill-data URL is content-addressed
  # (the objects/ path segment IS the sha256), so it is derived rather than asked for;
  # a mirror override carries no such segment and must bring its own digest.
  if [ -z "${PAPER_JAR_SHA256:-}" ]; then
    sha="${PAPER_JAR_URL#*/objects/}"
    sha="${sha%%/*}"
    case "$sha" in
      *[!0-9a-f]*|"") sha="" ;;
    esac
    if [ "${#sha}" -ne 64 ]; then
      die "cannot derive the Paper jar sha256 from PAPER_JAR_URL (not a content-addressed fill-data URL); set PAPER_JAR_SHA256"
    fi
    PAPER_JAR_SHA256="$sha"
  fi
  log "building $LOBBY_IMAGE (Paper $PAPER_MC_VERSION)"
  docker build -f "$SRC_DIR/deploy/lobby/Dockerfile" \
    --build-arg PAPER_JAR_URL="$PAPER_JAR_URL" \
    --build-arg PAPER_JAR_SHA256="$PAPER_JAR_SHA256" \
    -t "$LOBBY_IMAGE" "$SRC_DIR"
  docker save "$LOBBY_IMAGE" | "$K3S" ctr images import -

  # Plain Paper recommended base — same PAPER_JAR_URL, no plugins, no secret gate.
  : "${PAPER_IMAGE:=felis-paper:demo}"
  log "building $PAPER_IMAGE (plain Paper $PAPER_MC_VERSION, forwarding via the operator initContainer)"
  docker build -f "$SRC_DIR/deploy/paper/Dockerfile" \
    --build-arg PAPER_JAR_URL="$PAPER_JAR_URL" \
    --build-arg PAPER_JAR_SHA256="$PAPER_JAR_SHA256" \
    -t "$PAPER_IMAGE" "$SRC_DIR"
  docker save "$PAPER_IMAGE" | "$K3S" ctr images import -
fi

# 3. wire the images into the config `felis setup` reads ------------------------
log "wiring [velocity] images into $HOST_TOML"
# SKIP_BOOTSTRAP=1 trusts an earlier run to be complete. Check that it actually left
# the full stack behind: a base from before the game-stack installer, or one whose
# pieces were pruned by hand, must fail here with a pointer — not present as a proxy
# that accepts logins and routes nowhere, with nothing in any log to say why.
[ -f "$HOST_TOML" ] || die "missing $HOST_TOML — did bootstrap run?"
if grep -q '^\[velocity\]' "$HOST_TOML"; then
  echo "  [velocity] table already present — leaving it untouched"
else
  cat >> "$HOST_TOML" <<EOF

[velocity]
login_image = "$LIMBO_IMAGE"
lobby_image = "$LOBBY_IMAGE"
EOF
  echo "  appended login_image=$LIMBO_IMAGE / lobby_image=$LOBBY_IMAGE"
fi
grep -q '^\[velocity\]' "$HOST_TOML" \
  || die "$HOST_TOML has no [velocity] section — re-run the installer without SKIP_BOOTSTRAP so the system servers get wired"
[ -f "$PLUGIN_JAR" ] \
  || die "$PLUGIN_JAR missing — this base did not finish the full installer, and a proxy without it silently routes nothing; re-run the installer without SKIP_BOOTSTRAP"

# 4. interactive Owner creation + system-server provisioning -------------------
# 2. interactive Owner creation + system-server provisioning --------------------
if [ "${SKIP_SETUP:-0}" = 1 ]; then
  log "SKIP_SETUP=1 — base + images + config ready. Finish with:  sudo felis setup"
  log "SKIP_SETUP=1 — base + game stack ready. Finish with:  sudo felis setup"
else
  log "launching 'felis setup' — create the Owner account (this is the only interactive step)"
  exec "$FELIS" setup