For years, the gold standard for Laravel deployment has been the Nginx + PHP-FPM stack. While reliable, it involves multiple moving parts and communication overhead.
Enter FrankenPHP. Built on top of the Caddy web server, FrankenPHP is a modern PHP application server that supports HTTP/2, HTTP/3, and "Worker Mode" natively. When paired with Laravel Octane, it keeps your application in memory, eliminating the need to boot the framework on every request and resulting in staggering performance gains.
This guide will walk you through deploying a production-ready Laravel environment on an Ubuntu 24.04 VPS.
Why Choose FrankenPHP over Nginx?
Single Binary: No need to manage separate Nginx and PHP-FPM services.
Worker Mode: Keeps Laravel "booted" in RAM for millisecond response times.
Automatic SSL: Built-in Caddy integration handles Let's Encrypt certificates automatically.
Modern Protocols: Native support for 103 Early Hints and HTTP/3.
Step 1: Server Preparation
SSH into your VPS and ensure your system is up to date.
sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl unzip software-properties-commonStep 2: Install FrankenPHP Binary
We will download the static FrankenPHP binary, which contains its own optimized PHP environment.
cd ~
curl -L https://github.com/dunglas/frankenphp/releases/latest/download/frankenphp-linux-x86_64 -o frankenphp
chmod +x frankenphp
sudo mv frankenphp /usr/local/bin/frankenphpStep 3: Install PHP CLI and Composer
Even though FrankenPHP handles the web requests, you still need the PHP CLI on your server to run migrations, artisan commands, and Composer.
sudo apt install -y php8.3-cli php8.3-curl php8.3-mbstring php8.3-xml php8.3-zip php8.3-sqlite3 php8.3-bcmath php8.3-intl
# Install Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composerStep 4: Deploy Your Application
Navigate to your web directory and set up your project.
sudo mkdir -p /var/www
sudo chown $USER:www-data /var/www
cd /var/www
git clone https://github.com/your-repo/laravel-app.git .
composer install --no-dev --optimize-autoloaderEssential Permissions
For FrankenPHP to serve your files safely, the www-data user must own the project.
sudo chown -R www-data:www-data /var/www
sudo chmod -R 775 storage bootstrap/cacheStep 5: Configure Laravel Octane
Octane is the bridge that allows Laravel to run inside the FrankenPHP worker.
Install Octane:
composer require laravel/octaneInstall the Driver:
php artisan octane:install --server=frankenphpOptimize:
php artisan optimize
Step 6: Create the Systemd Service
To ensure your API stays online 24/7 and restarts after a server reboot, create a systemd service.
sudo nano /etc/systemd/system/frankenphp.service
Paste the following configuration:
[Unit]
Description=FrankenPHP Laravel Octane Server
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www
# We use port 8000 here; use 80/443 if you have no other web server
ExecStart=/usr/local/bin/frankenphp php-server --port=8000 --root-dir=/var/www/public
# Alternatively, if using Octane's worker mode:
# ExecStart=/usr/bin/php /var/www/artisan octane:start --server=frankenphp --host=0.0.0.0 --port=8000
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.targetActivate the service:
sudo systemctl daemon-reload
sudo systemctl enable frankenphp
sudo systemctl start frankenphpStep 7: Finalizing the Network
If you are using AWS, DigitalOcean, or Azure, ensure your Security Groups or Firewall allow traffic on port 8000.
Production Maintenance Checklist
When you push new code to your server, follow this sequence to avoid downtime or stale caches:
Pull latest code:
git pullUpdate dependencies:
composer install --no-devRun migrations:
php artisan migrate --forceClear/Rebuild cache:
php artisan optimizeRestart Octane:
sudo systemctl restart frankenphp
Troubleshooting FAQ
Q: I get "Permission Denied" on the logs. A: Ensure the www-data user has write access to your storage folder and your database file (if using SQLite).
Q: My changes aren't appearing on the site. A: Because Octane keeps the app in memory, it doesn't "see" code changes automatically. You must restart the service (systemctl restart frankenphp) for code changes to take effect.
Q: How do I enable HTTPS? A: If you point your domain directly to the VPS and run FrankenPHP on port 80/443, it will automatically provision a Let's Encrypt SSL certificate for you.









