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

GitHub Actions pentru Next.js: Pipeline de CI/CD complet pe propriul tău VPS

De Ioan Manole, 3 iun. 2026 · 2 vizualizări · 2 like-uri

Postat acum 6 zile
yaml
name: Deploy Next.js to VPS

on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: 'npm'

      - name: Cache Next.js build
        uses: actions/cache@v3
        with:
          path: ${{ github.workspace }}/.next/cache
          key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
          restore-keys: |
            ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-

      - name: Install dependencies
        run: npm ci

      - name: Run Lint & Tests
        run: |
          npm run lint
          npm run test -- --watchAll=false

      - name: Build application
        run: npm run build
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}

      - name: Compress build files
        run: tar -czf deploy.tar.gz .next public package.json package-lock.json next.config.js

      - name: Copy archive to VPS via SSH
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.VPS_IP }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          source: "deploy.tar.gz"
          target: "/var/www/my-next-app"

      - name: Deploy and Restart PM2
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.VPS_IP }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/my-next-app
            tar -xzf deploy.tar.gz
            rm deploy.tar.gz
            npm ci --only=production
            pm2 reload my-next-app || pm2 start npm --name "my-next-app" -- start

Să fim sinceri, Vercel este genial pentru prototipuri sau proiecte mici, dar când începi să ai trafic sau vrei să legi baza de date local, costurile devin ridicole. La un proiect recent, cu vreo 14.000 de utilizatori activi pe lună, am decis să mut totul pe un VPS ieftin de la Hetzner.

Marea provocare a fost să nu pierd confortul acelui „git push” care declanșează deploy-ul automat. Așa că mi-am scris propriul workflow în GitHub Actions. Am trecut prin toate erorile posibile de permisiuni și build-uri eșuate până am ajuns la o variantă stabilă, care rulează în mai puțin de 3 minute.

Optimizarea cache-ului: Cum am redus timpul de build cu 60%

Cea mai mare greșeală pe care o văd în pipeline-urile de Next.js este lipsa cache-ului pentru folderul .next/cache. Fără el, Next.js recompilează absolut fiecare pagină și componentă de la zero la fiecare rulare.

Inițial, build-ul meu dura aproape 7 minute pe runner-ul gratuit de la GitHub. După ce am configurat corect cache-ul pentru node_modules și .next/cache folosind actions/cache, timpul a scăzut la puțin sub 2 minute și jumătate. Diferența e uriașă când ai de făcut hotfix-uri rapide în producție.

Build pe runner vs. Build pe VPS

Aici e un trade-off important de care m-am lovit. Ai două opțiuni: faci build-ul pe serverul tău sau îl faci direct în GitHub Actions și trimiți doar rezultatul.

Eu am ales să fac build-ul pe runner-ul de GitHub dintr-un motiv simplu: next build mănâncă foarte multă memorie RAM. Dacă ai un VPS cu 2GB RAM și rulezi build-ul direct acolo în timp ce ai și utilizatori pe site, sunt șanse mari ca procesul să fie omorât de sistem (out of memory) sau site-ul să devină extrem de lent timp de un minut.

Prin urmare, pipeline-ul meu face build-ul în cloud, arhivează folderele .next, public, package.json și next.config.js, le trimite prin SSH pe VPS, le dezarhivează și dă restart la procesul de Node.js.

Compromisul sincer: Avantaje și dezavantaje

Să fim realiști, soluția asta nu e perfectă.

Ce câștigi: Plătești doar VPS-ul (5-10 euro pe lună), ai control total asupra serverului, poți rula baze de date sau procese de background pe aceeași mașină și nu ai limite de bandwidth absurde ca pe platformele serverless.

Ce pierzi: Trebuie să te ocupi singur de reverse proxy (Nginx sau Caddy), de reînnoirea certificatelor SSL cu Certbot și de monitorizarea proceselor. Dacă PM2 moare la 3 dimineața, e treaba ta să îl ridici înapoi.

Pentru a evita downtime-ul în timpul deploy-ului, folosesc PM2 în modul cluster. Când dau pm2 reload app, acesta repornește instanțele una câte una, asigurând zero downtime pentru vizitatori.

Cum vă gestionați deploy-urile de Next.js? Rămâneți pe Vercel pentru confort sau preferați controlul unui server dedicat?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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