[{"data":1,"prerenderedAt":215},["ShallowReactive",2],{"seo-verification":3,"blog-deploy-a-nuxt-application-on-a-vps-ma-en":6,"promo-bar-likely":214},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-deploy-a-nuxt-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":156,"ctaBody":157,"ctaButton":158,"ctaUrl":159,"relatedPosts":160},47,"deploy-a-nuxt-application-on-a-vps",{"fr":12,"en":10,"ar":13,"es":14},"deployer-nuxt-vps","نشر-تطبيق-nuxt-على-vps","desplegar-nuxt-en-un-vps","Deploy a Nuxt Application on a VPS","Deploy Nuxt on a VPS: Nitro, PM2, Nginx, SSL, rendering modes, routeRules, environment variables and production troubleshooting.",12,1,false,"2026-05-04T00:00:00+00:00","2026-11-08T01:13:12+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-nuxt-vps-poster.svg",{"categorySlug":34,"appSlug":35},"development","nuxt-stack","Nuxt and its Nitro engine produce a standalone Node.js artifact, perfectly suited for self-hosting on a VPS. This approach frees you from cloud function quotas and gives you full control over caching, HTTP headers, and per-page rendering strategies. This guide covers the complete setup: choosing a rendering mode, project configuration, build, environment variables, process supervision with PM2, Nginx reverse proxy and HTTPS, logs, and finally troubleshooting the errors that block production.",[38,42,54,83,86,89,114,117,120,143,146,149,153],{"type":39,"title":40,"body":41},"h2","Why Self-Host Nuxt on a VPS?","With Nitro, Nuxt generates a portable build (`preset: node-server`) that starts as a simple Node server listening on a port. This portability is ideal for a VPS: you benefit from server-side rendering, `server\u002Fapi` routes, and route caching without depending on a proprietary edge runtime.\n\nSelf-hosting removes function quotas and lets you tune caching, compression, and the number of Node instances. For a production Vue 3 application with authentication, server API calls, and careful SEO, the VPS offers the stability of a persistent server and a fixed cost, with no per-invocation billing surprises.\n\nYou still need a server that accepts a permanent Node.js process: most shared hosting does not allow it, which rules out SSR and server routes from the start. On a VPS you also choose the Node.js version, the reverse proxy (Nginx or Caddy) and how TLS certificates are managed, with no artificial cap on CPU or memory.",{"type":43,"title":44,"items":45},"ul","Concrete Benefits of a Self-Hosted Nuxt",[46,47,48,49,50,51,52,53],"`server\u002Fapi` server routes with no per-call billing.","SSR and Vue 3 hydration served from a persistent, stable Node server.","Portable Nitro build (`node-server`) easy to containerize and reproduce.","Route caching and `routeRules` rules (SSR, SSG, ISR, SWR) controlled on the server side.","Several Nuxt apps on a single VPS behind Nginx, each on its own internal port (3000, 3001…).","Runtime environment variables (`runtimeConfig`) managed directly on your own server.","Full control over HTTP headers (CSP, HSTS, cache-control) via Nitro middleware.","A site prerendered with `nuxt generate`, served by Nginx alone, with no permanent Node.js process.",{"type":55,"title":56,"headers":57,"rows":62},"comparison","SSR, SSG, SPA or Hybrid: Which Rendering Mode Should You Choose?",[58,59,60,61],"Mode","Rendering","Node.js process","Best for",[63,68,73,78],[64,65,66,67],"SSR (default)","Per request, on the server","Yes, supervised by PM2","Dynamic app, SEO, personalized content",[69,70,71,72],"SSG (`nuxt generate`)","At build time, as static HTML","No, Nginx serves `.output\u002Fpublic`","Blog, showcase site, rarely changing content",[74,75,76,77],"SPA (`ssr: false` + `nuxt generate`)","In the browser","No, Nginx is enough","Internal dashboard, app behind authentication",[79,80,81,82],"Hybrid (`routeRules`)","Per route: SSR, prerender, SWR, ISR","Yes, Nitro server","App mixing static pages and API routes",{"type":39,"title":84,"body":85},"Hardware and Software Prerequisites","As with any modern framework, the Nuxt build consumes memory: aim for at least 2 GB of RAM (the build can be done in CI if your VPS is more modest). At runtime, 1 vCPU and 1 GB are enough for the Nitro server under light load; move up to 2 vCPU \u002F 2 GB for applications with many simultaneous `server\u002Fapi` routes, and to 2 vCPU \u002F 4 GB if several Nuxt applications share the VPS.\n\nOn the version side, start from Nuxt 4: Nuxt 3 reached end of life on 31 July 2026 and no longer receives bug fixes or security patches. The deployment described here is the same for both versions, since Nitro is what produces the server. Install a Node.js LTS line that is still maintained, Node.js 24 or 26 (Node.js 20 has been end-of-life since 30 April 2026), via `nvm` or a `node:24-alpine` image, along with PM2 for process supervision. `node-server` is the preset Nitro applies by default to a production build: declaring it in `nuxt.config.ts` simply makes it explicit. A domain pointing to your VPS is required for the TLS certificate. Ubuntu 22.04 or 24.04 LTS remains the recommended base.",{"type":39,"title":87,"body":88},"Starting from the Nuxt Stack Template","The Nuxt Stack template in the ServOrbit Marketplace prepares an Ubuntu 24.04 VPS with Node.js on the current LTS line of the NodeSource repository, PM2 installed globally, Nginx and PostgreSQL. It saves you installing the runtime: the steps below then start at the project configuration.\n\nIt is a runtime environment, not an application with a login screen: you get in over SSH (`ssh root@\u003Cvps-ip>`) to upload your code. On first access, Nginx serves its default page on port 80; your application's virtual host, the Let's Encrypt certificate (Certbot is not preinstalled) and your code are still to be set up. PostgreSQL listens only locally, with peer authentication for the `postgres` system user (`sudo -u postgres psql`): enough to plug a `DATABASE_URL` into `127.0.0.1` without exposing the database.",{"type":90,"title":91,"steps":92},"steps","Deploy Nuxt Step by Step",[93,96,99,102,105,108,111],{"title":94,"body":95},"Configure the Project for Node","Set the Nitro preset in `nuxt.config.ts`:\n\n```ts\nexport default defineNuxtConfig({\n  nitro: { preset: 'node-server' }\n})\n```\n\nDeclare your secrets in `runtimeConfig` on the server side only — never in `runtimeConfig.public`. On the VPS, install Node.js 24 LTS via `nvm install 24 && nvm use 24 && nvm alias default 24`, then PM2 globally: `npm install -g pm2`. On the Nuxt Stack template, Node.js and PM2 are already in place.",{"title":97,"body":98},"Build the Application","Clone the repository and install dependencies:\n\n```bash\ngit clone https:\u002F\u002Fgit.yourdomain.com\u002Fyour-org\u002Fyour-app.git \u002Fsrv\u002Fnuxt-app\ncd \u002Fsrv\u002Fnuxt-app\nnpm ci\nnpm run build\n```\n\nNitro produces a self-contained `.output` folder containing `server\u002Findex.mjs` and static assets in `.output\u002Fpublic`. This folder is all the VPS needs to serve the application in production — you can also assemble it in CI and transfer it by rsync to avoid building on the server.",{"title":100,"body":101},"Create the Environment File","Create `\u002Fsrv\u002Fnuxt-app\u002F.env` with your runtime variables. All variables prefixed `NUXT_` override the corresponding keys in `runtimeConfig` at startup:\n\n```bash\nNUXT_MY_SECRET_KEY=production-value\nNITRO_HOST=127.0.0.1\nNITRO_PORT=3000\n```\n\nNever commit this file. Make sure it belongs to the user running PM2 and is readable only by that user (`chmod 600`).\n\nWith `NITRO_HOST=127.0.0.1`, Nitro listens only on the loopback interface: only Nginx can reach it, and port 3000 is not exposed to the Internet.",{"title":103,"body":104},"Launch the Nitro Server with PM2","Start the application in cluster mode, asking Node to load the environment file: Nuxt does not read `.env` in production, and the PM2 command line has no dedicated option for it.\n\n```bash\npm2 start \u002Fsrv\u002Fnuxt-app\u002F.output\u002Fserver\u002Findex.mjs \\\n  --name nuxt-app -i max \\\n  --node-args=\"--env-file=\u002Fsrv\u002Fnuxt-app\u002F.env\"\npm2 save\npm2 startup\n```\n\n`-i max` launches one instance per vCPU; this cluster mode is what makes the zero-downtime reloads of the last step possible. The `pm2 startup` command displays a line to copy-paste to create the systemd service. Run it with administrator rights. Verify the application is running: `pm2 status` should show the `online` state.",{"title":106,"body":107},"Configure Nginx as a Reverse Proxy","Create `\u002Fetc\u002Fnginx\u002Fsites-available\u002Fnuxt-app`:\n\n```nginx\nserver {\n    listen 80;\n    server_name yourdomain.com www.yourdomain.com;\n\n    # Hashed assets: long cache, served directly\n    location \u002F_nuxt\u002F {\n        root \u002Fsrv\u002Fnuxt-app\u002F.output\u002Fpublic;\n        expires 1y;\n        add_header Cache-Control \"public, immutable\";\n    }\n\n    # Static public files\n    location \u002Ffavicon.ico {\n        root \u002Fsrv\u002Fnuxt-app\u002F.output\u002Fpublic;\n    }\n\n    # Everything else → Nitro\n    location \u002F {\n        proxy_pass http:\u002F\u002F127.0.0.1:3000;\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\nEnable the site and test the configuration: `ln -s \u002Fetc\u002Fnginx\u002Fsites-available\u002Fnuxt-app \u002Fetc\u002Fnginx\u002Fsites-enabled\u002F && nginx -t && systemctl reload nginx`.",{"title":109,"body":110},"Enable HTTPS with Let's Encrypt","Install Certbot and the Nginx plugin, then generate the certificate:\n\n```bash\napt install certbot python3-certbot-nginx\ncertbot --nginx -d yourdomain.com -d www.yourdomain.com\n```\n\nCertbot automatically modifies the Nginx block to listen on port 443 and force HTTP → HTTPS redirect. Verify that `X-Forwarded-Proto` is correctly forwarded to Nitro — without it, `useRequestHeaders()` on the server side and protocol-based redirects may behave incorrectly. Automatic renewal is managed by Certbot's systemd timer, checkable with `systemctl status certbot.timer`.",{"title":112,"body":113},"Update Without Service Interruption","For an update, PM2 reload (not restart) guarantees continuity. Group the commands in a `\u002Fsrv\u002Fnuxt-app\u002Fdeploy.sh` script, which `set -e` stops at the first error, before any reload:\n\n```bash\n#!\u002Fbin\u002Fbash\nset -e\ncd \u002Fsrv\u002Fnuxt-app\ngit pull origin main\nnpm ci\nnpm run build\npm2 reload nuxt-app\n```\n\nMake it executable (`chmod +x deploy.sh`) and call it from your CI\u002FCD pipeline over SSH. In cluster mode, PM2 replaces the instances one by one: the new version takes over before the old one stops. For a rollback, revert to the previous commit, rebuild and reload. If the build happens in CI, transfer only the `.output` folder via rsync and reload without rebuilding on the server.",{"type":39,"title":115,"body":116},"Environment Variables: Public, Private and Reloading","Nuxt organizes its runtime configuration on two levels. Keys placed under `runtimeConfig.public` are sent to the browser and remain readable on the server: public API URL, analytics identifier. The other `runtimeConfig` keys never leave the server: secret keys, database access.\n\nAt startup, an environment variable overrides the matching key if it follows the `NUXT_\u003CNAME>` convention, or `NUXT_PUBLIC_\u003CNAME>` for a public key: `NUXT_PUBLIC_API_BASE` replaces `runtimeConfig.public.apiBase`. A value read elsewhere, for example `process.env.OTHER_VARIABLE` written in `nuxt.config.ts`, is only picked up at build time and stays frozen in the artifact.\n\nIn practice, changing an API URL or a key therefore does not require a rebuild: you edit the `.env` on the server, then reload PM2 (`pm2 reload nuxt-app`). The same `.output` folder can thus serve staging and production with two different environment files. The only condition is to have the process load that file, since Nuxt no longer reads `.env` once the application is built — hence the `--env-file` option passed to Node when starting with PM2.",{"type":39,"title":118,"body":119},"Optimize Rendering with routeRules","One of Nuxt's strengths on a VPS is the granularity of per-page rendering strategies, without changing infrastructure. In `nuxt.config.ts`, `routeRules` allow you to mix SSR, SSG, ISR, and SWR on a single Nitro deployment.\n\nStatic pages (blog, legal notices, landing pages) can be pre-generated at build time with `prerender: true`: Nitro serves them from disk, without Node. Semi-dynamic pages (product listings, public dashboards) benefit from `swr: 60` for a one-minute cache invalidated in the background. Full SSR remains reserved for personalized pages that depend on session or user profile.\n\nThis approach reduces the load on Node without requiring a paid CDN or an external cache layer — your Nginx caches what Nitro pre-generates.",{"type":55,"title":121,"headers":122,"rows":126},"Nitro server vs Docker vs Vercel\u002FNetlify for hosting Nuxt",[123,124,125],"Approach","Advantages","Constraints",[127,131,135,139],[128,129,130],"Nitro `node-server` + PM2","Simple, lightweight, zero-downtime reload, fixed VPS cost","Supervision to manage, single server without native high availability",[132,133,134],"Docker on VPS","Isolation, reproducibility, rollback by image, multi-app compose","Image to build and store, additional memory per container",[136,137,138],"Vercel \u002F Netlify","Zero configuration, global edge CDN, PR previews","Function quotas, variable cost, no infrastructure control",[140,141,142],"Kamal (zero-downtime deployment)","Orchestrates Docker and kamal-proxy, one-command deployment (`kamal deploy`)","Ruby tool (gem or Docker image), longer initial config, suited for teams",{"type":39,"title":144,"body":145},"Logs: Reading, Rotating, Cross-Checking with Nginx","PM2 centralizes the application's output: `pm2 logs nuxt-app` follows the live stream (standard output and errors), and `pm2 logs nuxt-app --lines 100` shows the latest lines. The files are written to `~\u002F.pm2\u002Flogs\u002F`, one `-out.log` and one `-error.log` per application, suffixed with the instance number in cluster mode.\n\nThese files do not rotate on their own. The pm2-logrotate module rotates them past 10 MB and keeps 30 by default; adjust these thresholds to the size of your disk:\n\n```bash\npm2 install pm2-logrotate\npm2 set pm2-logrotate:max_size 50M\npm2 set pm2-logrotate:retain 7\n```\n\nWhen the browser gets a 502 or a 504, look at Nginx first: `\u002Fvar\u002Flog\u002Fnginx\u002Ferror.log` tells you whether it could not reach `127.0.0.1:3000` (process stopped, wrong port) or whether Nitro took too long to respond.",{"type":39,"title":147,"body":148},"Troubleshooting: Common Production Errors","**`Error: listen EADDRINUSE: address already in use :::3000`**\nA process is already holding port 3000. Identify it with `ss -tlnp | grep 3000` and stop the orphaned PM2 instance: `pm2 delete nuxt-app` followed by a clean restart. Avoid running multiple instances without a load balancer — configure PM2's `cluster_mode` instead.\n\n**`502 Bad Gateway` in Nginx**\nNitro is not started or is listening on the wrong port. Check `pm2 status` and review the logs: `pm2 logs nuxt-app --lines 50`. Also verify that the `proxy_pass` directive in Nginx points to `http:\u002F\u002F127.0.0.1:3000` (not `localhost` which may resolve to IPv6 if the process only listens on IPv4).\n\n**`useRuntimeConfig()` returns undefined**\n`NUXT_*` variables are only read when the Nitro process starts: after changing `.env`, reload with `pm2 reload nuxt-app`. Check that the file is actually loaded through `--node-args=\"--env-file=…\"` rather than exported in the current shell, which disappears with the SSH session. If the value is missing in the browser only, the key must be declared under `runtimeConfig.public` and the variable prefixed `NUXT_PUBLIC_`.\n\n**`server\u002Fapi` routes return 404 in production**\nCheck that your build includes the `server\u002F` folder in `.output`. A misconfigured `nitro.preset` (for example `static` instead of `node-server`) generates a static site without a server. Rebuild with `npm run build` after verifying `nuxt.config.ts`.\n\n**`X-Forwarded-Proto` ignored, redirect loop**\nIf Nuxt redirects HTTP → HTTPS in a loop, it means the redirect middleware sees `http` despite the client-side HTTPS. Make sure Nginx forwards `proxy_set_header X-Forwarded-Proto $scheme` and that your `nuxt.config.ts` does not force HTTPS redirect twice alongside Certbot.",{"type":150,"title":151,"body":152},"tip","Monitoring and Metrics with PM2","Beyond simple `pm2 status`, PM2 exposes a real-time dashboard with `pm2 monit`: CPU, memory, restarts, and process logs. For a Nuxt application under load, enable cluster mode to use all available vCPUs:\n\n```bash\npm2 start .output\u002Fserver\u002Findex.mjs --name nuxt-app -i max\n```\n\nPM2 automatically distributes requests across workers. Export these metrics to Prometheus and Grafana to get alerted on unexpected restarts — a sign of a bug or memory leak to fix before it affects users.",{"type":150,"title":154,"body":155},"The Official Documentation","For advanced configuration and version changes, refer to the \u003Ca href=\"https:\u002F\u002Fnuxt.com\u002Fdocs\">official Nuxt documentation\u003C\u002Fa> (routeRules, `runtimeConfig`, modules), the \u003Ca href=\"https:\u002F\u002Fnitro.build\u002Fdeploy\u002Fruntimes\u002Fnode\">Nitro Node.js runtime page\u003C\u002Fa> for the `NITRO_PORT` and `NITRO_HOST` variables, and the \u003Ca href=\"https:\u002F\u002Fpm2.keymetrics.io\u002Fdocs\u002Fusage\u002Fcluster-mode\u002F\">PM2 cluster mode documentation\u003C\u002Fa>. This guide covers going live on a VPS; the vendor documentation remains the reference for fine-tuning.","Deploy Your Nuxt with Full Autonomy","The ServOrbit Cloud VPS provides a template with Node.js, PM2, Nginx, and automatic SSL, ideal for hosting your Nuxt 3 applications with SSR and server routes.","Deploy My Nuxt VPS","\u002Fvps-cloud",[161,178,195],{"id":162,"slug":163,"slugs":164,"title":168,"excerpt":169,"readTime":23,"views":18,"isPinned":19,"noindex":19,"publishedAt":170,"updatedAt":171,"category":172,"categories":173,"featuredImage":30,"bgImage":31,"posterImage":175,"relatedSolution":176},5,"deploying-laravel-on-a-vps-a-production-guide",{"fr":165,"en":163,"ar":166,"es":167},"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},[174],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fdeployer-laravel-vps-poster.svg",{"categorySlug":27,"appSlug":177},"laravel-stack",{"id":179,"slug":180,"slugs":181,"title":185,"excerpt":186,"readTime":187,"views":18,"isPinned":19,"noindex":19,"publishedAt":188,"updatedAt":21,"category":189,"categories":190,"featuredImage":30,"bgImage":31,"posterImage":192,"relatedSolution":193},43,"deploy-a-nodejs-application-on-a-vps",{"fr":182,"en":180,"ar":183,"es":184},"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",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[191],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fdeployer-nodejs-vps-poster.svg",{"categorySlug":34,"appSlug":194},"nodejs-stack",{"id":196,"slug":197,"slugs":198,"title":202,"excerpt":203,"readTime":204,"views":205,"isPinned":19,"noindex":19,"publishedAt":206,"updatedAt":207,"category":208,"categories":209,"featuredImage":30,"bgImage":31,"posterImage":211,"relatedSolution":212},44,"deploy-a-django-application-on-a-vps",{"fr":199,"en":197,"ar":200,"es":201},"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","2026-11-04T16:30:25+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[210],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fdeployer-django-vps-poster.svg",{"categorySlug":34,"appSlug":213},"django",true,1794270386642]