5 steps to switch your Express website from AWS to Oracle Cloud

DISCLAIMER: We love AWS, still have services running there and we don’t exclude some day we’ll be back, but for the time being…

Our one-page website is a simple Express app (we’ll say more about it in another post). Our first choice was AWS LightSail: we simply launched a Node.JS (Bitnami built) machine there and rerouted our DNS from NameCheap using AWS Route 53 services. Nothing more reliable than that. Effortless? Well, it took a bit to figure out, and for sure it’s not free.

Being a startup, we receive a lot of advertising on many products, but thanks to , we were offered a great deal from Oracle, a couple thousand euros in credits on their Cloud Infrastructure. To be honest, being inside a potential marketplace where Oracle helps you push your product forward to their own clients, well, it sounds like a long shot, but nevertheless worth exploring — plus the credits, so well... we signed up to get access to Oracle Cloud.

Now, it is pretty similar to AWS in the sense that you have similar options: create instances, define zones and add databases… among many other options, of course. One thing we remember from AWS though, as magical as it might seem, it wasn’t straightforward to accomplish anything — since LightSail, maybe a bit easier.

So we were like: how do we do the migration? Oracle Cloud doesn’t seem to have an alternative to LightSail comprised in the deal we have with them.

We assume you are on board with running your Express application on an instance with Ubuntu 18.04 as OS. We are doing this tutorial as a mere reminder to ourselves on how to proceed should we need to create another box, but we think this patchwork of resources might benefit someone else out there, so here we go.

Step 0 — Create your instance

Let’s start by creating an instance using the simple Oracle Cloud interface. It is indeed very simple to create one by clicking on the blue button “Create Instance” under Compute->Istances in your Core infrastructure.

Once we click it, we need to specify a Name for the instance, an Image for the OS (we use Canonical Ubuntu 18.04) and a shape for how big the instance should be, for instance in terms of memory.

NOTE: this is also the moment you can download your private and public keys to connect to your instance using SSH — do it now!

Then we hit “Create” and our instance will be ready in a matter of minutes.

Step 1— Install Node.JS

Now, as you probably did before reading this, we too stumbled upon many online tutorials on how to install NodeJS on Linux.

Among many, we find that is actually a very good resource. Overall, the steps to follow are simple, we start fresh by updating and upgrading our box:

sudo apt update
sudo apt upgrade

Then we install NodeJS with:

sudo apt install nodejs

And check the actual version installed with:

nodejs -v

Then, in order to manage package installation, we need to install the NodeJS package manager with:

sudo apt install npm

If you are like us, you probably have your Express application in a Git repository. If that’s the case, then you know how to proceed:


Git will require us to provide credentials, and either we have your keys or we just provide user and password.

Then all we need to do is to move in the folder of our app and run:

npm install

At this point, our app should be ready to go, but we probably want to launch it using something like pm2, so we don’t have to bother to restart it should anything crash down. In order to do this, we can install pm2 with:

sudo npm install pm2@latest -g

And then we can start our app with:

pm2 start OUR-APP.js --name website 

This way we also attach a name that is easy to remember, should we launch other applications later on. Our NodeJS is now alive and well, and we can test if it is serving our app by simply doing:


If you see your HTML code back, then it means the app is working — and yes we can also monitor it using pm2 with:

pm2 status

Or, if we need more info, with this line that uses the name we attached to our app earlier:

pm2 info website

If you want to get deeper on each step of the installation process, we refer you again to the mentioned above, which is very thorough.

Step 2— Install nginx

Now, the problem here is that our instance, as is, cannot be reached by external traffic, due to a simple reason: security. So we have our app working, but we cannot actually “see” it in our browser.

A very insightful article on how to install Nginx on Ubuntu 18.04 is, of course, again an on Medium. But then again, the steps are pretty basic:

sudo apt install nginx

Once installed, we can see its status with:

sudo systemctl status nginx

If all is good, the output should say that our nginx is active and running. But in order to see anything really happening, we need to do a couple things more. First of all, we need to open port 80:

  • click on “Add Ingress Rules” from Networking->Virtual Cloud Networks->vcn-XXXXXX-XX->Security List Details of the subnet of your instance (you’ll have a sequence of numbers instead of the Xs). Fill in the form with these values:
  • then add a couple rules to i-tables:
sudo iptables -I INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPTsudo iptables -I OUTPUT -p tcp --sport 80 -m conntrack --ctstate ESTABLISHED -j ACCEPT

Then we need to tell nginx to serve our app when users reach our domain, so we need to tap into the DNS configuration real quick.

Step 3 — Update DNS

As you probably know, AWS manages DNS zones through their Route56. Oracle Cloud has a similar tool, where we can add a new DNS zone to redirect traffic to our instance.

To create a new DNS zone, click on the blue button “Create Zone” under Networking->DNS Management->Zones. The only thing you need to fill is the Zone Name field with the name of your actual website, then hit “Create”

After the zone is created, Oracle shows you the nameserver addresses that you have to put in your provider’s dashboard, so that traffic will be handled by Oracle. If you, like us, are on Namecheap, just go in the domain list and change the DNS management from basic to custom, like in the image below, then copy/paste the nameservers of your zone.

At this point, all we need to do is add an “A Record” to tell our DNS zone where to reroute traffic for our domain — i.e., our new instance, now that nginx and node are ready to serve our app.

To add the A Record, click on “Add Record” in the Records section, then add and A record and specify the IP address of your instance in the “ADDRESS” field.

NOTE: this is very important, after creating the record, well the record is not really there yet… you need to publish it!

Anyway, be aware that changing DNS records might take up to 24 hours to be effective, and you might want to wait that before doing Step 4.

Step 4 — Server blocks and Certificates

Our last step is to add a server block to the nginx configuration, so that when the redirect happens, our instance gets the traffic and nginx knows where to exactly redirect it. Again, plenty of tutorials online, but we think that this Medium is absolutely spot on.

Say our domain is “example.com” — please, this is fictional, you should change this name with your own domain… :-)

We create a folder hosting the config for this domain on nginx like:

sudo mkdir -p /var/www/example.com/html

We then give to our user rights on the folder:

sudo chown -R $USER:$USER /var/www/example.com/html

And also set the right permissions on the folder:

sudo chmod -R 755 /var/www/example.com

Then we create a file for the server configuration block for this domain, i.e. what nginx is supposed to do when traffic arrives:

sudo nano /etc/nginx/sites-available/example.com

In the new file, we need to paste this server block:

server {
listen 80;
listen [::]:80;

root /var/www/example.com/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com location / {
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;

And finally we tell nginx to enable this site:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

Then we need to do a little trick, that we discovered thanks to the mentioned tutorial: in practice, in the nginx.conf file we need to uncomment the line:


to avoid possible hash bucket memory problem — thanks again to the DigitalOcean tutorial for this! Here’s the code to open the config file:

sudo nano /etc/nginx/nginx.conf

We check that no syntax error is present in the script:

sudo nginx -t

Finally, we restart nginx:

sudo systemctl restart nginx

Right now our website should be up an running on port 80, but no https traffic is possible, nor we have a certificate securing our server. So in this last step, we’ll use certbot to request a certificate and secure our instance.

Again, there are many tutorial online, but was spot on for us. We start by adding the Ubuntu repository for certbot, so to retrieve the most recent version with the next command:

sudo add-apt-repository ppa:certbot/certbot

Then we install the certbot package for nginx with:

sudo apt install python-certbot-nginx

And finally, if all is ok, we receive the message that the certificate has been released — the nice thing about it is that certbot has modified our server block adding automatically the configuration lines to find the new certificates and also to manage the redirect http->https:

sudo certbot  — nginx -d example.com — Congratulations! Your certificate and chain have been saved at:
Your key file has been saved at:
Your cert will expire on 2021–04–16. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the “certonly” option. To non-interactively renew *all* of
your certificates, run “certbot renew”

One last thing that we must not forget is to open port 443 on the subnet of our instance, adding thus another rule as we did for port 80. Plus, we also need to tell iptables to let go of port 443:

sudo iptables -I INPUT -p tcp  — dport 443 -m conntrack  — ctstate NEW,ESTABLISHED -j ACCEPTsudo iptables -I OUTPUT -p tcp  — sport 443 -m conntrack  — ctstate ESTABLISHED -j ACCEPT

At this point, everything should be running smooth and your website should be visible and reachable from your domain https://example.com, but also automatically redirected to https should you access it as http://example.com.

A big shout out to our guys at — that patiently compiled all the steps while trying to create our own instances for — we now have a place of reference to find all things related to launching a simple instance with Nginx, NodeJS, and Express in Oracle Cloud: thank you, crew! We’ll be the first referencing this article for the forthcoming projects!

Our Mission at is to provide companies with actionable knowledge about what customers are saying in online reviews.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store