Old Mac mini, New Tricks
October 19, 2026
I had an old 2014 Mac mini that had been sitting on a shelf, unused, for several years. You probably have one of these too: a perfectly good machine that got replaced and never quite made it to the recycling bin. I decided it was time to get it running again.
Here's what I was working with:
- CPU: Intel Core i5-4260U (2 cores / 4 threads)
- RAM: 4GB (3.7 GiB usable), soldered to the board, so no upgrades
- Storage: 500GB spinning hard drive (this is important later)
Stuck in the past
The good news: it booted right up and macOS ran fine. The bad news: it can't be upgraded any further. The last version Apple supports on this model is macOS 12 Monterey, which came out back in 2021, so it's roughly five years behind! No new features, no security updates, and a growing list of apps that won't run on it.
So the question became: what if it didn't run macOS at all? Linux has a great track record of breathing new life into older hardware, so that's where I headed.
To SSD or not to SSD
My first instinct was to do this properly: drop in an SSD for Linux and leave the original macOS hard drive as is. An SSD is the single biggest upgrade you can give an old machine.
Then I looked at prices. A compatible SSD was going to cost over $300, which is more than the Mac mini itself is worth at this point. For not much more money I could get a more modern machine outright. That didn't make sense for a side project, so I stuck with the spinning hard drive.
That decision shaped everything that came after. If the disk is the slowest part of the machine, the goal becomes simple: touch it as little as possible.
Making room for Linux
Instead of wiping the drive, I repartitioned it: 300GB for a new Linux partition, with macOS left alone on the rest. If I ever need to boot back into Monterey, it's still there.
For the distro I chose Linux Mint, specifically the Xfce edition. Mint is friendly and has a reputation for working well on older hardware, and Xfce is the lightest of its desktop options, which is exactly what this machine needed.
Side note: This wasn't my first time putting Linux on a Mac. A while back I experimented with Fedora Workstation on a 2019-era Intel MacBook Pro, the kind with Apple's T2 security chip. That one was a bit more work: T2 Macs have to be told to allow booting from external media, and a lot of the built-in hardware needs extra kernel support (the t2linux project is the place to start). I installed it on an external drive, so the MacBook itself wasn't changed at all. That machine still works well as a macOS system, so I left it that way. The Mac mini is stuck on an old macOS, so it got the full Linux treatment instead.
Burning the installer
I used good old dd right from macOS to write a fresh Mint ISO onto a USB key. It goes roughly like this:
# Find the USB key's disk number (e.g. /dev/disk4). Double-check this!
diskutil list
# Unmount it (don't eject)
diskutil unmountDisk /dev/disk4
# Write the ISO (rdisk is the raw device, which is much faster)
sudo dd if=linuxmint.iso of=/dev/rdisk4 bs=4m
A word of caution: dd will happily overwrite whatever disk you point it at, no questions asked. Make sure that disk number is your USB key and not your main drive!
To boot from it, hold the Option (⌥) key while the Mac powers on and pick the USB drive from the startup menu. I already had a compatible USB keyboard and mouse, so I plugged those in, connected a monitor, and got started.
The Wi-Fi gotcha
Here's the one real snag: the Mac mini's Wi-Fi uses a Broadcom chip, and the Broadcom drivers are NOT preinstalled with Linux Mint. Wi-Fi just wasn't going to work during the install.
To make things easier, I briefly set up my travel router to give the Mac mini a wired Ethernet connection. With that in place, the install went very smoothly. Once Mint was up, I installed the Broadcom driver over the wired connection, and Wi-Fi has worked fine ever since, so the cable didn't need to stick around.
Going headless (with some help from Claude)
With the initial setup done, I switched gears and used Claude Code, Anthropic's command-line coding agent, to handle the rest of the configuration. My goal was a headless machine: no monitor, keyboard, or mouse, but still reachable two ways:
- SSH for command-line work
- RDP (via xrdp) for a full desktop when I want one, using the Windows App on my Mac
Getting both of those working was the first job. Then I went a step further and turned off the desktop at boot:
sudo systemctl set-default multi-user.target
That makes the machine boot to a plain text login, so the graphical login screen (LightDM and its greeter) and a second X server never start. That alone saved about 200 MB. RDP still works because xrdp starts its own X server for each session. And if I DO plug a monitor in, I get a text login; sudo systemctl start lightdm brings the desktop up for that session.
With that, the keyboard, mouse, and monitor all came off.
One habit worth picking up: log out of RDP instead of just closing the window. A disconnected session keeps running in the background and hangs on to 600 to 700 MB of RAM.
Squeezing more out of 4GB
The starting point: 1.4 GiB used at idle, and no swap at all. On a machine with 3.7 GiB usable and no way to add more, that's not a lot of room. So Claude and I went looking for anything we could turn off or put to better use.
zram: swap without the disk
The best find was zram. It creates a compressed swap device in RAM itself. When memory gets tight, instead of shuffling pages out to disk, the system compresses them and keeps them in memory. It makes the machine feel like it has more RAM than it really does, and it protects against out-of-memory crashes without ever swapping to that slow hard drive.
I set it up with the zram-tools package, using zstd compression and sized at 50% of RAM (about 1.8 GiB):
# /etc/default/zramswap
ALGO=zstd
PERCENT=50
PRIORITY=100
Then a couple of kernel settings that suit zram, where swapping is cheap:
# /etc/sysctl.d/99-zram.conf
vm.swappiness=150
vm.page-cluster=0
A swappiness above 100 tells the kernel to prefer swapping to zram over throwing away cached files. page-cluster=0 stops it from reading swap back in eight pages at a time. That kind of read-ahead helps on a spinning disk, but in RAM it's wasted work.
Keeping the disk quiet
Remember that spinning hard drive? This is where it comes back. Every unnecessary write is a slow mechanical operation, so we cut down on them.
First, I added noatime to the root filesystem in /etc/fstab (backing the file up first!). By default, Linux periodically writes a "last accessed" timestamp when files are read. noatime turns that off, so reads are just reads.
Next, I capped the systemd journal at 100 MB so logs can't keep piling up on disk:
# /etc/systemd/journald.conf.d/size.conf
[Journal]
SystemMaxUse=100M
Finally, I turned off auto-refresh in Mint's Update Manager and removed its tray icon. I run updates by hand now with sudo apt update && sudo apt upgrade.
There's a nice side effect, too: every bit of RAM we freed up becomes room for Linux's file cache, so repeat reads come straight from memory and skip the disk entirely.
Trimming services
Next up was disabling services this box will never need:
- Bluetooth, since nothing here uses it
- CUPS printing (the service, socket and path units) and
cups-browsed - ModemManager, since there's no cellular modem
- kerneloops, the crash reporter
- casper-md5check, a leftover from the install USB that was showing as failed
- fwupd, masked rather than just disabled, since Apple doesn't ship firmware for this Mini through it
I deliberately left Avahi running, so I can still reach the box by its .local hostname on my network.
Then there's the desktop side. Even though the desktop only runs over RDP now, a whole pile of apps were set to launch with it: the Bluetooth tray, the print applet, the Mint welcome screen, Mint's system reports, Warpinator, Sticky Notes, the Evolution calendar alarm, and a few more. Each one got a matching file in ~/.config/autostart/ with Hidden=true, which stops it from starting.
A lesson in measuring memory
One fun discovery along the way: fwupd showed up as using about 47 MB, but stopping it only freed about 3 MiB. Most of that "usage" was shared libraries that other processes were using too. Per-process memory numbers can be misleading, so the real test is total usage before and after.
The results
| State | RAM used |
|---|---|
| Before | 1.4 GiB |
| After a reboot, SSH only | ~300–320 MiB |
| Plus Claude Code | about +390 MiB |
| Plus an RDP desktop | about +300 MiB |
Idle usage dropped by more than three quarters. Even with Claude Code running, the box sits around 700 MiB, leaving roughly 3 GiB of the 3.7 GiB free. Everything survived a reboot, and I tested RDP again afterwards to be sure.
Putting it to work
I was still figuring out what I wanted to use this machine for. It was never going to handle my bigger work projects, but it seemed like a good fit for some of my smaller personal ones. So I connected GitHub, cloned my markdown project (markdown.codeandkopi.com), and started making improvements.
I have to say, this is a pretty responsive system for this kind of work. It's not a big project, but the CLI is snappy, and even running the end-to-end Playwright tests (which drive a real browser!) is perfectly usable. And there's STILL RAM headroom left over.
From shelf to desk
What started as a fun side project turned into a machine I actually use. The Mac mini now sits on my desk doing double duty as a laptop stand. It makes no noise, doesn't use much power, and is ready whenever I want to SSH in and tinker.
Plenty of kopitiams in Singapore still brew on well-worn pots and kettles that have been going for decades. Old equipment, still doing good work. Turns out the same goes for old Macs.
So if you've got an old machine collecting dust, give it a second look. Put that old hardware to use!
Cheers,
Matthew