I remember years and years ago when I initially got interested in servers, when I tried to set up a Minecraft server, I had to download the official Minecraft server jar file, manually update Java, write batch files and manually port forward, which as a 13 year old at the time was such a headache.
FalkMC is a downloadable desktop application for Windows 10 & 11 that lets you quickly set up and self-host a Minecraft server with your friends, all from one application.
Today there are endless options to pick from. But what's still missing is an easy, beginner-friendly, privately self-hosted and fully free way to spin up a Minecraft server quickly. This is one reason I chose to make FalkMC Panel and to just give something back to the community and place where my interest in tech originated from.
So I guess we should not waste any more time and just dive into the reasons why I chose this stack decision, fun bugs, the packaging and what's next on the horizon for FalkMC.
The Stack Decision
FalkMC Panel is built with Python and CustomTkinter. The reason behind this was mainly because I started learning Python and wanted a project that would really elevate and challenge my newly gained skills, and let me tell you it's been a real challenge. But with how good LLMs have gotten, the rate at which I can find information and understand code is way quicker compared to when I was learning Lua or web dev.
As for packaging the executable, I went with Nuitka. This was mainly due to me having issues with PyInstaller and I already spent several hours trying to solve it and getting nowhere. So instead of going insane, I just went with another alternative and this is Nuitka that worked great out of the box.
The Fun bugs
So the server was starting, but no world folder was being generated. Turned out I was piping stdout/stderr to subprocess.PIPE and never reading them. As Minecraft writes a lot on startup, the OS buffer filled up and the JVM blocked on the next write. This was ultimately solved by redirecting the output to a log file instead of a pipe.
# Before
subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# After
log_file = open("falkmc_console.log", "w")
subprocess.Popen(cmd, stdout=log_file, stderr=subprocess.STDOUT)
The panel freezing on tab switches. Scanning folders, process lists and network calls all on the same thread was making the UI lock up and not respond for a while. This was fixed by moving everything to background threads and scheduling UI updates with self.after(0, …).
def refresh_servers(self):
threading.Thread(target=self._scan_servers, daemon=True).start()
def _scan_servers(self):
servers = scan_folders()
self.after(0, lambda: self._update_servers(servers))
Paper server setup not working. When I chose Paper, clicked create, I got “version not found”, and it turned out the URL I was using (api.papermc.io/v2/…/builds/latest) never existed. Paper also deprecated v2 entirely. So the simple fix was just moving to their v3 API.
# Before
url = f"https://api.papermc.io/v2/projects/paper/versions/{version}/builds/latest"
# After
headers = {"User-Agent": "FalkMC/0.3.0 (https://github.com/FalkMC/panel)"}
url = f"https://fill.papermc.io/v3/projects/paper/versions/{version}/builds"
builds = requests.get(url, headers=headers).json()
Packaging
PyInstaller kept failing with Tcl data directory “_tcl_data” not found. I tried every -add-data variation I could find but none of it worked. Nuitka on the other hand handled it first try with -enable-plugin=tk-inter.
But then the executable had another issue I never saw coming, it wrote settings.json and the servers folder to a temp location that Windows deletes when the app closes. So every time you reopened it, your servers and all data were gone.
Turns out a one-file exe doesn't actually run from where you put it. When you open it, it unpacks a copy of itself into a temp folder and runs from there, so the application thinks that is where it lives and Windows wipes it when you close. This was fixed by storing all the data in Documents\FalkMC instead of right next to the executable.
# Before
base_dir = os.path.dirname(sys.executable)
# After
base_dir = os.path.join(os.path.expanduser("~"), "Documents", "FalkMC")
What's Next?
Next up for FalkMC Panel is backups, hopefully backups will be out very soon. Next up would be UPnP port forwarding and modded servers with an auto mod downloader built into FalkMC.
Lessons for anyone building desktop apps
- Don't do anything major on the main thread, it will end up freezing.
- subprocess.PIPE without a reader will hang your child process, redirect it to a file.
- Package early, not at the end as some bugs only exist in the exe.
- Most importantly let AI speed up your learning, but make sure you fully understand it.
FalkMC Panel is free and open source, feel free to try it out!
- Website: https://falkmc.com/
- Docs: https://falkmc.com/docs/
- Source: https://github.com/FalkMC



Top comments (0)