eduardweb.
DevOps & VPSIntermediar#nextjs#devops#pm2#vps#github-actions

GitHub Actions pentru Next.js: Pipeline de la lint la deploy pe VPS prin SSH

De Maria Vasilescu, 24 mai 2026 · 4 vizualizări · 2 like-uri

Postat 24 mai 2026
yaml
name: CI/CD Pipeline

on:
  push:
    branches: [ main ]

jobs:
  test-and-lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
          
      - name: Install dependencies
        run: npm ci
        
      - name: Run Lint
        run: npm run lint

  deploy:
    needs: test-and-lint
    runs-on: ubuntu-latest
    steps:
      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          port: ${{ secrets.VPS_PORT || 22 }}
          script: |
            cd /var/www/app
            git pull origin main
            npm ci --omit=dev
            npm run build
            pm2 reload my-app

Mi s-a luat de facturile de pe Vercel când un proiect personal a trecut de 15k vizitatori unici pe lună și am început să fiu taxat aiurea pentru bandwidth. Am mutat totul pe un VPS de 6 euro de la Hetzner. Singura chestie care îmi lipsea era deploy-ul automat la fiecare push în main.

Am rezolvat problema cu un workflow simplu în GitHub Actions. Am economisit cam 35% la build time după ce am reglat cache-ul și acum am control total pe server. Mai jos îți arăt cum am structurat pipeline-ul și de ce probleme m-am lovit pe parcurs.

Strategia de build: Pe GitHub sau pe VPS?

Aici e primul trade-off major pe care trebuie să-l înțelegi. Ai două opțiuni:

  1. Faci build-ul direct pe GitHub Actions, creezi o arhivă cu folderul .next și o trimiți prin SCP pe server.
  2. Tragi codul pe VPS via Git și rulezi npm run build direct pe server.

Am început cu a doua variantă pentru că era mai simplu de scris în YAML. Dar am dat rapid de o problemă: dacă ai un VPS ieftin cu doar 1GB sau 2GB RAM, procesul de build de la Next.js o să consume toate resursele. OOM (Out Of Memory) killer-ul de la Linux o să-ți închidă procesul exact când ți-e lumea mai dragă.

Pentru proiecte mici, poți rula build-ul direct pe server doar dacă adaugi un fișier swap de măcar 2GB. În exemplul de mai jos, mergem pe varianta rulării pe server, dar cu mențiunea că swap-ul e obligatoriu dacă ai resurse limitate.

Structura pipeline-ului

Workflow-ul nostru face patru lucruri: verifică codul, rulează linter-ul, rulează testele (dacă ai) și apoi se conectează prin SSH pe server pentru a trage ultimele modificări și a restarta aplicația.

Folosesc appleboy/ssh-action pentru partea de SSH. E o acțiune stabilă, o folosesc de ani de zile și nu mi-a făcut niciodată figuri. Pe server, folosesc PM2 ca să țin aplicația Next.js pornită în fundal.

Setup-ul pe server

Înainte să dai drumul la pipeline, trebuie să pregătești serverul. Te conectezi prin SSH și clonezi repo-ul în directorul dorit (de exemplu, /var/www/app).

Tot acum trebuie să configurezi PM2. Rulează o singură dată manual:

pm2 start npm --name "my-app" -- start

După asta, pipeline-ul se va ocupa doar de pm2 reload my-app. Avantajul la reload față de restart este că PM2 va încerca să mențină aplicația online în timp ce încarcă noul cod, reducând downtime-ul la zero dacă ai configurat cluster mode.

Un mic pont pentru performanță

Implicit, Next.js are nevoie de cache-ul din .next/cache ca să facă build-uri rapide. Dacă rulezi build-ul pe GitHub Actions, merită să folosești acțiunea de cache dedicată pentru Next.js. Dacă rulezi build-ul direct pe VPS (ca în exemplul de mai jos), cache-ul se păstrează de la un build la altul în folderul local, ceea ce scurtează considerabil timpul de așteptare.

Tu cum abordezi deploy-ul de Next.js? Rămâi pe serverless sau preferi controlul și costurile fixe ale unui VPS?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.