Multi-Site Management on CloudPloy
Running multiple client sites or applications on a shared hosting plan means shared resources, shared risk, and shared downtime. CloudPloy takes a different approach: each application gets its own isolated Docker container, its own database, and its own deployment pipeline - but you manage them all from one dashboard. This page explains how agencies and teams use CloudPloy to manage dozens or hundreds of PHP applications without the operational overhead of maintaining multiple separate hosting accounts.
Two Models: Multiple Apps vs WordPress Multisite
There are two architecturally different things people mean when they say "multi-site":
| Model | What It Is | Best For |
|---|---|---|
| Multiple independent apps | Separate WordPress/Laravel installations, each with its own database and deployment | Agencies managing client sites that are independent from each other |
| WordPress Multisite network | One WordPress installation hosting many sites via the network feature | Publishing networks, SaaS products built on WordPress, franchises with shared design |
CloudPloy supports both. Most agencies use the first model (independent apps). WordPress Multisite is covered in detail in its own section below.
Managing Multiple Independent Applications
In CloudPloy, each application lives under a Server. One server can host dozens of apps. Navigate to your server and each app appears as a separate card with its own deployment status, domain, and logs.
Adding Applications to a Server
From Server > Apps > New Application:
- Connect the GitHub repository (or create a new app from a WordPress/PHP template)
- Select the framework (WordPress, Laravel, Symfony, PHP, Node.js)
- Assign a domain or subdomain
- Configure environment variables for this app
- Click Deploy
Each app gets a separate database (created automatically or linked to an existing one), separate environment variables (so client A's database credentials are never visible to client B's container), and separate deployment history.
Server Sizing for Multiple Apps
How many apps can a single server handle? It depends on traffic and application type:
| Server RAM | Typical App Count | Traffic Profile |
|---|---|---|
| 4GB | 10-20 apps | Low-traffic sites, brochure sites, development environments |
| 8GB | 20-40 apps | Mixed portfolio with some active WooCommerce stores |
| 16GB | 40-80 apps | Active sites with moderate traffic, Redis caching enabled |
| 32GB+ | 80+ apps | Agency portfolios, high-traffic client mix |
These are rough guidelines. Each PHP-FPM worker uses 30-80MB depending on the application. A WordPress site with heavy plugins (WooCommerce, page builders, SEO plugins) can use 100MB+ per worker. Monitor actual memory usage per app in App > Metrics and set memory limits in App > Settings > Resources to prevent one busy client from starving others.
Per-App Resource Limits
Set CPU and memory limits to isolate applications from each other:
# Example resource allocation per app tier
# Small brochure site: 256MB RAM, 0.25 CPU
# Active WordPress/WooCommerce: 512MB RAM, 0.5 CPU
# High-traffic Laravel SaaS: 2GB RAM, 2 CPU This prevents a traffic spike on one client's site from degrading response times for all other clients on the same server. Configure in App > Settings > Resources.
Agency Deployment Workflows
Staging Environments for Each Client
Each client application can have a corresponding staging app. The typical setup:
- Production app:
clientname.com- connected tomainbranch, auto-deploys on merge - Staging app:
staging.clientname.comorclientname-staging.youragency.dev- connected tostagingbranch
Both apps live on the same server. The staging app uses a separate database (with anonymized production data if needed) and separate environment variables (staging Stripe keys, sandbox payment gateways, debug mode enabled).
When a client requests changes:
- Developer pushes to
stagingbranch - staging auto-deploys - Client reviews at staging URL
- Client approves - developer merges to
main- production auto-deploys - Zero manual server interaction at any step
Cloning a Client Site for Staging
To create a staging environment from a live WordPress site:
# In App > Terminal for the production app
# 1. Export the production database
wp db export - | gzip > /tmp/prod-backup.sql.gz
# 2. Copy to staging app (or use CloudPloy's backup/restore feature)
# 3. In staging app terminal: import and anonymize
gunzip -c /tmp/prod-backup.sql.gz | wp db import -
# Replace production URLs with staging URLs
wp search-replace 'https://clientname.com' 'https://staging.clientname.com' \
--skip-columns=guid
# Anonymize customer data for GDPR compliance
wp user list --field=ID | xargs -I{} wp user update {} \
--user_email="user-{}@staging.invalid"
wp cache flush Deploy Hooks for Client Notifications
Configure webhook notifications when deployments complete. Useful for notifying clients or posting to Slack:
In App > Settings > Deploy Hooks, add a webhook URL. CloudPloy sends a POST request with deployment details (status, timestamp, commit SHA) on each deploy completion.
WordPress Multisite Setup on CloudPloy
WordPress Multisite (also called WordPress Network) runs multiple sites from a single WordPress installation. All sites share the same codebase, plugins, and themes, but have separate databases tables (using a per-site table prefix like wp_2_posts) and separate media uploads.
When to Use WordPress Multisite
- Publishing network with dozens of sub-publications sharing editorial workflows
- University or corporate intranet with departmental sub-sites
- Franchise business with many location sites sharing the same design
- SaaS product that provisions a WordPress site per customer
When NOT to use Multisite: client sites that are independent businesses - a billing issue, plugin conflict, or core update affecting the network affects every site simultaneously. For agencies managing independent client sites, the separate-apps model is safer.
Enabling WordPress Multisite on CloudPloy
Add to wp-config.php before the final comment line:
define('WP_ALLOW_MULTISITE', true); Then in wp-admin, go to Tools > Network Setup and choose subdomain or subdirectory mode. After setup, WordPress provides additional lines to add to wp-config.php and .htaccess. For CloudPloy (Nginx), the .htaccess rules are not used - Nginx handles rewrites automatically.
Add the network config lines to wp-config.php, using environment variables for the domain:
define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', true); // or false for subdirectory
define('DOMAIN_CURRENT_SITE', getenv('WP_DOMAIN') ?: 'network.example.com');
define('PATH_CURRENT_SITE', '/');
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);
// Required for subdomain multisite - allow cookies across subdomains
define('COOKIE_DOMAIN', '.' . getenv('WP_DOMAIN') ?: '.network.example.com'); DNS for Subdomain Multisite
Subdomain multisite requires a wildcard DNS record. In your DNS provider, add:
*.network.example.com A YOUR_SERVER_IP
network.example.com A YOUR_SERVER_IP Then in CloudPloy, add *.network.example.com as a domain in App > Settings > Domains. CloudPloy provisions a wildcard SSL certificate via Let's Encrypt for both the root domain and all subdomains.
WP-CLI for Network Management
# List all sites in the network
wp site list
# Create a new network site
wp site create --slug=newsite --title="New Site" --email=admin@example.com
# Activate a plugin network-wide
wp plugin activate woocommerce --network
# Run a command on all network sites
wp site list --field=url | xargs -I {} wp --url={} cache flush
# Export a specific network site's database
wp db export --tables=$(wp db tables --url=site2.network.example.com --all-tables-with-prefix --format=csv) - | gzip > site2-backup.sql.gz Multi-Framework Portfolios
Many agencies run mixed portfolios: some clients have WordPress sites, others have Laravel applications, some have static sites. CloudPloy handles all of these on the same server:
| Framework | Detection Method | Worker Type |
|---|---|---|
| WordPress | wp-login.php present | PHP-FPM with WordPress-specific Nginx config |
| Laravel | artisan + laravel/framework in composer.json | PHP-FPM with public/ as web root |
| Symfony | symfony/framework-bundle in composer.json | PHP-FPM with public/ as web root |
| Node.js | package.json without PHP framework markers | Node.js process, Nginx reverse proxy |
| Static HTML | index.html at root, no framework detected | Direct Nginx file serving |
Centralized Database Management
Each application gets a separate database. All databases on a server are visible in Server > Databases. From here you can:
- Create new databases for new client applications
- Access the built-in database admin UI (phpMyAdmin equivalent) without exposing it to the internet
- View database size per application
- Trigger manual backups
- Restore from any backup point
CloudPloy's daily automated backups cover all databases on a server. Backups are stored off-site and retained for 7 days by default (configurable to 30 days on paid plans).
Monitoring Across Multiple Apps
The server dashboard provides aggregate resource usage (total CPU, RAM, disk across all apps). Individual app dashboards show per-app metrics. For agency-wide monitoring, configure uptime alerts per app in App > Settings > Monitoring - alerts go to your email or webhook (Slack, PagerDuty).
Common monitoring setup for an agency server:
- Server-level alerts: CPU >90% for 5 minutes, disk usage >80%, RAM >85%
- App-level alerts: health check failure, deployment failure, response time >3s
- Alert recipients: agency team (Slack), client (email) - configurable per app
Common Agency Questions
Can I give clients access to their own app without seeing other clients' apps?
Yes. In Server > Team, invite a client as a "Developer" or "Viewer" and restrict their access to specific applications. They can view logs, trigger deployments, and manage environment variables for their app only. They cannot see other apps on the server.
How do I migrate all my existing client sites to CloudPloy?
Migrate one site first to validate the process, then repeat. For WordPress, use the Migrate from cPanel guide or the all-in-one migration plugin. For Laravel, connect the repository and configure environment variables. CloudPloy support offers concierge migration for agencies moving 10+ sites.
What happens if one client's app uses too much memory?
If you've configured resource limits (recommended), the container is OOM-killed and auto-restarts. Without limits, one app can consume all available server RAM. Set limits in App > Settings > Resources for every app.
Can I use a shared Redis instance across multiple apps?
Yes. Add one Redis instance to the server and configure multiple apps to use it. Ensure each app has a unique REDIS_PREFIX in their environment variables to avoid cache key collisions between clients.
Managing a large portfolio? Read the staging environment guide for setting up per-client staging, the monitoring guide for agency-wide alerting, or contact CloudPloy to discuss server sizing for your portfolio.