Laravel & FrankenPHP: Application Deployment

The Architecture Rationale

A standard PHP-FPM and Nginx configuration compiles and tears down the entire application life cycle with every single incoming HTTP request. For high-traffic, real-time applications, this process introduces unnecessary latency and CPU overhead.

To achieve maximum throughput and sub-millisecond response times, I engineered a high-performance Debian Linux LXC built around Laravel Octane and FrankenPHP (a state-of-the-art PHP server built on Caddy). By keeping the application in memory (worker mode) and managing real-time processes with Supervisor, this architecture optimizes resource usage and consolidates five crucial services under a single, isolated execution layer.

Phase 1: Consolidated Provisioning & Runtimes

To automate the setup and maintain a clean system, I use a custom deployment script. This automation updates the Debian system, registers the required PHP 8.4 binaries and production extensions, provisions Node.js, and installs crucial system tools for asset optimization and headless browser execution (used for PDF generation or web scraping).

Bash

nano install-laravel.sh
chmod +x install-laravel.sh
sudo ./install-laravel.sh

The Deployment Script

This script performs a full, hands-free installation of the required system packages, composer dependencies, system utilities, and application runtimes:

Bash

#!/bin/bash
set -euo pipefail

APP_DIR="$HOME/app"
SSH_KEY="$HOME/.ssh/github_deploy"
SUPERVISOR_DIR="/etc/supervisor/conf.d"

# 1. Capture Private Key silently for secure Git cloning
if [ ! -f "$SSH_KEY" ]; then
    echo "Paste your GitHub deployment private key (press ctrl+D):"
    cat > "$SSH_KEY"
    chmod 600 "$SSH_KEY"
fi

# 2. Register PHP 8.4 & Production Extensions
apt update
apt install -y \
  php8.4 php8.4-cli php8.4-common php8.4-fpm php8.4-curl php8.4-mbstring \
  php8.4-xml php8.4-zip php8.4-mysql php8.4-gd php8.4-intl php8.4-bcmath \
  php8.4-readline php8.4-sqlite3 php8.4-imagick \
  ca-certificates apt-transport-https curl lsb-release supervisor git wget unzip gnupg2 imagemagick  

# 3. Provision Node.js (v25) Runtime environment
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
\. "$HOME/.nvm/nvm.sh"
nvm install 25

# 4. Install Image Optimization utilities & Puppeteer dependencies
apt install -y jpegoptim optipng pngquant gifsicle libavif-bin
npm install -g svgo puppeteer
npx puppeteer browsers install chrome

# (Install required system libraries for headless Chromium sandbox environment)
apt install -y libx11-xcb1 libxcomposite1 libasound2t64 libatk1.0-0 libatk-bridge2.0-0 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1-0 CORES... [Complete headless bundle mapped]

Phase 2: Secure Repository Synchronization & Seeding

The script establishes a secure SSH bridge to GitHub using an isolated, non-default SSH configuration file to prevent permission crossover with other system resources:

Bash

# Registering specific SSH mapping config
cat >> "$HOME/.ssh/config" <<EOL
Host github_deploy
  HostName github.com
  User git
  IdentityFile $SSH_KEY
EOL

# Clone or securely pull the codebase
if [ -d "$APP_DIR"/.git ]; then
    cd "$APP_DIR" && git pull
else
    git clone github_deploy:username/repository.git "$APP_DIR"
fi

Once pulled, database migrations, configuration caching, and production asset compilation (Vite) are triggered automatically:

Bash

# Securely write the environment parameters passed via the interactive shell
cat > "$APP_DIR"/.env

# Build optimized production dependencies
composer install --no-dev --prefer-dist --optimize-autoloader
npm install --force && npm run build

# Seed cache states
php artisan storage:link
php artisan migrate --force
php artisan optimize

Phase 3: Process Orchestration via Supervisor

To keep the application running continuously, I utilize Supervisor to manage and monitor five distinct daemons:

Bash

# Require Laravel Octane to prepare the FrankenPHP bridge
composer require laravel/octane
php artisan octane:install --server=frankenphp

I configure Supervisor to run the following five background services, each with distinct performance targets:

1. HTTP Server (Laravel Octane & FrankenPHP)

Keeps the PHP application booted in-memory across dedicated worker processes to bypass traditional file-reading overhead on every request.

Ini, TOML

[program:laravel-octane]
command=php artisan octane:start --server=frankenphp --host=127.0.0.1 --port=8000 --workers=2 --max-requests=1000
directory=/root/app
autostart=true
autorestart=true
user=root
stdout_logfile=/root/app/storage/logs/octane.log

2. High-Priority Async Queue Worker

Processes background events (such as emails, transaction records, and file uploads) asynchronously without blocking user requests.

Ini, TOML

[program:laravel-queue]
command=php artisan queue:work --queue=high,default --sleep=3 --tries=3
directory=/root/app
autostart=true
autorestart=true
user=root
stdout_logfile=/root/app/storage/logs/queue.log

3. Continuous Cron Task Scheduler

Handles automated cron-like scheduling entirely within the framework loop.

Ini, TOML

[program:laravel-scheduler]
command=php artisan schedule:work
directory=/root/app
autostart=true
autorestart=true
user=root
stdout_logfile=/root/app/storage/logs/scheduler.log

4. Real-Time WebSockets Daemon (Laravel Reverb)

Manages real-time data streaming (like active dashboard updates or messaging components) over extremely fast, low-overhead WebSocket tunnels.

Ini, TOML

[program:laravel-reverb]
command=php artisan reverb:start --host=0.0.0.0 --port=8080
directory=/root/app
autostart=true
autorestart=true
user=root
stdout_logfile=/root/app/storage/logs/reverb.log

5. Inertia Server-Side Rendering (SSR) Engine

Pre-renders complex Vue or React components on the server for faster initial page loads and better search engine visibility.

Ini, TOML

[program:laravel-inertiaSSR]
command=php artisan inertia:start-ssr
directory=/root/app
autostart=true
autorestart=true
user=root
# Explicitly inject the specific node runtime directory into the environment path
environment=PATH="/root/.nvm/versions/node/v25.8.1/bin:/usr/local/bin:/usr/bin:/bin"
stdout_logfile=/root/app/storage/logs/inertiaSSR.log

Phase 4: Committing Process Controls

With the configuration blocks stored in /etc/supervisor/conf.d/, we reload the Supervisor process tree and bring up our services:

Bash

# Inform Supervisor of configuration changes and update processes
supervisorctl reread
supervisorctl update

# Verify that all 5 application nodes are healthy and running
supervisorctl status

Architectural Comparison

ParameterTraditional FPM + NginxOctane + FrankenPHP (LXC)
Boot CycleRestarts the framework on every requestKeeps application booted in-memory (persistent state)
I/O OverheadHigh (Disk reading and compiling PHP scripts)Zero (In-memory execution)
WebSockets IntegrationRequires external servers (e.g., Pusher, Socket.io)Native, integrated via Laravel Reverb
Process ControlHandled loosely across system unitsStandardized and unified under Supervisor