Deploying with FrankenPHP
Deploying with FrankenPHP
FrankenPHP is the recommended web server for deploying Hazaar Framework applications in production. Built on top of the Caddy web server and written in Go, FrankenPHP provides exceptional performance, modern features, and seamless PHP integration.
Why FrankenPHP?
- Superior Performance: Built-in worker mode keeps your application in memory for dramatic performance gains
- Modern Protocol Support: Native HTTP/2, HTTP/3, and Early Hints support
- Automatic HTTPS: Built-in automatic HTTPS with Let's Encrypt
- Simple Configuration: Minimal configuration required compared to traditional setups
- Production Ready: Powers the Hazaar API platform and other high-traffic applications
Prerequisites
Before deploying with FrankenPHP, ensure you have created a Hazaar application. See the Getting Started guide for installation instructions.
For containerized deployments with Docker, see the Docker deployment guide.
Installation
Download FrankenPHP
Download the latest FrankenPHP binary for your system from the official releases page.
For Linux x86_64:
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/Verify the installation:
frankenphp versionAlternative: Build from Source
If you need custom PHP extensions or specific configurations, you can build FrankenPHP from source. See the FrankenPHP documentation for detailed instructions.
Basic Configuration
FrankenPHP can run with minimal configuration. The simplest setup uses a Caddyfile to configure your application.
Create a Caddyfile in your application root directory:
{
frankenphp
}
localhost:8080 {
root * /home/user/myapp/public
encode gzip
php_server
}Key directives:
root- Points to your application'spublicdirectoryencode gzip- Enables compressionphp_server- Enables PHP processing with sensible defaults
Start FrankenPHP:
frankenphp runYour application is now available at http://localhost:8080.
Production Configuration
For production deployments, use a more comprehensive configuration with automatic HTTPS:
{
frankenphp {
num_threads {env.CADDY_NUM_THREADS}
}
}
myapp.example.com {
root * /home/user/myapp/public
encode gzip
# PHP configuration
php_server {
env APPLICATION_ENV production
}
# Security headers
header {
Strict-Transport-Security "max-age=31536000;"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
}
# Logging
log {
output file /var/log/frankenphp/access.log
}
}Key features:
- Automatic HTTPS via Let's Encrypt (just use your domain name)
- Environment variables for PHP
- Security headers
- Access logging
Running as a Service
For production deployments, configure FrankenPHP to run as a systemd service.
Create a systemd service file at /etc/systemd/system/frankenphp.service:
[Unit]
Description=FrankenPHP Server
After=network.target
[Service]
Type=notify
User=www-data
Group=www-data
ExecStart=/usr/local/bin/frankenphp run --config /etc/frankenphp/Caddyfile
ExecReload=/bin/kill -USR1 $MAINPID
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
Environment=CADDY_NUM_THREADS=auto
[Install]
WantedBy=multi-user.targetMove your Caddyfile to the system location:
sudo mkdir -p /etc/frankenphp
sudo cp Caddyfile /etc/frankenphp/Create log directory:
sudo mkdir -p /var/log/frankenphp
sudo chown www-data:www-data /var/log/frankenphpEnable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable frankenphp
sudo systemctl start frankenphpCheck the service status:
sudo systemctl status frankenphpWorker Mode
Worker mode is FrankenPHP's most powerful feature. Instead of bootstrapping your application for every request, worker mode loads your application once and keeps it in memory, processing requests through a persistent worker process.
Performance Benefits:
- 10-50x faster response times for typical applications
- Eliminates bootstrap overhead on every request
- Reduces memory usage through application reuse
- Ideal for high-traffic production environments
Production Ready: Worker mode is thoroughly tested and production-ready. The Hazaar API platform has been running in worker mode in production for an extended period with excellent stability and performance.
Enabling Worker Mode
The Hazaar example application includes a worker.php script in the public directory specifically designed for worker mode. To enable worker mode, update your Caddyfile to use worker.php instead of the standard PHP server:
{
frankenphp {
num_threads {env.CADDY_NUM_THREADS}
worker /home/user/myapp/public/worker.php
}
}
myapp.example.com {
root * /home/user/myapp/public
encode gzip
# Worker mode handles PHP automatically
php_server
# Environment variables
env APPLICATION_ENV production
# Security headers
header {
Strict-Transport-Security "max-age=31536000;"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
}
log {
output file /var/log/frankenphp/access.log
}
}The key change is adding the worker directive under the frankenphp global options block.
Worker Mode Considerations
When running in worker mode, be aware of these important considerations:
Application State: The application remains in memory between requests. Use proper request lifecycle management.
Memory Leaks: Any memory leaks will accumulate. Hazaar Framework is designed to properly clean up after each request.
Configuration Changes: Require a server restart to take effect (configuration is loaded once at startup).
Graceful Reloads: Use
systemctl reload frankenphpto restart workers without downtime.Number of Workers: Adjust
num_threadsbased on your server's CPU cores. Useautoto let FrankenPHP decide, or set explicitly:
{
frankenphp {
num_threads 4
worker /home/user/myapp/public/worker.php
}
}Monitoring Worker Mode
Monitor your worker mode application:
# View logs
sudo journalctl -u frankenphp -f
# Check memory usage
ps aux | grep frankenphp
# Reload workers gracefully
sudo systemctl reload frankenphpSSL/TLS Configuration
FrankenPHP automatically obtains and renews SSL certificates from Let's Encrypt when you use a domain name in your Caddyfile:
{
frankenphp
email [email protected]
}
myapp.example.com {
root * /home/user/myapp/public
php_server
}That's it! FrankenPHP handles certificate issuance, renewal, and HTTPS redirection automatically.
Custom SSL Certificates
To use custom SSL certificates:
myapp.example.com {
root * /home/user/myapp/public
tls /path/to/cert.pem /path/to/key.pem
php_server
}Development (Self-Signed Certificates)
For local development with HTTPS:
localhost {
root * /home/user/myapp/public
tls internal
php_server
}Performance Tuning
Worker Mode (Recommended)
The single most impactful performance improvement is enabling worker mode (see Worker Mode section above).
OPcache Configuration
Ensure PHP OPcache is enabled and properly configured. FrankenPHP typically includes OPcache, but verify your settings:
; php.ini or custom INI file
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.validate_timestamps=0 ; Disable in production
opcache.revalidate_freq=0
opcache.fast_shutdown=1Connection Limits
Adjust system limits for high-traffic applications:
; In systemd service file
LimitNOFILE=1048576
LimitNPROC=512Number of Workers
In worker mode, set the number of worker threads to match your CPU cores:
# Set in systemd service or environment
Environment=CADDY_NUM_THREADS=8Troubleshooting
Check FrankenPHP Logs
# Systemd service logs
sudo journalctl -u frankenphp -n 100 -f
# Application logs (if configured)
sudo tail -f /var/log/frankenphp/access.logVerify Configuration
frankenphp validate --config /etc/frankenphp/CaddyfileTest Without Worker Mode
If you encounter issues with worker mode, temporarily disable it to isolate the problem:
{
frankenphp
# worker /home/user/myapp/public/worker.php # Commented out
}Common Issues
Port 80/443 already in use:
- Another web server (Apache, Nginx) may be running
- Stop other web servers:
sudo systemctl stop apache2 nginx
Permission denied on ports 80/443:
- Ensure the systemd service has
AmbientCapabilities=CAP_NET_BIND_SERVICE - Or run FrankenPHP as root (not recommended)
Worker mode not starting:
- Check that
worker.phpexists in yourpublicdirectory - Verify file permissions:
chmod 644 /home/user/myapp/public/worker.php - Check logs for PHP errors
Migration from Apache/Nginx
Migrating from Apache or Nginx to FrankenPHP is straightforward:
- Install FrankenPHP as described above
- Create a Caddyfile pointing to your existing application
- Stop Apache/Nginx:
sudo systemctl stop apache2 nginx - Start FrankenPHP:
sudo systemctl start frankenphp - Enable worker mode for maximum performance
No changes to your Hazaar application code are required.