Instructions for deploying the a nodejs server to production.
- Deployment
- Resources
Once a linux server has been created in your preferred cloud platform (I am using Hetzner here), we need to prepare the server for production usage.
Generally speaking, you should get access to the root user when you create a server, which should allow you to ssh into the server using the command below:
$ ssh root@your_server_ip_addr
Once you have logged in, immediately the first thing to do is to set a password to the root account.
Use the command below to change password:
root $ passwd
Since working with root directly is generally discouraged for various security and safety reasons, we'll create a seperate user account with limited permissions who's job is to run the server.
Use the command below to create a new user account:
root $ adduser server_username
We can now provide our new user with admin privileges so we don't have to switch to root user every time we need to do an administrative task. This will allow the new user to do administrative tasks by prepending sudo
to their commands.
root $ usermod -aG sudo server_username
We can make use of ufw
firewall to limit the extent of ports etc that general public can access. To do this, first make sure to install ufw
on the server:
root $ apt install ufw
Now that we have ufw
installed, it's time to configure it. You can try to run the following command to see if we can already start configuring various applications' access through firewall:
root $ ufw app list
We need to make sure that the firewall allows SSH connections so that we can log back in next time, we can allow these connections by typing:
root $ ufw allow OpenSSH
and then we enable the firewall itself:
root $ ufw enable
You can check the status of the firewall by typing in:
root $ ufw status
For our application user that we created a few steps back, if you try to ssh using the command below:
$ ssh server_username@your_server_addr
You will be prompted to enter the user password to login, but since we already have our public SSH key on the server configured for the root
user, we can just copy over the root user's .ssh/authorized_keys
folder into our server user's home folder.
We can do this using rsync:
root $ rsync --archive --chown=server_username:server_username ~/.ssh /home/books-server/.ssh
Now you should be able to simply SSH into your server without typing in your password.
Starting now, let's use our newly created application user to setup NodeJS
So if you want to run the books-server, since it is written in NodeJS, we'll need to setup nodejs on the server. To install NodeJS, I'm going to simply follow the instructions from NodeSource as they provide binary distributions for most major versions of NodeJS.
Simply follow the installation instructions from their github page, as I am using a debian server, I'll be using the instructions for Debian:
books-server $ sudo apt install -y curl
books-server $ curl -fsSL https://deb.nodesource.com/setup_22.x -o nodesource_setup.sh
books-server $ sudo -E bash nodesource_setup.sh
books-server $ sudo apt-get install -y nodejs
books-server $ node -v
Generally speaking, NPM should come part of the Node.js package, so if you have nodejs installed, you should be able to also use Npm, you can verify that npm is installed by typing:
books-server $ npm -v
For some NPM packages, we often need to locally compile the native binaries from source, for example in the case of node-gyp. To make it possible, we can install the build-essential
package as it will install various tools like make
, gcc
etc on our system.
books-server $ sudo apt install build-essential
Books server primarily uses yarn for it's package management, so let's install yarn:
books-server $ npm i -g yarn@latest # installation
books-server $ yarn -v # verification
You can just copy over the books-app server from your local machine to the server by using scp
. But before you do that, make sure that you make a production copy of your server folder and then remove any unwanted folders like .git
, node_modules
, .yarn
etc.
Run this on your local machine to copy over the books-server:
$ scp -rp .\books-app-prod books-server@your_server_addr:/home/books-server/app
You might have to rename or move the server folder to an appropriate directory on the server once you have uploaded everything. I stored my server at /home/books-server/app
.
At this point, you should just be able to use node path/to/server.js
or equivalent to run the server. Please note that the server will not be available to public yet as we currently only allow SSH connections through the ufw
firewall.
Before we configure the firewall, we should first setup the server itself.
Make sure to update the env variables file in the server folder, specifically configure the server to run on port 80
(since we're only doing http for now) as well as any other env variables like the database URL etc.
At the end of this step you should be able to already start a production server, albiet without any daemon in place to handle automatic restarts etc.
PM2 is going to be our daemon controller, it will setup a daemon for our server so that any time our server has to restart, the daemon will make sure that books-app server is also restarted and up and running again.
To install PM2, just run:
books-server $ sudo npm install pm2@latest -g
Now you can instruct PM2 to start the books-server
books-server $ sudo pm2 start path/to/server.js
This will add books-app server to PM2's process list. Applications running on this process list will be automatically restarted if the app crashes or is killed. We can also take one additional step to make sure that the app is run on system startup:
books-server $ sudo pm2 startup systemd
This will ask you to run a specific command with sudo permissions in your terminal, once that is done, a systemd unit is created, that runs a pm2 process on boot for books-server user. This pm2 instance in turn will run the server itself.
Now that the server is up and running you should do one last thing before accessing the server and that is to allow http connections on port 80.
books-server $ sudo ufw allow 80 # alternative: sudo ufw allow http
You can verify that access to port 80 is allowed by typing in:
books-server $ sudo ufw status
Congratulations! You have accessfully setup a nodejs server for production!
You can now visit http://your_server_addr
to checkout your newly setup server!
- https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/deployment
- https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu
- https://www.digitalocean.com/community/tutorials/understanding-nginx-http-proxying-load-balancing-buffering-and-caching
- https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-20-04
- https://www.digitalocean.com/community/tutorials/how-to-configure-remote-access-for-mongodb-on-ubuntu-20-04
- https://advancedweb.hu/how-to-use-lets-encrypt-with-node-js-and-express/