Deploy Multi‑Tenant Node.js on CloudPanel with Auto Nginx Proxy
Deploy multi-tenant Node.js apps on Ubuntu 22.04 VPS using CloudPanel and pm2. Learn to automate Nginx proxy and SSL setup.
7 min read
Running several Node.js apps on a single server can be difficult. You need isolation, simple deployment, and a reliable web server that forwards traffic to the correct tenant. CloudPanel – a lightweight control panel for Ubuntu – takes care of Nginx configuration automatically. In this guide we walk through the full process of deploying a multi‑tenant Node.js application on a CloudPanel‑managed VPS, from creating system users to having Nginx reverse‑proxy each tenant without manual edits.
1. Prerequisites and Initial Server Setup
These steps assume you have a fresh Ubuntu 22.04 server provisioned through AtoZNode and that you can log in with root or a sudo user.
Ubuntu 22.04 LTS (64‑bit)
At least 2 GB RAM (recommended for multiple Node processes)
Domain name pointing to the server’s public IP (e.g., example.com)
These commands refresh the APT cache, apply pending security updates, and install tools we’ll need later.
2. Installing CloudPanel on Ubuntu 22.04
CloudPanel provides a one‑click installer script. Run it as root (or with sudo) and follow the prompts.
# Download and execute the installer
curl -sSL https://installer.cloudpanel.io/installer.sh | sudo bash
The script performs the following actions:
Installs Nginx, MariaDB, PHP‑FPM, and other dependencies.
Creates the cloudpanel system user and configures the web‑panel service.
Sets up a self‑signed SSL certificate for the panel (you can replace it later).
When the installer finishes, you’ll see a URL such as https://your-server-ip:8443. Open it in a browser, accept the self‑signed certificate, and log in with the credentials displayed at the end of the installation.
3. Preparing System Users for Each Tenant
CloudPanel isolates sites by assigning each a dedicated Linux user. This keeps file permissions clean and limits the impact of a compromised app.
Assume we have two tenants: tenantA and tenantB. Create the users via the CloudPanel UI (Sites → Add Site → Advanced → Create New System User) or from the command line:
# Replace tenant name as needed
sudo adduser --disabled-password --gecos "" tenantA
sudo adduser --disabled-password --gecos "" tenantB
These commands create a new user without a password (login is disabled) and set up a home directory at /home/tenantA and /home/tenantB. CloudPanel will later map each site’s document root to the user’s public_html folder.
4. Deploying the Node.js Application for Each Tenant
We’ll use pm2 to manage Node processes, ensuring they restart on failure or after a reboot.
4.1 Install Node.js and pm2 (system‑wide)
CloudPanel does not install Node by default, so we add the official NodeSource repository and install the LTS version (currently 20.x).
# Add NodeSource repo for Node 20.x
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
# Install Node.js and npm
sudo apt install -y nodejs
# Verify installation
node -v # e.g., v20.12.0
npm -v # e.g., 10.2.3
# Install pm2 globally
sudo npm install -g pm2
# Make pm2 start on boot for the root user (CloudPanel will run apps as tenant users)
pm2 startup systemd -u root --hp /root
4.2 Clone the Application Code
For each tenant, place the code inside their public_html directory. Example for tenantA:
# Switch to tenantA user
sudo -i -u tenantA
# Navigate to home and create public_html
cd ~
mkdir -p public_html
cd public_html
# Clone your repo (replace URL with your actual repo)
git clone https://github.com/yourorg/multi‑tenant‑node-app.git .
# Install dependencies
npm install
# Exit back to root
exit
Repeat the same steps for tenantB, changing the user name accordingly.
4.3 Create a pm2 Ecosystem File
Using an ecosystem file lets us define separate processes for each tenant while keeping a single pm2 command.
# As root, create /etc/pm2/multi‑tenant‑ecosystem.config.js
sudo nano /etc/pm2/multi-tenant-ecosystem.config.js
Paste the following (adjust script and env.PORT as needed):
cwd – working directory, ensures relative paths work.
env.PORT – each tenant listens on a unique local port (3001, 3002).
user – runs the process under the tenant’s Linux account.
Start the processes and save the pm2 list:
# Load the ecosystem file
pm2 start /etc/pm2/multi-tenant-ecosystem.config.js
# Save the current process list for auto‑restart
pm2 save
5. Configuring Automatic Nginx Reverse Proxy via CloudPanel
CloudPanel automatically creates Nginx server blocks for sites added through its UI. To leverage this, we’ll add each tenant as a separate “site” and point the proxy to the local port where pm2 runs the app.
5.1 Add a New Site for Tenant A
Log into the CloudPanel dashboard.
Navigate to Sites → Add Site.
Enter the domain (e.g., tenantA.example.com).
Choose the system user tenantA created earlier.
Under Advanced Settings → Proxy Settings, enable “Reverse Proxy”.
Set the proxy target to http://127.0.0.1:3001.
Save the site.
CloudPanel writes an Nginx configuration similar to:
After saving, click “Apply Changes” in the CloudPanel UI to reload Nginx.
5.2 Repeat for Tenant B
Follow the same steps, using tenantB.example.com and proxy target http://127.0.0.1:3002. CloudPanel will generate a second server block, keeping the two tenants completely isolated at the web‑server level.
5.3 Enable HTTPS (Let’s Encrypt)
CloudPanel includes built‑in Let’s Encrypt support. For each site:
Select the site in the dashboard.
Click “Enable SSL”.
Choose “Let’s Encrypt” and confirm the domain.
CloudPanel obtains a certificate and updates the Nginx block to listen on port 443.
From a browser, open https://tenantA.example.com and https://tenantB.example.com. You should see each app’s response. If you get a 502 error, check the pm2 logs:
# View logs for tenantA
pm2 logs tenantA
# View logs for tenantB
pm2 logs tenantB
6.2 Set Up Basic Monitoring
pm2 includes a lightweight monitoring dashboard:
pm2 monit
For longer‑term metrics, consider installing pm2-gui or using CloudPanel’s built‑in resource graphs (CPU, RAM, disk).
6.3 Updating the Application
When you need to deploy a new version for a specific tenant:
# Switch to the tenant user
sudo -i -u tenantA
# Pull latest code
cd ~/public_html
git pull origin main
# Reinstall dependencies if needed
npm install
# Restart the pm2 process for this tenant
pm2 restart tenantA
Because each tenant runs under its own user, updates do not affect the other sites.
Conclusion
By combining CloudPanel’s automatic Nginx reverse‑proxy handling with pm2’s process management, you can host multiple isolated Node.js applications on a single Ubuntu 22.04 VPS without manually editing Nginx files. The workflow scales neatly: add a new system user, clone the code, define a pm2 entry, and let CloudPanel create the proxy and SSL configuration. This approach saves time, reduces configuration errors, and keeps each tenant’s environment secure and independent—ideal for developers and agencies managing several Node.js projects on an AtoZNode server.