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

Cum mi-am automatizat flow-ul de Next.js pe VPS: GHA fără bătăi de cap

De Marian Apostol, 23 apr. 2026 · 2 vizualizări · 3 like-uri

Postat acum 4 zile
yaml
name: CI/CD Pipeline
on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    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: Lint & Test
        run: |
          npm run lint
          npm run test

      - name: Build project
        run: npm run build
        env:
          NEXT_PUBLIC_API_URL: ${{ secrets.API_URL }}

      - name: Deploy to VPS via SSH
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USERNAME }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            cd /var/www/my-app
            git pull origin main
            npm install --production
            npm run build
            pm2 restart my-next-app

Am trecut prin faza aia în care dădeam ssh în server, un git pull obosit, și apoi mă rugam să nu crape npm run build pentru că RAM-ul era deja la limită. La un proiect recent, un mic SaaS cu vreo 1200 de useri activi, am decis că e momentul să nu mai pierd 10 minute la fiecare deploy și să risc downtime că am uitat să dau install la o dependență nouă.

Să fim realiști: Vercel e mișto până când vezi factura sau când ai nevoie de un VPS pentru că rulezi și alte servicii pe lângă. Dacă ești pe un VPS de 5-10 euro, GitHub Actions e salvarea ta, dar trebuie configurat cu cap ca să nu pierzi ore întregi debuguind YAML-uri.

De ce facem build-ul pe GitHub și nu pe server?

Am pățit-o pe un VPS cu 2GB RAM: când dădeam build la un proiect Next.js mai mărișor, procesul de Webpack/Turbo mânca tot RAM-ul și îmi omora baza de date. E groaznic. Strategia mea e simplă: fac tot ce e greu pe runner-ul de la GitHub (care e moca în limitele de 2000 min/lună) și pe server doar mut fișierele și dau un restart la proces.

În pipeline-ul ăsta am inclus trei etape mari: verificarea codului, build-ul propriu-zis și mutarea fișierelor prin SSH. Am reușit să scad timpul total de la 5 minute la sub 160 de secunde folosind caching-ul de la GitHub pentru node_modules și .next/cache.

Pipeline-ul care nu dă rateuri

Prima parte e plictisitoare dar obligatorie: lint și test. Dacă ai uitat un punct și virgulă sau ai stricat un test de unitate, pipeline-ul crapă imediat. Nu vrei să ajungă cod prost pe producție.

Trade-off-ul aici e timpul de execuție. Dacă ai sute de teste, poate vrei să le rulezi în paralel, dar pentru majoritatea proiectelor noastre, rularea secvențială e ok.

După ce trece testarea, fac build-ul. Aici e un mic truc: trebuie să te asiguri că variabilele de mediu (.env) sunt disponibile și în faza de build dacă ai chestii care se injectează la compile-time. Eu le țin în GitHub Secrets și le scriu într-un fișier .env temporar înainte de npm run build.

Deploy-ul prin SSH: Rsync e sfânt

Am încercat diverse acțiuni de SSH din marketplace, dar appleboy/ssh-action combinat cu rsync mi se pare cea mai stabilă variantă. Ideea e să trimiți doar diferențele, nu tot folderul node_modules de fiecare dată.

Totuși, mare atenție la folderele pe care le trimiți. Dacă trimiți tot folderul .next, asigură-te că serverul știe să facă swap-ul rapid. Eu folosesc PM2 pentru managementul procesului pe VPS. După ce fișierele sunt sus, execut o comandă simplă: pm2 restart app-name.

Un mare minus la abordarea asta? Dacă build-ul tău e uriaș (sute de MB), transferul prin SSH poate dura. La proiectul de care ziceam, artifact-ul de build are cam 45MB arhivat, deci zboară rapid pe o conexiune de 1Gbps.

Ce am învățat pe pielea mea

  1. Cache is king: Fără actions/cache, instalezi dependențele de la zero la fiecare push. Am economisit cam 40% din build time doar cu asta.
  2. Security: Nu folosi parola de root. Creează un user separat (ex: deploy-user), dă-i acces doar în folderul proiectului și folosește o cheie SSH dedicată, fără passphrase, adăugată în GitHub Secrets.
  3. Artifacts: Uneori e mai bine să uploadezi build-ul ca artifact în GitHub și să-l downloadezi pe server, dar pentru simplitate, rsync direct din runner e mult mai rapid de configurat.

La final, ai un flux în care dai git push origin main și în 3 minute site-ul e live, testat și curat. Voi cum faceți? Mergeți pe varianta Dockerized sau rămâneți la deploy-ul clasic pe „fier”?

Deploy-ul pe VPS rămâne varianta mea preferată pentru proiecte medii unde vrei control total fără costurile de „convenience tax” ale platformelor de tip PaaS.

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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