Deploying a Node.js app used to mean SSHing in, installing Node and PM2 by hand, writing an Nginx server block, and running certbot for a certificate then doing it all again the next time you rotated servers. This walks through the version of that where you do none of it.
What you need
- A VPS you can reach over SSH a $5/month box is genuinely enough.
- A Node.js app in a GitHub repo (Express, Next.js, Fastify, whatever it doesn't need a
Dockerfile). - The DeployOS desktop app free tier works, no card required.
Step 1: Connect your server
Servers → Add Server, paste the host, SSH port, and either a password or a private key. Pick a reverse proxy (Traefik is the default) and hit Test connection DeployOS opens a real SSH session and only saves the server once it can actually run commands on it. Nothing is installed yet.
Then run Bootstrap from the server card. In one pass it installs Docker, configures the firewall for 22/80/443, sets up the shared network your apps join, starts the reverse proxy, and installs Railpack the build tool that's about to matter for step 3. All of it streams live so you can watch it happen instead of trusting a spinner.
Step 2: Point it at your repo
Applications → New App. Either connect GitHub (device-code flow, same as the gh CLI no token to paste) and pick your repo from a list, or just paste the URL directly, including a private git@github.com:... SSH URL. Give the app a name and click Create.
Step 3: Let Railpack handle the build
This is the "without touching Nginx" part, but it's also the without-touching-Dockerfile part. If your repo has no Dockerfile, DeployOS builds it with Railpack it inspects the repo, detects it's a Node project, and figures out the install/build/start commands itself, running entirely on your own server via a local BuildKit instance. If you already have a Dockerfile committed, DeployOS uses that instead; you don't have to choose between the two approaches, it picks the right one for what's actually in your repo.
Click Deploy on the app's Deploy tab and watch the live log: clone, build, start the container, attach it to the network, publish the proxy route, then a soft health check pings it to confirm it actually came up.
Step 4: Point a domain at it (optional, but this is the Nginx part)
Add an A record at your DNS provider pointing your domain at the server's IP, then set the Custom domain on the app's Config tab and redeploy. DeployOS publishes the route to whichever reverse proxy you picked and requests a Let's Encrypt certificate automatically the first time HTTPS traffic hits it no certbot, no server block to hand-edit. A DNS cutover card polls in the background and tells you the moment the domain resolves and the certificate is live, so you're not refreshing the browser to check.
What happens on your next push
Flip Auto-deploy on from the app's Overview tab and DeployOS starts watching your branch no public webhook needed, since a desktop app doesn't have a stable URL for GitHub to call. It polls the repo in the background and redeploys the moment the branch moves, same pipeline as clicking Deploy by hand. Close your laptop and it just catches up on the next push once you reopen it.
If a deploy ever goes out with a bug, the last 3 builds stay cached, so rolling back is instant no rebuild.
That's the whole thing
Repo in, HTTPS URL out, no Nginx config, no PM2, no certbot cron job to remember. If you outgrow "one Node app" later, the same server can run a Python API, a Postgres database, and a handful of one-click templates side by side it's a general-purpose VPS manager, not a Node-specific tool that happens to work today.