You wrote your entire project in NodeJS, or you have microservices with NodeJS for the main project. It can’t create awesome things if you can’t deploy it. But, no worries. Please close the ChatGPT tab on your browser. Also, you don’t need to be a system administrator or DevOps engineer. Let’s deploy your project step by step.
Prerequisites
- Ubuntu 24.04
- Root Access
Installing Nginx
First, make sure everything is up-to-date.
apt-get update
apt-get upgrade
Then, we can start with installing Nginx.
apt install nginx
Open your browser and enter your IP address in the address bar: http://YOURIP
.
If you see the “Welcome to nginx” page, it’s OK.
Installing NodeJS
We need to install NVM (Node Version Manager). Run the following command in your terminal.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash
Export the NVM_DIR
and reload your bash profile.
export NVM_DIR="$HOME/.nvm"
source .bashrc
Then, choose a Node.js version. You can choose a major version, and it will install the latest version of that major version.
nvm install 20
Verify the installation.
node -v
npm -v
It should print the Node.js and npm versions.
Installing PM2
Run the following command to install PM2 (process manager).
npm install pm2 -g
Then, verify your installation with the following command.
pm2 --version
Clone or upload your project
I used the Express generator to create a new Express.js project for testing deployment. However, I assume you already have a project. You should navigate to the /var/www
directory and create a directory for your project files.
Clone your git repository or upload your files under the directory that you created.
Run the following command to install the project dependencies.
npm i
Test your project via a web browser. If it works under the specified port, then we can continue to the deployment steps.
npm run start
Create a custom vhost config
Create a custom vhost config file under the sites-available
directory. I named it express-test
according to my project.
touch /etc/nginx/sites-available/express-test
Then, open the file with nano or your favorite editor and copy/paste the following vhost config. I’ve prepared a vhost config. You should change the server_name
, root
, access_log
, and proxy_pass
lines for your own project and domain.
server {
listen 80;
server_name express-test.hostname.tr; # YOUR DOMAIN
root /var/www/express-test/public; # YOUR PROJECT PATH
access_log /var/log/nginx/express-test.log;
location / {
proxy_pass http://localhost:3000; # CHANGE THE PORT FOR YOURS
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location = /favicon.ico {
log_not_found off;
access_log off;
return 204;
}
}
Then, enable the config for reading by Nginx.
cd /etc/nginx/sites-enabled
ln -s ../sites-available/express-test
Then, check the Nginx config.
nginx -t
And, if there is no error, you can reload the Nginx config.
nginx -s reload
Setting up Process Manager
Everything is fine, but we can’t keep the terminal open forever. We will use PM2 to run the process in the background. PM2 will handle this task.
You can write your start command between the double quotes, and you can give a name to remember the project on PM2.
pm2 start "npm run start" --name ExpressTest
Configure your DNS
There is no need to install Bind or PowerDNS on the server for resolving a single website or a couple of websites. I always prefer an external DNS server. Usually, I use Cloudflare for this purpose.
You can point your DNS to your server’s IP address.
134.122.66.17 A express-test.hostname.tr
Conclusion
We’ve completed the deployment steps. You should wait for the DNS changes to resolve. Then, you’re ready! Also, I suggest blocking port 3000 except for your server and local IP on your firewall (iptables
, csf
, etc.).