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

Pipeline complet de CI/CD pentru Next.js pe VPS cu GitHub Actions

De Elena Dumitrescu, 9 aug. 2026 · 8 vizualizări · 2 like-uri

Postat 9 aug. 2026
yaml
name: CI/CD Pipeline

on:
  push:
    branches: [main]

jobs:
  lint-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci
      - run: npm run lint

  deploy:
    needs: lint-and-test
    runs-on: ubuntu-latest
    steps:
      - name: Executare comenzi deploy pe VPS
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          script: |
            cd /var/www/my-next-app
            git pull origin main
            npm ci --omit=dev
            npm run build
            pm2 reload my-next-app || pm2 start npm --name "my-next-app" -- start

Vercel e minunat când începi un proiect, dar când traficul crește sau ai nevoie de procesare mai grea pe server, costurile sar aiurea. Am mutat recent o aplicație cu vreo 45k vizitatori lunari de pe Vercel pe un VPS de 6 euro de la Hetzner. Am câștigat control total, dar am pierdut deploy-ul automat la fiecare push — așa că a trebuit să mi-l construiesc singur cu GitHub Actions.

Strategia de deploy: build local vs build pe VPS

Prima dilemă la deploy-ul de Next.js pe un server privat este unde faci build-ul. Am încercat inițial să fac npm run build direct în runner-ul de GitHub, iar apoi să mut tot folderul .next prin rsync pe VPS. A fost o idee proastă.

Ecosistemul Next.js generează mii de fișiere mici în .next. Trimiterea lor prin SSH durează mai mult decât build-ul în sine, din cauza overhead-ului de rețea. Am schimbat abordarea: trag codul sursă pe VPS și fac build-ul direct acolo, gestionat prin PM2.

Atenție însă: dacă ai un VPS slab, de 1 vCPU și 1GB RAM, npm run build s-ar putea să dea Out Of Memory. În cazul ăla, soluția e să împachetezi build-ul din GitHub Actions într-o arhivă .tar.gz, o trimiți pe VPS și o dezarhivezi acolo.

Caching și optimizare: de la 6 minute la sub 2 minute

Fără un mecanism de cache, fiecare execuție de CI/CD descarcă din nou toate pachetele node_modules și recompilează toate paginile de la zero. La primele teste, pipeline-ul dura aproape 6 minute.

Am adăugat caching pentru două resurse critice:

  1. Directoriul de cache de la npm (prin acțiunea standard setup-node).
  2. Folderul .next/cache, unde Next.js păstrează rezultatele intermediare de la SWC/Babel și paginile statice pre-randate.

Rezultatul? Un build incremental care durează acum aproximativ 1 minut și 40 de secunde pe o schimbare medie de cod.

Gestionarea procesului cu PM2

Ca să nu ai downtime în momentul în care aplicația se repornește pe server, recomand folosirea PM2 în modul cluster sau pur și simplu un pm2 reload în loc de pm2 restart. Comanda reload așteaptă ca noul proces să fie gata înainte să le închidă pe cele vechi.

Pentru securitate, am creat un user separat pe VPS (deploy-user) care are acces doar la folderul aplicației /var/www/app și nu are drepturi de sudo. Am adăugat cheia SSH publică a pipeline-ului în ~/.ssh/authorized_keys ale acestui user.

Trade-off-ul e evident: pe Vercel dai un click și ai preview deployments pentru fiecare Pull Request. Pe VPS pierzi funcționalitatea asta (sau trebuie să ți-o construiești manual cu subdomenii dinamice), dar economisești sute de dolari anual și nu depinzi de o platformă proprietary.

Voi ce soluție folosiți pentru deploy-ul de Next.js pe infrastructură proprie — mergeți pe Docker cu Swarm/K8s sau direct Node process managers precum PM2?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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