flyemoji f532684249 feat(velocity): let 1.8.x players through the modern-forwarding proxy
Felis pins player-info-forwarding-mode = "modern", and Velocity's
HandshakeSessionHandler#handleLogin refuses anything below 1.13 outright: it reads
handshake.getProtocolVersion() and disconnects with
velocity.error.modern-forwarding-needs-new-client before the backend is ever
contacted. A player pinned to 1.8.9 never reaches the login gate, never sees the
onboarding link, and gets an error string that tells them to upgrade their client.

install_via_plugins now stages ViaVersion, ViaBackwards and ViaRewind into
/opt/felis/velocity/plugins alongside felis-velocity.jar. Nothing else moves: same
forwarding mode, same secret, no backend patched and no backend downgraded. The 1.13
floor turns out to be a property of the unassisted proxy pipeline rather than of the
forwarding protocol, so lifting it costs three jars and no source change.

This was measured, not assumed. Felis-Legacy's FL-007 probe stands a protocol-47
client in front of a stock Paper 1.21.11 backend behind a modern-forwarding proxy and
watches it join. The proof is the join itself rather than the log line: that backend
runs velocity.enabled with a shared secret, and Paper in that state rejects any login
not carrying forwarding data signed with a matching HMAC. The control cell without
Via is rejected before the backend is contacted, so Via is the only difference. A
second cell re-runs the same join with force-key-authentication = true, the way Felis
sets it, because a result that only holds under a config Felis does not run is not a
result about Felis; the 1.19+ signed chat key a protocol-47 client cannot produce is
never demanded, and it cannot be, since the pre-1.19 wire format has no player-key
field to decode.

The jars are pinned by sha256 and not by a moving tag. They sit in front of every
packet on the proxy and they are the exact bytes FL-007 measured; "latest" would
quietly make this an unmeasured configuration. The digests come from the GitHub
releases FL-006 locked, which is deliberate — Hangar's VELOCITY/download endpoint
serves different bytes for the same version numbers, so an installer that only
checked for HTTP 200 would ship artifacts nothing has tested. A version bump means a
digest bump here.

Two limits are worth writing down. Only protocol 47 was measured; the rest of Via's
documented 1.7-1.12 range is inference from that one point. And the probe runs
online-mode = false because it has no Mojang account, so Felis's online-mode = true
is untested — the untested part is the Mojang auth handshake specifically, which puts
the residual in Via's own login handling rather than in forwarding or in the
hasJoined multiplexer, whose request is protocol-independent.

Checks: a fresh install lands all three jars at the pinned digests and sizes with no
temp files left behind; a re-run downloads nothing; a tampered jar is restored to the
pinned bytes; and a deliberately wrong digest aborts without installing anything.
Existing installs pick this up by re-running bootstrap, which re-enters
install_velocity because bootstrap.done is written but never read as an early exit.
2026-07-22 17:03:01 +09:00
2026-07-20 18:53:25 +09:00
2026-07-20 18:53:25 +09:00
2026-07-12 01:42:07 +08:00

Felis

A Kubernetes-driven Minecraft server hosting platform — one command to deploy, automatic lifecycle, backup, and security.
一款 Kubernetes 驱动的 Minecraft 服务器托管平台,一行命令部署,自动管理生命周期与安全。

简体中文 | English

Table of Contents

Features

  • Wake on Join: Servers start automatically when a player connects, and stop when idle — like hibernate for your server.
  • Web Dashboard: Monitor server status, online players, and resource usage from your browser, with backup and restore management.
  • Auto Backup & Restore: Scheduled world backups with one-click rollback from any backup point.
  • World Reaper: Worlds idle for more than 15 days are automatically backed up and removed to free disk space.
  • Multi-core Support: Compatible with Paper, Fabric, Forge, and NeoForge, federated behind a Velocity proxy.
  • Modpack Submission: Players submit custom modpacks; admin approval triggers automatic build and deployment.
  • Passkey Login: Passwordless authentication via fingerprint, face recognition, or hardware security keys.
  • Zero Trust Security: Panel traffic protected by Cloudflare Access; the internal API is never exposed to the internet.

Getting Started

On a prepared Linux host, run:

curl -fsSL https://raw.githubusercontent.com/MliroLirrorsIngenuity/Felis/main/deploy/bootstrap.sh | sudo bash

The script installs K3s, deploys the control plane, and launches a setup wizard. Once done, open your browser at the configured domain.

Build from Source

Felis is built with Go and Node.js:

# Backend (Go 1.26+)
go build -o felis ./cmd/felis

# Frontend (Node.js 22+)
cd panel
npm ci
npm run build

# Docker image
docker build -t felis:custom .

License

The source code is released under AGPL-3.0-only.

License Notes

  1. Derivative works are AGPL too: Any distribution of this project or of software derived from it must be released under AGPL-3.0 and must include the original copyright notice and license statement.
  2. Running it as a network service also triggers the source obligation (AGPL section 13): if you host a modified Felis for other people to use, you must offer those users the complete source of your modified version — even if you never distribute a binary. This is the one substantive difference between AGPL and GPL, and since Felis is a hosting platform reached over a network, it will essentially always apply.
  3. Disclaimer: This project is provided "as is", without warranty of any kind.

Acknowledgements

Languages
Go 62.7%
TypeScript 22.5%
Shell 7.4%
Java 7.1%
Dockerfile 0.2%
Other 0.1%