[{"data":1,"prerenderedAt":169},["ShallowReactive",2],{"seo-verification":3,"blog-deploy-a-nextjs-application-on-a-vps-ma-en":6,"promo-bar-likely":168},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-deploy-a-nextjs-application-on-a-vps-ma-en",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":28,"featuredImage":30,"bgImage":31,"posterImage":32,"relatedSolution":33,"intro":36,"sections":37,"ctaTitle":110,"ctaBody":111,"ctaButton":112,"ctaUrl":113,"relatedPosts":114},46,"deploy-a-nextjs-application-on-a-vps",{"fr":12,"en":10,"ar":13,"es":14},"deployer-nextjs-vps","نشر-تطبيق-nextjs-على-vps","desplegar-nextjs-en-un-vps","Deploy a Next.js Application on a VPS","Deploy Next.js on a VPS: Node.js, PM2, Nginx, SSL, and SSR. A complete guide for developers and agencies who want to self-host.",13,1,false,"2026-05-05T00:00:00+00:00","2026-11-04T16:30:25+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},4,"Development","developpement","bg-warning\u002F10 text-warning","dev",[29],{"id":23,"name":24,"slug":25,"color":26,"icon":27},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fdeployer-nextjs-vps-poster.svg",{"categorySlug":34,"appSlug":35},"development","nextjs-stack","Next.js combines server-side rendering, static generation, and API routes in a single React framework. Deploying it on a VPS rather than on a proprietary platform frees you from function quotas, bandwidth limits, and vendor lock-in, while keeping SSR fully operational.",[38,42,52,55,58,61,83,86,89,92,95,98,101,104,107],{"type":39,"title":40,"body":41},"h2","Why Self-Host Next.js on a VPS?","Next.js is often associated with a specific hosting platform, but its standalone Node.js server runs perfectly on any VPS. Self-hosting becomes worthwhile as soon as you make intensive use of SSR, ISR (incremental static regeneration), or API routes: these features consume billed invocations on managed platforms, whereas they are free and without quota on your server. You control the ISR cache on disk, the bandwidth of optimized images, and the function execution time, with no 10-second limit. For an agency hosting several client sites, a VPS pools the costs and simplifies billing.",{"type":43,"title":44,"items":45},"ul","Concrete Benefits of a Self-Hosted Next.js",[46,47,48,49,50,51],"SSR and API routes with no invocation quota or per-function billing.","Persistent ISR cache on disk, no revalidation lost between deployments.","Included bandwidth, ideal for image- and video-rich sites.","Several Next.js projects on a single VPS, pooled under Nginx.","`next\u002Fimage` image optimization served locally with no per-transformation extra cost.","Build and deployment controlled via Git, CI\u002FCD, or a simple `git pull` and rebuild.",{"type":39,"title":53,"body":54},"Hardware and Software Prerequisites","The Next.js build is memory-hungry: plan for at least 2 GB of RAM (4 GB for a large project with many pages), otherwise the build may fail for lack of memory. On the runtime side, 1 to 2 vCPU are enough to serve SSR. Install Node.js 18 or 20 LTS, either natively with `nvm` or via a `node:20-alpine` Docker image. Use PM2 to supervise the Node process, or Docker for isolation. A domain pointed to the VPS is required for SSL. Enable `output: 'standalone'` in `next.config.js` for a lightweight deployment.",{"type":39,"title":56,"body":57},"Docker Multi-Stage Build: node:20-alpine","A Docker multi-stage build reduces the final image to the essentials and avoids shipping build tools into production. The three-stage strategy — **deps**, **builder**, **runner** — is the most common approach for Next.js in `standalone` mode.\n\n```dockerfile\n# Stage 1 — dependencies\nFROM node:20-alpine AS deps\nWORKDIR \u002Fapp\nCOPY package.json package-lock.json .\u002F\nRUN npm ci --omit=dev\n\n# Stage 2 — build\nFROM node:20-alpine AS builder\nWORKDIR \u002Fapp\nCOPY --from=deps \u002Fapp\u002Fnode_modules .\u002Fnode_modules\nCOPY . .\nRUN npm run build\n\n# Stage 3 — runner (final image)\nFROM node:20-alpine AS runner\nWORKDIR \u002Fapp\nENV NODE_ENV=production\nCOPY --from=builder \u002Fapp\u002F.next\u002Fstandalone .\u002F\nCOPY --from=builder \u002Fapp\u002F.next\u002Fstatic .\u002F.next\u002Fstatic\nCOPY --from=builder \u002Fapp\u002Fpublic .\u002Fpublic\nEXPOSE 3000\nCMD [\"node\", \"server.js\"]\n```\n\nThe `deps` stage installs production-only dependencies (`--omit=dev`). The `builder` stage copies the full source and runs `npm run build` with access to modules. The `runner` stage contains only the `standalone` folder generated by Next.js, static assets, and the `public` folder — no source `node_modules`, no build configuration files. The final image is often two to three times smaller than a naive image.",{"type":39,"title":59,"body":60},"Environment Variables: .env.local vs .env.production","Next.js distinguishes two families of variables according to their scope.\n\n**Public variables (`NEXT_PUBLIC_*`)**: they are bundled into the JavaScript bundle at build time and exposed to the browser. They are suitable for a public API URL, a Google Analytics ID, or a feature flag. Never place a secret in them.\n\n**Server variables**: read only on the Node side (API routes, Server Components, `getServerSideProps`). They are never sent to the client. This is where third-party API keys, database connection strings, and JWT secrets live.\n\n```bash\n# .env.local — local development (never committed)\nNEXT_PUBLIC_API_URL=http:\u002F\u002Flocalhost:4000\nDATABASE_URL=postgresql:\u002F\u002Fuser:pass@localhost:5432\u002Fmydb\n\n# .env.production — production values (never committed either)\nNEXT_PUBLIC_API_URL=https:\u002F\u002Fapi.example.com\nDATABASE_URL=postgresql:\u002F\u002Fuser:secret@db.internal:5432\u002Fmydb\n```\n\nOn the VPS, two approaches coexist: inject variables into the PM2 process environment via its ecosystem file (`ecosystem.config.js`), or pass them to Docker via `--env-file .env.production`. The second is preferable: the file stays on the server's disk, outside the git repository, and Docker mounts it at container startup without exposing it in logs.\n\nNote: `NEXT_PUBLIC_*` variables must be known **at build time**, not just at startup. If you change a public variable after the build, you must rebuild the application.",{"type":62,"title":63,"steps":64},"steps","Deploy Next.js Step by Step",[65,68,71,74,77,80],{"title":66,"body":67},"Prepare the Server","Over SSH, install Node.js 20 LTS and PM2 (`npm install -g pm2`), or Docker. Clone the repository and create `.env.production` with your variables (`NEXT_PUBLIC_*` for the client, server secrets for the API routes).",{"title":69,"body":70},"Build the Application","Run `npm ci`, then `npm run build`. With `output: 'standalone'`, Next.js generates a self-contained `.next\u002Fstandalone` folder containing only the necessary dependencies, which greatly lightens the image.",{"title":72,"body":73},"Start the Node Server","Start the server with `pm2 start node --name nextjs -- .next\u002Fstandalone\u002Fserver.js` on port 3000, or via a Docker container. Configure `pm2 startup` and `pm2 save` for automatic restart on VPS reboot.",{"title":75,"body":76},"Configure Nginx as the Front End","Create a server block that does `proxy_pass http:\u002F\u002Flocalhost:3000`, forwards the `Host` and `X-Forwarded-For` headers, and serves `\u002F_next\u002Fstatic\u002F` directly from disk to relieve Node. Enable gzip compression.",{"title":78,"body":79},"Install the SSL Certificate","Obtain a Let's Encrypt certificate via Certbot for `yourdomain.com`, force the HTTPS redirect, and configure automatic renewal. Verify that the `X-Forwarded-Proto` headers are properly forwarded for SSR.",{"title":81,"body":82},"Set Up Deployments","Automate the `git pull && npm ci && npm run build && pm2 reload nextjs` cycle via a script or a Git webhook. PM2's `reload` ensures a zero-downtime restart between two versions.",{"type":39,"title":84,"body":85},"Complete Nginx Configuration with Upstream","A complete Nginx block for Next.js goes beyond the minimal `proxy_pass`. You need to serve static assets directly from disk, manage cache headers, enable compression, and correctly forward client information.\n\n```nginx\nupstream nextjs_upstream {\n  server 127.0.0.1:3000;\n  keepalive 64;\n}\n\nserver {\n  listen 80;\n  server_name yourdomain.com www.yourdomain.com;\n  return 301 https:\u002F\u002F$host$request_uri;\n}\n\nserver {\n  listen 443 ssl http2;\n  server_name yourdomain.com www.yourdomain.com;\n\n  ssl_certificate     \u002Fetc\u002Fletsencrypt\u002Flive\u002Fyourdomain.com\u002Ffullchain.pem;\n  ssl_certificate_key \u002Fetc\u002Fletsencrypt\u002Flive\u002Fyourdomain.com\u002Fprivkey.pem;\n\n  gzip on;\n  gzip_types text\u002Fplain text\u002Fcss application\u002Fjavascript application\u002Fjson image\u002Fsvg+xml;\n\n  # Next.js static assets — long-duration cache\n  location \u002F_next\u002Fstatic\u002F {\n    alias \u002Fhome\u002Fdeploy\u002Fmyapp\u002F.next\u002Fstatic\u002F;\n    expires 1y;\n    add_header Cache-Control \"public, immutable\";\n  }\n\n  # Public files (images, favicons…)\n  location \u002Fpublic\u002F {\n    alias \u002Fhome\u002Fdeploy\u002Fmyapp\u002Fpublic\u002F;\n    expires 30d;\n  }\n\n  # Everything else to Next.js\n  location \u002F {\n    proxy_pass http:\u002F\u002Fnextjs_upstream;\n    proxy_http_version 1.1;\n    proxy_set_header Upgrade $http_upgrade;\n    proxy_set_header Connection 'upgrade';\n    proxy_set_header Host $host;\n    proxy_set_header X-Real-IP $remote_addr;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    proxy_set_header X-Forwarded-Proto $scheme;\n    proxy_cache_bypass $http_upgrade;\n  }\n}\n```\n\nThe `upstream` block with `keepalive 64` maintains a pool of persistent connections to Node, avoiding TCP negotiation on every request. The `proxy_http_version 1.1` directive is required for keepalive connections to actually work. `_next\u002Fstatic` assets receive `Cache-Control: immutable` because Next.js places content hashes in their URLs — the file never changes at the same URL.",{"type":39,"title":87,"body":88},"ISR Strategy: Revalidation and Cache Persistence","ISR (Incremental Static Regeneration) allows Next.js to regenerate a static page in the background after a given delay, without a full rebuild. On a VPS, this requires the cache to survive restarts.\n\n```js\n\u002F\u002F app\u002Fproducts\u002F[id]\u002Fpage.tsx (App Router)\nexport const revalidate = 3600; \u002F\u002F regenerate every hour\n\n\u002F\u002F pages\u002Fproducts\u002F[id].tsx (Pages Router)\nexport async function getStaticProps() {\n  return {\n    props: { ... },\n    revalidate: 3600\n  };\n}\n```\n\nOn the VPS, the ISR cache is stored in `.next\u002Fcache`. To make it survive redeployments, two options exist.\n\n**Option 1 — persistent volume**: mount `.next\u002Fcache` outside the deployment folder. During a `git pull` and rebuild, copy the old cache before overwriting `.next`, then restore it.\n\n**Option 2 — Redis cache handler**: for multiple Node instances or a sharing requirement between machines, Next.js supports custom cache handlers since version 13.4. This allows externalizing the ISR cache to Redis, guaranteeing consistency between instances.\n\nFor low-traffic sites, option 1 is sufficient. Option 2 becomes necessary when you have multiple Node processes (PM2 cluster) or multiple VPSs behind a load balancer.",{"type":39,"title":90,"body":91},"Server Components vs Client Components: RAM and CPU Impact","Since Next.js 13 and the App Router, components are **Server Components by default**. The distinction has direct consequences for your VPS resource consumption.\n\n**Server Components** run only on the server side. They can read the database directly, access the filesystem, and are never sent to the browser's JavaScript bundle. The result is pure HTML, which reduces the client bundle size and improves Core Web Vitals (LCP). On the server, they consume CPU on each non-cached SSR request.\n\n**Client Components** (`'use client'` at the top of the file) are hydrated in the browser. They are necessary for user interactions: events, local state, hooks (`useState`, `useEffect`). They increase the size of the JavaScript bundle sent to the client.\n\nThe practical rule on a VPS: **keep Server Components for everything data-related**, and limit Client Components to interaction zones. A component rendered 10,000 times per hour on the server consumes CPU; the same rendered client-side consumes the visitor's browser RAM, not your server.",{"type":39,"title":93,"body":94},"CI\u002FCD: GitHub Actions or Forgejo","Automating deployment avoids human errors and ensures that every merge to the main branch triggers a clean rebuild. Two common solutions on VPS: **GitHub Actions** (if your repository is on GitHub) and **Forgejo** (self-hosted forge, open-source alternative to GitHub\u002FGitea).\n\n**GitHub Actions** — deployment workflow via SSH:\n\n```yaml\nname: Deploy Next.js\non:\n  push:\n    branches: [main]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Deploy via SSH\n        uses: appleboy\u002Fssh-action@v1\n        with:\n          host: ${{ secrets.VPS_HOST }}\n          username: deploy\n          key: ${{ secrets.VPS_SSH_KEY }}\n          script: |\n            cd \u002Fhome\u002Fdeploy\u002Fmyapp\n            git pull origin main\n            npm ci\n            npm run build\n            pm2 reload nextjs\n```\n\n**Forgejo** — if you self-host your forge on the same VPS or a dedicated server, use a Forgejo Act runner. The workflow syntax is identical to GitHub Actions, which facilitates migration.\n\nIn both cases, secrets (SSH key, environment variables) are configured in the repository secrets and never appear in logs.",{"type":39,"title":96,"body":97},"Monitoring with PM2","PM2 is both the process manager and the first monitoring tool for your Next.js application. Key commands:\n\n```bash\n# Process status\npm2 list\n\n# Real-time logs\npm2 logs nextjs\n\n# CPU and RAM metrics\npm2 monit\n\n# Zero-downtime restart\npm2 reload nextjs\n\n# Full restart (brief downtime)\npm2 restart nextjs\n```\n\nPM2 can also log metrics to a file and export them to external systems. For more advanced monitoring, enable the `pm2-logrotate` module to prevent log files from filling up the disk:\n\n```bash\npm2 install pm2-logrotate\npm2 set pm2-logrotate:max_size 50M\npm2 set pm2-logrotate:retain 7\n```\n\nIn production, save the process list after each change: `pm2 save`. This list is automatically reloaded at system startup if you have run `pm2 startup` and validated the command it provides.",{"type":99,"body":100},"tip","If you use ISR, mount a persistent volume for the `.next\u002Fcache` folder so that revalidated pages survive redeployments. Without this, each rebuild starts from an empty cache and causes a spike of on-the-fly generation. For several Node instances behind a load balancer, externalize this cache to shared storage or Redis with a custom cache handler.",{"type":39,"title":102,"body":103},"Troubleshooting: Common Production Errors","Three to five errors recur systematically on the first deployment of a Next.js application on a VPS.\n\n**ENOMEM during `npm run build`**\nThe Next.js build compiles in parallel and can exceed 2 GB of RAM on a medium-sized project. If the build stops with `Killed` or `JavaScript heap out of memory`, increase Node's memory limit:\n\n```bash\nNODE_OPTIONS=\"--max-old-space-size=4096\" npm run build\n```\n\n**Port 3000 already in use**\nAn old PM2 process or orphan Node process is already listening on port 3000. Identify and stop it:\n\n```bash\nlsof -i :3000\nkill -9 \u003CPID>\n# Or, if PM2 already has the process:\npm2 delete nextjs\npm2 start ecosystem.config.js --env production\n```\n\n**MODULE_NOT_FOUND in production with `output: 'standalone'`**\nThe `.next\u002Fstandalone` folder contains a copy of the necessary dependencies, but not the static assets or the `public` folder. If you copy only `standalone`, these resources are missing and the server crashes at startup. Copy all three folders:\n\n```bash\ncp -r .next\u002Fstatic .next\u002Fstandalone\u002F.next\u002Fstatic\ncp -r public .next\u002Fstandalone\u002Fpublic\n```\n\n**`X-Forwarded-Proto` error and HTTPS redirect loop**\nIf Next.js detects that the request is HTTP while it has already passed through Nginx as HTTPS, it may create a redirect loop. Ensure Nginx forwards `X-Forwarded-Proto: https` and that your application reads this header to determine the actual protocol.",{"type":39,"title":105,"body":106},"Backing Up .next\u002Fcache","The `.next\u002Fcache` folder contains two types of valuable data: revalidated ISR pages and the Webpack\u002FSWC compilation cache. Losing this cache forces Next.js to regenerate all ISR pages on the fly at the first hit, which can create a load spike if your site has many static pages.\n\nSet up a simple backup with `rsync` or `tar` before each deployment. The Webpack cache significantly speeds up subsequent rebuilds — on an average project, a rebuild with a full cache takes 40 to 60 % less time than a cold build.",{"type":39,"title":108,"body":109},"Deploy Next.js in One Click from the Marketplace","The ServOrbit Marketplace offers a **Next.js Stack** template that automatically configures Node.js LTS, PM2, Nginx, and PostgreSQL on your VPS. In a few minutes, your production environment is ready to receive your React SSR application — no manual setup required.\n\nCompared to the installation described in this guide, the template handles the initial setup and lets you jump straight to the \"deploy your code\" step.","Your Next.js Environment Ready in Minutes","The Next.js Stack template automatically configures Node.js LTS, PM2, Nginx, and PostgreSQL — ready to receive your React SSR application.","Deploy My Next.js Stack","\u002Fapplications\u002Fdevelopment\u002Fnextjs-stack",[115,132,150],{"id":116,"slug":117,"slugs":118,"title":122,"excerpt":123,"readTime":23,"views":18,"isPinned":19,"noindex":19,"publishedAt":124,"updatedAt":125,"category":126,"categories":127,"featuredImage":30,"bgImage":31,"posterImage":129,"relatedSolution":130},5,"deploying-laravel-on-a-vps-a-production-guide",{"fr":119,"en":117,"ar":120,"es":121},"deployer-laravel-vps","نشر-laravel-على-خادم-vps-دليل-الإنتاج","desplegar-laravel-en-un-vps","Deploying Laravel on a VPS: a production guide","Take Laravel to production on a VPS: PHP, workers, cache, database, reverse proxy and HTTPS configured cleanly.","2026-02-09T00:00:00+00:00","2026-09-07T11:26:10+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[128],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fdeployer-laravel-vps-poster.svg",{"categorySlug":27,"appSlug":131},"laravel-stack",{"id":133,"slug":134,"slugs":135,"title":139,"excerpt":140,"readTime":141,"views":18,"isPinned":19,"noindex":19,"publishedAt":142,"updatedAt":143,"category":144,"categories":145,"featuredImage":30,"bgImage":31,"posterImage":147,"relatedSolution":148},43,"deploy-a-nodejs-application-on-a-vps",{"fr":136,"en":134,"ar":137,"es":138},"deployer-nodejs-vps","نشر-تطبيق-nodejs-على-vps","desplegar-una-aplicacion-nodejs-en-un-vps","Deploy a Node.js Application on a VPS","Deploy a Node.js application to production on a VPS: PM2, Nginx reverse proxy, Let's Encrypt SSL, and automatic startup at boot.",8,"2026-05-08T00:00:00+00:00","2026-11-08T01:13:12+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[146],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fdeployer-nodejs-vps-poster.svg",{"categorySlug":34,"appSlug":149},"nodejs-stack",{"id":151,"slug":152,"slugs":153,"title":157,"excerpt":158,"readTime":159,"views":160,"isPinned":19,"noindex":19,"publishedAt":161,"updatedAt":21,"category":162,"categories":163,"featuredImage":30,"bgImage":31,"posterImage":165,"relatedSolution":166},44,"deploy-a-django-application-on-a-vps",{"fr":154,"en":152,"ar":155,"es":156},"deployer-django-vps","نشر-تطبيق-django-على-vps","desplegar-una-aplicacion-django-en-un-vps","Deploy a Django Application on a VPS","Deploy Django on a VPS: Gunicorn, Nginx, PostgreSQL, Docker, and SSL. A complete guide for Python developers who want to self-host.",3,7,"2026-05-07T00:00:00+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[164],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fdeployer-django-vps-poster.svg",{"categorySlug":34,"appSlug":167},"django",true,1794270386158]