[{"data":1,"prerenderedAt":157},["ShallowReactive",2],{"seo-verification":3,"blog-deploy-a-nodejs-application-on-a-vps-ma-en":6,"promo-bar-likely":156},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-deploy-a-nodejs-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":98,"ctaBody":99,"ctaButton":100,"ctaUrl":101,"relatedPosts":102},43,"deploy-a-nodejs-application-on-a-vps",{"fr":12,"en":10,"ar":13,"es":14},"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,1,false,"2026-05-08T00: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-nodejs-vps-poster.svg",{"categorySlug":34,"appSlug":35},"development","nodejs-stack","Running a Node.js application in production takes more than a plain `node app.js`: you need a process manager that restarts it after a crash, environment variables kept out of the code, a reverse proxy for HTTPS, logs that do not fill the disk and automatic startup at boot. On a VPS you control every link in that chain, unlike a managed platform that bills you by usage. This guide starts from an Ubuntu server, either bare or prepared with the Node.js Stack template, and goes all the way to zero-downtime updates.",[38,42,55,58,61,86,89,92,95],{"type":39,"title":40,"body":41},"h2","Why Deploy Node.js on a VPS Rather Than on a Managed Platform?","Serverless and PaaS platforms are convenient at first, but their cost rises with traffic and they impose constraints (timeouts, cold starts, limits on WebSocket connections). A VPS gives you a persistent Node.js process, long-lived connections (WebSocket, SSE) without artificial limits, dedicated resources and a fixed, predictable cost. You choose the Node version, the process manager, the reverse proxy and the update strategy, without depending on a provider's conventions.\n\nNode.js's asynchronous, non-blocking model lets a single process hold a large number of simultaneous connections. That is what makes it a good fit for REST APIs, real-time features and microservices, as long as the process stays alive. This is exactly what most shared hosting refuses, by forbidding persistent processes or WebSockets. On a VPS, your npm dependencies, environment variables and PM2 configuration are not shared with any other account.",{"type":43,"title":44,"items":45},"ul","What You Gain with a VPS for Node.js",[46,47,48,49,50,51,52,53,54],"A persistent Node.js process, ideal for WebSocket, SSE and long-running tasks with no cold start","Automatic restart after a crash and when the server reboots, thanks to PM2","Cluster mode to use every CPU core of the VPS without changing your code","An Nginx reverse proxy in front of Node for HTTPS, compression and static files","Queue workers (BullMQ, Agenda) and scheduled jobs running next to the API on the same machine","Several applications on one VPS, each on its own internal port (3000, 3001…) and subdomain behind Nginx","Server-side rendering for frameworks such as \u003Ca href=\"\u002Fen\u002Fblog\u002Fdeploy-a-nuxt-application-on-a-vps\">Nuxt\u003C\u002Fa> or \u003Ca href=\"\u002Fen\u002Fblog\u002Fdeploy-a-nextjs-application-on-a-vps\">Next.js\u003C\u002Fa>, served by the same Node.js and PM2 foundation","A fixed, predictable cost, with no per-request billing and no scaling surprises","Full control over the Node.js version and system dependencies",{"type":39,"title":56,"body":57},"Prerequisites","A standard Node.js application (Express, Nest or Fastify API) runs comfortably on a VPS with 1 to 2 vCPUs and 1 to 2 GB of RAM; plan for more RAM if you compile a heavy front end at build time or run workers. Aim for 2 vCPUs and 2 GB as soon as the API shares the machine with SSR rendering or a PostgreSQL database.\n\nPick an LTS line that is still maintained: Node.js 20 has received no fixes since 30 April 2026, Node.js 24 moved to maintenance on 20 October 2026, and Node.js 26 has been the active LTS since 28 October 2026. Install it through nvm or the NodeSource repository to pin it, along with PM2 as the process manager and Nginx as the reverse proxy. You need a domain pointing to the VPS IP and ports 80\u002F443 open.",{"type":39,"title":59,"body":60},"Starting from the Node.js Stack Template","The Node.js Stack template in the ServOrbit Marketplace prepares an Ubuntu 24.04 VPS with Node.js on the current LTS line of the NodeSource repository, npm, PM2 installed globally, Nginx and PostgreSQL. It saves you the first step below; the rest of the guide applies as is.\n\nIt is not an application with a login screen but a runtime environment: you get in over SSH (`ssh root@\u003Cvps-ip>`) to upload your code. On first access, Nginx serves its default welcome page on port 80, because no virtual host has been written for your domain yet, and Certbot is not installed: the Nginx and HTTPS steps are still yours to do. PostgreSQL listens only locally and authenticates the `postgres` system user with the peer method: `sudo -u postgres psql` opens the console without a password.",{"type":62,"title":63,"steps":64},"steps","Deploy a Node.js Application to Production",[65,68,71,74,77,80,83],{"title":66,"body":67},"Prepare the VPS and Install Node.js","On an Ubuntu 24.04 VPS, update the system and install an LTS version of Node through nvm (`nvm install --lts`) or the NodeSource repository. Check with `node -v` and `npm -v`. Create a non-root user dedicated to the application instead of running everything as root: that user will own the code, the `.env` file and the PM2 processes. With the Node.js Stack template, Node.js, npm and PM2 are already installed, so only the user creation remains.",{"title":69,"body":70},"Fetch the Code and Build","Clone your repository on the VPS, install the production dependencies (`npm ci --omit=dev`) and run the build if needed (`npm run build`).\n\nPut sensitive variables in an uncommitted `.env` file that only the application user can read (`chmod 600 .env`). No library is needed to read it: since Node.js 20.6, the `--env-file` option loads that file into `process.env` at startup.",{"title":72,"body":73},"Prepare the PostgreSQL Database","If the application needs a database, create a dedicated role and database instead of working with the superuser:\n\n```bash\nsudo -u postgres createuser --pwprompt monapp\nsudo -u postgres createdb --owner=monapp monapp\n```\n\nThen set `DATABASE_URL=postgres:\u002F\u002Fmonapp:\u003Cpassword>@127.0.0.1:5432\u002Fmonapp` in the `.env`. Since PostgreSQL listens only locally, no database port has to be opened in the firewall.",{"title":75,"body":76},"Start the Application with PM2","Install PM2 globally (`npm install -g pm2`, already done on the template), then start the app from the project folder, asking Node to load the `.env`:\n\n```bash\npm2 start app.js --name monapp -i max --node-args=\"--env-file=.env\"\n```\n\nThe `-i max` flag enables cluster mode across all cores. PM2 automatically restarts the process if it crashes.",{"title":78,"body":79},"Enable Automatic Startup at Boot","Generate the systemd script with `pm2 startup`, run as the application user, execute the command it prints with sudo, then freeze the current state with `pm2 save`. On the next VPS reboot, your application will be restarted automatically, with no intervention.",{"title":81,"body":82},"Configure Nginx as a Reverse Proxy","Install Nginx if it is not already there and create `\u002Fetc\u002Fnginx\u002Fsites-available\u002Fmonapp`, a virtual host that proxies to Node's local port. The `Upgrade` and `Connection` headers are for WebSockets, and `X-Forwarded-Proto` tells the application that the client is on HTTPS:\n\n```nginx\nserver {\n    listen 80;\n    server_name yourdomain.com;\n\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-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n}\n```\n\nEnable the site, remove the default page, test the configuration and reload:\n\n```bash\nln -s \u002Fetc\u002Fnginx\u002Fsites-available\u002Fmonapp \u002Fetc\u002Fnginx\u002Fsites-enabled\u002F\nrm \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fdefault\nnginx -t && systemctl reload nginx\n```",{"title":84,"body":85},"Secure with HTTPS via Let's Encrypt","Install Certbot and its Nginx plugin, then request the certificate:\n\n```bash\napt install certbot python3-certbot-nginx\ncertbot --nginx -d yourdomain.com\n```\n\nCertbot obtains the certificate, sets up the HTTP→HTTPS redirect and schedules automatic renewal. Your Node application is now served over HTTPS.",{"type":39,"title":87,"body":88},"Centralize the Configuration in ecosystem.config.js","As soon as the VPS hosts more than one application, or an API comes with a worker, options passed on the command line become hard to keep track of. PM2 reads an `ecosystem.config.js` file that describes each process: script, folder, number of instances, memory limit and non-sensitive variables.\n\n```js\nmodule.exports = {\n  apps: [\n    {\n      name: 'api',\n      cwd: '\u002Fhome\u002Fmonapp\u002Fapp',\n      script: 'app.js',\n      instances: 'max',\n      exec_mode: 'cluster',\n      node_args: '--env-file=.env',\n      max_memory_restart: '500M',\n      env: { NODE_ENV: 'production', PORT: 3000 }\n    },\n    {\n      name: 'worker',\n      cwd: '\u002Fhome\u002Fmonapp\u002Fapp',\n      script: 'worker.js',\n      node_args: '--env-file=.env'\n    }\n  ]\n}\n```\n\n`pm2 start ecosystem.config.js` starts everything, `pm2 reload ecosystem.config.js` updates it, and the `--only api` option targets a single application. Here the API runs in cluster mode on every core and the worker as a single process. Version this file with the code; the secrets stay in the `.env`, outside the repository.",{"type":39,"title":90,"body":91},"Logs: Reading Them, Then Rotating Them","PM2 captures the standard output and error output of every process in `~\u002F.pm2\u002Flogs\u002F`, with one `-out.log` file and one `-error.log` file per application. `pm2 logs monapp` follows them live, and `pm2 logs monapp --lines 100` shows the latest lines.\n\nWithout rotation, these files grow until the disk is full. The pm2-logrotate module takes care of it; by default it rotates a file past 10 MB and keeps 30 of them, thresholds that are easy to adjust:\n\n```bash\npm2 install pm2-logrotate\npm2 set pm2-logrotate:max_size 50M\npm2 set pm2-logrotate:retain 7\n```\n\nOn the proxy side, a 502 error shows up in `\u002Fvar\u002Flog\u002Fnginx\u002Ferror.log`: it almost always means the Node.js process is stopped or listening on a different port from the one in `proxy_pass`.",{"type":93,"body":94},"tip","For zero-downtime deployments, combine PM2 cluster mode with `pm2 reload monapp` rather than `restart`: PM2 restarts the workers one at a time, always keeping at least one instance available during the update. Then watch memory with `pm2 monit` and set an automatic restart limit (`--max-memory-restart 500M`) to guard against memory leaks in production.",{"type":93,"title":96,"body":97},"The Official Documentation","For each tool's own options and version changes, refer to the \u003Ca href=\"https:\u002F\u002Fnodejs.org\u002Fdocs\u002Flatest\u002Fapi\u002F\">official Node.js documentation\u003C\u002Fa>, the \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fnodejs\u002FRelease\">Node.js LTS release schedule\u003C\u002Fa> and the \u003Ca href=\"https:\u002F\u002Fpm2.keymetrics.io\u002Fdocs\u002Fusage\u002Fquick-start\u002F\">PM2 documentation\u003C\u002Fa>. This guide covers putting an application into production on a VPS; the vendor documentation remains the reference for fine-tuning.","Put Your Node.js Application into Production on a Cloud VPS","Deploy a ServOrbit Cloud VPS with the Development template: Node.js, PM2, and Nginx preconfigured to move your application into production over HTTPS.","View Cloud VPS","\u002Fvps-cloud",[103,120,139],{"id":104,"slug":105,"slugs":106,"title":110,"excerpt":111,"readTime":23,"views":18,"isPinned":19,"noindex":19,"publishedAt":112,"updatedAt":113,"category":114,"categories":115,"featuredImage":30,"bgImage":31,"posterImage":117,"relatedSolution":118},5,"deploying-laravel-on-a-vps-a-production-guide",{"fr":107,"en":105,"ar":108,"es":109},"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},[116],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fdeployer-laravel-vps-poster.svg",{"categorySlug":27,"appSlug":119},"laravel-stack",{"id":121,"slug":122,"slugs":123,"title":127,"excerpt":128,"readTime":129,"views":130,"isPinned":19,"noindex":19,"publishedAt":131,"updatedAt":132,"category":133,"categories":134,"featuredImage":30,"bgImage":31,"posterImage":136,"relatedSolution":137},44,"deploy-a-django-application-on-a-vps",{"fr":124,"en":122,"ar":125,"es":126},"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},[135],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fdeployer-django-vps-poster.svg",{"categorySlug":34,"appSlug":138},"django",{"id":140,"slug":141,"slugs":142,"title":146,"excerpt":147,"readTime":148,"views":23,"isPinned":19,"noindex":19,"publishedAt":149,"updatedAt":132,"category":150,"categories":151,"featuredImage":30,"bgImage":31,"posterImage":153,"relatedSolution":154},45,"deploy-a-fastapi-application-on-a-vps",{"fr":143,"en":141,"ar":144,"es":145},"deployer-fastapi-vps","نشر-تطبيق-fastapi-على-vps","desplegar-una-aplicacion-fastapi-en-un-vps","Deploy FastAPI on a VPS: the complete production guide","Deploy FastAPI on a VPS with multi-stage Docker, Gunicorn, PostgreSQL, GitHub Actions CI\u002FCD and monitoring. Complete Python production guide 2025.",10,"2026-05-06T00:00:00+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[152],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fdeployer-fastapi-vps-poster.svg",{"categorySlug":34,"appSlug":155},"fastapi",true,1794270386307]