How I set up Strapi on my VPS for My Portfolio

How I set up Strapi on my VPS for My Portfolio

Published on: September 6, 2025

TL;DR

  • Problem: Images from Strapi were blocked due to Mixed Content when my portfolio ran on HTTPS.
  • Solution: Use Nginx Reverse Proxy to serve Strapi over HTTPS.
  • Result: Portfolio can fetch blog posts and images securely and reliably.

This post is to document my experience setting up Strapi CMS on a VPS and connecting it to my portfolio website.

It's written for:

  • Anyone who wants to self-host their own CMS.
  • Or simply curious about how to set up VPS + Strapi + Nginx Reverse Proxy.

When I worked on this project, I wanted everything to be basic and self-built, without relying on PaaS services or pre-made templates.

You might need to adjust some steps depending on where you purchased your domain.


1. Renting a VPS and Initial Setup

I rented a VPS running Ubuntu.

The very first thing to do after accessing the VPS is to update the system:

sudo apt update && sudo apt upgrade -y

This ensures your system is fully updated before installing Strapi or other software.


2. Installing Strapi

Next, I installed Strapi as usual:

npx create-strapi-app@latest my-project
cd my-project
npm run develop

At this point, Strapi runs at:

http://<VPS-IP>:1337/

Everything worked perfectly during development.

I then created two basic Collection Types:

  • Article → for blog posts.
  • Category → for classifying posts.

After that, I opened API Permissions to allow read access, so my portfolio site could fetch the blog data.


3. The Issue When Going Public

When I finished development and deployed my portfolio, I encountered a critical problem:

  • My portfolio runs on HTTPS (thanks to Cloudflare).
  • Strapi only runs on HTTP at http://<VPS-IP>:1337/.

This caused the browser to block all images fetched from Strapi due to Mixed Content — browsers don't allow HTTP content inside an HTTPS site.

Result: Blog images could not load on my portfolio.


4. The Solution: Nginx Reverse Proxy

To fix this, I used Nginx Reverse Proxy.

Here's how it works:

  • Nginx sits between the client and Strapi.
  • It takes HTTPS requests and forwards them internally to HTTP port 1337 on the VPS.

This way, users only see a clean HTTPS domain like:

https://strapi.jokholk.dev

While internally, Strapi continues to run on HTTP.


5. Setting Up Cloudflare

I used Cloudflare to manage my domain jokholk.dev.

First, I created an A Record:

  • Type: A
  • Name: strapi
  • IPv4 address: VPS IP
  • Proxy status: DNS Only (disable the orange proxy icon)

Now, strapi.jokholk.dev points to the VPS.

Note:

  • You can use any subdomain, like cms.yourdomain.com.
  • It doesn't have to be exactly strapi.

6. Running Strapi with PM2

To keep Strapi running in the background even after I close the terminal, I used PM2:

npm install -g pm2
pm2 start "npm run start" --name my-strapi
pm2 save

Check status:

pm2 status

PM2 ensures Strapi stays alive and restarts automatically if it crashes — perfect for production environments.


7. Installing and Configuring Nginx

Install Nginx:

sudo apt install nginx -y

Create a new config file for strapi.jokholk.dev:

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

Add the following configuration:

server {
    listen 80;
    server_name strapi.jokholk.dev;

    location / {
        proxy_pass http://127.0.0.1:1337;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Enable the config:

sudo ln -s /etc/nginx/sites-available/strapi /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

8. Adding SSL with Certbot

Finally, I used Certbot to enable free SSL for my domain:

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d strapi.jokholk.dev

Once completed, you can access Strapi via:

https://strapi.jokholk.dev

9. Testing the Result

  • Access the CMS admin panel via:
  • https://strapi.jokholk.dev/admin
  • Images in blog posts now load perfectly on the portfolio.
  • Mixed Content no longer exists.

10. How Nginx Reverse Proxy Works

The current data flow looks like this:

[Browser] --HTTPS--> [Nginx Reverse Proxy] --HTTP:1337--> [Strapi]
  • The user only interacts with a clean HTTPS domain.
  • Nginx acts as the middle layer, so Strapi doesn't need to manage SSL directly.

This completely solves the Mixed Content issue in a clean way.


11. Summary of Steps

Here's what I did from start to finish:

  1. Rent a VPS → Install Ubuntu → Update system.
  2. Install Strapi and set up basic collections (Article, Category).
  3. Use PM2 to keep Strapi running.
  4. Configure Nginx Reverse Proxy for HTTPS access.
  5. Manage domain via Cloudflare using an A record.
  6. Final result: Portfolio can safely fetch data from Strapi via HTTPS.