
Boost Laravel Performance: Running Octane with FrankenPHP in Production ( Zero downtime)
Posted by
kamlesh paulon
Dec 9, 2024| 5 min read
Last updated on : Dec 9, 2024
Are you looking to make your Laravel application blazing fast? With Laravel Octane and FrankenPHP, you can significantly speed up your app by running everything in memory, avoiding the overhead of bootstrapping the app repeatedly.
Laravel Octane makes your application stateful, meaning your app doesn’t need to rebuild everything for every request. Combined with FrankenPHP, a PHP-based web server built on Caddy, you can eliminate reverse proxies and serve PHP applications with unparalleled performance.
Table of contents
- Why FrankenPHP?
- Step 1: Install Laravel Octane and FrankenPHP
- Step 2: Test Locally
- Step 3: Run in Production
- Step 4: Customize FrankenPHP with a Caddyfile
- Step 5: Keep Octane Running with Supervisor
- Step 6: Extend PHP Extensions
- Step 7: Create a Deployment Script
- Conclusion
Why FrankenPHP?
FrankenPHP is a custom-built Caddy server designed for PHP applications. It lets you run your Laravel application efficiently without a reverse proxy, giving you direct control over performance.
Step 1: Install Laravel Octane and FrankenPHP
- Start by installing Laravel Octane via Composer:
composer require laravel/octane
- Next, install Octane with the FrankenPHP server option:
php artisan octane:install --server=frankenphp
This will download and configure the necessary files for FrankenPHP.
Step 2: Test Locally
- To test the setup on your local environment, run:
php artisan octane:start
This starts the server on localhost
. But in production, you’ll need to run it with your domain.
Step 3: Run in Production
- For production environments, run the following command to start the server with your domain:
php artisan octane:start --host=example.com
- However, this will start without HTTPS. To enable HTTPS and run on port 443, use:
php artisan octane:start --host=example.com --port=443 --https --admin-port=8000
This will run the server with your domain name and HTTPS, eliminating the need for a reverse proxy, making your app faster.
Step 4: Customize FrankenPHP with a Caddyfile
For optimal performance, you can configure FrankenPHP using a custom Caddyfile
. Place your Caddyfile
in the specified path, which should match the --caddyfile
flag used in the Supervisor configuration.
Here’s Caddyfile
with necessary headers and configurations:
{
{$CADDY_GLOBAL_OPTIONS}
admin localhost:{$CADDY_SERVER_ADMIN_PORT}
frankenphp {
worker "{$APP_PUBLIC_PATH}/frankenphp-worker.php" {$CADDY_SERVER_WORKER_COUNT}
}
}
{$CADDY_SERVER_SERVER_NAME} {
log {
level {$CADDY_SERVER_LOG_LEVEL}
# Redact the authorization query parameter that can be set by Mercure...
format filter {
wrap {$CADDY_SERVER_LOGGER}
fields {
uri query {
replace authorization REDACTED
}
}
}
}
route {
root * "{$APP_PUBLIC_PATH}"
encode zstd br gzip
# Mercure configuration is injected here...
{$CADDY_SERVER_EXTRA_DIRECTIVES}
@static {
file
path *.js *.css *.jpg *.jpeg *.gif *.png *.ico *.cur *.gz *.svg *.svgz *.mp4 *.mp3 *.ogg *.ogv *.webm *.htc *.woff2 *.woff
}
@staticshort {
file
path *.json *.xml *.rss
}
header {
# keep referrer data off of HTTP connections
Referrer-Policy "no-referrer-when-downgrade"
# enable HSTS
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Enable cross-site filter (XSS) and tell the browser to block detected attacks
X-Xss-Protection "1; mode=block"
# disable clients from sniffing the media type
X-Content-Type-Options "nosniff"
# clickjacking protection
X-Frame-Options "SAMEORIGIN"
# Upgrade insecure requests
Content-Security-Policy "upgrade-insecure-requests"
# Caching directives
# 1 year, similar to h5bp nginx config
@static Cache-Control "public, immutable, stale-while-revalidate, max-age=31536000"
# 1 hour max, gets validated with the origin server
@staticshort Cache-Control "no-cache, max-age=3600"
}
# Restrict access to dot files and certain file extensions
@rejected `path('*.bak', '*.conf', '*.dist', '*.fla', '*.ini', '*.inc', '*.inci', '*.log', '*.orig', '*.psd', '*.sh', '*.sql', '*.swo', '*.swp', '*.swop', '*/.*') && !path('*/.well-known/')`
error @rejected 401
php_server {
index frankenphp-worker.php
# Required for the public/storage/ directory...
resolve_root_symlink
}
}
}
This configuration ensures that your Laravel application is secure, fast, and efficient, with caching headers and security policies.
Ref link https://caddy.community/t/tweaking-frakenphp-caddyfile-for-laravel-octane/23926
Step 5: Keep Octane Running with Supervisor
In production, you’ll need to ensure Laravel Octane keeps running even after closing the terminal. This is where Supervisor comes in.
- Install Supervisor:
sudo apt-get install supervisor
- Create a new configuration file for Laravel Octane:
sudo nano /etc/supervisor/conf.d/laravel-octane.conf
Add the following configuration to keep Octane running:
[program:laravel-octane]
command=php /home/laravel/artisan octane:start
--host=example.com
--port=443
--https
--admin-port=2019
--workers=4 # Adjust based on your CPU count
--max-requests=1000
--caddyfile=/home/laravel/Caddyfile
stdout_logfile=/var/log/supervisor/laravel-octane.log
environment=HOME="/home/laravel"
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=your-actual-username # Ensure this is a valid username
redirect_stderr=true
stopwaitsecs=3600
To optimize performance, check your server’s
CPU count
and adjust the--workers
parameter accordingly. A common practice is to set the number of workers to the number of CPU cores available, allowing your application to handle multiple requests simultaneously without overloading the server.
- Next, reload the Supervisor configurations:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-octane
Step 6: Extend PHP Extensions
If you need additional PHP extensions that are not included by default, you can create the FrankenPHP binary from the FrankenPHP documentation. Follow the instructions provided to compile your custom binary, which you can place in the root of your project and use to enable any extra extensions your application may require.
Step 7: Create a Deployment Script
To streamline your deployment process, you can create a script that ensures everything is built for production and restarts Laravel Octane every time you make changes to your live server.
#!/bin/bash
set -e
echo "Deployment started ..."
# Pull the latest version of the app
git pull origin main
# Install composer dependencies
composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader
# Clear the old cache
php artisan clear-compiled
# Recreate cache
php artisan optimize
# Run database migrations
php artisan migrate --force
php artisan octane:reload
echo "Deployment finished!"
- To run this script:
Make it executable and then execute it:
chmod +x deploy.sh
./deploy.sh
This script ensures that your application is updated with the latest changes, optimized for production, and that Laravel Octane is restarted.
Conclusion
By leveraging Laravel Octane with FrankenPHP, you’re taking full advantage of memory-resident processes and eliminating unnecessary reverse proxies. This results in a highly optimized and scalable application.
Enjoy your blazing-fast Laravel app.
Get updates directly to your inbox.
Join 500+ developers getting updates on Laravel & Next.js tips. No spam,
unsubscribe anytime.