Modern websites and applications increasingly rely on headless CMS platforms: systems that provide content via APIs instead of tightly coupling it to a specific front-end theme. Strapi is one of the most popular open‑source headless CMS options in this space.
Strapi is a Node.js application that lets you define content types (pages, blog posts, products, FAQs, etc.), manage content through a web-based admin panel, and expose that content over REST or GraphQL APIs. Your front end can be anything you like—React, Next.js, Nuxt, a mobile app, or even a traditional server-rendered site—while Strapi focuses solely on content and APIs.
Why might you want to use Strapi?
- Flexibility: You can model content exactly the way your business needs it instead of fighting a rigid page template system.
- API-first: Content is delivered over APIs, which makes it easy to reuse across multiple sites, apps, or services.
- Self-hosted and open source: You control where it runs (and how it’s secured), which is attractive for compliance or cost reasons.
- Developer friendly: Strapi integrates cleanly with modern JavaScript toolchains and frameworks, and its plugin system makes it easy to extend.
Plesk, on the other hand, is a proven control panel that many teams already use to manage domains, DNS, SSL/TLS certificates, and web hosting. Running Strapi on a Plesk server is a natural fit: let Plesk handle the platform plumbing (domains, SSL, system users), while Strapi handles the content.
In this guide we’ll walk through installing Strapi on a Plesk server running Ubuntu 24.04, under a Plesk subscription such as strapi.acme.com. We’ll:
- Use NVM to manage Node versions
- Use npm (or yarn) to install Strapi
- Use PM2 to run Strapi as a background service
- Use Nginx as a reverse proxy via Plesk
- Configure Strapi to listen on a non-default port so that multiple Strapi instances can run on the same server
We’ll assume:
- Plesk Obsidian is already installed on Ubuntu 24.04.
- DNS for
strapi.acme.compoints to your Plesk server. - PostgreSQL is external (e.g., AWS RDS, DigitalOcean Managed PG, on-prem DB). We’ll just need its host, port, db name, user, and password.
1. Create the Plesk Subscription
First, create a standard Plesk subscription for the Strapi instance.
- Log in to Plesk as admin.
- Go to Subscriptions → Add Subscription.
- Set:
- Domain name:
strapi.acme.com - Username:
strapi(or something similar) - Password: choose a strong password
- Domain name:
- Plan / PHP settings don’t matter much for Strapi itself, but PHP may be used for other things on the subscription.
- Save to create the subscription.
This will create a system user (e.g. strapi) and a home directory, usually something like:
|
1 2 |
/var/www/vhosts/strapi.acme.com/ |
We’ll run Strapi under this UNIX user.
2. SSH into the Subscription User
SSH into the server as root (or your admin user), then switch to the subscription user:
|
1 2 3 |
sudo -i su - strapi |
Confirm you’re in the right home directory:
|
1 2 3 |
pwd # Expected: /var/www/vhosts/strapi.acme.com/ |
We’ll install NVM, Node, and Strapi from here.
3. Install NVM and Node.js
Strapi expects a modern LTS version of Node. Installing Node via NVM makes it easy to upgrade later and keep this user isolated.
From the strapi user shell:
|
1 2 3 |
# Install NVM (grab the latest install line from the NVM repo if needed) curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash |
Load NVM into your current shell:
|
1 2 3 |
export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" |
Install an LTS Node (replace with the current LTS you prefer):
|
1 2 3 4 |
nvm install --lts nvm use --lts nvm alias default 'lts/*' |
Verify:
|
1 2 3 |
node -v npm -v |
4. Create the Strapi Project
Decide where you want the Strapi code to live. A common pattern for Plesk:
|
1 2 |
cd ~/httpdocs |
Create a Strapi project (change cms to whatever you want):
|
1 2 3 4 |
npx create-strapi-app@latest cms # or for Strapi v5+ # npx create-strapi-app@latest cms --quickstart=false |
When prompted:
- Choose Custom (manual) if asked.
- Select PostgreSQL as the database.
- Skip sample content if you prefer a clean start.
Once created:
|
1 2 |
cd ~/httpdocs/cms |
5. Configure Strapi to Use a Non-Default Port
By default, Strapi often runs on port 1337. To support multiple Strapi instances on the same server, give each instance a unique port, e.g.:
strapi.acme.com→ port 1340strapi2.acme.com→ port 1341- etc.
Strapi uses environment variables (or .env) to define its port. Inside your Strapi project directory:
|
1 2 3 |
cd ~/httpdocs/cms ls |
If you don’t already have a .env file in production, create one. A simple .env might look like this (example):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# .env # App HOST=0.0.0.0 PORT=1340 APP_KEYS=someRandomString1,someRandomString2 API_TOKEN_SALT=someRandomString3 ADMIN_JWT_SECRET=someRandomString4 TRANSFER_TOKEN_SALT=someRandomString5 # Database (external PostgreSQL) DATABASE_CLIENT=postgres DATABASE_HOST=db.example.com DATABASE_PORT=5432 DATABASE_NAME=strapi_cms DATABASE_USERNAME=strapi_user DATABASE_PASSWORD=SuperSecretPassword DATABASE_SSL=true |
Key bit for running multiple instances:
|
1 2 |
PORT=1340 |
For another instance on the same server (maybe marketing.acme.com), just set a different port:
|
1 2 |
PORT=1341 |
Tip: Generate secure random strings for
APP_KEYS,API_TOKEN_SALT, etc. Don’t reuse them between projects.
6. Test Strapi Manually
Before adding PM2, confirm Strapi runs correctly.
From the Strapi project directory:
|
1 2 3 4 |
cd ~/httpdocs/cms npm run build # build admin panel npm run start # or `npm run develop` for dev mode |
You should see Strapi binding to 0.0.0.0:1340 (from your .env). Since Plesk’s firewall or public ports may not expose this directly, you may not be able to hit it from outside yet—that’s fine. We’ll use Nginx to proxy HTTP to this port.
Stop Strapi with Ctrl+C once you’re satisfied it starts without errors.
7. Install and Configure PM2
PM2 will keep Strapi running as a background process and restart it on crashes or reboot.
Still as the strapi user:
|
1 2 |
npm install -g pm2 |
Start Strapi with PM2:
|
1 2 3 |
cd ~/httpdocs/cms pm2 start npm --name "strapi-cms" -- run start |
Check status:
|
1 2 |
pm2 status |
You should see strapi-cms listed as online.
To make PM2 reload on reboot, run:
|
1 2 |
pm2 startup systemd |
This command will output another command that you must run as root. Copy it, open a new root shell, and run it. It will look something like:
|
1 2 |
sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u strapi --hp /var/www/vhosts/strapi.acme.com |
Then, save the current process list:
|
1 2 |
pm2 save |
Now, after a reboot, PM2 will automatically start Strapi for the strapi user.
8. Configure Nginx Reverse Proxy in Plesk
Plesk uses Nginx + Apache by default. We’ll configure Nginx to proxy traffic from https://strapi.acme.com to our Strapi app on 127.0.0.1:1340.
8.1 Enable SSL for the Domain
- In Plesk, go to Domains → strapi.acme.com.
- Click SSL/TLS Certificates (or Let’s Encrypt).
- Issue a certificate for
strapi.acme.com. - Make sure SSL/TLS support is enabled for the domain in Hosting Settings.
8.2 Add Custom Nginx Proxy Rules
- In Plesk, open Domains → strapi.acme.com → Apache & Nginx Settings.
- Scroll down to Additional Nginx directives.
- Add something like this:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
location / { proxy_pass http://127.0.0.1:1340; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 300; } |
- Click OK or Apply.
Nginx will now forward all requests for strapi.acme.com to the Strapi process on port 1340.
8.3 Restrict Apache (Optional)
If you want Nginx to handle everything and avoid Apache interfering, in the same screen you can choose:
- Proxy mode on (default)
- or tweak settings so static files can be offloaded, etc.
For most simple Strapi setups, the basic reverse proxy above is enough.
9. Verify the Setup
Open a browser and go to:
|
1 2 |
https://strapi.acme.com/admin |
You should see the Strapi admin panel login/setup screen.
If you get a 502/504:
- Check that PM2 shows the app as online:
pm2 status - Check that Strapi logs are clean:
12pm2 logs strapi-cms - Make sure the Nginx proxy port matches your
.envPORT. - Verify SSL is active and the certificate is correct.
10. Running Multiple Strapi Instances on the Same Server
Now that the first instance works, adding more is straightforward:
- Create another Plesk subscription or domain (e.g.
marketing.acme.com) and corresponding system user. - Repeat the NVM/Node/Strapi setup under that user, or choose to centralize Node in one user and manage multiple Strapi projects there — just be consistent.
- For each project:
- Use a unique port in
.env(e.g.,PORT=1341,PORT=1342, etc.). - Add a corresponding PM2 process with a unique name.
- Add Nginx proxy rules in Plesk that point to the correct port.
- Use a unique port in
Example .env snippet for a second instance:
|
1 2 3 4 |
HOST=0.0.0.0 PORT=1341 # rest of the config... |
Example Nginx directive for that domain:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
location / { proxy_pass http://127.0.0.1:1341; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 300; } |
With this pattern you can run multiple Strapi environments (staging, production, per-site CMS, etc.) safely on a single Plesk server.
11. Operational Tips
A few practical notes for production:
- Backups
Keep your Strapi project and uploads directory backed up (e.g.~/httpdocs/cmsand its/public/uploads), and use database-level backups for PostgreSQL. - Logs
PM2 captures logs, but you may want to implement log rotation or ship logs to a central system:
12pm2 logs strapi-cms - Updates
- Use NVM to install new Node LTS versions and test Strapi against them.
- Upgrade Strapi via
npm install @strapi/strapi@latest(or your chosen version), then rebuild:
123npm run buildpm2 restart strapi-cms
- Security
- Keep Plesk, Ubuntu packages, and Node dependencies patched.
- Use strong secrets in
.envand restrict access to that file (chmod 640and correct ownership). - Limit SSH to key-based auth if possible.
Conclusion
With Plesk handling domains and SSL, and Nginx/PM2 handling the application layer, you can host Strapi on a Ubuntu 24.04 Plesk server cleanly and repeatably. By using custom ports in .env, it’s trivial to run multiple Strapi instances on the same box without port conflicts.




