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

Pipeline complet de Next.js în GitHub Actions: De la lint la deploy pe VPS prin SSH

De Liliana Ghiță, 9 sept. 2026 · 18 vizualizări · 3 like-uri

Postat 9 sept. 2026
bash
name: Deploy Next.js to VPS

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - name: Install & Test
        run: |
          npm ci
          npm run lint
          npm run test

      - name: Build Standalone
        run: npm run build

      - name: Deploy to VPS via SSH
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          source: ".next/standalone, .next/static, public"
          target: "/var/www/my-app"

      - name: Restart PM2
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/my-app
            cp -r .next/static .next/standalone/.next/
            cp -r public .next/standalone/
            pm2 reload ecosystem.config.js --update-env

Am văzut prea mulți colegi care dau git pull și npm run build direct pe VPS. Pe un server ieftin de 4GB RAM, când Next.js compilează rutele și împachetează Webpack sau Turbopack, OOM Killer-ul de Linux intră peste procese ca mascații și-ți dă jos Nginx-ul sau baza de date.

Am pățit treaba asta anul trecut pe un magazin cu vreo 14k utilizatori activi lunar. Soluția sănătoasă e banală: folosești runnerii gratuiți de la GitHub pentru munca grea (lint, teste, build) și trimiți pe VPS doar rezultatul gata compilat.

De ce facem build-ul în CI și nu pe server

Next.js are prostul obicei să devoreze memorie la build, mai ales dacă folosești generateStaticParams sau pagini SSR masive. Runnerii GitHub au 7GB RAM și resurse dedicate. Dacă crapă ceva la TypeScript sau ESLint, crapă în GitHub Actions, nu în fața clienților tăi.

În plus, am economisit în jur de 3-4 minute la fiecare release. Pe server nu mai instalezi devDependencies, nu mai rulezi TypeScript compiler, nu mai instalezi pachete inutile. Serverul de producție doar primește fișierele și dă un reload la proces.

Structura pipeline-ului: Lint, Test, Build, Ship

Pipeline-ul are două joburi mari. Primul validează codul, al doilea compilează și trimite fișierele prin SSH.

  1. Etapa de validare: Rulăm npm run lint și suita de jest sau vitest. Dacă un singur test pică, totul se oprește instant. Nu are sens să pierdem minute compilând ceva stricat.
  2. Etapa de build: Setăm în next.config.js opțiunea output: 'standalone'. Asta e cheia. Next.js creează un folder .next/standalone care conține doar codul minim necesar pentru producție, fără sutele de mega din node_modules.
  3. Deploy-ul: Arhivăm folderul standalone, fișierele statice din public și folderul .next/static. Le copiem pe VPS prin rsync sau scp, dezarhivăm și dăm un simplu pm2 reload ecosystem.config.js.

Trade-off-uri de care te lovești

Metoda asta e excelentă pentru proiecte medii, dar vine cu niște compromisuri reale.

Merge brici pentru un singur VPS și aplicații monolitice. În schimb, e nasol dacă începi să scalezi orizontal pe 3-4 servere; în punctul ăla, rsync prin SSH devine o ciorbă greu de menținut și ar trebui să treci pe containere Docker împinse într-un registry (GitHub Container Registry) și orchestrate prin Dokku, Coolify sau direct Kubernetes.

Un alt risc stupid: cheile SSH. Dacă folosești un user cu drepturi de root pentru deploy, un secret expus accidental în GitHub îți compromite toată infrastructura. Fă-ți mereu un user dedicat de deploy (ex: deployer), fără privilegii de sudo, care are voie să scrie doar în /var/www/app și să execute doar comanda de reload pentru PM2.

Voi cum împingeți proiectele mici în producție? Mergeți pe varianta clasică cu PM2 și rsync sau ați containerizat deja totul chiar și pe servere simple?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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