feat(runtime): add authenticated system backends
This commit is contained in:
6 files changed
+210
-38
No files matched your search
+31
-9
@@ -5,16 +5,22 @@
|
||||
# the POST-auth /menu hub: it is reached only when the login gate transfers an
|
||||
# authenticated player onward, and it must never be a fallback target.
|
||||
#
|
||||
# Build:
|
||||
# Build (deploy/bootstrap.sh does this for you; the PAPER_JAR_URL comes from PaperMC's
|
||||
# Fill v3 API — api.papermc.io v2 has returned HTTP 410 since 2026-07-01):
|
||||
# docker build -f deploy/lobby/Dockerfile \
|
||||
# --build-arg PAPER_JAR_URL=https://<mirror>/paper-1.21.x-<build>.jar \
|
||||
# --build-arg PAPER_JAR_URL=https://fill-data.papermc.io/v1/objects/<sha>/paper-26.2-<build>.jar \
|
||||
# -t felis-lobby:demo .
|
||||
# docker save felis-lobby:demo | sudo k3s ctr images import -
|
||||
# # felis.toml → [velocity] lobby_image = "felis-lobby:demo"
|
||||
#
|
||||
# Contract: the game server listens on 25565 (the CRD GamePort). The lobby speaks
|
||||
# only the felis:control plugin-message channel (spec §12) — it holds no felis-api
|
||||
# token.
|
||||
# The Paper version must match the LOGIN gate's: LOOHP/Limbo speaks exactly ONE protocol
|
||||
# per build (its SERVER_IMPLEMENTATION_VERSION), and a client has to satisfy both hops.
|
||||
#
|
||||
# Contract: the game server listens on 25565 (the CRD GamePort). The lobby speaks only the
|
||||
# felis:control plugin-message channel (spec §12) — it holds no felis-api token. It DOES
|
||||
# receive FELIS_FORWARDING_SECRET (operator-injected from the felis-forwarding-secret
|
||||
# Secret) and refuses to start without it: a lobby that cannot verify the proxy's signed
|
||||
# handshake would trust an offline, forgeable UUID.
|
||||
|
||||
# ---- build the felis-paper plugin jar (Paper API is Java 21) ----
|
||||
# gradle:8.14-jdk21 — an official Gradle image on JDK 21 (this tree vendors no Gradle
|
||||
@@ -29,7 +35,10 @@ RUN cd plugins/paper \
|
||||
&& cp build/libs/*.jar /felis-paper.jar
|
||||
|
||||
# ---- assemble the runtime ----
|
||||
FROM eclipse-temurin:21-jre
|
||||
# 25-jre, not 21: Paper 26.2 declares `java.version.minimum = 25` (PaperMC Fill v3,
|
||||
# GET /v3/projects/paper/versions/26.2) and refuses to boot on anything older. A 25 JRE
|
||||
# also runs the plugin's Java-21 bytecode, so only the runtime moves.
|
||||
FROM eclipse-temurin:25-jre
|
||||
ARG PAPER_JAR_URL
|
||||
WORKDIR /paper
|
||||
RUN set -eu; \
|
||||
@@ -42,8 +51,21 @@ RUN set -eu; \
|
||||
mkdir -p /paper/plugins; \
|
||||
echo "eula=true" > /paper/eula.txt
|
||||
COPY --from=plugin /felis-paper.jar /paper/plugins/felis-paper.jar
|
||||
# The entrypoint writes the Velocity modern-forwarding config (and REFUSES to start
|
||||
# without the secret — an offline-mode lobby would trust forged identities) before
|
||||
# launching Paper.
|
||||
COPY deploy/lobby/entrypoint.sh /usr/local/bin/felis-entrypoint.sh
|
||||
|
||||
# The operator mounts the world PVC at /data. Runtime state lives there; /paper
|
||||
# remains the immutable image seed copied into the volume by the entrypoint.
|
||||
WORKDIR /data
|
||||
|
||||
# FELIS_GAME_PORT is the port the entrypoint pins Paper to; it MUST equal the operator's
|
||||
# GamePort (internal/operator/builders.go). Default 25565 — override only in lockstep
|
||||
# with the operator.
|
||||
ENV FELIS_GAME_PORT=25565
|
||||
EXPOSE 25565
|
||||
# nogui headless; the first boot generates server.properties (align online-mode /
|
||||
# forwarding with the Velocity proxy afterwards — see README).
|
||||
ENTRYPOINT ["java", "-jar", "paper.jar", "--nogui"]
|
||||
# felis-entrypoint.sh writes config/paper-global.yml + server.properties, then execs
|
||||
# `java -jar paper.jar --nogui` from /data (headless: the pod has no console). Invoked via
|
||||
# `sh` so no +x bit is needed from the (Windows) build host.
|
||||
ENTRYPOINT ["/bin/sh", "/usr/local/bin/felis-entrypoint.sh"]
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/bin/sh
|
||||
# Felis lobby (Paper) entrypoint.
|
||||
#
|
||||
# The lobby sits BEHIND the login gate: a player only reaches it once the limbo has
|
||||
# authenticated them and Velocity transferred them onward. For that transfer to arrive
|
||||
# with a real identity, Paper has to be told to verify the proxy's signed handshake —
|
||||
# otherwise it derives an offline UUID from the username and every /menu action would be
|
||||
# attributed to whoever typed the name. So, exactly as in deploy/limbo/entrypoint.sh:
|
||||
# NO SECRET, NO START. Refusing to boot is the safe failure; a lobby that came up in
|
||||
# offline mode would look healthy while trusting forged identities.
|
||||
#
|
||||
# Two files carry the settings:
|
||||
#
|
||||
# config/paper-global.yml proxies.velocity.{enabled,online-mode,secret} — enable modern
|
||||
# forwarding and share the proxy's HMAC key. online-mode mirrors
|
||||
# the proxy's own online-mode (true: Velocity did the Mojang
|
||||
# auth), which is what makes the forwarded UUID trustworthy.
|
||||
#
|
||||
# server.properties online-mode=false — the PROXY authenticated the player, so the
|
||||
# backend must not try to reach Mojang itself (Paper refuses to
|
||||
# start with velocity forwarding on and online-mode=true). This
|
||||
# is not a downgrade: the trust comes from the signed handshake.
|
||||
# server-port is pinned to the operator's GamePort (25565), the
|
||||
# single const the Service, probes and NetworkPolicy all key off.
|
||||
set -eu
|
||||
|
||||
PORT="${FELIS_GAME_PORT:-25565}"
|
||||
SECRET="${FELIS_FORWARDING_SECRET:-}"
|
||||
RUNTIME_DIR="/paper"
|
||||
DATA_DIR="/data"
|
||||
PROPS="server.properties"
|
||||
|
||||
if [ -z "$SECRET" ]; then
|
||||
echo "felis-lobby: FATAL — FELIS_FORWARDING_SECRET is empty." >&2
|
||||
echo " Without Velocity modern forwarding Paper cannot verify who a joining player is," >&2
|
||||
echo " and would trust an offline UUID derived from the username alone." >&2
|
||||
echo " Provision the secret with deploy/bootstrap.sh, then re-run 'sudo felis setup'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Keep worlds, generated config, and plugin data on the operator-mounted PVC while
|
||||
# refreshing executable artifacts from the immutable image on every boot.
|
||||
mkdir -p "$DATA_DIR/plugins"
|
||||
cp -f "$RUNTIME_DIR/paper.jar" "$DATA_DIR/paper.jar"
|
||||
cp -f "$RUNTIME_DIR/plugins/felis-paper.jar" "$DATA_DIR/plugins/felis-paper.jar"
|
||||
printf 'eula=true\n' > "$DATA_DIR/eula.txt"
|
||||
cd "$DATA_DIR"
|
||||
|
||||
# set_prop KEY VALUE — replace the key's line in server.properties, or append it if absent.
|
||||
set_prop() {
|
||||
if [ -f "$PROPS" ] && grep -q "^$1=" "$PROPS"; then
|
||||
sed -i "s|^$1=.*|$1=$2|" "$PROPS"
|
||||
else
|
||||
printf '%s=%s\n' "$1" "$2" >> "$PROPS"
|
||||
fi
|
||||
}
|
||||
|
||||
set_prop server-port "$PORT"
|
||||
set_prop online-mode false
|
||||
|
||||
# ponytail: rewritten whole, not merged. Paper loads this file and fills every key it does
|
||||
# not find with the default, then writes the full tree back — so a proxies-only file is a
|
||||
# complete, stable input, and the lobby's other globals are simply always the defaults.
|
||||
# That is true of a system server Felis owns end to end; if admins are ever allowed to tune
|
||||
# the lobby's globals, this has to become a real YAML merge (yq) instead.
|
||||
mkdir -p config
|
||||
cat > config/paper-global.yml <<YAML
|
||||
# Written by felis-lobby's entrypoint on every boot. Do not hand-edit: the forwarding
|
||||
# secret is injected from the felis-forwarding-secret Secret and must match the proxy.
|
||||
proxies:
|
||||
velocity:
|
||||
enabled: true
|
||||
online-mode: true
|
||||
secret: "${SECRET}"
|
||||
YAML
|
||||
|
||||
echo "felis-lobby: server-port=${PORT}, velocity modern forwarding on (UUIDs are Mojang-verified)"
|
||||
JAVA_MEMORY_ARG=""
|
||||
if [ -n "${JAVA_MEMORY:-}" ]; then
|
||||
JAVA_MEMORY_ARG="-Xmx${JAVA_MEMORY}"
|
||||
fi
|
||||
set -f
|
||||
# JAVA_FLAGS is emitted by the operator as a whitespace-separated JVM argument list.
|
||||
# shellcheck disable=SC2086
|
||||
exec java $JAVA_MEMORY_ARG ${JAVA_FLAGS:-} -jar paper.jar --nogui "$@"
|
||||
Reference in new issue
Block a user