Loading deploy/bootstrap.sh +13 −10 Changes for deploy/bootstrap.sh: 13 added lines, 10 removed lines. Original line number Diff line number Diff line Loading @@ -38,10 +38,12 @@ # FELIS_NANO_PROXY_CIDR the proxy allowed to reach a non-loopback nano bind, as an address # with a prefix length (for example 10.0.0.7/32). firewalld opens the # port to that source only; unset, it opens nothing # FELIS_LEGACY_FORWARDING_SERVERS comma-separated backends that receive their identity # through the handshake address instead of modern forwarding # (default: legacy18). Read once at Velocity start, so changing it # means re-running this script and restarting the proxy. # FELIS_LEGACY_FORWARDING_SERVERS comma-separated backends that always receive their # identity through the handshake address instead of modern forwarding # (default: legacy18). A floor: any server whose MinecraftServer CR is # labelled felis.lolicon.best/forwarding=legacy joins it while the # proxy runs (docs/operations.md), so a new 1.8 backend needs a label, # not a re-run. Changing the floor itself means re-running this script. # FELIS_VELOCITY_XMX maximum heap of the Velocity proxy, as <n>M or <n>G (default: 1G; # at least 256M). docs/operations.md sizes it by player count. # FELIS_VELOCITY_FORK_JAR path to a Felis-Legacy Velocity fork build to install as the Loading Loading @@ -2741,12 +2743,13 @@ install_velocity_service() { # fork reads this list from -Dfelis.legacy-forwarding.servers and forwards those servers legacy; # every other backend keeps modern+secret untouched. # # The list is a JVM system property, so it is fixed for the life of the proxy process and a # change needs a Velocity restart. FELIS_LEGACY_FORWARDING_SERVERS makes that reachable # without editing this script, which is as far as a startup property can go. Having it follow # the MinecraftServer CRs instead is a larger change: the forwarding decision lives in the # fork's patch to Velocity core, not in the Felis plugin, so core would need to read state the # plugin owns and refreshes. # This value is the floor of the list. The felis-velocity plugin adds every server whose # MinecraftServer CR is labelled felis.lolicon.best/forwarding=legacy by rewriting the same # property on each server-list refresh (LegacyForwarding.java), and drops it again when the # label goes; the floor always stays in. A fork carrying patch 0004 re-reads the property on # every backend connection, so a label applies from the next connection. A fork with 0003 # alone reads it once, after the plugin's first refresh, so a label applies at the next proxy # restart. Stock Velocity ignores it, and the plugin logs a warning for a labelled server. # # The -D below is double-quoted in ExecStart on purpose. The fork trims each element, so it # accepts "legacy18, legacy112", but systemd splits ExecStart on whitespace before java ever Loading docs/openapi.yaml +6 −0 Changes for docs/openapi.yaml: 6 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -482,6 +482,12 @@ components: playerCountUnknown: type: boolean description: Present and true while the operator cannot read the player count over RCON; idle auto-stop waits until it can. legacyForwarding: type: boolean description: >- Present and true when the CR carries the label felis.lolicon.best/forwarding=legacy. The proxy then forwards this server's players BungeeCord-style in the handshake address instead of modern forwarding (Felis-Legacy Velocity fork only). FleetServer: description: One row of the fleet-wide admin read (internal/api/handlers_user.go fleetServerView). Loading docs/operations.md +32 −0 Changes for docs/operations.md: 32 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -383,6 +383,38 @@ version, in this order, each step one release: 3. A later release stops serving `v1alpha1`. Felis itself reads through one Go type at a time, so the operator and felis-api switch in the release that moves storage. ### Legacy-forwarded backends [VM-VERIFIED] A 1.8-era backend sits behind ViaVersion, which drops modern forwarding's login plugin message on the way down to protocol 47, so the proxy has to hand that server the player's identity BungeeCord-style, in the handshake address. Only the Felis-Legacy Velocity fork can do that per server. Mark the server's CR and the proxy picks it up at its next server-list refresh (every 15 s): ```sh kubectl -n minecraft label minecraftserver <name> felis.lolicon.best/forwarding=legacy kubectl -n minecraft label minecraftserver <name> felis.lolicon.best/forwarding- # back to modern journalctl -u felis-velocity | grep 'legacy forwarding list' ``` The installer's `FELIS_LEGACY_FORWARDING_SERVERS` (default `legacy18`) stays in the list whatever the labels say. What a label does depends on the proxy the host runs: | Proxy | A label applies | |---|---| | Fork with patch 0004 (`build-velocity.sh` default arm) | from the next connection to that server | | Fork with 0003 alone (`--deployed`) | at the next `systemctl restart felis-velocity` | | Stock Velocity | never; the log line is a warning naming the server | On the test VM (fork with 0004) labelling a server logged `legacy forwarding list is now [legacy18,resolvecheck]` 12 s later, and removing the label logged the list back to `[legacy18]`. The fork's own test (`FelisLegacyForwardingTest`) covers the next connection following the rewritten list. Legacy forwarding carries no secret. A marked server believes any identity that reaches its game port, which `felis-allow-game-from-velocity` limits to the proxy and the node itself; anything else running on the node can reach it too. ## 5. Disaster recovery The procedures are in §16: what a database bundle holds, restoring one on the same host, Loading internal/api/cluster.go +3 −0 Changes for internal/api/cluster.go: 3 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -34,6 +34,9 @@ type ServerInfo struct { // PlayerCountUnknown is true while the operator cannot read the player // count over RCON; idle auto-stop waits until it can. PlayerCountUnknown bool `json:"playerCountUnknown,omitempty"` // LegacyForwarding mirrors the CR's forwarding=legacy label: the proxy // forwards this server's players in the handshake address (#15). LegacyForwarding bool `json:"legacyForwarding,omitempty"` } // CreateServerInput is the validated, structured create-server form (spec §15). Loading internal/api/k8scluster.go +1 −0 Changes for internal/api/k8scluster.go: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -446,6 +446,7 @@ func serverInfo(ms *v1alpha1.MinecraftServer) *ServerInfo { IdleStopSeconds: idleStopSeconds(ms), PlayerCountUnknown: ms.Status.Phase == v1alpha1.PhaseRunning && meta.IsStatusConditionFalse(ms.Status.Conditions, v1alpha1.ConditionPlayersCounted), LegacyForwarding: ms.Labels[v1alpha1.LabelForwarding] == v1alpha1.ForwardingLegacy, } } Loading Loading
deploy/bootstrap.sh +13 −10 Changes for deploy/bootstrap.sh: 13 added lines, 10 removed lines. Original line number Diff line number Diff line Loading @@ -38,10 +38,12 @@ # FELIS_NANO_PROXY_CIDR the proxy allowed to reach a non-loopback nano bind, as an address # with a prefix length (for example 10.0.0.7/32). firewalld opens the # port to that source only; unset, it opens nothing # FELIS_LEGACY_FORWARDING_SERVERS comma-separated backends that receive their identity # through the handshake address instead of modern forwarding # (default: legacy18). Read once at Velocity start, so changing it # means re-running this script and restarting the proxy. # FELIS_LEGACY_FORWARDING_SERVERS comma-separated backends that always receive their # identity through the handshake address instead of modern forwarding # (default: legacy18). A floor: any server whose MinecraftServer CR is # labelled felis.lolicon.best/forwarding=legacy joins it while the # proxy runs (docs/operations.md), so a new 1.8 backend needs a label, # not a re-run. Changing the floor itself means re-running this script. # FELIS_VELOCITY_XMX maximum heap of the Velocity proxy, as <n>M or <n>G (default: 1G; # at least 256M). docs/operations.md sizes it by player count. # FELIS_VELOCITY_FORK_JAR path to a Felis-Legacy Velocity fork build to install as the Loading Loading @@ -2741,12 +2743,13 @@ install_velocity_service() { # fork reads this list from -Dfelis.legacy-forwarding.servers and forwards those servers legacy; # every other backend keeps modern+secret untouched. # # The list is a JVM system property, so it is fixed for the life of the proxy process and a # change needs a Velocity restart. FELIS_LEGACY_FORWARDING_SERVERS makes that reachable # without editing this script, which is as far as a startup property can go. Having it follow # the MinecraftServer CRs instead is a larger change: the forwarding decision lives in the # fork's patch to Velocity core, not in the Felis plugin, so core would need to read state the # plugin owns and refreshes. # This value is the floor of the list. The felis-velocity plugin adds every server whose # MinecraftServer CR is labelled felis.lolicon.best/forwarding=legacy by rewriting the same # property on each server-list refresh (LegacyForwarding.java), and drops it again when the # label goes; the floor always stays in. A fork carrying patch 0004 re-reads the property on # every backend connection, so a label applies from the next connection. A fork with 0003 # alone reads it once, after the plugin's first refresh, so a label applies at the next proxy # restart. Stock Velocity ignores it, and the plugin logs a warning for a labelled server. # # The -D below is double-quoted in ExecStart on purpose. The fork trims each element, so it # accepts "legacy18, legacy112", but systemd splits ExecStart on whitespace before java ever Loading
docs/openapi.yaml +6 −0 Changes for docs/openapi.yaml: 6 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -482,6 +482,12 @@ components: playerCountUnknown: type: boolean description: Present and true while the operator cannot read the player count over RCON; idle auto-stop waits until it can. legacyForwarding: type: boolean description: >- Present and true when the CR carries the label felis.lolicon.best/forwarding=legacy. The proxy then forwards this server's players BungeeCord-style in the handshake address instead of modern forwarding (Felis-Legacy Velocity fork only). FleetServer: description: One row of the fleet-wide admin read (internal/api/handlers_user.go fleetServerView). Loading
docs/operations.md +32 −0 Changes for docs/operations.md: 32 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -383,6 +383,38 @@ version, in this order, each step one release: 3. A later release stops serving `v1alpha1`. Felis itself reads through one Go type at a time, so the operator and felis-api switch in the release that moves storage. ### Legacy-forwarded backends [VM-VERIFIED] A 1.8-era backend sits behind ViaVersion, which drops modern forwarding's login plugin message on the way down to protocol 47, so the proxy has to hand that server the player's identity BungeeCord-style, in the handshake address. Only the Felis-Legacy Velocity fork can do that per server. Mark the server's CR and the proxy picks it up at its next server-list refresh (every 15 s): ```sh kubectl -n minecraft label minecraftserver <name> felis.lolicon.best/forwarding=legacy kubectl -n minecraft label minecraftserver <name> felis.lolicon.best/forwarding- # back to modern journalctl -u felis-velocity | grep 'legacy forwarding list' ``` The installer's `FELIS_LEGACY_FORWARDING_SERVERS` (default `legacy18`) stays in the list whatever the labels say. What a label does depends on the proxy the host runs: | Proxy | A label applies | |---|---| | Fork with patch 0004 (`build-velocity.sh` default arm) | from the next connection to that server | | Fork with 0003 alone (`--deployed`) | at the next `systemctl restart felis-velocity` | | Stock Velocity | never; the log line is a warning naming the server | On the test VM (fork with 0004) labelling a server logged `legacy forwarding list is now [legacy18,resolvecheck]` 12 s later, and removing the label logged the list back to `[legacy18]`. The fork's own test (`FelisLegacyForwardingTest`) covers the next connection following the rewritten list. Legacy forwarding carries no secret. A marked server believes any identity that reaches its game port, which `felis-allow-game-from-velocity` limits to the proxy and the node itself; anything else running on the node can reach it too. ## 5. Disaster recovery The procedures are in §16: what a database bundle holds, restoring one on the same host, Loading
internal/api/cluster.go +3 −0 Changes for internal/api/cluster.go: 3 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -34,6 +34,9 @@ type ServerInfo struct { // PlayerCountUnknown is true while the operator cannot read the player // count over RCON; idle auto-stop waits until it can. PlayerCountUnknown bool `json:"playerCountUnknown,omitempty"` // LegacyForwarding mirrors the CR's forwarding=legacy label: the proxy // forwards this server's players in the handshake address (#15). LegacyForwarding bool `json:"legacyForwarding,omitempty"` } // CreateServerInput is the validated, structured create-server form (spec §15). Loading
internal/api/k8scluster.go +1 −0 Changes for internal/api/k8scluster.go: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -446,6 +446,7 @@ func serverInfo(ms *v1alpha1.MinecraftServer) *ServerInfo { IdleStopSeconds: idleStopSeconds(ms), PlayerCountUnknown: ms.Status.Phase == v1alpha1.PhaseRunning && meta.IsStatusConditionFalse(ms.Status.Conditions, v1alpha1.ConditionPlayersCounted), LegacyForwarding: ms.Labels[v1alpha1.LabelForwarding] == v1alpha1.ForwardingLegacy, } } Loading