PHP forced the upgrade and Apple sent nothing: modernizing an old macOS Server in one run
Published 2026-10-24
On 21 October 2026 PHP fixed two critical flaws that let an unauthenticated request run code on the server. On a Linux host the fix arrives as a package. On a Mac still running Apple's Server.app, nothing arrives at all. Server.app's websites run Apple's PHP 7.1, loaded into Apache as mod_php. php.net rates that setup the most dangerous of all, PHP stopped fixing 7.1 in 2019, and Apple will never update it again.
So on an old Mac server, upgrading PHP is no longer something to get round to. It has to happen now, and without breaking sites that have run unchanged for years. FrontierStack 2.11, released on 23 October, makes the Modernize Old Mac Server pane do that in a single run. It also goes a step further than we had planned and takes Apple's unpatched Apache off the internet.
Why waiting for Apple isn't an option
- macOS Server is discontinued. Apple ended it in April 2022. Server 5.6 for High Sierra was the last version that still ran websites and mail.
- The operating system is out of support. High Sierra's last security update shipped in November 2020, Mojave's in July 2021.
- Apple no longer ships PHP. PHP was removed from macOS in Monterey, so no macOS update will ever carry a fixed PHP 7.1. PHP's own backports of the October fixes start at 7.4.
- Apple's Apache is frozen too. On High Sierra, serviceproxy, the Apache that faces the internet for every Server.app website, is Apache 2.4.33 from 2018.
PHP's critical October 2026 fixes on a Mac covers the two flaws, and what to do on Homebrew, MacPorts and MAMP. This post covers what they changed in the Modernize pane.
Modernize automatically: one run, every step checked
The pane now opens with two buttons. Install the tools puts everything in place without touching the websites. Modernize automatically does the whole job in the in-app console, one step after another:
- Apple's command-line tools, if they are missing. MacPorts needs them, and FrontierStack gets them from Apple's Software Update on the server itself, with no screen and nobody logged in. Apple still offers them for High Sierra.
- MacPorts, then PHP 8.5 and newer curl, OpenSSL and rsync, all in
/opt/local. They sit beside Apple's copies, not over them. - The websites move to PHP-FPM 8.5 and keep your old php.ini limits.
- Apple's PHP 7.1 is retired: Apache stops loading it at all.
- MacPorts Apache is tested beside serviceproxy, then takes its place.
Every step loads every site before and after. If a site breaks, or a page starts showing its PHP source instead of running it, that step undoes itself. The run stops there, and every step before it stays done and checked. Websites pause for a few seconds at each switch, no longer.
PHP 8.5.12 or nothing
The pane installs PHP 8.5 and refuses anything older than 8.5.12, the first 8.5 release with the October fixes. Install, Switch and Move all check the version first. Once PHP is installed, Install becomes Update, which upgrades the MacPorts ports in place. The next PHP security release is then one click on each server, not a rebuild.
Servers modernized earlier on PHP 8.4 aren't left behind. Update first brings their PHP 8.4 to 8.4.27, which has the fixes, so they are safe straight away. Move to PHP 8.5 then moves their sites to 8.5 with the same before-and-after check, and goes back to 8.4 by itself if a site breaks.
Running this on our own servers turned up two smaller problems. PHP-FPM's stock pool allows only five workers, too few for a busy server, so the pane now sizes the pool from the memory each worker actually uses and what the database needs. And on old code, PHP 8's error log can grow by tens of megabytes in a few hours, so the install now sets up log rotation.
Taking Apple's Apache off the internet
Our first Modernize post said Apple's Apache couldn't be replaced, because Server.app's websites, Profile Manager, Wiki and Calendar all run through it. That is still true of the Apache behind the proxy. What has changed is the part in front of it.
serviceproxy is the copy of Apache that answers on ports 80 and 443 for everything Server.app serves. The same three problems came up again and again:
- It gets no security fixes.
- It hangs on old Macs. The backend keeps running, but every site is unreachable.
- It unlocks the sites' TLS keys from the System keychain. At startup macOS checks that keychain, and if the check fails, macOS sets it aside and creates an empty one. serviceproxy then can't find the keys, and no restart or reboot brings HTTPS back.
Replacing it takes three buttons, one at a time:
- Replace serviceproxy installs MacPorts Apache and changes nothing else. It converts serviceproxy's configuration, along with every file Server.app includes from it. It keeps each certificate, key and chain together as a set in root-only files, and leaves out the few directives only Apple's Apache understands.
- Test beside serviceproxy runs the converted copy on 127.0.0.1. It compares every site and every Server.app path with serviceproxy's answers, including Profile Manager, Wiki, Calendar and Contacts. The answers must be identical.
- Switch to new serviceproxy… stops serviceproxy, switches it off in launchd and gives its ports to MacPorts Apache. If any answer differs after the switch, serviceproxy comes straight back.
Server.app keeps running and keeps managing everything behind the proxy. When you change a site in Server.app, or a certificate renews, a re-sync job converts the configuration again by itself, and the pane tells you if a re-sync fails. Back to serviceproxy… undoes the whole change.
There is one caveat, and we would rather say it than hide it. For enrolled devices, serviceproxy used a certificate check that only Apple's Apache has. MacPorts Apache checks device certificates the standard way. The test can't act as an iPhone, so after switching, open Profile Manager and make sure an enrolled device still checks in.
A healer, not a reboot loop
Many old Server.app Macs have a hand-made watchdog that reboots the machine when the websites stop answering. A reboot can't fix a proxy fault. And if Websites is switched off in Server.app, the watchdog reboots the Mac over and over. This week we saw exactly that on two servers.
The service-proxy healer replaces the watchdog. Every minute it checks ports 80 and 443, and the Apache behind them, using each site's real name. When the proxy is stuck, it restarts only the proxy. After three restarts in fifteen minutes it stops trying and reports what it found. It recognises the TLS-key errors in the log that no restart can fix, and tells you to re-import the certificate instead. It never reboots the Mac. After the switch it watches MacPorts Apache in the same way, and every incident appears in FrontierStack's alerts.
Nothing else may answer
On a Server.app Mac, only Server.app should serve web pages. The pane now looks for anything else that does: the Apache built into macOS, a second Apache or nginx started by a launch daemon, an old copy of MAMP. On two of our own servers, the built-in Apache had been switched on years ago. It was answering on port 80 on one server and port 8080 on the other, and sending PHP files as plain text. That is exactly how a site's database password ends up in public. The checklist marks such a server as failing and offers to switch the extra server off. The healer also raises an alert if anything answers on port 80 while Websites is off.
The System keychain, guarded
That keychain reset at startup happens more often than you would expect: this week it took HTTPS down on one of our servers. Version 1.27 of FrontierStack's remote agent backs up the System keychain on protected servers and notices when macOS has replaced it. It can then put the original back, at most once per boot, and on its own only if you allow it. Moving the websites to MacPorts Apache takes their keys out of the keychain altogether. The guard covers everything else that still depends on it, mail included.
Across the rest of the fleet
- Fleet Run › PHP versions & security fixes finds every PHP on every linked server. For each one it shows where it came from (Homebrew, MacPorts, MAMP, Apple or a Linux distribution) and whether it serves web pages, and compares it with php.net's latest security release. It warns rather than updating anything itself. Copy AI Prompt gives you exact instructions to follow yourself or hand to an AI agent.
- The PHP pane on your own Mac has a Security section that covers its Homebrew, MAMP, MacPorts and system PHP.
- OPNsense firewalls run PHP too. Router Health now reads the PHP version in the firmware and raises an alert when it falls behind.
- Security Check and Server Protection now work on every linked macOS and Linux server, not just old Macs. Server Protection adds daily file-integrity checks and a firewall for admin ports.
What it still can't fix
None of this brings back Apple's security updates for macOS itself. After modernizing, the websites run on a supported PHP behind a maintained Apache, but the kernel underneath is still High Sierra's. Keep these servers behind a firewall that inspects traffic, keep their admin ports off the internet, and give them a network of their own. Another ten years from the Mac servers you already own covers that hardening and the network wall around the server. What replaced macOS Server (and how to move) covers moving off Server.app entirely when you are ready.
Getting started
Update to FrontierStack 2.11 and link the old server. Then open Modernize Old Mac Server under Setup & Migration, or press Modernize this server on the page of any server running macOS 10.x. The pane only shows sections for services the server actually runs. If you would like to watch each step yourself, start with Install the tools, which changes nothing your visitors can see. Everything the pane does keeps a backup and can be undone.
Run it from your Mac.
FrontierStack installs, monitors and secures services on this Mac and on linked servers; and keeps your passwords and keys out of any AI's sight.
Download FrontierStackApple notarized · Safe & secure · macOS 13 Ventura+
