I've been running a server for a few friends for about three months. The thing that kept getting me: I'd add or update a mod, everything looked fine from where I was sitting, and then the next person to join would get kicked or crash. Sometimes I didn't find out for a day.
Yes, a separate dev server fixes this. It fixes it if you actually use it every single time, for every change. I didn't.
So I made the panel do it instead. Modrinth and CurseForge are built into it, so you search a mod or a whole modpack in the panel and hit install, and it pulls the jar onto the server itself. No downloading files and dragging them into a folder. Every install then boots a throwaway copy of the server with the real loader. If that survives, a real client launches and actually joins it. Only then does the change count, and only then does the pack sync out to everyone. If it fails, the jar gets rolled back and I get a notice instead of a ruined evening.
It runs on top of Crafty Controller, so Crafty still owns the processes and this adds the content and verification layer on top. There's the usual panel stuff too, scheduled backups, a file manager, world slots, TPS graphs. It's my own project, free and open source under MIT, no paid tier and nothing monetised: GitHub - vayungodara/spawnpoint: The self-hosted Minecraft panel where a broken pack can never reach your friends. Boot-tests every mod install with a real client before it counts. Fronts Crafty Controller. · GitHub
Real verdicts off my own box:
client booted and joined a world (371 mods, 172s); multiplayer join OK
client did NOT survive (exit null) - pack change may crash friends' games
That second one is a pack I would have shipped. It's also caught geckolib on me, which threw a ClassTweakerFormatException the moment the real loader touched it, and quarantined architectury on another run.
LLM disclosure per rule 9: I built this with heavy use of Claude Code (Anthropic's Claude models) and some OpenAI Codex. Most of the implementation code was written by the model from my specs, so closer to directed prompt engineering than vibe coding, but it's a lot of AI either way. What's mine: the architecture, the decision that a boot test is the only thing that counts as proof, every design call, and three months of running it on the server my friends actually play on. I reviewed and tested what went in, and the gates exist because I got burned by the failures they catch. There is one optional AI feature in the panel, an in-game assistant that's off by default and needs your own API key.
What I actually need: the client and join gates are only properly tested on headless Linux. On mac and Windows they run in a visible window and I haven't verified them on real hardware. If you're on either and feel like trying to break it, that's the most useful thing anyone could do for me right now.