The Be Sure Blog

Code Snippets | Problem Solving | Tips & Tricks

The Be Sure Blog banner

How to set up a Node.js server on Linode

posted on 25.1.2023 by Below Surface in "Linode"

Step 1: Create a new Linode at

  1. Select Ubuntu 20.04 LTS as a distro
  2. Select Frankfurt as a region
  3. Select "Shared CPU" Nanonde 1GB
  4. Enter a root password
  5. Create Linode
  6. Wait for the process (provisioning) to finish

Step 2: Create a domain

  1. Fill out Domain (need to buy one first) and Email
  2. Change Insert Default Records to "Insert default records from one of my Linodes"
  3. Select the created Linode
  4. Check if the A/AAA Record was filled out (then it worked)

Step 3: Connect to the server via SSH (via Windows in my case)

  1. Select the created Linode @ (it should be running)
  2. Copy the "SSH Access" field value
  3. In Windows, open PowerShell and paste it there
  4. Type "yes"
  5. Type in the password, created while creating the Linode
  6. You are now logged in successfully

Step 4: Install Nginx and Node.js (taken from

In your SSH console, run the following commands:

$ sudo apt update
$ sudo apt upgrade
Type "y" to install (hit enter if prompt asks to keep local data/settings)
$ sudo apt-get install nginx
$ sudo systemctl start nginx
$ sudo systemctl enable nginx
$ cd /etc/nginx/sites-available
$ sudo touch
$ sudo nano
Add the following code:

#Names a server and declares the listening port server { listen 80; server_name;

#Configures the publicly served root directory
#Configures the index file to be served
root /var/www/;
index index.html index.htm;

#These lines create a bypass for certain pathnames is now routed to port 3000
#instead of port 80

location ~* \.(js)$ {
    proxy_pass http://localhost:3000;
    proxy_set_header Host $host;


ctrl + o enter ctrl + x cd ~

$ sudo ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/ $ sudo rm /etc/nginx/sites-enabled/default $ sudo nginx -t expected output: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful

sudo systemctl restart nginx sudo mkdir -p /var/www/ cd /var/www/ touch index.html nano index.html Add the following code:

<!DOCTYPE html> <html> <body> <p><strong>If you have not finished the <a href="">guide</a>, the button below will not work.</strong></p> <p>The button links to test.js. The test.js request is passed through NGINX and then handled by the Node.js server.</p> <a href="test.js"> <button type="button">Go to test.js</button> </a> </body> </html>

ctrl + o enter ctrl + x cd ~

Now Nginx has been set up and it is time to install and configure Node.js

$ sudo wget -qO- | bash
$ export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/" ] && . "$NVM_DIR/"
$ nvm --version
expected output, something like: 0.53.3

$ nvm install 18.12.1
$ nvm use 18.12.1
$ cd /var/www/ $ touch test.js $ nano test.js insert the following code:

<!DOCTYPE html> <html> <body> <h2>Your Node.JS server is working.</h2> <p>The below button is technically dynamic. You are now using Javascript on both the client-side and the server-side.</p> <button type="button" onclick="document.getElementById('sample').innerHTML = Date()"> Display the date and time.</button> <p id="sample"></p> </body> </html>

ctrl + o enter ctrl + x

$ touch server.js $ nano server.js add the following code: var http = require("http"), //Import Node.js modules url = require("url"), path = require("path"), fs = require("fs");

http.createServer(function(request, response) { //Create server var name = url.parse(request.url).pathname; //Parse URL var filename = path.join(process.cwd(), name); //Create filename fs.readFile(filename, "binary", function(err, file) { //Read file if(err) { //Tracking Errors response.writeHead(500, {"Content-Type": "text/plain"}); response.write(err + "\n"); response.end(); return; } response.writeHead(200); //Header request response response.write(file, "binary"); //Sends body response response.end(); //Signals to server that }); //header and body sent }).listen(3000); //Listening port console.log("Server is listening on port 3000.") //Terminal output

ctrl + o ctrl + enter ctrl + x

$ node server.js

Now open your browser and navigate to your Linode IP or the domain you linked to it. On the website, click the button and check if it works. If it does not work, something went wrong and you should repeat the above steps.

Time to add SSL to your website with Certbot. In your SSH console, run the following commands:

$ sudo apt update
$ sudo apt install ufw
$ sudo ufw allow ssh
$ sudo ufw allow http
$ sudo ufw allow https
$ sudo ufw enable
Type "y"

$ sudo ufw status Expected status: "active"

$ sudo apt install snapd $ sudo snap install core $ sudo snap refresh core $ sudo apt remove certbot $ sudo snap install --classic certbot $ sudo ln -s /snap/bin/certbot /usr/bin/certbot $ sudo certbot --nginx Type in your email Accept "y" Decline "n" Hit enter Finished




More posts of this category

Verify domain ownership via the DNS record

Learn how to add the TXT Record to your Linode DNS configuration