PHP 5 can now safely be considered ancient technology. However, many businesses still depend on applications built with it, and some of those applications cannot be upgraded easily.

One project we inherited was built with an older version of the Zend Framework. Because of the framework’s architecture and dependencies, the typical approach of updating a few database calls and changing the PHP version was not realistic.

For many years, we already had server infrastructure running older versions of PHP and MySQL. Supporting the application was mostly a matter of keeping those servers operational.

Unfortunately, time remains undefeated. The physical hardware was beginning to fail, and rebuilding the application properly was going to take time. We needed a temporary solution that would move the application away from our aging dedicated servers without requiring an immediate rewrite.

Can You Still Purchase PHP 5 Hosting?

A few hosting companies still advertise support for PHP 5.

The first provider I selected was IONOS. Its website indicated that legacy PHP hosting was available, so I decided to give it a try.

After creating an account, I discovered that the legacy hosting environment could not be configured through the standard control panel. I had to contact support and order the service directly.

At first, everything appeared promising, and I informed the client that we probably had a workable solution.

However, while preparing the application and database for migration, I discovered that the oldest available MySQL version was MySQL 8. Our PHP 5 application relied on MySQL 5 behavior and an older Zend database layer.

That made the hosting plan far less practical than it initially appeared.

Approach 1: Use MariaDB 10

The hosting provider also offered MariaDB, which is often an easy replacement for MySQL.

MariaDB supports much of the same syntax for basic operations such as:

  • SELECT queries
  • INSERT statements
  • UPDATE statements
  • Table joins

In many applications, moving from MySQL to MariaDB only requires disabling strict mode and making a few database configuration changes.

However, our application used a very old version of the Zend Framework. We expected compatibility problems involving behavior that older versions of MySQL allowed but modern database systems handle differently.

Potential problems included:

  • Very loose GROUP BY behavior
  • Older implicit type conversions
  • Unusual date-handling behavior
  • Deprecated MySQL-specific functionality
  • Compatibility issues inside the legacy Zend Framework

Because our goal was to change as little code as possible, migrating the application to MariaDB did not appear to be the safest option.


Looking for PHP 5 and 7 Uprage Help? Firecane Digitial has the expertise you need!

PHP 5 Upgrades

Approach 2: Build a New Legacy Server in the Cloud

DigitalOcean is one of several cloud providers that allows customers to create highly customized virtual servers.

Our plan was to build a server that closely matched the original environment:

  • CentOS
  • Apache
  • MySQL 5
  • PHP 5
  • Zend Framework

Running an outdated operating system such as CentOS 6 or CentOS 7 is not secure and is strongly discouraged. However, we were dealing with a temporary legacy migration in which every available option involved some compromise.

Building a custom cloud server appeared to provide a clear path away from the failing physical hardware, even though it would require considerable setup work before we could begin migrating the application.

Approach 3: Move the Existing Virtual Machine to Azure

PHP, MySQL, and CentOS were not the only legacy components in our environment. The entire system was running on an old Microsoft Hyper-V platform.

Initially, we did not seriously consider moving the existing virtual machine directly into the cloud. After researching the available options, however, we discovered that Microsoft Azure provided several possible migration paths.

Method 1: Upload a VHD File

If a virtual machine can be exported as a VHD file, it may be possible to upload the disk directly to Azure.

The basic process is:

  1. Export or convert the virtual machine to a fixed-size VHD.
  2. Upload the VHD to Azure Storage.
  3. Create an Azure virtual machine using the uploaded disk.

Azure generally requires a fixed-size VHD rather than a dynamic VHD or VHDX file.

Method 2: Use Azure Migrate

Azure Migrate is Microsoft’s official migration platform and is often the easier option for supported environments.

It can:

  • Replicate an existing virtual machine to Azure
  • Assist with disk conversion
  • Allow testing before the final migration
  • Reduce the amount of manual configuration required

The typical process is:

  1. Install the Azure Migrate appliance.
  2. Connect it to the existing Hyper-V or VMware host.
  3. Replicate the virtual machine.
  4. Test the migrated system.
  5. Complete the final cutover.

This approach can eliminate many of the manual conversion steps involved in uploading a virtual disk directly.

What We Tried

I decided not to continue with the MariaDB approach. Ideally, we wanted to touch as little of the application code as possible.

Instead, I created a DigitalOcean account and attempted to build a custom Droplet.

The first problem was that DigitalOcean no longer provided the old CentOS version we needed as a standard operating system option. To use it, we would have to create and upload a custom server image.

The proposed process was:

  1. Download a CentOS installation image from an archive or mirror.
  2. Install CentOS inside VirtualBox.
  3. Configure the legacy LAMP stack.
  4. Export or convert the virtual disk into a format DigitalOcean would accept.
  5. Upload the custom image and create a Droplet from it.

My first attempt failed because I was using a Mac with Apple silicon. Running and exporting the required older x86 environment was more complicated than expected.

I then moved the project to a low-end Windows laptop. I struggled to create and mount the virtual disks properly, and the laptop was too slow to make the process practical.

After more research, I found a utility that could convert Hyper-V virtual disks into VMware-compatible files or the QCOW2 format used by many cloud platforms.

The utility was qemu-img. Instructions for installing and using it are available in this qemu-img installation guide.

After multiple conversion attempts, I created an image file that was approximately 20 GB. Unfortunately, DigitalOcean repeatedly rejected the upload, and the error messages did not provide enough information to identify the problem.

At that point, I abandoned the DigitalOcean plan and returned to Microsoft Azure.

Approach 4: Run Hyper-V Inside an Azure Virtual Machine

Our next idea was to create an older Windows Server virtual machine in Azure, enable Hyper-V inside it, and then run our existing legacy virtual machine within that environment.

This is known as nested virtualization.

Nested virtualization is not an ideal permanent solution. It adds additional overhead, can reduce performance, and leaves the application running on unsupported software. However, we were looking for a temporary bridge that would keep the application operating while a replacement was developed.

The first obstacle was Azure’s processor quota. Many of the suitable Azure virtual machine sizes required at least two virtual processors. I had to contact Azure support and wait for our quota to be increased before I could create the required machine.

The next problem was selecting an Azure VM family that supported nested virtualization.

I initially selected a lower-cost VM size and created the server. When I attempted to enable Hyper-V, Windows displayed an error indicating that Intel VT-x or AMD-V virtualization support was required.

I eventually learned that not every Azure VM family supports nested virtualization. I created a new VM using a compatible E-series configuration, enabled Hyper-V, and was finally able to start the legacy virtual machine.

The Virtual Machine Started, but We Could Not Log In

After the virtual machine booted, we were unable to log in.

At first, I assumed that we had forgotten the root username or password. The system had been created many years earlier, so that seemed entirely possible.

To test the theory, I uploaded another virtual machine whose credentials and IP configuration were known. That machine experienced the same problem.

After more research, I discovered that older Linux virtual machines may require several packages and an Azure Linux agent before they can operate correctly in Azure. Network and login problems can be symptoms of a machine that has not been prepared for the Azure environment.

The required update commands appeared straightforward. Unfortunately, when I attempted to run them, the original CentOS YUM repositories were no longer available.

Because the operating system had reached end of life, many of its normal package mirrors had been removed.

I found instructions for modifying the repository configuration so that YUM would use archived CentOS repositories. We also could have downloaded and installed the required packages manually.

By that point, however, the project had consumed too much time. Every solution created another compatibility problem, and we were still relying on an unsupported operating system.

Approach 5: Put the Legacy Application in a Docker Container

After trying several less-than-ideal approaches, I finally asked our senior Linux administrator and developer what he considered the best solution.

His recommendation was not to recreate the entire legacy server environment.

Instead, we moved the application and its required dependencies into a Docker container. The container could then run on a modern cloud hosting platform without requiring the entire host server to use an outdated operating system.

This approach allowed us to preserve the PHP 5 application environment while moving the underlying infrastructure to a modern platform.

It was still a temporary solution. PHP 5 remains unsupported, and the application will eventually need to be rebuilt or substantially upgraded. However, containerizing the application gave us a practical bridge between failing physical hardware and a complete application rewrite.

Lessons Learned from Migrating a PHP 5 Application

The biggest lesson was that supporting a legacy application involves much more than finding a server that can run an old PHP version.

The entire technology stack matters:

  • PHP version
  • Database version
  • Framework dependencies
  • Operating system
  • Package repositories
  • Virtualization platform
  • Networking configuration
  • Cloud provider requirements

A hosting company may advertise PHP 5 support, but that does not necessarily mean it can reproduce the database behavior, operating system, framework dependencies, or server configuration required by a specific application.

Building an entirely new legacy server is possible, but it can involve significant security, compatibility, and maintenance problems.

For our application, Docker provided the most practical short-term solution. It allowed us to isolate the outdated software while using a modern hosting platform underneath it.

The long-term answer is still to rebuild the application. However, containerization gave us the time needed to plan that rebuild without depending on hardware that could fail at any moment.