Strapi 5 on a VPS: Secure Production Setup in Under an Hour

Web Development

Strapi 5 on a VPS: Secure Production Setup in Under an Hour

Introduction: Why Self-Hosting Strapi 5 Makes Business Sense

In today's digital landscape, content management systems (CMS) form the backbone of most modern websites and applications. While cloud-hosted solutions offer convenience, self-hosting on a Virtual Private Server (VPS) provides unparalleled control, security, and cost-effectiveness for growing businesses.

Strapi 5, the latest iteration of the popular open-source headless CMS, delivers exceptional flexibility for developers while maintaining an intuitive interface for content editors. When deployed correctly on a VPS, it creates a powerful foundation for scalable content-driven experiences across web, mobile, and IoT platforms.

This comprehensive guide walks technical teams through establishing a production-ready Strapi 5 instance on a VPS in under 60 minutes. Whether you're migrating from a cloud-hosted solution or building from scratch, these battle-tested steps ensure a secure, optimized deployment that maximizes performance while minimizing operational costs.

Key Benefit: Self-hosting Strapi 5 on a VPS typically reduces monthly hosting costs by 40-70% compared to equivalent managed services while providing complete control over your infrastructure and data.

Prerequisites: What You'll Need

Before diving into the deployment process, ensure you have:

  1. A VPS instance with at least 2GB RAM and 1 vCPU (recommended providers: DigitalOcean, Linode, or Vultr)
  2. Domain name with DNS management access
  3. SSH access to your VPS (terminal for Mac/Linux or PuTTY for Windows)
  4. Basic command line knowledge and familiarity with Node.js ecosystems
  5. Existing Strapi project (or create one with npx create-strapi-app@latest my-project)

Pro Tip: While 2GB RAM is the minimum recommendation, allocating 4GB significantly improves build performance when working with complex content types or numerous API endpoints.

Step 1: Initial VPS Configuration and Security Hardening

Your VPS security forms the foundation of your Strapi deployment. Let's establish a robust environment before installing any application components.

1.1 Accessing Your VPS via SSH

Connect to your newly provisioned server using:

bash
ssh username@YOUR_SERVER_IP

If you encounter connection issues due to known_hosts errors, apply these permissions:

bash
chmod 700 ~/.ssh
chmod 600 ~/.ssh/known_hosts

1.2 Setting the Hostname and Configuring DNS

Establish a proper hostname for system identification:

bash
sudo hostnamectl set-hostname content.yourdomain.com

Next, update your hosts file to reflect this configuration:

bash
sudo nano /etc/hosts

Add the following line:

txt
1YOUR_SERVER_IP content.yourdomain.com

In your domain registrar's DNS settings, create an A record that points content.yourdomain.com to your server's IP address. This configuration typically propagates within 30 minutes to 24 hours, depending on your DNS provider.

1.3 System Updates and Essential Packages

Ensure your system packages are current to patch potential security vulnerabilities:

bash
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl git unzip ufw

Step 2: Setting Up the Database Environment

Strapi 5 supports multiple database systems, but PostgreSQL offers the best combination of performance, reliability, and feature support for production deployments.

2.1 PostgreSQL Installation

Install PostgreSQL server and client tools:

bash
sudo apt install -y postgresql postgresql-contrib

2.2 Database and User Configuration

Create a dedicated database and user for your Strapi application:

bash
sudo -i -u postgres
psql

Inside the PostgreSQL console, execute:

sql
1CREATE DATABASE strapidb;
2CREATE USER strapiuser WITH ENCRYPTED PASSWORD 'YOUR_SECURE_PASSWORD';
3GRANT ALL PRIVILEGES ON DATABASE strapidb TO strapiuser;
4\q
5exit

Security Note: Generate a strong, unique password for your database user. Consider using openssl rand -hex 16 to create a cryptographically secure random string.

Step 3: Node.js Environment Setup

Strapi 5 requires Node.js 18 or higher. Let's install the LTS version for optimal stability.

bash
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs

Verify the installation with:

bash
node -v  # Should show v18.x.x or higher
npm -v   # Should show 8.x.x or higher

Step 4: Deploying Your Strapi 5 Application

With our environment prepared, we can now deploy the Strapi application itself.

4.1 Clone Your Repository

If your Strapi project is hosted in a Git repository (recommended for team environments):

bash
cd ~
git clone https://github.com/YOUR_USERNAME/YOUR_REPO.git strapi-production
cd strapi-production

Alternatively, you can transfer your local project via SCP or SFTP.

4.2 Installing Dependencies

Install required packages and production dependencies:

bash
npm install
npm install pg dotenv --save

4.3 Environment Configuration for Production

Create a dedicated production environment configuration:

bash
mkdir -p config/env/production
touch config/env/production/.env

Edit this file with your preferred text editor and add:

txt
1HOST=0.0.0.0
2PORT=1337
3APP_KEYS=key1,key2,key3,key4
4API_TOKEN_SALT=YOUR_TOKEN_SALT
5ADMIN_JWT_SECRET=YOUR_ADMIN_JWT
6JWT_SECRET=YOUR_JWT_SECRET
7TRANSFER_TOKEN_SALT=YOUR_TRANSFER_SALT
8
9# Database
10DATABASE_CLIENT=postgres
11DATABASE_HOST=localhost
12DATABASE_PORT=5432
13DATABASE_NAME=strapidb
14DATABASE_USERNAME=strapiuser
15DATABASE_PASSWORD=YOUR_SECURE_PASSWORD
16DATABASE_SSL=false

For the various secret keys, generate random strings:

bash
openssl rand -hex 32  # Run this multiple times for each key

4.4 Database Connection Configuration

Create a database configuration file specific to production:

bash
nano config/env/production/database.ts

Add the following configuration:

typescript
1export default ({ env }) => ({
2  connection: {
3    client: env('DATABASE_CLIENT', 'postgres'),
4    connection: {
5      host: env('DATABASE_HOST', 'localhost'),
6      port: env.int('DATABASE_PORT', 5432),
7      database: env('DATABASE_NAME', 'strapidb'),
8      user: env('DATABASE_USERNAME', 'strapiuser'),
9      password: env('DATABASE_PASSWORD'),
10      ssl: env.bool('DATABASE_SSL', false),
11    },
12    debug: false,
13  },
14});

4.5 Building for Production

Build your Strapi application for production deployment:

bash
NODE_ENV=production npm run build

This process may take several minutes, especially on VPS instances with limited resources.

Step 5: Process Management with PM2

To ensure your Strapi application runs continuously and restarts automatically after server reboots, we'll implement PM2.

5.1 Installing PM2

bash
npm install -g pm2

5.2 Starting Strapi with PM2

bash
pm2 start npm --name "strapi-production" -- run start

5.3 Configuring PM2 Startup

bash
pm2 save
pm2 startup systemd

Follow the instructions provided by the pm2 startup command to enable automatic startup.

Step 6: Reverse Proxy with Nginx and SSL

To expose your Strapi instance securely to the internet, we'll use Nginx as a reverse proxy with SSL encryption.

6.1 Installing Nginx

bash
sudo apt install -y nginx

6.2 Configuring Nginx

Create a new Nginx configuration file:

bash
sudo nano /etc/nginx/sites-available/strapi

Add the following configuration:

nginx
1server {
2    server_name content.yourdomain.com;
3
4    location / {
5        proxy_pass http://localhost:1337;
6        proxy_http_version 1.1;
7        proxy_set_header X-Forwarded-Host $host;
8        proxy_set_header X-Forwarded-Server $host;
9        proxy_set_header X-Real-IP $remote_addr;
10        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
11        proxy_set_header X-Forwarded-Proto $scheme;
12        proxy_set_header Host $http_host;
13        proxy_set_header Upgrade $http_upgrade;
14        proxy_set_header Connection "Upgrade";
15        proxy_pass_request_headers on;
16    }
17}

Enable this configuration:

bash
sudo ln -s /etc/nginx/sites-available/strapi /etc/nginx/sites-enabled/
sudo nginx -t  # Test configuration
sudo systemctl restart nginx

6.3 SSL Certificate with Let's Encrypt

Secure your application with a free SSL certificate:

bash
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d content.yourdomain.com

Follow the prompts to complete the SSL configuration.

Step 7: Firewall Configuration

Implement a basic firewall to protect your server:

bash
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Verify the firewall status:

bash
sudo ufw status

Step 8: Data Migration (For Existing Projects)

If you're migrating from Strapi Cloud or another hosting provider, you'll need to transfer your data.

8.1 Using Strapi's Transfer Tool

For automated migration from another Strapi instance:

bash
npx strapi transfer --from=remote --url=https://YOUR_EXISTING_STRAPI/admin --token=YOUR_TRANSFER_TOKEN

8.2 Manual Database Migration

If automatic transfer isn't available:

  1. Export from source:

    bash
    pg_dump -h SOURCE_HOST -U SOURCE_USER -d SOURCE_DB -F c -f backup.dump
  2. Transfer to your VPS:

    bash
    scp backup.dump username@YOUR_SERVER_IP:/home/username/
  3. Restore on your VPS:

    bash
    pg_restore -U strapiuser -d strapidb -F c backup.dump

8.3 Media Files Transfer

For transferring uploads and media files:

bash
rsync -avz -e ssh /path/to/local/uploads/ username@YOUR_SERVER_IP:/home/username/strapi-production/public/uploads/

Step 9: Performance Optimization

Fine-tune your Strapi deployment for optimal performance:

9.1 Node.js Memory Allocation

Edit your PM2 configuration:

bash
pm2 stop strapi-production
pm2 start npm --name "strapi-production" --node-args="--max_old_space_size=2048" -- run start
pm2 save

9.2 Nginx Caching for Static Assets

Enhance Nginx configuration for static asset caching:

bash
sudo nano /etc/nginx/sites-available/strapi

Add within the server block:

nginx
1location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
2    proxy_pass http://localhost:1337;
3    expires 30d;
4    add_header Cache-Control "public, no-transform";
5}

Restart Nginx:

bash
sudo systemctl restart nginx

Step 10: Maintenance and Update Strategy

Establish a robust maintenance routine for long-term stability:

10.1 Regular Backups

Set up automated daily database backups:

bash
mkdir -p ~/backups
crontab -e

Add:

txt
10 0 * * * pg_dump -U strapiuser -d strapidb -F c -f ~/backups/strapi-backup-$(date +\%Y\%m\%d).dump

10.2 Update Procedure

When updating your Strapi application:

  1. Pull latest changes:

    bash
    cd ~/strapi-production
    git pull origin main
  2. Install dependencies:

    bash
    npm install
  3. Rebuild and restart:

    bash
    NODE_ENV=production npm run build
    pm2 restart strapi-production

10.3 Monitoring

Implement basic monitoring with PM2:

bash
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 10M
pm2 set pm2-logrotate:retain 7

Conclusion: Your Strapi Deployment is Complete

Following this guide, you've successfully deployed a production-ready Strapi 5 instance on your VPS with:

  • PostgreSQL database integration
  • Process management with PM2
  • Secure HTTPS access through Nginx
  • Automated backups
  • Performance optimizations

Your Strapi CMS is now ready to power your content-driven digital experiences with maximum flexibility and control at a fraction of the cost of cloud-hosted alternatives.

Did you know? Self-hosting Strapi can reduce your total cost of ownership by up to 65% compared to equivalent managed SaaS alternatives over a two-year period.

Need Expert Development Support?

At Ideaflow Studio, we specialize in crafting exceptional digital experiences powered by modern headless CMS architectures. Our team of certified Strapi experts can help you:

  • Design and implement custom content models optimized for your business needs
  • Develop feature-rich front-end applications using Next.js, Nuxt, or React
  • Optimize your existing Strapi deployment for maximum performance and security
  • Migrate from legacy CMS platforms to a modern headless architecture

Contact us today at hello@ideaflow.studio to discuss how we can help accelerate your digital transformation with Strapi.

*[VPS]: Virtual Private Server *[CMS]: Content Management System