Author name: solarbluseth

Custom PHP Development

My Streaming PC Died After a Simple Reboot, and Windows Recovery Fought Me the Whole Way

💻 My Streaming PC Died After a Simple Reboot, and Windows Recovery Fought Me the Whole Way

What I tried, what failed, the workarounds that got me in, and what I’m changing so it never happens again.

I’ve been building websites and fixing computers since 1996. Thirty years, thousands of machines, and I can count on one hand the problems I couldn’t solve myself. So when my streaming PC wouldn’t boot on a Thursday night, I figured I’d be back online in twenty minutes.

It took me into Friday night. Here’s the whole story, plus the tricks that finally worked, so if it happens to you, it takes you less time than it took me.

💀 What Happened

Nothing dramatic. I shut the computer down, walked away, came back, and turned it on. It wouldn’t boot. It dropped me into Windows Recovery and a command prompt.

My first guess was a full drive, so I started with the usual cleanup commands. That’s when things got weird.

⌨️ The Keyboard That Couldn’t Type a Backslash

Every time I typed C:\, the screen showed C:#.

I swapped keyboards. Same thing. That ruled out hardware: the recovery environment had loaded a UK keyboard layout. On a UK layout, the key where we Americans keep the backslash types a #, and the real backslash lives on an extra key next to the left Shift that US keyboards don’t have.

Nearly every Windows repair command needs a backslash. Losing it is like getting a toolbox with every wrench welded shut.

What I tried:

  • wpeutil SetKeyboardLayout 0409:00000409 (switches to US, no slashes needed). Didn’t take.
  • Alt codes: Alt + 92 on the number pad types \. Didn’t work in my recovery environment either.

🔧 The Workaround: Old-School DOS Navigation

If you can’t type a backslash, you can still get anywhere by moving one folder at a time:

E:
cd Windows
cd System32

And cd .. goes back up a level. Old DOS skills to the rescue.

Another handy trick: the command prompt remembers a separate current folder for each drive. So C:seth (no backslash) means “the seth folder inside wherever C: currently is.” That lets you copy between drives without ever typing a slash.

🔍 Your C: Drive Might Not Be C:

This one tripped me up for a while. In Windows Recovery, drive letters get shuffled. My Windows drive showed up as E:. Then C:. A USB stick grabbed E: at one point. The “C: drive” I’d been checking for free space didn’t even have a Windows folder on it.

Here’s how to find the real one:

diskpart
list volume
exit

Look for the big NTFS volume. Then run dir on that letter. If you see Windows, Users, and Program Files, you’ve found it. (X: is the recovery environment itself, so skip it.)

Bonus confusion: in list disk, a “Free” column of 0 B does not mean your drive is full. It means there’s no unpartitioned space. Use dir and read the bytes free line instead.

❌ Everything That Failed

Once I’d found the right drive, I went through the whole playbook:

  • Startup Repair: ran several times, couldn’t determine the cause.
  • Uninstall latest quality update: hung forever.
  • System Restore: the restore point was corrupted.
  • “Reset this PC” / reinstall from recovery: refused.
  • DISM: “not recognized as a command.” Then “unable to access image.”
  • xcopy and robocopy: also missing.

That last part was the big clue. DISM, xcopy, and robocopy are normally built into Windows Recovery. Missing tools plus the wrong keyboard layout meant the recovery environment itself was damaged. It lives on the same drive as Windows, so whatever broke Windows likely broke it too. I was trying to fix a broken system with broken tools.

🤔 So What Actually Caused It?

My best guess: an interrupted Windows update. When an update is pending, Windows often finishes installing it during shutdown, the “Working on updates, don’t turn off your computer” screen. If anything goes wrong in that window, you come back to a machine that won’t start.

Windows’ Fast Startup (on by default) makes it worse. It doesn’t fully shut down. It saves the system state to the drive and reloads it next boot. If that saved state gets corrupted, the next boot fails.

Before reinstalling, I ruled out hardware:

wmic diskdrive get model,status

That returned OK, and a chkdsk scan backed it up. Good news: the drive was healthy.

✅ What Finally Worked

Booting a Windows install USB directly didn’t work on this machine, so I did it the sideways way:

  1. On another Windows PC, I formatted a USB stick as NTFS, mounted the Windows 11 ISO, and copied all the files inside it onto the stick. (Not the .iso file itself. Recovery can’t open that.)
  2. Back in the recovery command prompt, I found the stick’s letter with diskpart → list volume.
  3. Switched to it and launched the installer:
I:
setup

No backslash required. The full Windows installer opened right inside the broken recovery environment.

Then I made one smart call: I installed Windows onto a different partition instead of wiping the old one. My entire old profile stayed intact, so I could copy files out at my own pace afterward.

During setup I picked English (United States) and the US keyboard. That ended the # problem for good.

📦 Getting My Stuff Back

A few things I learned moving data from the old install:

  • The old partition may not get a drive letter. Fix it in Disk Management, or in diskpart: select volume 3 then assign letter=O. Never click “Initialize” or “Format” on it.
  • You’ll get “Access denied.” The new Windows sees your old user as a stranger, even with the same name. Take ownership in one shot from an admin command prompt:
takeown /f "O:\Users\yourname" /r /d y
icacls "O:\Users\yourname" /grant %USERNAME%:F /t /c
  • Don’t copy all of AppData\Roaming. Mine was 44 GB, mostly caches. I grabbed only the app folders I needed (like obs-studio, which holds every scene and source).
  • Install the app first, then restore its folder. Install, open once, close it, then paste the old folder over the new one.
  • Steam games don’t need a redownload. In Steam, go to Settings → Storage → Add Drive and point it at the old library. It finds the installed games and just verifies them.
  • Back up your browser bookmarks. I’m glad I had my Firefox bookmarks exported.

🛡️ What I’m Doing So This Never Happens Again

  1. Turn off Fast Startup. Control Panel → Power Options → “Choose what the power buttons do.” A shutdown should be a real shutdown, and the boot menu key starts working again.
  2. Set Windows Update active hours to cover streaming times, and pause updates during big stream weeks.
  3. Build a rescue USB with Ventoy. Drop Windows 11, Ubuntu, and MemTest86 ISOs on one stick and boot whichever you need. No more depending on a recovery partition living on the same drive that just broke.
  4. Make a recovery drive (search “Create a recovery drive” in Start) while everything is working.
  5. Take a full drive image once the rig is set up. Next time, restore in 20 minutes instead of losing a weekend.
  6. Turn on Firefox Sync so passwords and bookmarks follow me automatically.

🎮 Back Online

The streaming rig is back, running on a clean Windows install, with my files, scenes, and settings intact. It wasn’t the twenty-minute fix I expected, and the boot process wasn’t up to my standards, but I got it done without wiping a single file.

If your PC drops you at a recovery prompt and nothing works, don’t panic. Find the real drive letter, work around whatever’s broken, and remember the old DOS way still works: one folder at a time.

Need help with a PC that won’t boot, or a website that needs fixing? That’s what I do. Get in touch with SolarBlu.net.

— Seth

Custom PHP Development

Your Google Listing Is Working. Your Website Isn’t.

Your Google Listing Is Working. Your Website Isn’t.

📍 You did the hard part. Don’t let a broken link hand your customers to the competition.

Picture this. Someone in your town grabs their phone and searches for exactly what you do. There you are near the top: great stars, real reviews, a listing you’ve spent years earning. They tap Website…

“This domain has expired.”

They hit the back button and tap the next business on the list. You never knew they were there.

That’s not a made-up scenario. We recently reviewed thousands of local business websites across Illinois, and a surprising number of good businesses — with good reputations on Google — are quietly losing customers this way every single day.


🔍 What we actually found

These weren’t abandoned businesses. Many were open, busy, and well reviewed. Their websites just weren’t holding up their end:

  • Expired or parked domains. The website address lapsed, and now it shows a “for sale” page or an ad page from the domain company.
  • “Page not found” or “this site isn’t connected.” Something changed behind the scenes and nobody reconnected it.
  • Broken sites. Database errors, blank pages, and servers that simply don’t answer.
  • Free-plan websites with the website builder’s own ads plastered across the top.
  • Hacked sites. A couple of local business websites were showing gambling spam to every visitor. The owners almost certainly had no idea. 😬
  • “Our website” is really a directory listing on somebody else’s site, next to ads for your competitors.

💸 Why this costs more than you think

When your Google listing is strong, people are already looking for you. That’s the expensive, slow part of marketing — and you’ve already won it. A broken website throws that win away at the last step.

  • Lost calls. Most people check your website before they call: hours, photos of your work, prices, “is this place legit?” A dead page answers that question for them — and not in your favor.
  • Google notices, too. A site that stays down for a long time can start dropping out of search results. A hacked site can get a “This site may be hacked” label right in Google, or a red warning screen that scares visitors away before they ever see your page.
  • Someone else can grab your address. An expired domain can be bought by anyone — and then the traffic and links you built over the years point to them, not you.
  • It looks like you’re closed. To a new customer, a broken website reads as “out of business,” even if you’re booked solid.

✅ The 5-minute self-check

You don’t need to be technical to do this. Grab your phone:

  1. Google yourself like a customer would. Search your business name and your town. Tap the Website button on your Google listing. Does your real site come up?
  2. Look at it on your phone. Does it load quickly? Can you read it without zooming? Is there a padlock next to the address?
  3. Check the basics. Are your phone number, hours, and address right? Is the copyright year at the bottom from this decade?
  4. Check your domain renewal. Log into wherever you bought your web address. Is it set to auto-renew? Is the card on file still good? (An expired credit card is the #1 way good businesses lose their domain.)
  5. Search for anything weird. Type site:yourdomain.com into Google. If you see pages about casinos, pills, or anything that isn’t you, your site has likely been hacked.

Bonus question: do you have the logins for your domain, your hosting, and your Google Business Profile? If the answer is “my nephew set that up in 2015,” that’s worth sorting out before something breaks.

🛠️ Found a problem? Don’t panic.

Almost everything on that list is fixable, and often faster than you’d expect. An expired domain can usually be renewed if you catch it in time. A broken site can usually be brought back. A hacked site can be cleaned up, secured, and reported to Google so the warnings come off. The worst move is waiting — every day it stays broken is another day of customers clicking “back.”

If your site turned out to be hacked, treat it as urgent. It’s not just hurting you; it can put your visitors at risk too.


🦸 Need a hand? Send us a signal.

We’ve been building, fixing, and rescuing websites since 1996 — expired domains, broken WordPress sites, hacked sites, and sites that just look tired. If your self-check turned up something you don’t like, tell us what you’re seeing and a hero will be in touch.

Send for Backup →

Custom PHP Development

Lead Gen, Part 2: Finding the Businesses That Actually Need a Hero 🦸

Lead Gen, Part 2: Finding the Businesses That Actually Need a Hero 🦸

🎯 Thousands of leads are nice. Knowing which ones genuinely need help is what turns them into clients.

In Part 1 we built our own lead generator and went from “0 leads across the board” to thousands of real, callable local businesses in an afternoon. Great problem to have — but it created a new one.

A big list isn’t a marketing plan. Plenty of those businesses already have a great website and a developer they love. Calling them, or mailing them a flier, wastes their time and ours. So this round was all about one question: which businesses actually need our help, and how do we reach them without spamming everyone?

Here’s the pipeline today, in plain English:

Town × industry list → search → filter → de-dupe → leads database → free enrichment (emails + screenshots + site checks) → review (hot levels & postcard rounds) → hand-off to sales

Same rule as last time: we’ll share the lessons, not the whole playbook. 🤫


1. 🩺 Let the computer do the first look

We had over 4,300 website screenshots. Nobody wants to flip through 4,300 screenshots by hand — we know, because we tried, and made it about 14 pages in.

So we added a free, automatic site check to every lead. It looks at the things a web pro checks in the first ten seconds: Is the site up? Is it secure? Does it work on a phone? Is it slow? Is the copyright year from another decade? Is it on a do-it-yourself builder, or on WordPress (and which version)? Each site gets a simple “needs work” score and a short list of what’s wrong.

Then we read the text on every screenshot and sorted them into buckets. What turned up was eye-opening:

  • Dead links. Expired domains, parked pages, “this domain isn’t connected,” 404s — real businesses still advertising a website that doesn’t exist.
  • Broken sites. Database errors and servers that simply don’t answer.
  • Free-plan sites still showing the builder’s ads across the top.
  • “Our website is a directory listing.” Businesses whose only web presence is someone else’s page.
  • Hacked sites. A couple of local business sites were serving gambling spam to every visitor. The owners almost certainly have no idea. 😬

Takeaway: Those aren’t “leads.” Those are people with a problem we can fix this week. That’s a very different phone call.

2. 👀 Trust the robot — then check its homework

Automatic sorting is fast, and it’s wrong just often enough to embarrass you. Two real examples from this week:

  • Our spam detector flagged a bunch of perfectly normal auto shops and HVAC companies as “hacked.” Why? The word “Specialist” happens to contain the name of a certain little blue pill. 🤦 One missing word boundary, a dozen false alarms.
  • Beautiful, photo-heavy sites with almost no text were being labeled “blank page.” Less text isn’t the same as nothing loaded.

We caught both by eyeballing a random sample from every bucket before trusting the totals. Then we did the honest thing with the screenshots the computer couldn’t judge — security checks, bot walls, half-loaded pages — and put them in their own “manual review” pile instead of guessing.

Takeaway: Automation should narrow the list, not make the final call. Always spot-check every category, and give “I don’t know” its own bucket.

3. 🔥🔥🔥 Not all hot leads are equally hot

A single “hot” flag stops being useful once you have hundreds of hot leads. Which one do you call first tomorrow morning?

So we gave our hot list three levels: 🔥 hot, 🔥🔥 hotter, 🔥🔥🔥 hottest. One click on a flame sets the level, the list sorts hottest-first, and the stats page shows how many are at each level. A hacked site gets three flames. A slightly dated site gets one. Everyone on the team knows where to start without a meeting.

We also put each lead’s review notes right next to it — what’s wrong with the site and a one-line pitch idea — so whoever picks up the phone already knows what to say.

4. 📮 Postcards without the double-send

Nothing says “we don’t pay attention” like mailing the same business the same flier twice.

Every lead now tracks which marketing round it’s been tagged for, and the newest hot leads were added to round one only if they weren’t already on it. Since our first round came in under our print run, we simply merged everyone into round one and kept round two clear for later. The tool prints the mailing labels straight from the browser and skips anyone missing a street address or ZIP, so no label gets wasted on an incomplete address.

Takeaway: Keep the “who got what, when” in the same place as the lead — not in somebody’s memory or a spreadsheet on their desktop.

5. 📱 Closing the loop: a postcard that talks back

Our new “Hire a Super Hero” postcard has a QR code on it. Scan it and you land on a page that looks like the back of the postcard — with a short contact form where the mailing address would be. 🦸

The fun part: a postcard gets passed around. The owner scans it, then hands it to their office manager, who hands it to their brother-in-law who’s been “meaning to fix his website.” Every one of those people can reach us, and every submission lands right in our leads database, tagged with where it came from. If the database ever hiccups, the message still gets emailed, so nothing falls through the cracks.

Takeaway: Print marketing doesn’t have to be a one-way street. Make the response just as easy as the flier — and make sure it ends up in the same system as the rest of your leads.

6. 🐛 Small bugs, real costs

A few unglamorous fixes that made a real difference:

  • Page 2 showed page 1 again. Thousands of leads shared the exact same timestamp, so the database was free to return them in any order. Adding a tiebreaker to every sort fixed it. If your paging ever “repeats,” this is probably why.
  • Duplicates hiding in plain sight. Hundreds of leads had byte-for-byte identical screenshots — the same business saved under different records, or several “businesses” that all pointed at one directory page. Identical screenshots turned out to be a great duplicate detector.
  • Deleting is now admin-only. Staff can review, tag, and call — but only an admin can remove a lead. One accidental click shouldn’t erase a prospect.

🤫 What we’re still not telling you

Our territories, industries, scoring rules, and exactly how the pieces talk to each other — that stays in the kitchen. 😉

But here’s the big lesson from round two: more leads was never the goal. Better-matched leads was. When you can show a business owner that their domain expired, their site is serving spam, or their “website” is a directory listing, you’re not cold-calling anymore. You’re the one who noticed.

Is your website secretly in trouble?

We’ve been building and rescuing websites since 1996 — dead domains, broken WordPress installs, hacked sites, and sites that just look tired. If any of this sounds familiar, send us a signal and a hero will be in touch. 🦸

Custom PHP Development

We Built Our Own Lead Generator. Here’s What Actually Matters (Hint: It’s Not the Scraping)

We Built Our Own Lead Generator. Here’s What Actually Matters (Hint: It’s Not the Scraping)

🚀 Lessons from turning “0 leads across the board” into thousands of real, callable businesses in a single afternoon.

Scroll TikTok for five minutes and you’ll see it: “I made $10K with this one lead-gen hack.” Scrape this, automate that, plug in some AI and watch the leads roll in.

We actually built one. A real, working lead generator for our own outreach — search, filter, de-duplicate, enrich, review, and hand off to sales. Along the way we learned that the flashy part (grabbing data off the internet) is the easy part. The parts that decide whether you get ten leads or ten thousand are boring, unglamorous engineering: choosing the right data source, using your API properly, pagination, timing, and measuring what’s really happening.

We’re not going to hand over our whole playbook (more on that at the end 🤫), but here’s what we learned that you can use today.


1. 🔎 Your data source matters more than your filters

Our first version searched social media for small business pages. For a while it worked. Then one day, nearly every search came back with zero leads.

We spent hours tuning filters and squeezed it up to about one usable lead per search. Then we stepped back and asked a better question: where do real, operating local businesses actually list themselves? Switching to local map-style business results took us to roughly 13–20 new leads per search — and they came with phone numbers, addresses, categories, and websites already attached.

Takeaway: If you’re fighting your data source, stop polishing the filter. Find a better source. Search engines change how they handle tricks like site: operators without warning, and a technique that worked last year can quietly die.

2. 📊 Measure before you fix

“0 results” told us nothing. Was the API broken? Were we out of credits? Were the results all duplicates?

The fix that mattered most was tiny: we made every search report why each result was kept or thrown away — how many came back, how many were already in our database, how many were directories, how many failed a rule. Within one run, the real culprit was obvious: the search provider was wrapping results in redirect links, and our filter didn’t recognize them.

Takeaway: A few honest counters in your logs will save you more time than any clever algorithm. When something says “0,” make it tell you 0 out of what, and why.

3. 📄 Pagination: stop paying for page one over and over

Here’s a mistake almost every DIY scraper makes: it searches the same keywords again and again, and every time it gets the same first page of results. You pay for the search, find nothing new, and assume the market is tapped out.

What works:

  • Track the page for every query. Each keyword + location combo remembers which page it’s on, so a re-run asks for page 2, not page 1 again.
  • Go breadth-first. Run page 1 for every combo before anyone’s page 2. Page 1 is almost always the most valuable page per call, so cover your whole map before digging deeper.
  • Only advance when the provider says there’s more. Most APIs tell you if a next page exists. Respect it, and cap the depth (we stop at a few pages).
  • Know when to quit. Deeper pages drift farther from the town center and overlap more with neighbors. When a page stops paying for itself, stop.

4. ⏱ API utilization and timing: respect the limits (they’re there either way)

Paid search APIs usually have two limits: a monthly quota and an hourly throughput cap. Ignore either one and your tool falls over at the worst moment.

  • Trust the provider’s numbers, not your own counter. Our tool once said we’d used 942 searches; the provider’s dashboard said 431. Our counter was counting requests the provider didn’t bill (like cached repeats). Read usage from the source of truth.
  • Pace yourself and resume automatically. When you hit the hourly cap, don’t crash — wait, then pick up exactly where you left off.
  • Failures must not eat your work. A combo should only be marked “done” after a successful search. A timeout shouldn’t silently burn through your queue with fake zeros.
  • Retry with a backoff. Networks hiccup. Pause, retry, and give up gracefully after a sensible number of tries.
  • Use caching to your advantage. Many providers serve identical recent searches from cache for free — perfect for debugging without spending credits.
  • Clean your inputs. One business listing had a 500+ character website URL stuffed with tracking codes, and it broke a database insert. Strip the junk before you store it.

5. 📧 Free enrichment beats paid enrichment

Lots of lead tools charge extra to “enrich” a lead with an email or details. When your source is good, you often don’t need to. Once a lead has a website, a polite visit to the homepage and contact page finds a surprising number of email addresses — no API credits required.

We also capture a screenshot of every business website (📸 over 4,000 on day one). For a web design company, that’s gold: in a few seconds you can tell whether a site is modern, dated, broken, or missing entirely. Flip through them gallery-style, tag the ones worth a conversation, and move on.

6. ⚖️ Compliance is a feature, not an afterthought

The TikTok version of lead gen rarely mentions this part. It should be front and center:

  • Honor Do Not Call lists — automatically, every time, not “when someone remembers.”
  • Put your outreach rules in the code. If your team can only contact certain regions or channels, the tool should enforce it so nobody has to think about it.
  • Deleted means deleted. If someone asks to be removed, or a lead is junk, it should never sneak back in on the next search.
  • Different channels, different rules. A mailed postcard and a phone call aren’t governed the same way — build your filters to match.

7. 👥 Build for a team, not a spreadsheet

Spreadsheets are where lead lists go to die: five copies, three versions, nobody knows who called whom. We kept everything in one live tool:

  • Assign leads, add notes, and track call status in one place
  • 🔥 Mark hot leads (with the date) and filter to your call list for tomorrow
  • Tag leads for different postcard campaigns and export clean mailing lists
  • Separate admin and staff views, so the team sees what they need and nothing they shouldn’t
  • A one-click hand-off that sends a qualified lead straight into the sales process

🤫 What we’re not telling you

Our target industries, our territories, our search keywords, our scripts, and exactly how the pieces fit together — that’s the secret sauce, and it stays in the kitchen. 😉

But the lessons above are universal. Whether you’re building your own tool or buying one, ask: Is the data source solid? Does it paginate properly? Does it respect API limits and timing? Can I see why it keeps or drops a result? Does it enforce my compliance rules? If the answer to any of those is “no,” no amount of AI magic will fix it.

Want a tool like this for your business?

We’ve been building custom websites and web tools since 1996. If you need a lead pipeline, a custom CRM, or just a website that doesn’t look like it’s from 2009, let’s talk.

Custom PHP Development

Your Host Patched PHP2Shell. Did You Patch Your Dev Machine?

Security Alert · PHP2Shell

Your Host Patched PHP2Shell. Did You Patch Your Dev Machine?

YOUR HOST $ php -v PHP 8.5.5 YOUR LAPTOP

If you run PHP anywhere outside a managed host — your laptop, a VPS, a Raspberry Pi, a Docker container — check it today. On October 21, 2026, PHP shipped emergency fixes for two critical flaws, CVE-2026-109618 and CVE-2026-109619, nicknamed PHP2Shell. Together they let an attacker run code on a server with no login, through any PHP page, before WordPress or your own code even loads.

The good news: most managed WordPress hosts patched their servers within about a day. My own sites were covered at the server level by the next evening.

The bad news: nobody patches your machine for you. The laptop running a local stack, the $5 VPS you set up last year, the Docker image you built and forgot — those stay vulnerable until you update them. That long tail is where the attacks will land over the next few months.

How big is this?

PHP is not a niche language. It runs most of the web, and WordPress sits on top of a huge share of it.

69.3%
of websites with a known server-side language run PHP
W3Techs, Oct 23, 2026
42.6%
of all websites run WordPress, which is built on PHP
W3Techs via Barn2, Apr 2026
22.6M
internet-facing instances flagged as potentially vulnerable
Palo Alto Networks via TechTarget, Oct 21, 2026
2.24M
servers openly advertising PHP in their headers
Shodan count via CybelAngel, Oct 20, 2026
59%
of those that show a version are on branches with no official fix coming
Shodan count via CybelAngel
34.6%
of PHP websites still run PHP 7 or PHP 5
W3Techs, Oct 23, 2026

And the machines nobody counts

Those numbers only cover servers you can see from the internet. Nobody counts the PHP installs on developer laptops, office PCs, and forgotten test boxes. Here’s a rough sense of scale: about 1 in 5 developers uses PHP (18.2% in Stack Overflow’s 2024 survey), and SlashData estimated 6.3 million PHP developers back in 2021. Most of them run at least one local stack — MAMP, XAMPP, WampServer, Homebrew, Docker, or Laravel Herd — and many run several.

That’s likely millions of unmanaged PHP installs that no hosting company will ever patch. That last part is my estimate, not a measured number, but it’s why I’m writing this.

Patched for you

  • Managed WordPress hosting
  • Shared and reseller hosting (cPanel, CloudLinux)
  • Managed VPS and dedicated servers

Patched by YOU

  • Your laptop: MAMP, XAMPP, WAMP, Homebrew, Herd
  • Self-managed VPS and Raspberry Pi
  • Docker images and AI-built dev servers

Which PHP versions are safe

You need PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 or newer. Anything older on those branches is vulnerable.

Your PHP branch Fixed in Notes
8.5 8.5.12 Current branch
8.4 8.4.27 Supported through 2028
8.3 8.3.36 Supported
8.2 8.2.35 End of life December 31, 2026
8.1, 8.0, 7.4 No official release Minimal source patches only; cPanel and CloudLinux backported fixes into their packages
7.3 and older None Upgrade or retire it
🔍

Version number looks old? Some hosts patch without changing it. CloudLinux put the fix into its existing builds, so a patched server can still say 8.4.26. Check the Build Date in phpinfo: anything built on or after October 21, 2026 has the fix.

Find every PHP you’re running

Most of us have more than one PHP and don’t realize it. Check each place it could live.

On a website or local server: phpinfo

  1. Create a file with a hard-to-guess name, like check-8x3k.php. Don’t call it info.php; bots look for that name.
  2. Put this one line in it:
    <?php phpinfo(); ?>
  3. Upload it to the site’s root folder (usually public_html), or drop it in your local web folder.
  4. Open it in your browser: yoursite.com/check-8x3k.php or localhost:8080/check-8x3k.php.
  5. Read three lines near the top: PHP Version (compare it to the table), Build Date (on or after Oct 21, 2026 = fixed), and Loaded Configuration File (tells you which PHP install it is).

Only need the number? Use <?php echo phpversion(); ?> instead. It reveals less.

On the command line

php -v
which -a php

which -a lists every PHP on your path. Two or three results means multiple installs, and each one needs updating.

⚠️

Check both. The command-line PHP and your web server’s PHP can be different. I updated PHP on my Mac, php -v said 8.5.12, and phpinfo still said 8.5.5 because Apache was holding the old version in memory.

Docker, VPS, and everything else

  • Docker: docker exec <container> php -v. Restarting a container does not update it. You need docker pull and a rebuild.
  • VPS or Raspberry Pi: SSH in, run php -v, update with apt or dnf, then restart Apache or PHP-FPM.
  • MAMP, XAMPP, Laravel Herd: these bundle their own PHP. Check for an app update.

Delete the phpinfo file when you’re done

The moment you’ve read the version, delete the file. A forgotten phpinfo page is a gift to attackers:

What it exposes

  • Your exact PHP version and build
  • Every setting, file path and module
  • The cookies of whoever views it. When I loaded mine while logged into WordPress, my login cookie was right there on the page.

How to delete it

  • cPanel: File Manager, select it, Delete
  • FTP / Dreamweaver: delete it on the remote server, then confirm the URL shows a 404
  • Mac: rm it from your web folder

If you viewed it while logged into WordPress and shared a screenshot or copy, log out and back in. That ends the session the cookie belonged to.

Updating PHP on a Mac (Homebrew)

If you installed PHP with Homebrew, this takes about five minutes. Run each command on its own line in Terminal.

  1. Update and upgrade PHP.
    brew update
    brew upgrade php

    You should see something like php 8.5.5 -> 8.5.12.

  2. See what Homebrew has running.
    brew services list
  3. Restart PHP and your web server (whatever shows as started).
    brew services restart php
    brew services restart httpd

    Use nginx instead of httpd if that’s what you run.

  4. Reload your phpinfo page. It should show the new version.

If phpinfo still shows the old version

This happened to me. The upgrade worked, but Apache showed error in brew services list and kept serving the old PHP from memory. Here’s the fix:

  1. Check Apache’s config is valid. It should say Syntax OK.
    /opt/homebrew/bin/httpd -t
  2. Check which PHP Apache loads.
    grep -n "libphp" /opt/homebrew/etc/httpd/httpd.conf

    If the path contains a version like Cellar/php/8.5.5, Apache is pinned to the old one. Change that line to the path that always points to the current version:

    LoadModule php_module /opt/homebrew/opt/php/lib/httpd/modules/libphp.so
  3. Kill the old Apache and start fresh.
    brew services stop httpd
    sudo apachectl stop
    pgrep -l httpd

    If pgrep still lists anything, run sudo killall httpd. Then:

    brew services start httpd
    brew services list

    Once httpd says started, reload phpinfo.

💡

Terminal tip: don’t paste commands with # comments on the end. The Mac’s Terminal passes them to brew as extra words, and you’ll get No available formula with the name "#".

Not using Homebrew?

  • MAMP: MAMP menu → Check for Updates. MAMP bundles its own PHP, so Homebrew won’t touch it.
  • Laravel Herd: open Herd, go to the PHP tab, and update.
  • Windows (WampServer / XAMPP): download the Thread Safe x64 build of the fixed version from windows.php.net, or update the whole stack.

Still running PHP 5 or 7 scripts? Now’s the time to move them

If you’ve been holding a server on PHP 7.x or even 5.x because an old script breaks on PHP 8, this is your wake-up call. PHP 7.3 and older got no fix at all for PHP2Shell. PHP 7.4, 8.0 and 8.1 only got minimal emergency patches. The next serious flaw may not get even that.

The good news: most old scripts break for the same handful of reasons, and they’re fixable in an afternoon.

What usually breaks

Old code Removed in Replace with
mysql_connect(), mysql_query() and other mysql_* PHP 7.0 mysqli or PDO with prepared statements
ereg(), eregi(), split() PHP 7.0 preg_match(), preg_split()
each() PHP 8.0 foreach
create_function() PHP 8.0 Anonymous functions: function() { ... }
$string{0} curly-brace offsets PHP 8.0 $string[0]
utf8_encode(), utf8_decode() Deprecated in 8.2 mb_convert_encoding()
Adding properties to objects on the fly Deprecated in 8.2 Declare the property in the class

PHP 8 is also stricter. Undefined variables and array keys throw warnings, passing the wrong type to built-in functions throws errors instead of quietly returning null, and 0 == "abc" is now false. Code that relied on PHP being forgiving will start complaining.

How to tackle it

  1. Scan before you change anything. PHPCompatibility checks your code against a target PHP version and lists every problem by file and line.
  2. Let a tool do the boring fixes. Rector rewrites a lot of old syntax automatically. Review its changes before you deploy.
  3. Swap mysql_* for prepared statements. Usually the biggest job, and it closes SQL injection holes at the same time.
  4. Test locally on PHP 8.4 or 8.5 with error reporting turned all the way up. Click every page and submit every form.
  5. Switch the live site in cPanel’s MultiPHP Manager only after it runs clean locally. Keep the old version handy for a day in case you need to roll back.
🤖

Let AI do the grunt work. Hand an AI coding assistant a file and ask it to modernize it for PHP 8.4 and explain each change. It’s tedious, pattern-based work they do well. Just test the result before it goes live.

Your 15-minute checklist

  • Ask your host if your server is patched, or check its status page
  • Run phpinfo on one live site; check Version and Build Date
  • Delete the phpinfo file
  • Run php -v and which -a php on your computer
  • Update every local PHP: Homebrew, MAMP, Herd, Docker
  • Restart your local web server and re-check phpinfo
  • Stop local servers and tunnels you aren’t using
  • Check any VPS or Raspberry Pi you’ve forgotten about
  • List scripts still on PHP 5 or 7 and schedule the upgrade
  • Bookmark your host’s status page for next time
Your host has your back on the server. Your own machines are on you.

Sources

SolarBlu
Scroll to Top