Hosting My Own Minecraft Server: Replacing Aternos with a Mac Mini

After several months of dealing with Aternos with the queues, the sluggishness, the general sense of unreliability, I decided to host my own Minecraft server. I already had an M2 Mac mini being my main computer and a background in breaking things until they work. This seemed like a reasonable use of time.

Why I Gave Up on Aternos

Aternos is fine. It does what it says. It’s free. But once the novelty of “free server hosting” wears off, the cracks start to show. The 10-minute queue before you can even start your own server is tolerable the first few times, but quickly becomes a chore. Friends couldn’t just jump in either, they had to wait for me to start it manually, usually after texting to ask why it wasn’t online. Which, to be fair, is a reasonable question.

Performance was inconsistent. Some days it worked. Other days it choked under basic load. The setup just didn’t suit how we play — irregularly, impulsively, and often without warning.

The Stack (Probably Overthought)

I didn’t go the quick route. What should have been a single java -jar became this... monstrosity:

mc.ewancroft.uk
↓
Cloudflare
↓
TCPShield
↓
DuckDNS
↓
Home Router
↓
Docker Container

Whether this is overengineered or mildly practical depends on your perspective. It works, and I haven't accidentally exposed the Mac to the entire internet (yet), so I'll take that as a success.

Custom Domain

The server runs at mc.ewancroft.uk because I already own the apex domain and didn’t want to mess with public IPs or weird third-party subdomains. It's clean, it works, and it's easier to remember than a string of numbers.

TCPShield

DDoS protection on a private server for ~10 people is obviously overkill, but TCPShield has a free tier, and it integrates cleanly with Cloudflare. It probably isn’t doing much, but it looks professional, and the setup process was surprisingly painless.

DuckDNS

My IP address changes on a whim, so DuckDNS handles dynamic DNS. A tiny script checks for changes every five minutes. I keep expecting it to break or rate-limit me, but so far it hasn’t. That alone feels suspicious, but I’m not going to complain.

Port Forwarding

Standard router config: port 25565 forwarded to the Mac. No insights here. Just a bit of tinkering, a few reboots, and the usual moment of panic when the router UI stops responding.

Docker Container

This bit went smoother than expected. I used itzg/minecraft-server to containerise everything. Running the server in Docker means less hassle with system dependencies and makes it easier to roll back if something breaks.

The image supports plugins, config tweaks, and version switching with minimal idiocy. For what it’s worth, I would do this part the same way again.

Plugins and Preferences

The server runs PaperMC 1.21.1 with 4GB of RAM. That’s been enough for our group.

Plugins:

ViaVersion / ViaBackwards (to support laggards on older clients)

AxGraves (keeps items after lava-based deaths)

TreeFeller / VeinMiner (cut corners without shame)

Backuper (because I don’t trust myself)

Chunky (to avoid terrain loading spikes mid-session)

I use the Bare Bones resource pack . It’s clean, readable, and doesn’t get in the way. The whitelist keeps out strangers, which is good, because I haven’t secured this to enterprise-level production standards and don’t intend to.

Preventing Sleep

The Mac mini likes to sleep when left unattended. A few simple scripts handle this:

caffeinate runs while the server is up

When the server stops, the system is allowed to sleep again

It works. I’ve resisted the urge to add more logic, mostly because I know I’ll break it.

Not a 24/7 Server

This isn’t a 24/7 setup. It’s started manually when we want to play, and shut down when we’re done. That’s usually at odd hours (like 20:43, 00:17, 14:52) whenever someone feels the need to terraform a mountain or test a new datapack.

My typical group is entirely neurodivergent. Planning ahead is rarely an option. Everything’s spontaneous, which means the server needs to be easy to bring online with short notice - and easy to forget about for a week without something catching fire.

It works for us.

What Improved

Compared to Aternos:

No startup delay

More stable performance

Full control over settings and plugins

Backups that actually happen

A proper domain instead of a random link

No shutdowns unless I choose to

What I Learned

Layered setups aren’t always overkill, but they do get complex fast

Docker simplifies things that would otherwise be painful

Automation is worth the time it saves later

A subdomain makes the whole thing feel vaguely official

More importantly, I realised I actually enjoy this kind of work. Infrastructure tinkering was never the plan, but here we are.

What’s Next

I’m considering:

Dedicated low-power hardware

Offsite backups (because I’ve had enough close calls)

Better monitoring (even if I’ll mostly ignore it)

Multiple server instances for different world types

Or maybe I’ll just leave it as-is and play when we feel like it. That’s probably more realistic.

Closing

Moving off Aternos was the right call. The new setup isn’t perfect, but it’s fast, stable, and completely mine - which means when it breaks, I know exactly who to blame.

If you’ve got spare hardware and don’t mind a bit of trial-and-error, hosting your own server is absolutely worth a go. Just keep the scope small, or you’ll wake up at 03:00 wondering whether your DNS settings broke TCPShield again.

All scripts and config files are on GitHub if you're curious - or if you want a working setup that includes several questionable decisions.