60b0ec97ac90225ed8517dbd9966afa247ff368e
/invite <player> posts a chat card to the invitee with a green [Accept] and a red [Deny] button, and Accept walks them to the server the inviter is standing on. It is a UX wrapper over `/felis go` and nothing more: the accept runs the same doGo path on the ACCEPTING player's own verified uuid, so a stored invite carries a server name and never an identity to act as, and the prompt needs no unguessable token. Why it can be this simple: an invite can only name the server its sender is currently on, so the target is running by construction, and a running felis server already admits any linked player through <name>.<root-domain> on the link check alone (WaitingRouter.onServerPreConnect) — no wake, no autostartPolicy consultation. Hence enqueueFromInvite: a READY backend is joined directly, and only the not-ready case falls through to the policy-gated wake path unchanged. Routing an accept through wakeAndWaitLinked would have asked the API to wake a server that needs no waking, and autostartPolicy defaults to ownerOnly, so the API would answer 403 and the green button would do nothing for exactly the people you would invite. It is not consequence-free, and the inviter is told so at send time rather than in a comment only we read. Landing on a felis server records the player in its allowlist (onServerConnected -> join-event -> RecordJoin); on an autostartPolicy=allowlist server that row is what lets them come back and START the thing later. The same row they would earn by walking in unaided — the invite shortened the walk, it did not widen the door — but it outlives the invite, so accessNotice says so. The wording follows the policy: only under allowlist does it claim they will be able to start the server themselves, because under the ownerOnly default (and the empty string the API reports for an unset field) that row grants no waking and the claim would be a lie. InviteBook also holds a 30s per-sender cooldown, because the one capability /invite genuinely adds is "make a chat card appear on any online player", and unrated that is a way to follow someone around their own chat log. It is charged in put() rather than at the top of the command, so an invite refused for an offline name or a player already on the server costs the sender nothing, and the gate sits after every other validation for the same reason. The stamp is global per sender on purpose: a per-(sender, invitee) key would wave through one player papering the whole proxy, which is the thing being limited. The card lives in InviteCard as a pure function so the buttons — the whole point of the feature — can be asserted without a live proxy, and the button clicks are pinned to the server the card named, so a stale card cannot answer a newer invite (checked with peek before the invite is spent, so refusing a superseded card leaves the live one answerable). Verified: production gradle 8.14 + JDK 21 build; jar carries the plugin classes and no test classes; InviteBookTest (36 checks) and InviteCardTest (48 checks); and a live Velocity 3.5.1 that loads the jar, registers /invite <player> and answers /invite accept <server>, with a malformed subcommand as a negative control.
Felis
A Kubernetes-driven Minecraft server hosting platform — one command to deploy, automatic lifecycle, backup, and security.
一款 Kubernetes 驱动的 Minecraft 服务器托管平台,一行命令部署,自动管理生命周期与安全。
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 the MIT License.
License Notes
- Attribution: Any distribution of this project or derivative works must include the original copyright notice and license statement.
- Disclaimer: This project is provided "as is", without warranty of any kind.
Acknowledgements
- Kubernetes: Container orchestration engine
- K3s: Lightweight Kubernetes distribution
- Cloudflare Zero Trust: Zero trust security infrastructure
- PostgreSQL: Data persistence
- React: User interface framework
- Vite: Frontend build tool
- TailwindCSS: CSS framework
- Bubble Tea: TUI framework
- Minecraft: What makes this all worthwhile
Description
No description provided
https://felismc.com
9.2 MiB
0 Stars
2 Watchers
0 Forks
Languages
Go
62.7%
TypeScript
22.5%
Shell
7.4%
Java
7.1%
Dockerfile
0.2%
Other
0.1%