Sumesh R.30 Sep 2026Updated 30 Sep 2026Servers & VPS9 min read

How to Deploy a Node.js App from GitHub to a VPS

On this page

Key Takeaways: Deploy a Node.js App from GitHub to a VPS

  • To deploy a Node.js app, you clone your GitHub repository onto a VPS, install Node.js and dependencies, and configure the app for production.
  • Environment variables and secrets (API keys, database credentials) never belong in GitHub; they live in a .env file on the server, kept out of version control.
  • PM2 keeps your Node.js process running after you close SSH, and restarts it automatically after crashes or a server reboot.
  • Nginx sits in front of your app as a reverse proxy, so visitors hit your domain over HTTPS instead of your app's internal port directly.
  • Your domain connects to the VPS through a DNS A record pointing at the server's IP. Nginx then routes that traffic to your app.
  • HostAfrica's Node.js Hosting suits simpler setups where you don't want to manage a server; a Linux VPS suits apps that need root access and full control.

Node.js is an open-source JavaScript runtime environment that lets you run JavaScript on the server, not just in the browser. According to Stack Overflow's 2025 Developer Survey, it's the most-used web technology among professional developers, used by roughly half of respondents. That makes it a staple of modern web development, and many Node.js applications eventually need to make this exact jump from laptop to production. This guide covers that jump. 



You've built a Node.js app. It could be an API, a web service, or a full web application. It runs fine locally with npm start. The source code is sitting in a GitHub repository, ready to go.  Now you need it running on a real server reachable at a real domain, over HTTPS, without falling over the moment you close your laptop.

That gap trips up a lot of developers the first time. Not because any single step is hard, but because nobody explains why each piece exists.

This guide shows you how to deploy a Node.js app along the whole path: GitHub → Linux VPS → Node.js/npm → environment variables → PM2 → Nginx → domain/HTTPS → live application. By the end, you'll understand what you're typing and why.


github to live node.js app


Step 1: Prepare the VPS

Connect over SSH:

ssh your_user@your_server_ip

New to SSH or the terminal? HostAfrica's beginner's guide to SSH and terminal basics is worth a read first.

Update packages, then install Git and Node.js:

sudo apt update && sudo apt upgrade -y
sudo apt install git -y

(Assumes Ubuntu/Debian; adjust for dnf/yum on AlmaLinux.)

The Node.js version you need depends on your project; check package.json for an engines field, or match whatever LTS you developed against. Grab it from the official Node.js downloads page, or check the release schedule for current LTS status. Confirm it installed correctly:

node -v
npm -v

github to live node.js app map


Step 2: Clone the GitHub Repository

Copy your repository's URL from its page on https://github.com (under the green Code button), then clone it onto the server: 

git clone https://github.com/your-username/your-repo.git
cd your-repo

That works for public repos. Private ones need SSH keys or a deploy key. GitHub dropped password authentication for Git operations years ago. GitHub's SSH authentication docs cover generating and adding a key properly.

Watch out:
Don't embed credentials directly in a git clone command. If a token ends up in your shell history, you've effectively leaked it.

Shaky on Git itself? HostAfrica has a beginner's intro to Git and GitHub.


Step 3: Install Dependencies

With the source code on the server, install the packages it depends on. If your repo has a committed package-lock.json, use npm ci rather than npm install: 

npm ci

It's stricter than npm install: it installs exactly what's in the lock file, wipes any existing node_modules first, and fails if package.json and the lock file don't match. That's exactly what you want in a deployment: no version drift between your machine and the server.

No lock file, or unsure it's compatible? Fall back to npm install. Some projects also need a build step first; check package.json for a build script.


Step 4: Configure Environment Variables

Database credentials, API keys, session secrets none of that belongs in GitHub. If it's committed, anyone with repo access has it too.

Security:
Never commit production secrets to GitHub. Keep them in a .env file on the server, and make sure .env is in your .gitignore.

github to node.js app environment variables

DATABASE_URL=postgres://user

@localhost
/mydb

API_KEY=your-production-key

NODE_ENV=production

PORT=3000

Lock down the file so only your app's user can read it:

chmod 600 .env

Most apps read these via dotenv or process.env; either way, the rule's the same: code in Git, secrets on the server.


Step 5: Test the Application

Before adding PM2 or Nginx, confirm the app runs on the server as-is:

npm start

If it starts and you can reach it, say, on localhost:3000, though the actual port depends on your app, the fundamentals are working: Node.js installed correctly, dependencies resolved, env vars being read.

Pro Tip:
Get the application running first. Then configure the web-facing layers. If something breaks later, you'll already know whether the problem is your app or the infrastructure around it.

Stop it with Ctrl+C. Running it directly in your SSH session isn't how it should run long-term.


Step 6: Keep It Running with PM2

npm start only runs as long as your SSH session stays open. Close the terminal, and the process dies. That's fine for testing, but not for a production web service.

Good to Know:
PM2 doesn't replace Node.js; it manages the process, keeps it alive, restarts it on crashes, and brings it back after a reboot.

pm2 and nginx flow

sudo npm install -g pm2
pm2 start app.js --name my-app
pm2 status
pm2 logs my-app
pm2 restart my-app

To survive a reboot:

pm2 startup
pm2 save

That covers the core workflow; see PM2's quick start guide and startup script docs for more.


Step 7: Put Nginx in Front of Node.js

Your app's running, but only reachable on its internal port, not something to expose directly. Nginx solves this as a reverse proxy: it receives public traffic on ports 80/443 and forwards it internally.

Visitor → domain → Nginx → Node.js app (internal port)

sudo apt install nginx -y

Basic config (e.g.,/etc/nginx/sites-available/your-app):

server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

sudo ln -s /etc/nginx/sites-available/your-app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

nginx -t checks your config before reloading; a bad config will stop Nginx from starting, so always test first.

Good to Know: Nginx is the public-facing web server. Your app keeps listening internally on port 3000; visitors never touch it directly. Full proxy_pass options are in Nginx's reverse proxy guide.

node.js hosting vs vps hosting


Step 8: Connect the Domain and Enable HTTPS

Domain → DNS A record → VPS IP → Nginx → Node.js app

  1. Point the domain at your VPS with an A record.
  2. Update Nginx's config with the real domain in server_name.
  3. Test over plain HTTP first; confirm DNS and Nginx work before adding SSL.
  4. Enable HTTPS with Certbot, which automates issuing a free certificate from Let's Encrypt. See Let's Encrypt's getting-started guide.
  5. Verify by loading the domain over https:// and checking for a valid certificate.

Don't skip step 3: debugging DNS, Nginx, and SSL simultaneously is much harder than confirming each layer separately.


Updating the Application

Push to GitHub → SSH in → git pull → install/build if needed → restart with PM2

cd your-repo
git pull
npm ci   # if dependencies changed
pm2 restart my-app
Watch out:
A git pull doesn't mean your running app has picked up the changes. Depending on the project, you may need to reinstall dependencies with npm ci or npm install, rebuild, or explicitly restart PM2.

Deploying often? Worth eventually automating this with GitHub Actions, a separate setup outside the scope of your first deployment.


Node.js Hosting vs Linux VPS

Node.js HostingLinux VPS
Setup complexitySimplerYou configure it yourself
Server managementManaged for youSelf-managed
Root accessNoYes
Custom configurationLimitedFull control
Persistent processes (PM2)Not the intended use caseYes
Multiple servicesNoYes
Best forLightweight Node use alongside a standard siteProduction web applications like the one in this guide 

To be direct: HostAfrica's Node.js Hosting is DirectAdmin shared hosting, built primarily for PHP/MySQL sites with Node.js available for lighter use. An app needing PM2, a custom port, and a persistent process exactly what this guide covers needs the root access and control a Linux VPS provides.

Choose Node.js Hosting when simplicity matters more than control. Choose a Linux VPS when you need root access and full control over the environment.


Troubleshooting

ProblemFirst thing to check
App won't startNode.js version matches the project; dependencies installed cleanly
App crashes after startingpm2 logs for the actual error; often a missing env var
Works locally, not on VPSCompare Node.js versions and confirm env vars are set on the server
Wrong/unexpected portWhat your app's actually listening on vs. what Nginx proxies to
PM2 shows app stoppedpm2 logs, then pm2 restart
502 Bad GatewayNginx can't reach your app; check pm2 status
Domain doesn't loadDNS A record correct, and propagation complete
HTTPS not workingCertbot ran successfully for the right domain

FAQ: Deploy a Node.js App from GitHub to a VPS

How do I deploy a Node.js app from GitHub?

Clone the GitHub repository onto your server, install Node.js and dependencies, configure environment variables, and run the app managed by PM2, with Nginx handling incoming traffic.

Can I host a Node.js app on a VPS?

Yes. A Linux VPS gives you root access and full environment control, which is what a production Node.js app with a process manager and reverse proxy needs.

How do I keep a Node.js app running after closing SSH?

Use a process manager like PM2; it runs your app independently of your SSH session and restarts it after crashes or reboots.

Do I need Nginx for a Node.js app?

Not strictly, but it's standard practice. It handles public traffic and HTTPS, and proxies to your app's internal port instead of exposing Node.js directly.

Can I automatically deploy from GitHub?

Yes, typically with GitHub Actions triggering a deploy on push, a separate setup from the manual deployment path covered here.

What's the difference between Node.js Hosting and a VPS?

Node.js Hosting is managed shared hosting for lighter Node use; a Linux VPS gives you root access and control, which production apps using PM2 actually need.


Conclusion

GitHub stores your source code. The VPS provides the server. Node.js runs the app. PM2 keeps the process alive. Nginx handles incoming traffic. The domain and HTTPS make it publicly and securely accessible.

Once that's working, you've got a real, repeatable deployment, not a one-off that happens to work.

If you're weighing where to run it, HostAfrica's Node.js Hosting suits a simpler managed setup, while a Linux VPS fits the control this guide walks through. Once your domain points to the server, HostAfrica's DNS setup guide is a useful reference for getting the records right.

Need more power and control?

Scalable Linux VPS servers with full root access and instant provisioning.

Avatar for Sumesh R.

Sumesh R.

The Author

Sumesh Ramdin is a South African web developer and digital consultant with over 12 years of experience in web development, SEO, eCommerce, and digital marketing. He specialises in WordPress, Shopify, technical SEO, analytics, and digital solutions that help businesses grow online. He also writes practical technical articles covering web development, digital tools, SEO, and emerging technologies.