Tools
Tools: Report: I Turned My Old Broken 2011 MacBook Pro Into My First Home Server
The machine
Turning it back on
Installing Debian
My unexpected networking problem
What's running on it now
The documentation
It's been a couple months, What do I think? I’ve been thinking about three things a lot recently. With a growing family, I've been thinking a lot about data and privacy. About how aggressive ads have gotten on platforms we already pay for. About what happens to a lifetime of photos. Those three things were in the back of my mind when YouTube served me a video about turning old MacBook Pros into home servers... and I happened to have one. Of course Google/YouTube know that somehow. It's an old MacBook Pro from 2011. I thought it was completely dead. One day the screen suddenly failed and never worked again. A Genius Bar tech told me the graphics card was toast. Classic 2011 MacBook Pro problem, apparently. Google "RadeonGate" if you want to fall down that rabbit hole. Anyway, I had so much stuff on that hard drive that I held onto it for all these years with a plan to recover all the data. After watching some of those YouTube videos, it made me wonder: did my dusty MacBook Pro have a second life in it? I ordered a new charging cable and a mini DisplayPort adapter off Amazon and figured I'd find out. The first little win was seeing that the MacBook still charged. Good sign. I connected the external monitor, hit the power button, and voila - it turned on. But still, no display. The mini DisplayPort cable wasn't sending a signal to the monitor whether the lid was open or closed (and of course, the MacBook's screen was still failing). But I could hear it. The fans were spinning up. The startup chime was firing. Something was happening in there. What happened most commonly on boot was this: it would reach the Apple loading screen and freeze. The display looked completely destroyed with rainbow pixels and distortion so bad you couldn't see the progress of the loading bar. It was just stuck there. However, in true tinkering spirit, I was determined to get this thing to work and I was expecting a battle, so a few bumps in the road were not going to deter me. I searched for alternative boot modes and the mode that actually gave me something to work with was verbose boot. On a Mac, you hold Command + V right at startup. Instead of the Apple loading screen, you get a wall of scrolling text showing exactly what the system is doing as it loads. It gives you pure information. The problem was the text was just as distorted as everything else. All the letters and words looked like corrupted data. It wasn't legible at all. So I started taking photos of the screen with my phone and sending them to Claude. This is where things got interesting. Claude could pick out patterns in the distortion. It picked up on partial words, recognizable kernel extension names, and fragments of log lines. And it identified exactly where the boot process was hanging, which was the AMD GPU driver loading and causing a cascade failure. Turns out the machine wasn't completely toast, but it was fighting with itself. The GPU firmware indeed seemed corrupt or degraded, and every normal boot attempt ended with the system trying to initialize it and failing to do so. With that information, I continued to stumble forward with high hopes. I tried a few different approaches across several sessions and boot modes including single-user mode (Command + S), safe mode (hold Shift), different NVRAM and SMC resets. Over the course of a couple days I realized I could actually get the MacBook screen to turn on randomly without the distorted graphics after many power up attempts (which was very revealing that again, it wasn't totally toast). So I just kept doing that. I eventually got the machine booted far enough a handful of times, to do what I needed. I backed up everything on the hard drive. Said goodbye to the old system; and wiped it. Following Claude's instructions (always cross-check these), I flashed a USB drive with the server-only distro of Debian 13 and got ready to install it on the MacBook. The server-only distro of Debian is text-based, so it doesn't rely on the GPU for display. But I still needed to address the AMD GPU hardware issue. For this, I learned I could set radeon.modeset to zero, which would prevent the Radeon kernel driver from loading. This driver tries to initialize the broken GPU and would freeze the system before the installer even appears. This variable gets set at the GRUB boot menu, so I edited the boot parameters and added radeon.modeset=0 to the kernel line before starting. Next, I began to get familiar with the system and started learning specific commands to see what was going on inside. When I checked the temperature sensors, I saw the GPU was sitting around 47°C and the fans were spinning at over 5,000 RPM trying to compensate. Even with radeon.modeset=0 preventing the driver from loading, the GPU hardware itself was still active and generating heat. And it turns out Linux does not natively control Apple fans, so it seems that this was the Apple hardware reacting to the heat on its own. I needed to disable the GPU and fix the communication between Linux and the Apple hardware. I immediately did these two things in order: Made sure the GPU was permanently disabled. I had Claude create a custom GRUB script that sends low-level commands to the graphics multiplexer chip, telling it to route everything through the Intel integrated graphics and power down the AMD GPU entirely. After that, the GPU temperature dropped from ~47°C to basically 3°C (reporting as off), and fan speeds dropped from 5,000+ RPM to around 2,800 RPM. Installed fan control. I installed macfanctld, which gives Linux the ability to actively manage fan response. I also wrote a custom temperature monitoring script that runs every minute and sends a push notification to my phone via ntfy.sh if the server gets too hot, with a follow-up notification when it cools back down to avoid false positives. I assumed getting the server onto the internet would be simple. It was not. I had the server hard-wired to my Ruckus router via ethernet. It had an IP address, but it couldn't resolve any domain names. This turned out to be a problem caused by not having the resolvconf package installed. Without resolvconf, DHCP could not update the DNS configuration. Running apt install resolvconf fixed this issue. The bigger problem was that my other devices couldn't reach the server at all. The server on ethernet was sitting on one subnet, while all my other devices on WIFI were on a totally different subnet. The Ruckus router isolates them from each other. From my devices on WIFI, it was as if the server didn't exist on the network. Enter Tailscale. Tailscale solves this problem immediately. It creates a WireGuard-based mesh VPN, so all my devices are able to join the same private network (regardless of what subnet they're on). Plus I can join from anywhere else in the world. Once I had Tailscale running, I could SSH into the server no problem. I realize that I haven't actually fixed the root subnet problem, and that Tailscale can be seen like a band-aid for my situation, but I'm okay with this setup for now. The Ruckus router has been difficult to deal with, so as long Tailscale keeps working for me, I'm good. After networking was stable, everything else moved fast. I set up Docker, Portainer (a web UI for managing containers), and Cockpit (a system dashboard for monitoring the machine itself). The fun part came next, deploying services. Services currently running on the server: Immich: Photo management for our family photos, finally. Firefly III: Fully featured personal finance tracking system. Home Assistant: Primarily for a custom built family dashboard. Caddy: Reverse proxy that handles HTTPS automatically for each service. Homepage: A single dashboard view of everything running on the server. All of this is accessible over Tailscale, meaning nothing is exposed to the public internet. My family keeps convenience, while I get to keep the control. Once I make some hardware upgrades, I'll work on adding either Plex or Jellyfin. One thing I did early on that I'd recommend doing from day one is documentation. In my case, I created a private Git repo documenting everything. For me, that meant a setup log file tracking every change in chronological order, specific hardware notes, architecture diagrams, and a troubleshooting guide for issues I've already encountered and solved. A separate active log file gets updated every time I make a meaningful change. The goal is that if something breaks six months from now, I'm not starting from scratch trying to remember what I learned or what I did. And, the repo becomes the source of truth. My server came online a couple months ago. I'm making real progress addressing my privacy concerns. I feel some level of ownership and control, and that feels so good. I don't control everything I want to yet, but I'm on the path. There is a lot of maintenance involved so far, which is one thing about managed services - it's so nice to not have to maintain any of it. So most of this comes down to what you're willing to trade. Have everything managed for you, but give up all your privacy and data, or gain control of them at the expense of some time and effort. With that being said, I've learned so much and still am. This whole process has exposed me to new skills. It's helped build on top of other ones. And in general, I feel a little more well rounded as a dev. But the best part is I get to keep tinkering with this system and take back control of my family's privacy and data. If you have an old piece of metal laying around, I encourage you to find a use for it. It's so worth it and incredibly satisfying to give an old piece of gear a new life. Maybe the first step is to just turn the thing back on. Templates let you quickly answer FAQs or store snippets for re-use. as well , this person and/or - Made sure the GPU was permanently disabled. I had Claude create a custom GRUB script that sends low-level commands to the graphics multiplexer chip, telling it to route everything through the Intel integrated graphics and power down the AMD GPU entirely. After that, the GPU temperature dropped from ~47°C to basically 3°C (reporting as off), and fan speeds dropped from 5,000+ RPM to around 2,800 RPM.
- Installed fan control. I installed macfanctld, which gives Linux the ability to actively manage fan response. I also wrote a custom temperature monitoring script that runs every minute and sends a push notification to my phone via ntfy.sh if the server gets too hot, with a follow-up notification when it cools back down to avoid false positives.