Innovate | Connect | Transform
ContactService statusUSD $

GICT knowledge base

How to Deploy Node.js Applications with Nginx

Published

Node.js

You built a great Node.js app. It works perfectly on your computer. But now you need to get it running on a real server so people can actually use it. I’ll walk you through the entire process of setting up Nginx with your Node.js application.

Server deployment might feel overwhelming when you’re starting out. Lots of moving parts need to work together perfectly. But don’t worry – after going through this process once or twice, it becomes second nature. By the end of this post, you’ll have your app running smoothly in production.

Why Use Nginx with Node.js

Your Node.js app is great at handling business logic and generating responses. But it’s not so good at other things like serving images quickly or handling SSL certificates. That’s where Nginx comes in.

Nginx is really fast at serving static files like images, CSS, and JavaScript. It can also handle thousands of users at once without slowing down. Setting up SSL certificates becomes straightforward with Nginx too.

Picture this scenario: Your Node.js app works like a talented cook in a busy kitchen. The chef is amazing at cooking food but terrible at greeting customers and managing the dining room. Nginx is like the restaurant manager who handles all the front-of-house stuff so the chef can focus on cooking.

Getting Ready for Deployment

First, you’ll need a Linux server. Ubuntu works best for beginners because it has great documentation and community support.

Your Node.js application should be complete and tested on your local machine. It should run on your computer without any issues. Make sure you have all your dependencies listed in package.json.

You should know basic command line stuff. Nothing fancy, just how to run commands and edit files.

Setting Up Your Server

First, log into your server using SSH. Then update everything to make sure you have the latest security patches.

sudo apt update
sudo apt upgrade -y

Now let’s install Node.js. I like using the official repository because it gives you the newest stable version.

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

Let’s also install Nginx right now.

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

Check that everything is installed correctly.

node --version
npm --version
nginx -v

If you see version numbers, you’re good to go. If you navigate to your server’s IP address using any web browser, you’ll see the welcome page that Nginx displays by default.

Getting Your App on the Server

Create a folder for your app. I like putting apps in the /opt directory.

sudo mkdir -p /opt/myapp
sudo chown $USER:$USER /opt/myapp

Now copy your app files to the server. You can use git, FileZilla, or just copy and paste if your app is small. Put everything in the /opt/myapp folder.

Go into your app folder and install the dependencies.

cd /opt/myapp
npm install --production

Test that your app works by running it.

node app.js

If you see your app start up without errors, you’re ready for the next step. Press Ctrl+C to stop it for now.

Installing PM2 – Your App’s Bodyguard

Here’s something important. You can’t just run your app with node app.js and leave it. What happens when your application stops unexpectedly? What about server reboots? Your app will just stop working and visitors will see error messages.

PM2 solves this problem. It acts like a guardian for your application. When your application stops working unexpectedly, PM2 brings it back to life immediately. If the server reboots, PM2 starts your app again.

Install PM2.

sudo npm install -g pm2

Start your app with PM2 instead of the regular node command.

pm2 start app.js --name myapp

Now tell PM2 to start your app automatically when the server boots up.

pm2 startup
pm2 save

PM2 will show you a command to run. Copy it exactly and run it.

Some PM2 commands you’ll use a lot are pm2 status to see what’s running, pm2 restart myapp to restart your app, and pm2 logs myapp to see what’s happening.

Configuring Nginx – The Magic Part

Now we need to tell Nginx how to work with your Node.js app. Create a new configuration file.

sudo nano /etc/nginx/sites-available/myapp

Put this configuration in the file. Replace yourdomain.com with your actual domain name.

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


    location / {
        proxy_pass http://127.0.0.1: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_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

This tells Nginx to take any request that comes to your domain and send it to your Node.js app running on port 3000.

Now enable this configuration.

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

The nginx -t command checks for mistakes in your configuration. Always run this before reloading Nginx.

If everything worked, you should now be able to visit your domain in a web browser and see your Node.js app.

Adding HTTPS Because Security Matters

Every website needs HTTPS these days. Browsers show warnings for sites without it, and Google ranks HTTPS sites higher in search results.

Let’s Encrypt gives you free SSL certificates. Install their tool called Certbot.

sudo apt install certbot python3-certbot-nginx -y

Get your SSL certificate. Replace yourdomain.com with your actual domain.

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Certbot will ask you some questions and then automatically set up HTTPS for your site. It even configures Nginx to redirect HTTP traffic to HTTPS.

Set up automatic renewal so your certificate doesn’t expire.

sudo crontab -e

Add this line to check for renewal every day.

0 3 * * * /usr/bin/certbot renew --quiet

Making Your Site Faster

Let’s add some optimizations to make your site load faster. Edit your Nginx configuration.

sudo nano /etc/nginx/sites-available/myapp

Add these lines inside your server block.

# Enable compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;


# Cache static files
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    root /opt/myapp/public;
    expires 1y;
    add_header Cache-Control "public, immutable";
}


# Add security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";

Reload Nginx to apply the changes.

sudo nginx -t
sudo systemctl reload nginx

Making Deployments Easy

Create a simple script to make updating your app easier. Create a new file called deploy.sh.

nano /opt/myapp/deploy.sh

Put this in the file.

#!/bin/bash
echo "Starting deployment..."
cd /opt/myapp
git pull origin main
npm install --production
pm2 restart myapp
echo "Deployment complete!"

Make the script executable.

chmod +x deploy.sh

Now whenever you want to update your app, just run ./deploy.sh and it will pull the latest code and restart your app.

Keeping Your App Healthy

Check on your app regularly. Use these commands to see how things are going.

pm2 status
pm2 logs myapp
htop
df -h

The first command shows you if your app is running. The second shows you recent log messages. The third shows you system resources like CPU and memory usage. The fourth shows you disk space.

Set up log rotation so your log files don’t fill up your disk.

sudo nano /etc/logrotate.d/myapp

Put this in the file.

/opt/myapp/logs/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
}

When Things Go Wrong

Here are some common problems and how to fix them.

If you see a 502 Bad Gateway error, it usually means Nginx can’t connect to your Node.js app. Check if your app is running with pm2 status. Make sure the port numbers match between your app and the Nginx configuration.

If you have SSL certificate problems, run sudo certbot certificates to see the status of your certificates. You can test renewal with sudo certbot renew –dry-run.

If your app is using too much memory, check pm2 monit to see resource usage. You might need to restart your app or upgrade your server.

If your app won’t start, check the logs with pm2 logs myapp. Look for error messages that tell you what’s wrong. Common issues are missing dependencies or wrong file paths.

Basic Security

Don’t forget about security. Set up a basic firewall.

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

Keep your system updated.

sudo apt update && sudo apt upgrade -y

Use strong passwords. Consider setting up SSH keys instead of passwords for better security.

Handling More Traffic

As your app gets popular, you might need to handle more traffic. Here are some options.

You can upgrade your server to have more CPU and RAM. This is the easiest solution and works well for most apps.

You can run multiple copies of your app. PM2 makes this easy.

pm2 delete myapp
pm2 start app.js -i max --name myapp

This starts as many copies as you have CPU cores.

You can also add more servers and use a load balancer to distribute traffic between them. This is more complex but gives you better reliability.

Wrapping Up

You did it. Your Node.js app is now running in production with Nginx, SSL certificates, automatic restarts, and performance optimizations. This is the same setup used by many professional websites.

The key things to remember are that Nginx handles the front-end stuff like SSL and static files, while your Node.js app focuses on your business logic. PM2 keeps everything running smoothly and makes deployments easy.

From here, you might want to set up monitoring tools, add a CDN for even better performance, or implement automated testing. But what you have now is a solid foundation that will serve you well.

Don’t be afraid to experiment and try new things. Every expert started exactly where you are now. The most important thing is to keep learning and building great apps.

Related guides

Account services are unavailable until the production backend is configured.