One command to tune your CloudPanel VPS for production SaaS workloads.
Auto-detects hardware, calculates optimal values, applies safe configurations — with full backup and rollback.
Works on any VPS size from 2GB to 128GB+.
A fresh CloudPanel VPS ships with conservative defaults designed for shared hosting — not for running production SaaS applications. You'll typically see:
- MySQL buffer pool using only a fraction of available RAM
- PHP-FPM pools set to
ondemandwith cold-start delays - PHP memory_limit at 768M per process (wastefully high)
- No OPcache tuning — recompiling PHP on every request
- Redis running without memory limits
- Nginx serving uncompressed responses with low connection limits
- Kernel using default TCP and file descriptor settings
The result? TTFB of 1.5–3+ seconds, high CPU usage on MySQL, and a server that buckles under moderate traffic.
This script auto-detects your server specs and calculates optimal values — no manual tuning required.
sudo bash cloudpanel-optimize.shThat's it. One command runs all 7 optimization steps: MySQL, PHP (all versions), PHP-FPM pools, Redis, kernel, and Nginx global tuning.
| Server | MySQL Buffer Pool | FPM max_children | Redis |
|---|---|---|---|
| 4GB / 2 cores | 512M | 20/pool | 128mb |
| 16GB / 4 cores | 3G | 40/pool | 1024mb |
| 48GB / 12 cores | 9G | 80/pool | 4096mb |
|
|
Step 1 is always a full config backup before any changes are made.
| Metric | Before | After | Improvement |
|---|---|---|---|
| TTFB | 1.5 – 3.0s | 0.15 – 0.7s | ~85% |
| Response size (text) | 100% | 20 – 40% | 60-80% smaller |
| MySQL CPU | 40 – 90% | 5 – 15% | ~80% |
| Free RAM (48GB server) | 2 – 4 GB | 8 – 12 GB | ~3x |
| PHP cold start delay | 1 – 3s | Eliminated | 100% |
| PHP processes per site | 250+ (uncontrolled) | 20 – 150 (tuned) | Controlled |
curl -O https://raw.githubusercontent.com/jsahani/cloudpanel-optimizer/main/cloudpanel-optimize.sh
chmod +x cloudpanel-optimize.shsudo bash cloudpanel-optimize.sh --dry-runsudo bash cloudpanel-optimize.shsudo bash cloudpanel-optimize.sh --statussudo bash cloudpanel-optimize.sh # Run full optimization (7 steps)
sudo bash cloudpanel-optimize.sh --dry-run # Preview all changes
sudo bash cloudpanel-optimize.sh --rollback # Restore latest backup
sudo bash cloudpanel-optimize.sh --status # Current server health
sudo bash cloudpanel-optimize.sh --help # Show usage
CloudPanel lets each site use a different PHP version. This script handles that automatically — it scans all /etc/php/*/fpm/pool.d/ directories and optimizes each version's pools and php.ini independently.
── Server Profile Detection ──
▸ PHP versions (8.0+): 8.0 8.1 8.2 8.3 8.4 8.5
▸ Website pools found: 3
▸ → PHP 8.3/fpm/pool.d/app.example.com.conf
▸ → PHP 8.4/fpm/pool.d/api.example.com.conf
▸ → PHP 8.5/fpm/pool.d/dashboard.example.com.conf
PHP versions below 8.0 are automatically skipped.
| Feature | Description |
|---|---|
| Full Backup | Timestamped backup of all configs (MySQL, PHP, Redis, Nginx, sysctl) |
| Auto-Cleanup | Only the 3 most recent backups are kept — older ones are pruned automatically on each run |
| Config Validation | Tests PHP-FPM, MySQL, and Nginx configs before restarting services |
| Auto-Rollback | If a service fails to start or nginx -t fails, configs are restored automatically |
| Idempotent | Safe to run multiple times — completed steps auto-skip |
| Dry Run | Preview every change without modifying anything |
| Selective Restart | Only restarts PHP-FPM versions with modified pools |
| CloudPanel Safe | Never touches /etc/nginx/sites-enabled/* — vhosts remain CloudPanel-managed |
# Restore most recent backup
sudo bash cloudpanel-optimize.sh --rollback
# Restore a specific backup
sudo bash cloudpanel-optimize.sh --rollback /root/cp-backup-20260228-112931All values are derived from your actual hardware specs — no hardcoded magic numbers.
MySQL buffer pool = RAM × 20%
Buffer pool instances = buffer_pool_GB (max 16)
Max connections = CPU_cores × 50 (min 256, max 1024)
Table cache = max_connections × 4
PHP memory_limit = 512M (≥32GB RAM) or 256M
FPM max_children = (RAM × 50% / 50MB) / number_of_sites
FPM start_servers = max_children × 20%
FPM min_spare = start_servers × 70%
FPM max_spare = max_children × 40%
Redis maxmemory = RAM × 10% (max 4GB)
Nginx worker_connections = 65535
Nginx worker_rlimit = 65535
Nginx gzip_comp_level = 5
Nginx open_file_cache = 10000 entries
MySQL buffer pool : 9G (9 instances)
MySQL max connections: 600
FPM max_children : 80 per pool
FPM start_servers : 16
Redis maxmemory : 4096mb
Nginx gzip : on (level 5)
Nginx connections : 65535
┌─────────────────────────────────────┐
│ 1. Provision fresh VPS │
│ 2. Install CloudPanel │
│ 3. Run optimizer (first pass) │ ← MySQL, PHP, Redis, kernel, Nginx
│ 4. Add your sites in CloudPanel │
│ 5. Run optimizer (second pass) │ ← Optimizes new pools, skips the rest
│ 6. Configure Redis in each .env │
│ 7. Enable HTTP/3 per site (UI) │ ← CloudPanel Vhost Editor toggle
└─────────────────────────────────────┘
The script prints Redis credentials after optimization:
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=<your-password>
HTTP/3 is a per-site setting managed through CloudPanel's UI (not this script):
- Go to your site in CloudPanel → Vhost Editor
- Change
http3 off;tohttp3 on; - Ensure UDP port 443 is open in your firewall
- Requires a valid Let's Encrypt certificate (not self-signed)
- OS: Ubuntu 22.04 / 24.04 (or any Debian-based distro)
- Panel: CloudPanel 2.x
- PHP: 8.0+ (lower versions are auto-skipped)
- RAM: 2GB minimum (recommended 4GB+)
- Access: Root (
sudo) - Disk: SSD recommended (I/O settings are SSD-optimized)
| File | What Changes |
|---|---|
/etc/mysql/my.cnf (or equivalent) |
InnoDB, connections, buffers, logging |
/etc/php/*/fpm/php.ini |
memory_limit, execution time, OPcache |
/etc/php/*/fpm/pool.d/*.conf |
PM mode, children, spare servers, backlog |
/etc/redis/redis.conf |
maxmemory, eviction policy, keepalive |
/etc/sysctl.d/99-cloudpanel-optimize.conf |
TCP, swappiness, file descriptors |
/etc/security/limits.d/99-cloudpanel-optimize.conf |
nofile, nproc limits |
/etc/nginx/nginx.conf |
worker_rlimit_nofile, worker_connections, multi_accept |
/etc/nginx/conf.d/cloudpanel-optimize.conf |
Gzip, keepalive, buffers, file cache, server_tokens |
Not modified: /etc/nginx/sites-enabled/* — CloudPanel vhosts are never touched.
All originals are backed up to /root/cp-backup-YYYYMMDD-HHMMSS/ before modification. Only the 3 most recent backups are retained.
MIT — Use it, fork it, improve it.