{"id":83809,"date":"2026-06-29T08:00:00","date_gmt":"2026-06-29T15:00:00","guid":{"rendered":"https:\/\/dhblog.dream.press\/blog\/?p=83809"},"modified":"2026-06-29T08:00:44","modified_gmt":"2026-06-29T15:00:44","slug":"nodejs-vps","status":"publish","type":"post","link":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/","title":{"rendered":"How To Run Node.js on a VPS"},"content":{"rendered":"<div class=\"tldr-block\" style=\"display: none;\">\n\t<div class=\"svg\">\n\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 119.25 37.8\">\n\t<g>\n\t\t<g>\n\t\t\t<path fill=\"#ffffff\" d=\"M23.4,6.93h-8.1v24.57h-7.2V6.93H0V0h23.4v6.93Z\" \/>\n\t\t\t<path fill=\"#ffffff\" d=\"M45,24.57v6.93h-18.45V0h7.2v24.57h11.25Z\" \/>\n\t\t\t<path fill=\"#ffffff\"\n\t\t\t\td=\"M90.9,15.75c0,8.91-6.61,15.75-15.3,15.75h-12.6V0h12.6c8.68,0,15.3,6.84,15.3,15.75ZM83.97,15.75c0-5.4-3.42-8.82-8.37-8.82h-5.4v17.64h5.4c4.95,0,8.37-3.42,8.37-8.82Z\" \/>\n\t\t\t<path fill=\"#ffffff\"\n\t\t\t\td=\"M105.57,21.15h-3.42v10.35h-7.2V0h12.6c5.98,0,10.8,4.81,10.8,10.8,0,3.87-2.34,7.38-5.81,9.13l6.71,11.56h-7.74l-5.94-10.35ZM102.15,14.85h5.4c1.98,0,3.6-1.75,3.6-4.05s-1.62-4.05-3.6-4.05h-5.4v8.1Z\" \/>\n\t\t<\/g>\n\t\t<path\n\t\t\tfill=\"#0173ec\"\n\t\t\td=\"M53.97,37.8h-5.4l1.8-13.27h7.2l-3.6,13.27ZM49.02,12.55c0-2.34,1.93-4.27,4.27-4.27s4.27,1.94,4.27,4.27-1.93,4.27-4.27,4.27-4.27-1.94-4.27-4.27Z\"\n\t\t \/>\n\t<\/g>\n<\/svg>\n\t<\/div>\n\t<div class=\"tldr-wrap\">\n\t\t\n\n<p class=\"wp-block-paragraph\">Running Node.js on a VPS means installing the current Node.js LTS (24.x &#8220;Krypton&#8221; as of May 2026) on a Linux server you control, then running your app behind a process manager and a reverse proxy with HTTPS. You get a single always-on box that handles long-lived connections, background jobs, and heavy compute without per-function billing or cold starts.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Target setup:<\/strong> Ubuntu 24.04 LTS + Node 24 via NodeSource or nvm + PM2 (or systemd) + NGINX + Let&#8217;s Encrypt.<\/p>\n\n\n\t<\/div>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Heroku killed its free tier and bumped the floor. Vercel charges per seat and times out long-running jobs. Render and Railway scale price with traffic.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open the most recent bill from your hosting provider. The Node app, a Postgres database, and a Redis cache. Three line items, three sets of overage warnings, one frantic Slack thread the day marketing finally launches a campaign.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That bill is why a lot of teams are taking another look at the VPS. <a target=\"_blank\" href=\"https:\/\/www.dreamhost.com\/blog\/what-is-node-js\/\">Node.js<\/a> itself doesn&#8217;t <em>care<\/em> where it runs. The only thing serverless was protecting you from was finding out what happens after \u2018npm start.\u2019<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s look at a production-setup pattern for Node.js on a Linux box you control. If you can SSH into a box and read a config file, by the end, you\u2019ll have a production stack you can run for years on a couple of hours of maintenance a month.<\/p>\n\n\n\n<h2 id=\"h-when-does-running-node-js-on-a-vps-make-sense\" class=\"wp-block-heading\">When Does Running Node.js on a VPS Make Sense?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A VPS is the right home for Node.js when you have a long-lived process, a stack you want to consolidate into one bill, or a managed-runtime invoice that&#8217;s outgrown the convenience.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Broadly speaking, there are three good fits:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Long-lived processes:<\/strong> WebSocket servers, queue workers, cron schedulers, MCP servers. Anything that has to <em>stay<\/em> running and listening. Most serverless platforms still optimize around short-lived execution and request lifecycles. A Node process on a VPS just sits there.<\/li>\n\n\n\n<li><strong>Cost consolidation:<\/strong> Node app, Postgres, Redis, plus a small build worker all live on the same 4 GB box. One bill line, not four.<\/li>\n\n\n\n<li><strong>Apps that outgrew PaaS:<\/strong> Function timeouts on your long PDF generation job. Per-seat pricing on a team that finally hired a fourth engineer. A <a target=\"_blank\" href=\"https:\/\/www.heroku.com\/pricing\/\">Heroku<\/a> invoice climbing past $60 a month for a workload that runs fine on a $15 VPS.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>And there are three <\/strong><strong><em>wrong<\/em><\/strong><strong> fits:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Static sites and SSG content:<\/strong> A Next.js export, an Astro build, a Gatsby blog. Vercel&#8217;s free tier is the right tool. A VPS is overkill.<\/li>\n\n\n\n<li><strong>Sparse, event-driven workloads: <\/strong>AWS Lambda or Cloudflare Workers cost pennies for a webhook that runs ten times a day. A VPS costs the same whether the app is busy or asleep.<\/li>\n\n\n\n<li><strong>Horizontally-scaled real-time apps: <\/strong>If your WebSocket server needs to fan out to 100,000 concurrent connections, one VPS is not the answer. That\u2019s a Kubernetes cluster, a distributed edge infrastructure, or a managed real-time platform.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">JavaScript is the most-used language in the <a target=\"_blank\" href=\"https:\/\/survey.stackoverflow.co\/2025\/technology\">2025 Stack Overflow Developer Survey<\/a>, and Node.js remains one of the default ways developers run JavaScript on the backend. That\u2019s a lot of people running Node somewhere. This article is for the slice of them who\u2019d be happier running it on a server they control.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ve watched teams move four production Node services off Heroku onto a single 4 GB VPS, with the same uptime, a third of the bill, and long-lived WebSockets that finally worked without a workaround.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The migration is mostly an afternoon of \u2018apt install,\u2019 a \u2018pm2 start,\u2019 and a DNS change.<\/p>\n\n\n\n<h2 id=\"h-what-vps-specs-does-node-js-actually-need\" class=\"wp-block-heading\">What VPS Specs Does Node.js Actually Need?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Node.js itself is lightweight. A minimal Express server can idle well under 100 MB of resident memory. The \u201cNode only needs 1 GB\u201d advice you\u2019ll still find on older blogs is technically true and practically useless. By the time you\u2019ve added Postgres, Redis, logs, and a deployment process that isn\u2019t held together with hope, you\u2019re already pushing past that on a quiet day.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Realistic sizing for common workloads:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th><strong>Workload<\/strong><\/th><th><strong>RAM<\/strong><\/th><th><strong>vCPU<\/strong><\/th><th><strong>Storage<\/strong><\/th><th><strong>Notes<\/strong><\/th><\/tr><\/thead><tbody><tr><td>Small Express API, no DB on the box<\/td><td>2 GB<\/td><td>1-2<\/td><td>40 GB NVMe<\/td><td>Realistic floor for one production app<\/td><\/tr><tr><td>Node API + Postgres + Redis on one box<\/td><td>4 GB<\/td><td>2<\/td><td>80 GB NVMe<\/td><td>The sweet spot; most teams land here<\/td><\/tr><tr><td>SSR-heavy app (Next.js, Nuxt, Remix)<\/td><td>8 GB<\/td><td>4<\/td><td>80 GB NVMe<\/td><td>SSR rendering and build pipelines are where the memory goes<\/td><\/tr><tr><td>Real-time\/WebSocket app, moderate scale<\/td><td>8 GB<\/td><td>4<\/td><td>80 GB NVMe<\/td><td>Every persistent connection consumes memory<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">A few specifics to pin down before you provision:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>NVMe storage matters more than raw disk size: <\/strong>Modern Node apps touch thousands of small files during installs, builds, and startup. Slow disks make dependency installs, cold boots, and SSR rebuilds noticeably worse.<\/li>\n\n\n\n<li><strong>KVM virtualization, not OpenVZ:<\/strong> Older OpenVZ-based plans share a kernel with the host, which can mean outdated kernel versions and occasional compatibility headaches with newer runtimes. Most reputable VPS providers are KVM-only now, but it\u2019s still worth checking.<\/li>\n\n\n\n<li><strong>Swap space:<\/strong> Enable 1-2 GB of swap on smaller boxes. Node&#8217;s V8 heap can swing hard during garbage collection. Without swap, a transient spike kills the process. I&#8217;ve watched a 4 GB box OOM during a routine deploy because someone had disabled swap thinking it was a Docker-era anachronism.<\/li>\n\n\n\n<li><strong>Bandwidth:<\/strong> Most modern VPS plans include 1-4 TB of monthly bandwidth, enough for almost everything short of video hosting. <a target=\"_blank\" href=\"https:\/\/www.dreamhost.com\/hosting\/self-managed-vps\/\">Self-Managed VPS plans<\/a> include unmetered bandwidth, one fewer line on the capacity-planning spreadsheet.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A 4 GB VPS runs around $15 a month at market rate. That&#8217;s 50 cents a day, or roughly one airport coffee every two weeks. Compared to paying separately for app runtimes, managed Postgres, and Redis on a PaaS, the economics flip surprisingly fast.<\/p>\n\n\n\n<h2 id=\"h-which-node-js-version-should-you-install\" class=\"wp-block-heading\">Which Node.js Version Should You Install?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Install <strong>Node.js 24 (codename Krypton)<\/strong>. It\u2019s the current Active LTS release, promoted in October 2025 and supported through April 2028 according to the official <a target=\"_blank\" href=\"https:\/\/nodejs.org\/en\/about\/previous-releases\">Node.js release schedule<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A lot of tutorials still point people at Node 22. Those guides haven\u2019t been updated. If you\u2019re starting a new deployment today, pin your CI image and your VPS to Node 24.x.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th><strong>Version<\/strong><\/th><th><strong>Codename<\/strong><\/th><th><strong>Status<\/strong><\/th><th><strong>EOL<\/strong><\/th><\/tr><\/thead><tbody><tr><td>Node.js 26.x<\/td><td>(none)<\/td><td>Current<\/td><td>Promotes to LTS in late 2026<\/td><\/tr><tr><td>Node.js 24.x<\/td><td>Krypton<\/td><td>Active LTS<\/td><td>April 2028<\/td><\/tr><tr><td>Node.js 22.x<\/td><td>Jod<\/td><td>Maintenance LTS<\/td><td>April 2027<\/td><\/tr><tr><td>Node.js 20.x<\/td><td>Iron<\/td><td>End-of-life |<\/td><td>Reached EOL April 30, 2026. Do not use.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">A few rules of thumb:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Don&#8217;t run Current (non-LTS) releases in production: <\/strong>Node 26 exists for testing future compatibility and new runtime features, not for the app your revenue depends on.<\/li>\n\n\n\n<li><strong>Node 22 is the fallback option if a critical dependency still hasn\u2019t caught up with Node 24 compatibility: <\/strong>Most of the ecosystem stabilized within a few months of the LTS promotion.<\/li>\n\n\n\n<li><strong>Pin your Node version everywhere: <\/strong>Your CI image, Dockerfile, .nvmrc, and production VPS should all agree. \u201cWorks on my machine\u201d gets expensive fast once native modules enter the chat.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83e\udd14<a target=\"_blank\" href=\"https:\/\/www.dreamhost.com\/blog\/bun-vs-node\/\"><strong>Considering Bun<\/strong><\/a><strong>?<\/strong> It\u2019s faster on some workloads and genuinely impressive, but the ecosystem is still smaller, and the production track record is shorter than Node\u2019s. For most teams, boring wins.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">NodeSource, which maintains the apt and yum repositories many production teams install Node from, highlights improvements in the 24.x line, starting with a newer V8 engine. Node 24 also ships now-mature tooling like built-in node &#8211;watch and a stable native test runner (node: test), both of which stabilized in the 20\u201322 lines and carry forward here. None of it is flashy. It just removes a little operational friction every month.<\/p>\n\n\n\n<h2 id=\"h-how-do-you-install-node-js-on-a-vps\" class=\"wp-block-heading\">How Do You Install Node.js on a VPS?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You have two realistic install paths. Pick based on whether the server runs one Node app or several.<\/p>\n\n\n\n<h3 id=\"h-nodesource-for-a-single-app-server\" class=\"wp-block-heading\">NodeSource for a Single-App Server<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This is the simplest production path. One setup script and one <strong><code>apt install<\/code><\/strong> get you the current Node 24 LTS line as a system package, and future security updates flow through normal package upgrades.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On Ubuntu or Debian:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -fsSL https:\/\/deb.nodesource.com\/setup_24.x | bash -\napt install -y nodejs<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify the install:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node -v\nnpm -v<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"2560\" height=\"1344\" data-src=\"https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-scaled.webp\" alt=\"Terminal commands displaying Node.js version 24.14.0 and npm version 11.9.0 installed on DreamHost.\" class=\"wp-image-83813 lazyload\" data-srcset=\"https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-scaled.webp 2560w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-300x158.webp 300w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-1024x538.webp 1024w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-768x403.webp 768w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-1536x806.webp 1536w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-2048x1075.webp 2048w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-600x315.webp 600w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-1200x630.webp 1200w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-730x383.webp 730w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-1460x767.webp 1460w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-784x412.webp 784w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-1568x823.webp 1568w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-877x460.webp 877w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/01_nodesource_for_a_single_app_server-1754x921.webp 1754w\" data-sizes=\"(max-width: 2560px) 100vw, 2560px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 2560px; --smush-placeholder-aspect-ratio: 2560\/1344;\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">You should see a Node 24.x release.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">RHEL-family distro instructions (yum\/dnf) live in the official NodeSource distributions repository.<\/p>\n\n\n\n<h3 id=\"h-nvm-for-per-project-version-switching\" class=\"wp-block-heading\">nvm for Per-Project Version Switching<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><a target=\"_blank\" href=\"https:\/\/github.com\/nvm-sh\/nvm\">nvm<\/a> (Node Version Manager) installs Node into your home directory and lets different projects run different Node versions. Useful if you host multiple apps on the same server or don\u2019t have sudo access.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Run this as your app user, not root:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -o- https:\/\/raw.githubusercontent.com\/nvm-sh\/nvm\/v0.40.5\/install.sh | bash<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Reload your shell, then install Node 24:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nvm install 24\nnvm use 24\nnvm alias default 24<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\ud83d\udc49One important rule: <\/strong>Don\u2019t use <code>sudo \u2018npm install -g\u2019<\/code> for application dependencies.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Global installs are usually reserved for machine-level CLI tools like pm2, typescript, or nodemon. Your app dependencies belong in package.json and should be installed from the project directory with npm ci.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th><strong>NodeSource<\/strong><\/th><th><strong>nvm<\/strong><\/th><\/tr><\/thead><tbody><tr><td>One Node version per server<\/td><td>Multiple Node versions per server<\/td><\/tr><tr><td>Installed system-wide, runs as any user<\/td><td>Installed per user<\/td><\/tr><tr><td>Auto-updates with <code>\u2018apt\u2019<\/code><\/td><td>Managed manually<\/td><\/tr><tr><td>Requires <code>sudo<\/code><\/td><td>No <code>sudo<\/code> required<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">If you\u2019re unsure, start with NodeSource. Most single-purpose production servers don\u2019t need per-project Node version switching.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83d\udc49<strong>DreamHost Self-Managed VPS users: <\/strong>The Node app available at provisioning ships with Node 22 LTS \u2014 still supported through April 2027. To run Node 24, use the NodeSource or nvm steps above after provisioning.<\/p>\n\n\n\n<h2 id=\"h-should-you-use-pm2-or-systemd-to-keep-your-app-running\" class=\"wp-block-heading\">Should You Use PM2 or systemd to Keep Your App Running?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Either one works. The honest answer is whichever your team is comfortable with. PM2 is the developer-friendly path. systemd is the Unix-native path. Both solve the same three problems: restart on crash, start at boot, and graceful shutdown on \u2018SIGTERM.\u2019<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re starting fresh, here&#8217;s how to pick:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th><\/th><th><strong>PM2<\/strong><\/th><th><strong>systemd<\/strong><\/th><\/tr><\/thead><tbody><tr><td>Setup time<\/td><td>3 minutes<\/td><td>10 minutes<\/td><\/tr><tr><td>Cluster mode (multi-core)<\/td><td>Built in<\/td><td>Not built in (start N units)<\/td><\/tr><tr><td>Log rotation<\/td><td>Module: <code>\u2018pm2-logrotate\u2019<\/code><\/td><td>Built in via <code>\u2018journalctl\u2019<\/code><\/td><\/tr><tr><td>Zero-downtime reload<\/td><td><code>\u2018pm2 reload\u2019<\/code><\/td><td>Usually handled manually with rolling restarts or multiple units<\/td><\/tr><tr><td>Memory overhead (daemon)<\/td><td>Small daemon overhead<\/td><td>None (no extra daemon)<\/td><\/tr><tr><td>Best for<\/td><td>Single-box, JS-shop, fast iteration<\/td><td>Multi-app boxes, ops-team comfort<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The <a target=\"_blank\" href=\"https:\/\/pm2.keymetrics.io\/docs\/usage\/quick-start\/\">PM2 quick start<\/a> is exactly that, quick:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm install -g pm2\npm2 start app.js --name api\npm2 startup    # prints the systemd startup command to run\npm2 save       # saves the current process list<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">PM2 then becomes the only thing you talk to: \u2018<code>pm2 logs<\/code>,\u2019 \u2018<code>pm2 reload api<\/code>,\u2019 \u2018<code>pm2 monit<\/code>.\u2019<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\ud83d\udc49Also worth knowing:<\/strong> \u2018<code>pm2 startup<\/code>\u2019 writes a systemd unit, so the PM2 setup <em>actually<\/em> uses systemd under the hood.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A minimal systemd unit for direct Node management at \u2018\/etc\/systemd\/system\/api.service\u2019:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>[Unit]<br>Description=My Node API<br>After=network.target<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>[Service]<br>Type=simple<br>User=app<br>WorkingDirectory=\/var\/www\/api<br>ExecStart=\/usr\/bin\/node server.js<br>Restart=on-failure<br>RestartSec=5<br>Environment=NODE_ENV=production<br>StandardOutput=journal<br>StandardError=journal<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>[Install]<br>WantedBy=multi-user.target<\/code><br>Then \u2018<code>systemctl enable --now api<\/code>.\u2019 Logs live in \u2018<code>journalctl -u api -f<\/code>.\u2019<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re already running PM2 and it&#8217;s working, don&#8217;t migrate to systemd just because someone on Hacker News said so. The PM2 daemon\u2019s memory isn\u2019t why you\u2019d migrate away from it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Migrate when you have a real reason, like running half a dozen Node processes where every megabyte counts, or shipping into an ops environment where every other service is a systemd unit, and PM2 stands out as the odd one.<\/p>\n\n\n\n<h2 id=\"h-how-do-you-put-nginx-or-caddy-in-front-of-your-node-app\" class=\"wp-block-heading\">How Do You Put NGINX (or Caddy) in Front of Your Node App?<\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"1600\" height=\"1099\" data-src=\"https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node.webp\" alt=\"NGINX acts as reverse proxy between client requests and Node.js app backend.\" class=\"wp-image-83812 lazyload\" data-srcset=\"https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node.webp 1600w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node-300x206.webp 300w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node-1024x703.webp 1024w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node-768x528.webp 768w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node-1536x1055.webp 1536w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node-600x412.webp 600w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node-1200x824.webp 1200w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node-730x501.webp 730w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node-1460x1003.webp 1460w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node-784x539.webp 784w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node-1568x1077.webp 1568w, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/02_how_nginx_sits_in_front_of_node-877x602.webp 877w\" data-sizes=\"(max-width: 1600px) 100vw, 1600px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 1600px; --smush-placeholder-aspect-ratio: 1600\/1099;\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">You want a reverse proxy in front of Node for five reasons: HTTPS termination, gzip\/brotli compression, static asset serving, running multiple apps on the same box, and easier rate limiting. Node <em>can<\/em> do all of these. NGINX and Caddy do them better, and they don&#8217;t take your event loop down when something misbehaves.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pick NGINX if anyone on your team already knows it. Pick Caddy if you want <a target=\"_blank\" href=\"https:\/\/www.dreamhost.com\/blog\/ultimate-guide-ssl-tls\/\">HTTPS<\/a> in three lines of config and you\u2019re fine with a smaller advanced-configuration ecosystem.<\/p>\n\n\n\n<h3 id=\"h-minimal-nginx-config\" class=\"wp-block-heading\">Minimal NGINX Config<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Put this proxy block in <strong>\/etc\/nginx\/sites-available\/api<\/strong>, symlink to <strong><code>sites-enabled<\/code><\/strong>, then <strong><code>nginx -t &amp;&amp; systemctl reload nginx<\/code><\/strong>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n    listen 80;\n    server_name api.example.com;\n\n    location \/ {\n        proxy_pass http:\/\/127.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}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The \u2018Upgrade\u2019 and \u2018Connection\u2019 headers are the WebSocket-support lines. <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/websocket.html\">NGINX\u2019s own docs call out<\/a> that Upgrade is a hop-by-hop header, so it needs explicit handling when proxying WebSocket traffic.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Leave them in if your app uses WebSockets now, or might later. Socket.IO, GraphQL subscriptions over WebSockets, and a surprising number of \u201cregular\u201d real-time features depend on that upgrade handshake.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The single most common production bug I see in Node setups is a Socket.IO server behind <a target=\"_blank\" href=\"https:\/\/help.dreamhost.com\/hc\/en-us\/articles\/216431827-Nginx-overview\">NGINX<\/a> without those two lines. Connections fail intermittently, devs blame Socket.IO, and the actual problem is usually proxy config.<\/p>\n\n\n\n<h3 id=\"h-minimal-caddyfile\" class=\"wp-block-heading\">Minimal Caddyfile<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The <a target=\"_blank\" href=\"https:\/\/caddyserver.com\/docs\/quick-starts\/reverse-proxy\">Caddy reverse proxy quickstart<\/a> version of the same thing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>api.example.com {\n    reverse_proxy 127.0.0.1:3000\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s the entire file. As long as the domain points to the server and ports 80\/443 are reachable, Caddy provisions and renews HTTPS automatically. Caddy\u2019s docs say <a target=\"_blank\" href=\"https:\/\/caddyserver.com\/docs\/automatic-https\">automatic HTTPS provisions<\/a> TLS certificates for sites and keeps them renewed; its reverse proxy quickstart also notes HTTPS is automatic when Caddy knows the hostname.<\/p>\n\n\n\n<h3 id=\"h-bind-node-to-localhost-not-0-0-0-0\" class=\"wp-block-heading\">Bind Node to localhost, Not 0.0.0.0<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Whatever proxy you pick, configure your Node app to listen on 127.0.0.1:3000, not 0.0.0.0:3000. The only thing that should face the public internet on a Node box is the proxy. Pair this with UFW, Ubuntu\u2019s common firewall frontend, to deny everything except ports 22, 80, and 443.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ufw default deny incoming\nufw allow 22\/tcp\nufw allow 80\/tcp\nufw allow 443\/tcp\nufw enable<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If SSH runs on a custom port, allow that port before enabling UFW.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bind to localhost from day one. The meeting where someone admits \u201cthe app was exposed because Node bound to 0.0.0.0\u201d is not a meeting you want to have.<\/p>\n\n\n\n<h2 id=\"h-how-do-you-set-up-https-for-your-node-js-app\" class=\"wp-block-heading\">How Do You Set Up HTTPS for Your Node.js App?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use <a target=\"_blank\" href=\"https:\/\/help.dreamhost.com\/hc\/en-us\/articles\/216539558-Let-s-Encrypt-SSL-certificate-overview\">Let&#8217;s Encrypt<\/a>. It&#8217;s free, automated, and trusted by every browser. There are two paths, depending on which proxy you picked.<\/p>\n\n\n\n<h3 id=\"h-nginx-certbot\" class=\"wp-block-heading\">NGINX + Certbot<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Point an A record at your VPS IP and wait for DNS to propagate.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Install Certbot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apt install certbot python3-certbot-nginx<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>certbot --nginx -d api.example.com<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Certbot updates your NGINX config and reloads the server automatically.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On modern Ubuntu releases, a systemd timer installed by the Certbot package handles renewal automatically.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open <strong>https:\/\/api.example.com<\/strong> and confirm the lock icon.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <a target=\"_blank\" href=\"https:\/\/certbot.eff.org\/instructions?ws=nginx&amp;os=snap\">official Certbot docs<\/a> also cover the snap-based install path if your distro package is outdated.<\/p>\n\n\n\n<h3 id=\"h-caddy\" class=\"wp-block-heading\">Caddy<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Add the domain to the Caddyfile (the example above already has it), then restart Caddy. As long as the domain resolves correctly and ports 80\/443 are reachable, the certificate provisions automatically on first start. There\u2019s no Certbot.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Don&#8217;t terminate TLS in Node itself for production.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Node&#8217;s https module works perfectly well, but reverse proxies like NGINX and Caddy are purpose-built for TLS termination. They give you OCSP stapling, modern cipher defaults, automatic certificate renewal, HTTP\/2 support, and \u2014 in Caddy&#8217;s case \u2014 HTTP\/3 support out of the box.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Could you handle all of that directly in Node? Sure. You&#8217;d just be rebuilding infrastructure that your proxy already solves extremely well.<\/p>\n\n\n\n<h2 id=\"h-what-does-a-production-ready-node-js-setup-actually-look-like\" class=\"wp-block-heading\">What Does a Production-Ready Node.js Setup Actually Look Like?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Eight things bite people in production. Most of them aren&#8217;t in install tutorials because they don&#8217;t fit the &#8220;install Node, run app&#8221; arc. They&#8217;re the difference between an app that survives month two and one that doesn&#8217;t.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>NODE_ENV=production:<\/strong> The single most-missed step. In many Node frameworks and libraries, it disables dev-only behavior and enables production optimizations. Express, for example, caches compiled view templates and returns terser errors in production \u2014 its own docs cite up to a 3x performance improvement. Set the \u2018env var\u2019 everywhere.<\/li>\n\n\n\n<li><strong>Graceful shutdown:<\/strong> When your VPS reboots or PM2 sends \u2018SIGTERM,\u2019 your app has a few seconds to drain in-flight requests, close database connections, and exit cleanly. Wire up a \u2018process.on(&#8216;SIGTERM&#8217;, &#8230;)\u2019 handler. PM2\u2019s default shutdown timing depends on configuration and environment, so don\u2019t assume you\u2019ll always have much time to clean up.&nbsp;<\/li>\n\n\n\n<li><strong>Log rotation:<\/strong> PM2&#8217;s \u2018pm2-logrotate\u2019 module handles this for PM2. The systemd journal handles it for direct systemd units. Without rotation, your logs eat the disk in a quarter of the time you&#8217;d expect.<\/li>\n\n\n\n<li><strong>.env discipline:<\/strong> Never commit secrets, never log them. Use \u2018dotenv\u2019 for local dev. In production, set env vars via your systemd unit&#8217;s \u2018Environment=\u2019 or your PM2 ecosystem file. The day you \u2018console.log(process.env)\u2019 by accident is the day you rotate every credential.<\/li>\n\n\n\n<li><strong>A reverse proxy in front of Node: <\/strong>Bind Node to localhost; let NGINX or Caddy face the public internet.<\/li>\n\n\n\n<li><strong>A firewall:<\/strong> UFW deny everything except 22, 80, 443. Moving SSH away from port 22 won\u2019t stop a determined attacker, but it dramatically cuts down on automated brute-force noise and junk auth logs.<\/li>\n\n\n\n<li><strong>Monitoring:<\/strong> A healthcheck endpoint your monitoring tool hits every minute. PM2 has built-in basics. For anything serious, run Prometheus and Grafana, or use a hosted uptime service like <a target=\"_blank\" href=\"https:\/\/betterstack.com\/\">Better Stack<\/a> or <a target=\"_blank\" href=\"https:\/\/uptimerobot.com\/\">UptimeRobot<\/a>. You want to know your app is down <em>before<\/em> a customer tells you.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Maintenance estimate for the stack above: one to three hours a month.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Apt updates, occasional dependency bumps, and a quarterly look at log volume. That&#8217;s the trade for the cost and control wins.<\/p>\n\n\n\n<h2 id=\"h-when-is-a-vps-the-wrong-choice-for-node-js\" class=\"wp-block-heading\">When Is a VPS the Wrong Choice for Node.js?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A VPS is the wrong call when your workload is built for something else. Be honest about which side you&#8217;re on before you provision.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Static sites and SSG content:<\/strong> Next.js export, Astro, Gatsby, and an Eleventy blog. Platforms like Vercel, Netlify, or Cloudflare Pages give you globally cached static hosting, Git-based deploys, and automatic rebuilds out of the box. A VPS is usually unnecessary infrastructure for purely static content.<\/li>\n\n\n\n<li><strong>Sparse, event-driven workloads: <\/strong>Cloudflare Workers and AWS Lambda are inexpensive for webhooks running ten times per day.&nbsp;<\/li>\n\n\n\n<li><strong>Real-time apps that need 100,000+ concurrent connections:<\/strong> One VPS doesn&#8217;t horizontally scale. You&#8217;ll need orchestration (Kubernetes, ECS, Nomad) or a managed real-time platform like Ably or Pusher.<\/li>\n\n\n\n<li><strong>Compliance-heavy regulated workloads:<\/strong> HIPAA, PCI-DSS Level 1, FedRAMP. A managed PaaS with built-in compliance certifications saves audit pain. Self-hosting compliance on a VPS is a multi-quarter project you probably don&#8217;t want.<\/li>\n\n\n\n<li><strong>No <\/strong><a target=\"_blank\" href=\"https:\/\/www.dreamhost.com\/blog\/linux-distros\/\"><strong>Linux<\/strong><\/a><strong> comfort \u2014 and no appetite to build it: <\/strong>Platforms like Render, Railway, and DigitalOcean App Platform sit somewhere between raw VPS hosting and fully managed PaaS. Tools like Dokploy add Heroku-style deployment workflows on top of your own VPS infrastructure. You still get a lot of the cost and control benefits without needing to become deeply familiar with iptables, systemd internals, or reverse-proxy debugging at 1 a.m.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">There&#8217;s no shame in any of those answers. The best technical decision is the one that matches your workload.<\/p>\n\n\n\n<h2 id=\"h-picking-your-node-stack-and-moving-in\" class=\"wp-block-heading\">Picking Your Node Stack and Moving In<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Open that hosting invoice one more time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You&#8217;re about to replace a surprising amount of it with a single VPS bill.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\ud83d\udc49The stack:<\/strong> Ubuntu 24.04 LTS, Node 24, PM2 (or systemd), NGINX (or Caddy), Let&#8217;s Encrypt via Certbot (or Caddy&#8217;s built-in).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Spin up the smallest VPS plan that hits the RAM you sized for, install Node, run your app on \u2018127.0.0.1,\u2019 point NGINX at it, and switch your DNS.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the app survives a deploy, a reboot, and an overnight run without drama, you&#8217;re most of the way there.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The rest is maintenance. An hour or two a month, the occasional \u2018apt upgrade\u2019 window, a quarterly dependency bump. That&#8217;s the deal you made when you traded a per-seat invoice for a flat one, and DreamHost\u2019s Self-Managed VPS Stack 4 is where you can start.<\/p>\n\n\n\n\n<div class=\"article-cta-shared article-cta-small article-cta--product\">\n\t<div class=\"tr-img-wrap-outer jsLoading\"><img decoding=\"async\" class=\"js-img-lazy \" src=\"https:\/\/www.dreamhost.com\/blog\/wp-content\/themes\/blog2018\/assets\/img\/lazy-loading-transparent.webp\" data-srcset=\"https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/cta_image_a-877x522.webp 1x, https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/cta_image_a.webp 2x\"  \/><\/div>\n\n\t<a href='https:\/\/www.dreamhost.com\/hosting\/vps\/' class='link-top' target='_blank' rel='noopener noreferrer'>\n\t\t<span>VPS<\/span>\n\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 384 512\" width=\"15\"><path d=\"M342.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L274.7 256 105.4 86.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z\"\/><\/svg>\n\t<\/a>\n\n\t<div class=\"content-btm\">\n\t\t<h2 class=\"h2--md\">\n\t\t\tOwn Your Entire Stack. Apps, AI, Databases, and More.\n\t\t<\/h2>\n\t\t<p class=\"p--md\">\n\t\t\tKeep every credential and conversation on a server you control, with NVMe speed and unmetered bandwidth built in.\n\t\t<\/p>\n\n\t\t        <a\n            href=\"https:\/\/www.dreamhost.com\/hosting\/vps\/\"\n                        class=\"btn btn--white-outline btn--sm btn--round\"\n                                    target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            >\n                            Explore VPS Hosting Plans                    <\/a>\n\n\t<\/div>\n<\/div>\n\n\n<h2 id=\"h-frequently-asked-questions-about-running-node-js-on-a-vps\" class=\"wp-block-heading\">Frequently Asked Questions About Running Node.js on a VPS<\/h2>\n\n\n\n<h3 id=\"h-can-i-run-node-js-on-any-vps\" class=\"wp-block-heading\">Can I run Node.js on any VPS?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Most modern VPS plans run Node.js fine. Modern KVM-based VPS plans with a 64-bit Linux distro are the safest default for current Node.js releases.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Older OpenVZ-based plans sometimes have kernel restrictions that break newer Node versions. If you&#8217;re picking between providers, ask whether they&#8217;re KVM-based.<\/p>\n\n\n\n<h3 id=\"h-how-much-ram-does-node-js-need-on-a-vps\" class=\"wp-block-heading\">How much RAM does Node.js need on a VPS?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A minimal Express server idles well under 100 MB, but a realistic production app with middleware, logging, and a connection pool typically runs in the 150-300 MB range.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The realistic minimum for one production app is 2 GB; the sweet spot for a Node + Postgres + Redis stack is 4 GB. <a target=\"_blank\" href=\"https:\/\/www.dreamhost.com\/hosting\/self-managed-vps\/\">DreamHost&#8217;s Self-Managed VPS<\/a> Stack 4 (4 GB) handles most production Node workloads. Jump to Stack 8 (8 GB) for SSR-heavy or real-time apps.<\/p>\n\n\n\n<h3 id=\"h-what-s-the-current-node-js-lts-version\" class=\"wp-block-heading\">What&#8217;s the current Node.js LTS version?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The current Active LTS is Node.js 24.x (&#8220;Krypton&#8221;), promoted on October 28, 2025, and supported through April 2028. Node.js 22.x (&#8220;Jod&#8221;) is in Maintenance LTS through April 2027 if a dependency forces backward compatibility. <a target=\"_blank\" href=\"https:\/\/nodejs.org\/en\/blog\/release\/v26.0.0\">Node.js 26 launched on May 5, 2026<\/a>, as Current and will be promoted to LTS in October 2026.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Most production teams stick to LTS releases unless they specifically need newer runtime features.<\/p>\n\n\n\n<h3 id=\"h-do-i-need-pm2-if-i-have-systemd\" class=\"wp-block-heading\">Do I need PM2 if I have systemd?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No, you don&#8217;t need both. PM2 and systemd solve the same problem: keeping your Node app running through crashes and reboots. Many Node-focused teams pick PM2 for built-in clustering, log management, and reload tooling.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Teams already running systemd units for everything else pick systemd.<\/p>\n\n\n\n<h3 id=\"h-why-put-nginx-in-front-of-node-js\" class=\"wp-block-heading\">Why put NGINX in front of Node.js?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">NGINX (or Caddy) in front of Node.js centralizes TLS termination, compression, static asset serving, and rate limiting in software designed specifically for proxying and web serving.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It also lets you run multiple Node apps on the same VPS without port conflicts. In production, Node listens on localhost; NGINX faces the public internet.<\/p>\n\n\n\n<h3 id=\"h-is-node-js-on-a-vps-cheaper-than-heroku-or-vercel\" class=\"wp-block-heading\">Is Node.js on a VPS cheaper than Heroku or Vercel?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes, often. A 4 GB VPS commonly lands somewhere in the $15-$25\/month range at market rate and can consolidate app runtime, database, and cache costs that are billed separately on many PaaS platforms.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Vercel Pro pricing is seat-based, and serverless platforms still impose execution-duration limits depending on runtime and plan.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The trade is that you handle operations yourself, about one to three hours a month.<\/p>\n\n\n\n<h3 id=\"h-can-i-run-multiple-node-apps-on-one-vps\" class=\"wp-block-heading\">Can I run multiple Node apps on one VPS?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes, and it&#8217;s the most common reason teams move from PaaS to a VPS. Run each app on its own internal port (3000, 3001, 3002) and route traffic with NGINX server blocks by hostname. PM2 manages all of them as separate processes; systemd uses one unit file per app.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A 4 GB VPS can often handle several lightweight Node services alongside a small database workload.<\/p>\n\n\n\n<h3 id=\"h-can-i-run-node-js-on-dreamhost-shared-hosting\" class=\"wp-block-heading\">Can I run Node.js on DreamHost shared hosting?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. Node.js needs persistent processes, root-level package installs, and direct port binding, none of which shared hosting provides. <a target=\"_blank\" href=\"https:\/\/www.dreamhost.com\/hosting\/self-managed-vps\/\">DreamHost&#8217;s Self-Managed VPS plans<\/a> (Stack 4 and up) fit Node workloads with full root access, NVMe storage, and unmetered bandwidth.<\/p>\n\n\n<p><script type=\"application\/ld+json\"><br \/>\n{<br \/>\n  \"@context\": \"https:\/\/schema.org\",<br \/>\n  \"@graph\": [<br \/>\n    {<br \/>\n      \"@type\": \"FAQPage\",<br \/>\n      \"mainEntity\": [<br \/>\n        {<br \/>\n          \"@type\": \"Question\",<br \/>\n          \"name\": \"Can I run Node.js on any VPS?\",<br \/>\n          \"acceptedAnswer\": {<br \/>\n            \"@type\": \"Answer\",<br \/>\n            \"text\": \"Most modern VPS plans run Node.js fine. The requirement is KVM (or similar full virtualization) and a 64-bit Linux kernel. Older OpenVZ-based plans sometimes have kernel restrictions that break newer Node versions. If you're picking between providers, ask whether they're KVM-based.\"<br \/>\n          }<br \/>\n        },<br \/>\n        {<br \/>\n          \"@type\": \"Question\",<br \/>\n          \"name\": \"How much RAM does Node.js need on a VPS?\",<br \/>\n          \"acceptedAnswer\": {<br \/>\n            \"@type\": \"Answer\",<br \/>\n            \"text\": \"A minimal Express server idles well under 100 MB, but a realistic production app with middleware, logging, and a connection pool typically runs in the 150-300 MB range. The realistic minimum for one production app is 2 GB; the sweet spot for a Node + Postgres + Redis stack is 4 GB. DreamHost's Self-Managed VPS Stack 4 (4 GB) handles most production Node workloads. Jump to Stack 8 (8 GB) for SSR-heavy or real-time apps.\"<br \/>\n          }<br \/>\n        },<br \/>\n        {<br \/>\n          \"@type\": \"Question\",<br \/>\n          \"name\": \"What's the current Node.js LTS version?\",<br \/>\n          \"acceptedAnswer\": {<br \/>\n            \"@type\": \"Answer\",<br \/>\n            \"text\": \"The current Active LTS is Node.js 24.x ('Krypton'), promoted on October 28, 2025 and supported through April 2028. Node.js 22.x ('Jod') is in Maintenance LTS through April 2027 if a critical dependency forces backward compatibility. Node.js 26 launched May 5, 2026 as Current and promotes to LTS in October 2026. Don't run Current (non-LTS) releases in production.\"<br \/>\n          }<br \/>\n        },<br \/>\n        {<br \/>\n          \"@type\": \"Question\",<br \/>\n          \"name\": \"Do I need PM2 if I have systemd?\",<br \/>\n          \"acceptedAnswer\": {<br \/>\n            \"@type\": \"Answer\",<br \/>\n            \"text\": \"No, you don't need both. PM2 and systemd solve the same problem, keeping your Node app running through crashes and reboots. Most teams pick PM2 for the cluster-mode, log-rotate, and zero-downtime-reload conveniences out of the box. Teams that already manage systemd units for everything else pick systemd. Use whichever your team is comfortable with.\"<br \/>\n          }<br \/>\n        },<br \/>\n        {<br \/>\n          \"@type\": \"Question\",<br \/>\n          \"name\": \"Why put NGINX in front of Node.js?\",<br \/>\n          \"acceptedAnswer\": {<br \/>\n            \"@type\": \"Answer\",<br \/>\n            \"text\": \"NGINX (or Caddy) in front of Node.js handles TLS termination, gzip and brotli compression, static asset serving, and rate limiting more efficiently than Node itself. It also lets you run multiple Node apps on the same VPS without port conflicts. In production, Node listens on localhost; NGINX faces the public internet. This is the standard production pattern, not an optional optimization.\"<br \/>\n          }<br \/>\n        },<br \/>\n        {<br \/>\n          \"@type\": \"Question\",<br \/>\n          \"name\": \"Is Node.js on a VPS cheaper than Heroku or Vercel?\",<br \/>\n          \"acceptedAnswer\": {<br \/>\n            \"@type\": \"Answer\",<br \/>\n            \"text\": \"Yes, often. A 4 GB VPS runs in the $15-$25 a month range and replaces a Heroku Basic dyno plus Heroku Postgres plus Heroku Redis stack that frequently lands in $25-$60 a month. Vercel Pro starts at $20 a seat with function timeouts. The trade is that you handle operations yourself, about one to three hours a month of maintenance.\"<br \/>\n          }<br \/>\n        },<br \/>\n        {<br \/>\n          \"@type\": \"Question\",<br \/>\n          \"name\": \"Can I run multiple Node apps on one VPS?\",<br \/>\n          \"acceptedAnswer\": {<br \/>\n            \"@type\": \"Answer\",<br \/>\n            \"text\": \"Yes, and it's the most common reason teams move from PaaS to a VPS. Run each app on its own internal port (3000, 3001, 3002) and route traffic with NGINX server blocks based on hostname. PM2 manages all of them as separate processes; systemd would use one unit file per app. A 4 GB VPS comfortably runs three or four small Node services plus a database.\"<br \/>\n          }<br \/>\n        },<br \/>\n        {<br \/>\n          \"@type\": \"Question\",<br \/>\n          \"name\": \"Can I run Node.js on DreamHost shared hosting?\",<br \/>\n          \"acceptedAnswer\": {<br \/>\n            \"@type\": \"Answer\",<br \/>\n            \"text\": \"No. Node.js needs persistent processes, root-level package installs, and direct port binding, none of which shared hosting provides. DreamHost's Self-Managed VPS plans (Stack 4 and up) fit Node workloads with full root access, NVMe storage, and unmetered bandwidth.\"<br \/>\n          }<br \/>\n        }<br \/>\n      ]<br \/>\n    },<br \/>\n    {<br \/>\n      \"@type\": \"HowTo\",<br \/>\n      \"name\": \"How to Run Node.js on a VPS\",<br \/>\n      \"step\": [<br \/>\n        {<br \/>\n          \"@type\": \"HowToStep\",<br \/>\n          \"name\": \"Install Node.js 24 LTS\",<br \/>\n          \"text\": \"On Ubuntu or Debian, run: curl -fsSL https:\/\/deb.nodesource.com\/setup_24.x | bash -, then apt install -y nodejs. Verify with node -v. Use nvm instead if you need per-project version switching.\"<br \/>\n        },<br \/>\n        {<br \/>\n          \"@type\": \"HowToStep\",<br \/>\n          \"name\": \"Set up a process manager\",<br \/>\n          \"text\": \"Install PM2 with npm install -g pm2, then pm2 start app.js --name api, pm2 startup, pm2 save. Or write a systemd unit at \/etc\/systemd\/system\/api.service and run systemctl enable --now api.\"<br \/>\n        },<br \/>\n        {<br \/>\n          \"@type\": \"HowToStep\",<br \/>\n          \"name\": \"Install NGINX and configure a reverse proxy\",<br \/>\n          \"text\": \"Install NGINX with apt install nginx. Create a server block in \/etc\/nginx\/sites-available\/api with proxy_pass http:\/\/127.0.0.1:3000 and the WebSocket upgrade headers. Symlink to sites-enabled and reload.\"<br \/>\n        },<br \/>\n        {<br \/>\n          \"@type\": \"HowToStep\",<br \/>\n          \"name\": \"Bind Node to localhost and enable a firewall\",<br \/>\n          \"text\": \"Configure your Node app to listen on 127.0.0.1:3000 rather than 0.0.0.0:3000. Enable UFW with default deny incoming, then allow ports 22, 80, and 443.\"<br \/>\n        },<br \/>\n        {<br \/>\n          \"@type\": \"HowToStep\",<br \/>\n          \"name\": \"Configure HTTPS with Let's Encrypt\",<br \/>\n          \"text\": \"Point an A record at your VPS IP. Install Certbot with apt install certbot python3-certbot-nginx, then run certbot --nginx -d yourdomain.com. Certbot installs a systemd timer that renews the cert automatically.\"<br \/>\n        }<br \/>\n      ]<br \/>\n    }<br \/>\n  ]<br \/>\n}<br \/>\n<\/script><\/p>","protected":false},"excerpt":{"rendered":"<p>Run Node.js on a VPS with full control: no cold starts, no function timeouts, no per-seat bills. Current LTS, PM2 vs. systemd, NGINX with Let&#8217;s Encrypt.<\/p>\n","protected":false},"author":2,"featured_media":83811,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"toc_headlines":"[[\"h-when-does-running-node-js-on-a-vps-make-sense\",\"When Does Running Node.js on a VPS Make Sense?\"],[\"h-what-vps-specs-does-node-js-actually-need\",\"What VPS Specs Does Node.js Actually Need?\"],[\"h-which-node-js-version-should-you-install\",\"Which Node.js Version Should You Install?\"],[\"h-how-do-you-install-node-js-on-a-vps\",\"How Do You Install Node.js on a VPS?\"],[\"h-should-you-use-pm2-or-systemd-to-keep-your-app-running\",\"Should You Use PM2 or systemd to Keep Your App Running?\"],[\"h-how-do-you-put-nginx-or-caddy-in-front-of-your-node-app\",\"How Do You Put NGINX (or Caddy) in Front of Your Node App?\"],[\"h-how-do-you-set-up-https-for-your-node-js-app\",\"How Do You Set Up HTTPS for Your Node.js App?\"],[\"h-what-does-a-production-ready-node-js-setup-actually-look-like\",\"What Does a Production-Ready Node.js Setup Actually Look Like?\"],[\"h-when-is-a-vps-the-wrong-choice-for-node-js\",\"When Is a VPS the Wrong Choice for Node.js?\"],[\"h-picking-your-node-stack-and-moving-in\",\"Picking Your Node Stack and Moving In\"],[\"h-frequently-asked-questions-about-running-node-js-on-a-vps\",\"Frequently Asked Questions About Running Node.js on a VPS\"]]","hide_toc":false,"footnotes":""},"categories":[550,807,804],"tags":[],"class_list":["post-83809","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","category-vps-hosting","category-web-hosting"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.3 (Yoast SEO v27.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>How To Run Node.js on a VPS - DreamHost<\/title>\n<meta name=\"description\" content=\"Run Node.js on a VPS with full control: no cold starts, no function timeouts, no per-seat bills. Current LTS, PM2 vs. systemd, NGINX with Let&#039;s Encrypt.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How To Run Node.js on a VPS: PM2, NGINX, and HTTPS\" \/>\n<meta property=\"og:description\" content=\"Run Node.js on a VPS with Node 24 LTS, PM2 or systemd, an NGINX reverse proxy, and free HTTPS via Let&#039;s Encrypt. No cold starts or per-seat billing.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/\" \/>\n<meta property=\"og:site_name\" content=\"DreamHost Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/DreamHost\/\" \/>\n<meta property=\"article:published_time\" content=\"2026-06-29T15:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-06-29T15:00:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/1220_x_628_ogimage_bun_vs_node_js-scaled.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1318\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Dallas Kashuba\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"How To Run Node.js on a VPS: PM2, NGINX, and HTTPS\" \/>\n<meta name=\"twitter:description\" content=\"Run Node.js on a VPS with Node 24 LTS, PM2 or systemd, an NGINX reverse proxy, and free HTTPS via Let&#039;s Encrypt. No cold starts or per-seat billing.\" \/>\n<meta name=\"twitter:creator\" content=\"@http:\/\/twitter.com\/dallas\" \/>\n<meta name=\"twitter:site\" content=\"@dreamhost\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Dallas Kashuba\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"17 minutes\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"How To Run Node.js on a VPS - DreamHost","description":"Run Node.js on a VPS with full control: no cold starts, no function timeouts, no per-seat bills. Current LTS, PM2 vs. systemd, NGINX with Let's Encrypt.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/","og_locale":"en_US","og_type":"article","og_title":"How To Run Node.js on a VPS: PM2, NGINX, and HTTPS","og_description":"Run Node.js on a VPS with Node 24 LTS, PM2 or systemd, an NGINX reverse proxy, and free HTTPS via Let's Encrypt. No cold starts or per-seat billing.","og_url":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/","og_site_name":"DreamHost Blog","article_publisher":"https:\/\/www.facebook.com\/DreamHost\/","article_published_time":"2026-06-29T15:00:00+00:00","article_modified_time":"2026-06-29T15:00:44+00:00","og_image":[{"width":2560,"height":1318,"url":"https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/1220_x_628_ogimage_bun_vs_node_js-scaled.webp","type":"image\/webp"}],"author":"Dallas Kashuba","twitter_card":"summary_large_image","twitter_title":"How To Run Node.js on a VPS: PM2, NGINX, and HTTPS","twitter_description":"Run Node.js on a VPS with Node 24 LTS, PM2 or systemd, an NGINX reverse proxy, and free HTTPS via Let's Encrypt. No cold starts or per-seat billing.","twitter_creator":"@http:\/\/twitter.com\/dallas","twitter_site":"@dreamhost","twitter_misc":{"Written by":"Dallas Kashuba","Est. reading time":"17 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/#article","isPartOf":{"@id":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/"},"author":{"name":"Dallas Kashuba","@id":"https:\/\/www.dreamhost.com\/blog\/#\/schema\/person\/f6a12ad459538e8e418cf31b8b603814"},"headline":"How To Run Node.js on a VPS","datePublished":"2026-06-29T15:00:00+00:00","dateModified":"2026-06-29T15:00:44+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/"},"wordCount":3603,"publisher":{"@id":"https:\/\/www.dreamhost.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/#primaryimage"},"thumbnailUrl":"https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/1460_x_1095_blog_hero_bun_vs_node_js-scaled.webp","articleSection":["Tutorials","VPS Hosting","Web Hosting"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/","url":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/","name":"How To Run Node.js on a VPS - DreamHost","isPartOf":{"@id":"https:\/\/www.dreamhost.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/#primaryimage"},"image":{"@id":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/#primaryimage"},"thumbnailUrl":"https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/1460_x_1095_blog_hero_bun_vs_node_js-scaled.webp","datePublished":"2026-06-29T15:00:00+00:00","dateModified":"2026-06-29T15:00:44+00:00","description":"Run Node.js on a VPS with full control: no cold starts, no function timeouts, no per-seat bills. Current LTS, PM2 vs. systemd, NGINX with Let's Encrypt.","breadcrumb":{"@id":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/#primaryimage","url":"https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/1460_x_1095_blog_hero_bun_vs_node_js-scaled.webp","contentUrl":"https:\/\/www.dreamhost.com\/blog\/wp-content\/uploads\/2026\/06\/1460_x_1095_blog_hero_bun_vs_node_js-scaled.webp","width":2560,"height":1920,"caption":"How To Run Node.js on a VPS"},{"@type":"BreadcrumbList","@id":"https:\/\/www.dreamhost.com\/blog\/nodejs-vps\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.dreamhost.com\/blog\/"},{"@type":"ListItem","position":2,"name":"How To Run Node.js on a VPS"}]},{"@type":"WebSite","@id":"https:\/\/www.dreamhost.com\/blog\/#website","url":"https:\/\/www.dreamhost.com\/blog\/","name":"DreamHost Blog","description":"","publisher":{"@id":"https:\/\/www.dreamhost.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dreamhost.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.dreamhost.com\/blog\/#organization","name":"DreamHost","url":"https:\/\/www.dreamhost.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.dreamhost.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/dhblog.dream.press\/blog\/wp-content\/uploads\/2019\/01\/dh_logo-blue-2.png","contentUrl":"https:\/\/dhblog.dream.press\/blog\/wp-content\/uploads\/2019\/01\/dh_logo-blue-2.png","width":1200,"height":168,"caption":"DreamHost"},"image":{"@id":"https:\/\/www.dreamhost.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/DreamHost\/","https:\/\/x.com\/dreamhost","https:\/\/www.instagram.com\/dreamhost\/","https:\/\/www.linkedin.com\/company\/dreamhost\/","https:\/\/www.youtube.com\/user\/dreamhostusa"]},{"@type":"Person","@id":"https:\/\/www.dreamhost.com\/blog\/#\/schema\/person\/f6a12ad459538e8e418cf31b8b603814","name":"Dallas Kashuba","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/05ab6fb1606be97d16c74efb0fba01b3c11e91501dc5f9661bdfbb5c5b0cd113?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/05ab6fb1606be97d16c74efb0fba01b3c11e91501dc5f9661bdfbb5c5b0cd113?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/05ab6fb1606be97d16c74efb0fba01b3c11e91501dc5f9661bdfbb5c5b0cd113?s=96&d=mm&r=g","caption":"Dallas Kashuba"},"description":"Dallas Kashuba co-founded DreamHost while attending Harvey Mudd College and has spent nearly three decades building infrastructure at scale. Today he serves as an advisor, board member, and investor for various tech startups, with a consistent focus on user privacy, open source, and data portability. When he's not thinking about the Open Web, he's probably making music. Follow Dallas on X.","sameAs":["http:\/\/www.idallas.com\/","https:\/\/x.com\/http:\/\/twitter.com\/dallas"],"url":"https:\/\/www.dreamhost.com\/blog\/author\/dallas\/"}]}},"lang":"en","translations":{"en":83809},"pll_sync_post":{},"_links":{"self":[{"href":"https:\/\/www.dreamhost.com\/blog\/wp-json\/wp\/v2\/posts\/83809","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dreamhost.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dreamhost.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dreamhost.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dreamhost.com\/blog\/wp-json\/wp\/v2\/comments?post=83809"}],"version-history":[{"count":4,"href":"https:\/\/www.dreamhost.com\/blog\/wp-json\/wp\/v2\/posts\/83809\/revisions"}],"predecessor-version":[{"id":83818,"href":"https:\/\/www.dreamhost.com\/blog\/wp-json\/wp\/v2\/posts\/83809\/revisions\/83818"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dreamhost.com\/blog\/wp-json\/wp\/v2\/media\/83811"}],"wp:attachment":[{"href":"https:\/\/www.dreamhost.com\/blog\/wp-json\/wp\/v2\/media?parent=83809"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dreamhost.com\/blog\/wp-json\/wp\/v2\/categories?post=83809"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dreamhost.com\/blog\/wp-json\/wp\/v2\/tags?post=83809"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}