Back to blog
Deployment

Deploying a Node.js App to DigitalOcean: A Practical Guide from Zero to Production

Kim BoenderKim Boender
March 29, 2026 7 min read
Deploying a Node.js App to DigitalOcean: A Practical Guide from Zero to Production

So you've built a Node.js app and it works great on localhost. Now what?

Getting from a working local app to a live, production-ready deployment is one of those skill gaps that trips up a lot of developers, juniors and seniors alike. In this guide, we'll walk through deploying a Node.js application to DigitalOcean step by step. We'll cover spinning up a Droplet (their virtual machine product), configuring a Linux server from scratch, setting up Nginx as a reverse proxy, and keeping your app alive with PM2.

By the end, you'll have a publicly accessible app running on a real server, and you'll understand why each step exists.

New to DigitalOcean? You can sign up and get $200 in free credit for 60 days, which is more than enough to follow this entire guide without spending a cent.

Why DigitalOcean?

There are plenty of cloud providers, but for many developers building side projects, SaaS products, or freelancing, DigitalOcean hits a sweet spot.

Pricing is predictable. No surprise bills. You know what you pay. The documentation and community tutorials are genuinely excellent. Droplets start at $4/month, which is hard to beat for a hobby project or MVP. And there's a strong developer community with tons of tutorials, Q&A, and guides.

For larger teams or AI workloads, DigitalOcean also offers Kubernetes, Managed Databases, and Gradient AI Inference Cloud, but that's a topic for another post.

What we're building

We'll deploy a simple Express.js REST API. The concepts apply to any Node.js app: Next.js, Fastify, NestJS, etc. Express just makes the example easy to follow.

Prerequisites: basic comfort with the terminal and SSH, a Node.js app ready to deploy, and a DigitalOcean account.

Step 1: Create a DigitalOcean Droplet

A Droplet is DigitalOcean's term for a virtual machine. Log into your dashboard and click Create > Droplets.

Choose a region closest to your target users. For the image, select Ubuntu 22.04 LTS: stable, widely supported, with excellent community resources. For the plan, the Basic / Regular tier at $6/month (1 vCPU, 1GB RAM, 25GB SSD) is plenty to start.

For authentication, choose SSH Key (strongly recommended over password). If you don't have an SSH key pair, generate one locally:

ssh-keygen -t ed25519 -C "your_email@example.com"

Then paste the contents of ~/.ssh/id_ed25519.pub into the DigitalOcean SSH key field. Give your Droplet a hostname and click Create. Within about 60 seconds, your server is live.

Step 2: Connect to your server

ssh root@YOUR_DROPLET_IP

You should be greeted by the Ubuntu welcome message. You're now inside your virtual server.

Running everything as root is a security risk. Create a deploy user:

adduser deploy
usermod -aG sudo deploy
rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy

From now on, connect as deploy.

Step 3: Install Node.js

Use nvm (Node Version Manager). It lets you install and switch between Node versions easily, which matters on long-lived servers.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install --lts
node -v

Step 4: Deploy your app

Clone from Git (recommended):

git clone https://github.com/YOUR_USERNAME/YOUR_REPO.git
cd YOUR_REPO
npm install --production

Create a .env file on the server. Never commit secrets to Git. SSH in and create your environment file:

nano /home/deploy/YOUR_REPO/.env

Add your variables:

NODE_ENV=production
PORT=3000
DATABASE_URL=your_database_url_here

Step 5: Keep your app running with PM2

Node.js apps crash. Servers reboot. PM2 is a process manager that keeps your app running, restarts it on crashes, and starts it automatically after reboots.

npm install -g pm2
pm2 start app.js --name "my-app"
pm2 startup
# Copy and run the output command
pm2 save

Check your app's status:

pm2 status
pm2 logs my-app

Your app is now running persistently on port 3000. But users shouldn't be hitting port 3000 directly. That's where Nginx comes in.

Step 6: Set up Nginx as a reverse proxy

Nginx sits in front of your Node.js app and forwards HTTP/HTTPS traffic to it. This gives you port 80/443 routing, SSL termination, static file serving, and the ability to add rate limiting and load balancing when you grow.

sudo apt update
sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx

Configure the reverse proxy:

sudo nano /etc/nginx/sites-available/my-app

Paste this configuration:

server {
  listen 80;
  server_name yourdomain.com www.yourdomain.com;

  location / {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_cache_bypass $http_upgrade;
  }
}

Enable the config and reload:

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

Step 7: Point your domain and enable HTTPS

In your domain registrar, create an A record pointing your domain to your Droplet's IP. DNS propagation can take a few minutes to a few hours.

Then get a free SSL certificate with Certbot:

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Follow the prompts. Certbot will automatically configure Nginx for HTTPS and set up auto-renewal. Your app is now serving traffic over HTTPS for free.

Step 8: Configure the firewall

Lock down your server. Only allow the traffic you need:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status

This blocks everything except SSH and HTTP/HTTPS.

Bonus: Set up a DigitalOcean Managed Database

If your app uses PostgreSQL or MySQL, consider DigitalOcean's Managed Databases instead of running a database on the same Droplet. You get automated backups, one-click standby replicas, automatic security patching, and a connection pooler. It starts at around $15/month and saves a huge amount of operational pain. For any serious project, it's worth it.

Production checklist

Before you call it done, run through this list:

  • Non-root user in use for deployments
  • Firewall (UFW) enabled with only necessary ports open
  • HTTPS enabled via Let's Encrypt
  • PM2 startup configured so the app survives reboots
  • Environment variables in .env, not committed to Git
  • DigitalOcean Droplet monitoring enabled with alerting
  • Automated Droplet backups turned on (about 20% of Droplet cost per month, absolutely worth it)

Going further

Once your app is stable, there are natural next steps depending on where you're headed.

For scaling up, DigitalOcean Kubernetes is great if you need to run multiple containers and want zero-downtime deployments. Their managed Kubernetes is significantly simpler to operate than rolling your own.

For faster deployments, DigitalOcean App Platform handles all of the above automatically (build, deploy, SSL, scaling) if you'd rather not manage a server at all. Just connect your GitHub repo and push. It's a great option for teams or projects where DevOps bandwidth is limited.

For AI workloads, check out Gradient AI, DigitalOcean's inference cloud, if you're building something with LLMs or GPU-intensive inference.

Wrapping up

Deploying to a real server teaches you things that managed platforms abstract away, and that knowledge makes you a better engineer. You now understand how Nginx proxies traffic, how PM2 keeps processes alive, how UFW filters connections, and how Let's Encrypt issues certificates.

That said, don't be dogmatic about it. Once you understand the fundamentals, using App Platform or Kubernetes to automate this stuff is completely reasonable.

If you're just getting started, DigitalOcean's free credit offer is a great way to experiment without risk. Spin up a Droplet, break things, learn, and delete it when you're done.

Frequently Asked Questions

How much does it cost to host a Node.js app on DigitalOcean? +
The cheapest Droplet starts at $4/month (512MB RAM), but for a Node.js app with any real traffic, the $6/month plan (1GB RAM, 1 vCPU, 25GB SSD) is a more comfortable starting point. If you add a Managed Database, that starts at around $15/month. DigitalOcean also offers $200 in free credit for new accounts, so you can run everything for free for the first 60 days.
Do I need to know Linux to deploy to a DigitalOcean Droplet? +
You don't need to be a Linux expert, but you should be comfortable with basic terminal commands — navigating directories, editing files with nano or vim, and running commands as sudo. The commands in this guide are copy-paste friendly, so a beginner can follow along. That said, understanding what each command does will make you much more confident when things go wrong (and they sometimes do).
What is the difference between a Droplet and DigitalOcean App Platform? +
A Droplet is a raw virtual machine — you get full control of the OS, but you're also responsible for everything: installing software, configuring Nginx, managing security updates, etc. App Platform is a fully managed PaaS (Platform as a Service) where you just connect your GitHub repo and DigitalOcean handles builds, deployments, SSL, and scaling automatically. Droplets give you more flexibility and lower cost at scale; App Platform is faster to set up and requires far less DevOps knowledge.
Why use PM2 instead of just running node app.js? +
Running node app.js directly means your app dies the moment it crashes or the SSH session ends. PM2 is a process manager that automatically restarts your app on crashes, keeps it running in the background, and can be configured to start your app automatically when the server reboots. It also provides built-in log management, cluster mode for multi-core CPUs, and a handy dashboard (pm2 monit). For any production deployment, it's essentially mandatory.
How do I deploy updates to my app without downtime? +
For a single-Droplet setup, SSH in, pull the latest code with git pull, run npm install if dependencies changed, then reload with pm2 reload my-app (which performs a graceful reload with zero downtime). For true zero-downtime deployments across multiple instances, PM2's cluster mode or DigitalOcean Kubernetes with rolling updates are the right tools. For most small-to-medium projects, pm2 reload is perfectly sufficient.

Try it yourself

JSON Formatter

Format, validate, and beautify JSON instantly

Open JSON Formatter