To run CakePHP on cloud hosting you need four things: PHP 8.2 or newer with the intl, mbstring, pdo and simplexml extensions, Composer, SSH access, and a document root you can point at the app’s webroot directory. Any host that gives you those will run CakePHP 5 comfortably.
composer create-project --prefer-dist cakephp/app:~5.0 myapp, point the web server at myapp/webroot, set your database credentials in config/app_local.php, then run bin/cake migrations migrate and make tmp/ and logs/ writable. Shared hosting that locks the document root to public_html is the one setup worth avoiding.CakePHP 5.4 landed in July 2026 and the whole 5.x line requires PHP 8.2 as a hard minimum, with 8.3 and 8.4 both fine in production. That matters because a lot of cheap hosting is still shipping PHP 8.1 as a default. This guide assumes you can open a terminal, you know roughly what a web server virtual host is, and you would rather understand the deploy than click a one-click installer and hope.
What CakePHP actually needs from a host
CakePHP is not demanding, but it is specific. The framework’s own composer.json declares hard dependencies on ext-intl, ext-json and ext-mbstring, and the documentation adds PDO and SimpleXML on top. Composer refuses to install if the platform check fails, which is actually helpful — you find out at deploy time rather than in production.
| Requirement | What to look for | Why it matters |
|---|---|---|
| PHP version | 8.2 minimum, 8.3 or 8.4 preferred | CakePHP 5.x will not install on 8.1 or older |
| intl | Enabled, not just present | Used for i18n, number and date formatting; a hard dependency |
| mbstring, json | Enabled | String handling and serialization throughout the core |
| pdo + driver | pdo_mysql or pdo_pgsql | The ORM talks to the database through PDO only |
| simplexml | Enabled (Debian/Ubuntu ship it in php-xml) | XML view classes and several plugins expect it |
| Composer 2 | Available over SSH | There is no zip-and-upload install path for CakePHP 5 |
| Writable tmp/ and logs/ | Owned or group-writable by the PHP-FPM user | Cache, sessions and the log files all live here |
| Configurable document root | Ability to set it to a subdirectory | Everything outside webroot must stay unreachable |
Database support is broad: MySQL 5.7+, MariaDB 10.1+, PostgreSQL 9.6+, SQL Server 2012+ and SQLite 3 all work out of the box. Almost every cloud host gives you MySQL 8 or MariaDB 10.11, so this is rarely the constraint.
Why the document root must point at /webroot
A CakePHP project is a directory with src/, config/, vendor/, tmp/, logs/ and a single public folder called webroot/. Only webroot/ contains a front controller. The official docs are blunt about it: for Apache you set DocumentRoot /cake_install/webroot, and for Nginx the example server block uses root /var/www/example.com/public/webroot;.
If you point the document root at the project root instead, two bad things happen. Your config/app_local.php becomes fetchable over HTTP the moment PHP stops executing (a bad deploy, a misconfigured handler), and /vendor/ is exposed to anyone scanning for known vulnerable packages.
webroot/ up into public_html/ and edit the two require paths in index.php, or you can add a rewrite rule in public_html/.htaccess that forwards every request into myapp/webroot/. Both work. Both leave the rest of the app one server misconfiguration away from being readable. If you have the choice, change hosts instead.The three hosting shapes that actually work
Almost every real CakePHP deployment falls into one of three buckets. The honest answer to “which is best” is that it depends on whether you would rather pay money or spend evenings.
| Shape | Examples | You manage | Effort | Best for |
|---|---|---|---|---|
| Managed PHP platform | Cloudways (now part of DigitalOcean), Ploi, RunCloud | The app, the webroot setting, the PHP version | Low | Small teams that want SSH and deploy hooks but no sysadmin work |
| Raw VPS you configure | DigitalOcean Droplet, Hetzner, Vultr, Linode | Everything: OS, Nginx, PHP-FPM, MySQL, TLS, backups | Medium to high | Custom extensions, non-standard stacks, lowest cost per GB of RAM |
| PaaS / containers | Fly.io, Platform.sh, your own Kubernetes cluster | A Dockerfile and config as code; the platform runs it | Medium | Multiple environments, CI-driven deploys, horizontal scaling |
On price, Cloudways’ Flexible plans start at $11 per month for a 2 GB DigitalOcean server, and Ploi’s Basic tier is EUR 8 per month on top of whatever you pay your own cloud provider. A managed platform is the shortest route if CakePHP is the only thing you are hosting; I have written up the full walkthrough for installing CakePHP on Cloudways separately because the webroot handling there has a specific quirk.
The container route is worth it once you have more than two environments to keep in sync. If you are trying it for the first time, building the chart locally is a cheap way to learn the moving parts — our guide to installing Helm in Minikube covers the local cluster half of that.
Step 1: Provision the server and install the stack
Start with a current Ubuntu LTS image and at least 1 GB of RAM (2 GB if MySQL runs on the same box). Then install Nginx, PHP-FPM and the extensions CakePHP needs. Swap the PHP version number for whatever your release ships, or add the ondrej/php PPA if you need to pin one.
sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx mysql-server unzip git curl
sudo apt install -y php8.3-fpm php8.3-intl php8.3-mbstring php8.3-xml php8.3-mysql php8.3-curl php8.3-zip
php -m | grep -E 'intl|mbstring|SimpleXML|pdo_mysql'That last line is the check that saves you an hour later. If intl does not appear, nothing downstream will work. Install Composer next, following the signature-verified installer on the official Composer download page rather than a copy-pasted one-liner from a forum.
Step 2: Create the project and install dependencies
cd /var/www
sudo mkdir -p example.com && sudo chown $USER:$USER example.com
composer create-project --prefer-dist cakephp/app:~5.0 example.com/appOn a production box you normally deploy from Git rather than scaffolding in place. In that case clone the repo and install without dev dependencies, which skips PHPUnit, DebugKit and the code sniffer:
cd /var/www/example.com/app
composer install --no-dev --optimize-autoloader --no-interactioncomposer.lock and never run composer update on the server. --no-dev plus a committed lock file is what makes two deploys of the same commit produce identical vendor/ trees.Step 3: Write the Nginx server block
Create /etc/nginx/sites-available/example.com. Note the root line ends in /webroot — that is the whole trick.
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/app/webroot;
index index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~* /(config|src|tmp|logs|vendor)/ {
deny all;
}
}Enable it and reload:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginxStep 4: Create the database and configure the app
Create a database and a dedicated user, then put the credentials in config/app_local.php. CakePHP splits config deliberately: app.php holds settings that do not vary by environment and is committed, while app_local.php holds per-environment values and is not.
sudo mysql -e "CREATE DATABASE cakeapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
sudo mysql -e "CREATE USER 'cakeuser'@'localhost' IDENTIFIED BY 'a-long-random-password';"
sudo mysql -e "GRANT ALL PRIVILEGES ON cakeapp.* TO 'cakeuser'@'localhost'; FLUSH PRIVILEGES;"
cp config/app_local.example.php config/app_local.phpBoth config files read values through the env() helper, so you can keep secrets out of files entirely and set them in the PHP-FPM pool or systemd unit instead. If you prefer a dotenv file, copy config/.env.example to config/.env, install josegonzalez/dotenv, and add it to your ignore list. Do not ship a dotenv file to production with DEBUG=true in it.
Step 5: Run migrations, fix permissions, clear cache
The app skeleton ships with the cakephp/migrations plugin already required, so the migration command is available immediately.
bin/cake migrations migrate
bin/cake migrations status
sudo chown -R $USER:www-data tmp logs
sudo find tmp logs -type d -exec chmod 775 {} +
sudo find tmp logs -type f -exec chmod 664 {} +
bin/cake cache clear_allLoad the site. You should get the CakePHP welcome page with green check marks next to the database connection. Every subsequent deploy is the same four commands: pull, composer install --no-dev, migrations migrate, cache clear_all.
Step 6: Queue workers and cron
Anything slow — outbound email, image processing, third-party API calls — belongs in a queue. The official plugin is cakephp/queue, and its worker runs as a long-lived process:
composer require cakephp/queue
bin/cake plugin load Cake/Queue
bin/cake queue workerDo not run that in a screen session and call it done. Give it a systemd unit so it restarts on failure and on reboot. A minimal unit file at /etc/systemd/system/cake-worker.service needs ExecStart=/usr/bin/php /var/www/example.com/app/bin/cake queue worker, User=www-data, Restart=always, and WantedBy=multi-user.target. Managed platforms usually expose the same thing as a Supervisor entry in their UI.
Scheduled work is plain cron calling a CakePHP command. Add it to the web user’s crontab so file ownership stays consistent:
*/5 * * * * cd /var/www/example.com/app && /usr/bin/php bin/cake my_nightly_task >> logs/cron.log 2>&1Production hardening you should not skip
Four settings separate a working CakePHP site from a safe one.
- Set debug to false. In
config/app_local.php,'debug' => filter_var(env('DEBUG', false), FILTER_VALIDATE_BOOLEAN). With debug on, an exception page prints your stack trace, file paths and often query parameters. - Generate a real Security.salt. The skeleton writes a random one at create-project time, but cloned repos and copied config files carry the same value everywhere. Set it per environment from an environment variable and treat it like a password.
- Force HTTPS. Issue a certificate with certbot, then enable CakePHP’s own redirect by adding
$middlewareQueue->add(new HttpsEnforcerMiddleware(['redirect' => true]))insrc/Application.php. Doing it in the app as well as the web server means a future vhost change cannot silently drop TLS. - Keep secrets out of the document root. Verify it:
curl -I https://example.com/config/app_local.phpmust return 404, not 200 or 403.
Troubleshooting the four failures you will actually hit
White screen, no error, HTTP 500
PHP died before CakePHP’s error handler loaded. Look at /var/log/nginx/error.log and the PHP-FPM log, not logs/error.log. In order of likelihood: vendor/autoload.php is missing because composer install never ran, a required extension is missing, or tmp/ is unwritable so the cache write fatals.
“You must enable the intl extension to use CakePHP”
Exactly what it says. Install the package (php8.3-intl on Debian and Ubuntu) and restart PHP-FPM, not just Nginx. A very common trap: the CLI and the FPM pool load different php.ini files, so php -m can show intl while the website still cannot see it. Confirm with a one-line phpinfo page, then delete the page.
Homepage works, every other route 404s
URL rewriting is not reaching index.php. On Nginx the try_files line in Step 3 is what fixes it. On Apache you need AllowOverride All for the directory and mod_rewrite enabled, otherwise the .htaccess file CakePHP ships is ignored entirely.
Permission errors on tmp/ and logs/
This is almost always caused by running bin/cake as root or as your own user, which leaves root-owned cache files that www-data then cannot overwrite. Fix the ownership, then stop creating the problem: run CLI commands as the web user with sudo -u www-data bin/cake .... Setting the setgid bit on those directories (chmod g+s tmp logs) keeps the group correct for anything created later.
Frequently asked questions
Can I run CakePHP on shared hosting?
Sometimes, but check two things first: PHP 8.2 or newer, and whether you can set the document root to a subdirectory. Many shared plans allow both through cPanel’s domain settings. If the host also gives you SSH for Composer, shared hosting is workable for a small site. Without SSH it is not.
What PHP version should I use for CakePHP 5?
PHP 8.3 is the safe default in 2026 — well supported by extensions and by every managed host. PHP 8.2 is the minimum for CakePHP 5.x and 8.4 is supported. Avoid being first to a brand-new PHP release in production; wait until your key composer packages declare support.
Do I need Nginx or is Apache fine?
Both are fine. Apache is slightly easier because CakePHP ships working .htaccess files, so a correct DocumentRoot plus mod_rewrite gets you running. Nginx needs the try_files rule written by hand but uses less memory per connection on small servers.
How do I add full-text search to a CakePHP app?
Start with your database’s own full-text index. If you outgrow it, add a search engine as a separate service on the same private network. Our guide to installing Elasticsearch on Cloudways covers the RAM sizing and the localhost-only binding, which are the two things people get wrong.
Should I use a control panel on my VPS?
If you are managing more than two or three sites, yes — a panel handles vhosts, TLS renewal and PHP versions for you. Something like CyberPanel on a Hostinger VPS gives you that without a monthly platform fee, at the cost of one more piece of software to keep patched.
Wrapping up
The mechanics of running CakePHP on cloud hosting come down to one decision and one detail. The decision is how much server administration you want to own: a managed PHP platform for the least, a raw VPS for the most control and the lowest bill, containers when you have several environments to keep identical. The detail is the document root, and it is non-negotiable — webroot is public, everything else is not.
If you are starting fresh today, I would take a 2 GB VPS with Ubuntu LTS, PHP 8.3, Nginx and the server block above. It is roughly an hour of work, it costs less than a managed plan, and you learn where every file lives — which is exactly the knowledge you need at 2 a.m. when the queue worker has stopped. Verify the requirements against the official CakePHP installation docs before you provision, since the minimum PHP version moves with each major release.

