Deployment
This guide covers deployment procedures for PivotPHP v1.1.4 applications with performance optimizations and extension support.
🚀 PivotPHP v1.1.4 Production Deployment
Revolutionary performance with 84,998 ops/sec peak performance. ReactPHP extension achieves 19,707 req/sec (market leader) for high-performance production deployments.
Revolutionary performance with 84,998 ops/sec peak performance. ReactPHP extension achieves 19,707 req/sec (market leader) for high-performance production deployments.
Performance Deployment Options
🔥 ReactPHP Extension (Recommended for High Performance)
- Performance: 19,707 req/sec (market leader)
- Use Case: WebSocket apps, real-time features, high-concurrency
- Deployment: Continuous runtime with Supervisor
💫 Core Framework (Traditional HTTP)
- Performance: 2,122 req/sec Peak (Docker validated v1.2.0)
- Use Case: REST APIs, microservices, serverless functions
- Deployment: Standard web server (Nginx/Apache)
🎯 Cycle ORM Extension (Database-Heavy Apps)
- Performance: 457,870 ops/sec (database operations)
- Use Case: Database-driven applications
- Deployment: Zero-configuration database setup
Server Requirements
Before deploying PivotPHP v1.1.4, ensure your server meets these requirements:
Core Requirements
- PHP 8.1 or higher (8.4+ recommended for array callable syntax)
- Composer 2.0 or higher
- Web Server: Nginx or Apache (for Core) or Supervisor (for ReactPHP)
- Database: MySQL 5.7+, PostgreSQL 10+, or SQLite 3.8.8+
- Memory: 512MB minimum (1GB+ recommended for ReactPHP)
- CPU: 2+ cores recommended for high-performance deployments
PHP Extensions
- Required: BCMath, Ctype, JSON, Mbstring, OpenSSL, PDO, Tokenizer, XML
- ReactPHP: pcntl, posix, sockets (for async operations)
- Performance: OPcache, JIT (for optimal performance)
Performance Recommendations
- OPcache: Enable with
opcache.enable=1
- JIT: Enable with
opcache.jit=1255
- Memory:
memory_limit=512M
(1GB+ for ReactPHP) - Execution Time:
max_execution_time=300
(unlimited for ReactPHP)
Optimization
Composer Optimization
# Install dependencies without dev packages
composer install --optimize-autoloader --no-dev
# Or if already installed
composer dump-autoload --optimize --no-dev
Configuration Caching
Cache your configuration files for better performance:
# Cache configuration
php bin/console config:cache
# Clear configuration cache
php bin/console config:clear
Route Caching
Cache your routes for faster route resolution:
# Cache routes
php bin/console route:cache
# Clear route cache
php bin/console route:clear
View Caching
If using a template engine:
# Cache views
php bin/console view:cache
# Clear view cache
php bin/console view:clear
Web Server Configuration
Nginx Configuration
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
location ~ /\.(?!well-known).* {
deny all;
}
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Gzip compression
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types application/json application/javascript text/css text/plain;
}
# SSL Configuration
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
root /var/www/example.com/public;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# ... rest of configuration same as above
}
Apache Configuration
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public
<Directory /var/www/example.com/public>
AllowOverride All
Require all granted
# Enable .htaccess
Options -MultiViews -Indexes
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</Directory>
# Security Headers
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
Environment Configuration
Production .env File
APP_NAME="My Application"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://example.com
# Security
APP_KEY=base64:your-secure-random-key-here
# Database
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=production_db
DB_USERNAME=db_user
DB_PASSWORD=secure_password
# Cache
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_DRIVER=redis
# Redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
# Mail
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailgun.org
MAIL_PORT=587
MAIL_USERNAME=your-username
MAIL_PASSWORD=your-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@example.com
MAIL_FROM_NAME="${APP_NAME}"
# Logging
LOG_CHANNEL=daily
LOG_LEVEL=error
# External Services
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
Securing Environment Variables
# Set proper permissions
chmod 600 .env
# Ensure .env is in .gitignore
echo ".env" >> .gitignore
# Use environment variables from server
# In Apache
SetEnv APP_KEY "your-key"
# In Nginx (in PHP-FPM pool config)
env[APP_KEY] = "your-key"
Database Deployment
Running Migrations
# Run migrations
php bin/console migrate --force
# With seeding (be careful in production!)
php bin/console migrate --seed --force
# Rollback if needed
php bin/console migrate:rollback --force
Database Optimization
-- MySQL optimization example
ALTER TABLE users ADD INDEX idx_email (email);
ALTER TABLE posts ADD INDEX idx_user_created (user_id, created_at);
ALTER TABLE sessions ADD INDEX idx_user_id (user_id);
-- Analyze tables
ANALYZE TABLE users, posts, comments;
-- Optimize tables
OPTIMIZE TABLE users, posts, comments;
Zero-Downtime Deployment
Deployment Script
#!/bin/bash
# Configuration
APP_DIR="/var/www/example.com"
NEW_RELEASE_DIR="${APP_DIR}/releases/$(date +%Y%m%d%H%M%S)"
SHARED_DIR="${APP_DIR}/shared"
CURRENT_DIR="${APP_DIR}/current"
# Create new release directory
mkdir -p $NEW_RELEASE_DIR
# Pull latest code
cd $NEW_RELEASE_DIR
git clone https://github.com/yourrepo/yourapp.git .
# Install dependencies
composer install --optimize-autoloader --no-dev
# Copy environment file
cp ${SHARED_DIR}/.env .env
# Link shared directories
ln -nfs ${SHARED_DIR}/storage storage
ln -nfs ${SHARED_DIR}/public/uploads public/uploads
# Run deployment commands
php bin/console migrate --force
php bin/console config:cache
php bin/console route:cache
php bin/console view:cache
# Warm up cache
php bin/console cache:warmup
# Switch symlink atomically
ln -nfs $NEW_RELEASE_DIR $CURRENT_DIR
# Reload PHP-FPM
sudo service php8.1-fpm reload
# Clean up old releases (keep last 5)
cd ${APP_DIR}/releases && ls -t | tail -n +6 | xargs rm -rf
echo "Deployment completed successfully!"
Using Envoy
// Envoy.blade.php
@servers(['web' => 'user@example.com'])
@setup
$repository = 'git@github.com:yourrepo/yourapp.git';
$releases_dir = '/var/www/example.com/releases';
$app_dir = '/var/www/example.com';
$release = date('YmdHis');
$new_release_dir = $releases_dir .'/'. $release;
@endsetup
@task('deploy')
echo 'Cloning repository'
[ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }}
git clone --depth 1 --branch master {{ $repository }} {{ $new_release_dir }}
echo 'Installing composer dependencies'
cd {{ $new_release_dir }}
composer install --prefer-dist --no-dev --optimize-autoloader
echo 'Linking .env file'
ln -nfs {{ $app_dir }}/.env {{ $new_release_dir }}/.env
echo 'Linking storage directory'
ln -nfs {{ $app_dir }}/storage {{ $new_release_dir }}/storage
echo 'Running migrations'
cd {{ $new_release_dir }}
php bin/console migrate --force
echo 'Caching configuration'
php bin/console config:cache
php bin/console route:cache
echo 'Linking current release'
ln -nfs {{ $new_release_dir }} {{ $app_dir }}/current
echo 'Restarting FPM'
sudo service php8.1-fpm reload
@endtask
Run deployment:
envoy run deploy
Container Deployment
Dockerfile
FROM php:8.1-fpm-alpine
# Install dependencies
RUN apk add --no-cache \
git \
curl \
libpng-dev \
oniguruma-dev \
libxml2-dev \
zip \
unzip \
nginx \
supervisor
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Set working directory
WORKDIR /var/www
# Copy application files
COPY . /var/www
# Install application dependencies
RUN composer install --optimize-autoloader --no-dev
# Copy configuration files
COPY docker/nginx/nginx.conf /etc/nginx/nginx.conf
COPY docker/php/php.ini /usr/local/etc/php/conf.d/app.ini
COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Set permissions
RUN chown -R www-data:www-data /var/www
# Expose port
EXPOSE 80
# Start services
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
Docker Compose
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
image: pivotphp-app
container_name: pivotphp-app
restart: unless-stopped
working_dir: /var/www
volumes:
- ./:/var/www
- ./docker/php/php.ini:/usr/local/etc/php/conf.d/app.ini
networks:
- pivotphp
nginx:
image: nginx:alpine
container_name: pivotphp-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./:/var/www
- ./docker/nginx:/etc/nginx/conf.d
networks:
- pivotphp
mysql:
image: mysql:8.0
container_name: pivotphp-mysql
restart: unless-stopped
environment:
MYSQL_DATABASE: pivotphp
MYSQL_ROOT_PASSWORD: secret
MYSQL_PASSWORD: secret
MYSQL_USER: pivotphp
volumes:
- dbdata:/var/lib/mysql
networks:
- pivotphp
redis:
image: redis:alpine
container_name: pivotphp-redis
restart: unless-stopped
networks:
- pivotphp
networks:
pivotphp:
driver: bridge
volumes:
dbdata:
driver: local
Monitoring
Health Check Endpoint
// routes/web.php
$app->get('/health', function() {
$checks = [
'database' => $this->checkDatabase(),
'cache' => $this->checkCache(),
'queue' => $this->checkQueue(),
'storage' => $this->checkStorage(),
];
$healthy = !in_array(false, $checks);
return response()->json([
'status' => $healthy ? 'healthy' : 'unhealthy',
'checks' => $checks,
'timestamp' => now()->toIso8601String(),
], $healthy ? 200 : 503);
});
Logging
Configure proper logging for production:
// config/logging.php
'channels' => [
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/helix.log'),
'level' => env('LOG_LEVEL', 'error'),
'days' => 14,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'PivotPHP Log',
'emoji' => ':boom:',
'level' => 'critical',
],
'papertrail' => [
'driver' => 'monolog',
'level' => 'debug',
'handler' => SyslogUdpHandler::class,
'handler_with' => [
'host' => env('PAPERTRAIL_URL'),
'port' => env('PAPERTRAIL_PORT'),
],
],
],
Performance Optimization
OPcache Configuration
; php.ini
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.save_comments=0
PHP-FPM Tuning
; /etc/php/8.1/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
Security Checklist
- Disable debug mode (
APP_DEBUG=false
) - Set secure APP_KEY
- Configure HTTPS with valid SSL certificate
- Set proper file permissions (755 for directories, 644 for files)
- Disable directory listing
- Configure firewall rules
- Set up fail2ban for brute force protection
- Regular security updates
- Configure backup strategy
- Monitor logs for suspicious activity
- Use strong database passwords
- Restrict database access to localhost only
- Enable query logging for auditing
- Configure rate limiting
- Set up monitoring and alerting