Strapi Deploy with GitHub Actions on Ubuntu 22.04 VPS

System Information
  • Strapi Version: 4.15.5
  • Operating System: Ubuntu 22.04 LTS
  • Database: MySQL 8.0.35
  • Node Version: 20.10
  • NPM Version: 10.2.4
  • Yarn Version: 1.22.21

I’ve managed so far to create locally a clean strapi app, setup and secure MySQL and Nginx on the server. I have for now a basic workflow, only to see if I could get it working. The actions runner runs as a service on Ubuntu, always ready to pick up any commit/push to my GH repo.

There’s one thing that doesn’t work though, that’s the automatic PM2 process launch.
When I push any change, the GH action says it is successfull, I have a PM2 process running my strapi instance, but always get a “502 bad gateway” when hitting the deployment URL.

If I stop the PM2 process and start the app with a remote yarn develop, the app is running as it should!

I have this basic PM2 config file:

module.exports = {
  apps: [
    {
      name: 'Strapi app LSP',
      script: 'yarn',
      args: 'develop',
    },
  ],
}

When typing pm2 start ecosystem.config.js, I’m getting the “502 bad gateway”.

Here’s my workflow YAML file (and, yes, my env variables are generated and valid because yarn develop works):

name: CD

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: self-hosted

    strategy:
      matrix:
        node-version: [20.x]

    steps:
      - name: Checkout 🛎
        uses: actions/checkout@v4

      - name: Install dependencies 👨🏻‍💻
        run: yarn install

      - name: Create .dotenv file
        uses: iamsauravsharma/create-dotenv@v2.0.1
        with:
          input-prefix: ""
          file-path: ".env"
          output-prefix: ""
        env:
          ADMIN_JWT_SECRET: ${{ secrets.ADMIN_JWT_SECRET }}
          API_TOKEN_SALT: ${{ secrets.API_TOKEN_SALT }}
          APP_KEYS: ${{ secrets.APP_KEYS }}
          HOST: ${{ secrets.HOST }}
          JWT_SECRET: ${{ secrets.JWT_SECRET }}
          PORT: ${{ secrets.PORT }}
          TRANSFER_TOKEN_SALT: ${{ secrets.TRANSFER_TOKEN_SALT }}
          DATABASE_CLIENT: ${{ secrets.DATABASE_CLIENT }}
          DATABASE_HOST: ${{ secrets.DATABASE_HOST }}
          DATABASE_PORT: ${{ secrets.DATABASE_PORT }}
          DATABASE_USERNAME: ${{ secrets.DATABASE_USERNAME }}
          DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
          DEV_DATABASE_NAME: ${{ secrets.DEV_DATABASE_NAME }}
          DEV_DATABASE_SSL: ${{ secrets.DEV_DATABASE_SSL }}
          PROD_DATABASE_NAME: ${{ secrets.PROD_DATABASE_NAME }}
          PROD_DATABASE_SSL: ${{ secrets.PROD_DATABASE_SSL }}
          CLOUDINARY_NAME: ${{ secrets.CLOUDINARY_NAME }}
          CLOUDINARY_KEY: ${{ secrets.CLOUDINARY_KEY }}
          CLOUDINARY_SECRET: ${{ secrets.CLOUDINARY_SECRET }}
          DEV_CLOUDINARY_FOLDER: ${{ secrets.DEV_CLOUDINARY_FOLDER }}
          PROD_CLOUDINARY_FOLDER: ${{ secrets.PROD_CLOUDINARY_FOLDER }}

      - name: Build Strapi app
        run: yarn build
     
      - name: Start Strapi app
        run: pm2 start ecosystem.config.js

      - name: Check PM2 status before
        run: pm2 status

      - name: Sync PM2
        run: pm2 save

So my pipeline is almost good, the last step is failing.
Can anyone help? Thanks!!

Well, in fact that works… wasn’t waiting long enough for Strapi to be fully fired and functional. This is wayyyyy longer than it used to as now a simple yarn develop rebuilds the entire admin panel even if it doesn’t need to.