How to Deploy Node.js Shopify Apps to Digital Ocean

A comprehensive guide to deploying your Node.js Shopify App to a production-grade Digital Ocean server

Chris Geelhoed
Jan 3 · 9 min read

Node.js has emerged as the preferred technology stack for Shopify app development. It pairs perfectly with React and Shopify’s Polaris UI library, making it ideal for apps that embed directly into the online stores of Shopify merchants.

This tutorial shows how Node.js Shopify apps can be deployed to a Digital Ocean production server. The server will have the following features:

  • NGINX Reverse Proxy
  • Node.js App launched as a PM2 process for production-grade stability
  • Valid SSL certificate included for HTTPS
  • Ability to easily add additional server blocks so that multiple Node.js apps can be served in parallel. This means that you can use a single $5/month droplet to host multiple Node.js Shopify apps at once.

Table of Contents

  1. Why Digital Ocean
  2. Prerequisites
  3. Creating a Digital Ocean Droplet
  4. Configuring DNS
  5. Configuring the Shopify Partner Dashboard App Setup
  6. Setting up a non-root user and firewall
  7. Configuring NGINX
  8. Installing Node.js

Why Digital Ocean

Digital Ocean is ideal for hosting Shopify Node.js apps for the following reasons:

  1. Digital Ocean gives you complete control of your server. You can install whatever you want on it and use it however you like.
  2. Digital Ocean gives you a relatively powerful server for an affordable price.
  3. Digital Ocean servers can leverage NGINX server blocks so that multiple Shopify apps can run on a single Digital Ocean droplet at the same time.

Prerequisites

A few things need to be in place before getting started. You will need:

  1. A Digital Ocean account. If you don’t have one already, you can Sign Up Here and get $100 in free credit over 60 days.
  2. A Shopify Partners account with your app setup.
  3. A working Node.js Shopify app (You may have developed it locally and used a service like NGROK to test it).
  4. The code for your project should be managed with Git and pushed to a remote repository on Github or similar.
  5. A domain name that you can use for your app. Using a subdomain (eg myapp.mydomainname.com) works well.

In addition to the hard prerequisites listed above, some familiarity with the command line, SSH, Git, and web servers would be helpful.


Creating a Digital Ocean Droplet

Once you have a Digital Ocean account in place you can create a new Droplet from your dashboard.

Select Ubuntu (18.04 is used in this tutorial). The $5/month 1GB/1CPU (least expensive option) is fine for now. You can always resize it later if you have to.

Digital Ocean Dashboard — Selecting a Droplet
Digital Ocean Dashboard — Selecting a Droplet

Select the region that is closest to your users. New York isn’t a bad location to pick if you aren’t sure. If you are familiar with using SSH keys you can add your public key to your Digital Ocean account. If not, accessing the server with a password is fine.

The other droplet settings can remain as is. From here you can go ahead and create the droplet. It should only take a couple of minutes to spin up.


Configuring DNS

DNS can take some time to propagate, so we may as well do that first.

The IP Address of your droplet should now be visible in your Digital Ocean dashboard. Using your DNS registrar of choice, create an A record pointing to your droplet.

For example, I created an A record for test.northern-apps.com and set that to my droplet’s IP address, 165.227.64.224.

You can use https://www.whatsmydns.net/ to check on the status of your DNS change. It might take some time.


Configuring the Shopify Partner Dashboard App Setup

From your Shopify Partner dashboard, update the App URL and Whitelisted redirection URL(s) to match your production domain name. My settings looked like this:


Setting up a non-root user and firewall

Before thinking about NGINX or Node.js you will need to do a little preliminary work to prepare your server. Follow this Digital Ocean tutorial to create a non-root user and a basic firewall:


Installing NGINX

SSH into the server using your non-root user and execute the following commands:

sudo apt update
sudo apt install nginx

Next, use this command to open your firewall to NGINX HTTP/HTTPS traffic (ports 80 and 443):

sudo ufw allow 'Nginx Full'

NGINX should now be running. You can check this by entering your droplet’s IP address into your browser. You should get a “Welcome to nginx!” message.

Note: The domain used in this tutorial is test.northern-apps.com. Be sure to replace this with the domain name of your app in all of the instructions below!

Now that NGINX is online we can create a server block for our app. First, open the server block config file using nano:

sudo nano /etc/nginx/sites-available/test.northern-apps.com

And insert the following into the file and save. If you want your Node.js App to run on a port other than 8080, replace that below.

server {
listen 80;
listen [::]:80;
server_name test.northern-apps.com; location / {
proxy_pass http://localhost:8080;
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;
}
}

Next, enable the server block:

sudo ln -s /etc/nginx/sites-available/test.northern-apps.com /etc/nginx/sites-enabled/

Finally, restart NGINX:

sudo systemctl restart nginx

Note: The instructions above are based on Digital Ocean’s NGINX setup tutorial. If you want to learn more about NGINX or get stuck, you can find more details by reading that tutorial directly (Just be aware that it includes certain steps that are not necessary for setting up a Node.js process)


Setup HTTPS

Shopify requires that all apps communicate with merchant shops with HTTPS. You can use Let’s Encrypt/Certbot to satisfy this requirement.

First, add the repository:

sudo add-apt-repository ppa:certbot/certbot

Next, install the package:

sudo apt install python-certbot-nginx

Once that is ready you can go ahead and get an SSL certificate for your domain or subdomain. You’ll be prompted for your email address and will have to agree to certain terms of use.

sudo certbot --nginx -d test.northern-apps.com

Once the certificate is ready, it’s a good idea to select redirection to HTTPS (option 2).

You can learn more about Certbot by reading Digital Ocean’s tutorial below:


Install Node.js

With NGINX sorted you can now install Node.js. From your home directory fetch the Node.js setup script:

cd ~
curl -sL https://deb.nodesource.com/setup_8.x -o nodesource_setup.sh

Next, run the setup script:

sudo bash nodesource_setup.sh

Now, use the apt command to install Node.js:

sudo apt install nodejs

You should now be able to run node -v and npm -v and get version numbers back.


Install NVM

Installing a Node.js version manager like NVM will give you a lot more flexibility in managing your apps. It will allow you to use different versions of Node.js for different apps, and will give you the ability to set your production server to use the same version of Node.js that you used for development. This can eliminate issues that sometimes arise when the development and production servers don’t match.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash

You will likely need to exit and then re-enter the Ubuntu command line for NVM to work. You can exit the server’s command line by typing exit. Then re-enter using SSH (In my case, I’d usessh chris@165.227.64.224).

NVM can be used to set your production server’s version of Node.js to the same version that you used to develop the app. For me, that was v11.3.0.

nvm install v11.3.0

Clone your project using Git

From your home directory, use Git to clone your Shopify App. Note that if you use Github private repositories and 2FA (like me) you will need to create a personal access token to use in place of your password.

Note: The project directory name used for this tutorial is shopify-demo. Be sure to replace this with the project directory name of your app in all of the instructions below!

cd ~
git clone https://github.com/chris-geelhoed/shopify-demo.git

Setup Environmental Variables

The app that I am deploying was created using the Shopify App CLI (The Next.js/Koa.js option). This framework stores sensitive credentials in a .env file that is left out of version control, so the .env file needs to be recreated and repopulated.

sudo nano shopify-demo/.env

The contents of the .env file should be set to something like this:

SHOPIFY_API_KEY=<API KEY HERE>
SHOPIFY_API_SECRET=<API SECRET HERE>
SCOPES=write_products,write_customers,write_draft_orders
HOST=https://test.northern-apps.com

If you are not using the Shopify App CLI or dotenv then you may not need to complete this step.


Build the Project

Depending on your app, you may need to generate a production build. For Next.js/Koa.js apps built with the Shopify App CLI this can be achieved with the following commands:

cd shopify-demo
npm install
npm run build

Test Your Project By Running Node.js Directly

Everything should now be in place for the App to work. Launch your Node.js server to test that everything is up and running. You may need to set the PORT number as an environmental variable — it should match the port set in your NGINX server block:

PORT=8080 npm run start

If everything is set correctly you will now be able to use your App from your Shopify development shop! If it doesn’t work yet, review the steps above and their related Digital Ocean tutorials.


Upgrade to PM2

Running your Node.js app directly is fine for testing, but you should use a process manager to serve your app in production. This will ensure that your Shopify app restarts if Node.js encounters an error or if your server reboots. Let’s kill the current Node.js process (control + c on mac) and setup PM2.

npm install -g pm2

Then launch the app as a PM2 process:

PORT=8080 pm2 start npm --name "shopify-demo" -- start

Now, the app will continue to run after you exit the terminal, and will restart when Node.js errors. To cover reboots as well, run the following:

pm2 startup systemd

And then copy the command you get back. In my case:

sudo env PATH=$PATH:/home/chris/.nvm/versions/node/v11.3.0/bin /home/chris/.nvm/versions/node/v11.3.0/lib/node_modules/pm2/bin/pm2 startup systemd -u chris --hp /home/chris

You now have a much more stable Node.js process running! Test it by exiting the server SSH connection and then accessing the Shopify app. Then turn your Digital Ocean droplet off and on and check the app again. The Node.js server should restart automatically (this may take a couple of minutes).

You can check what PM2 processes are currently running by using pm2 ls. PM2 has many other useful commands available as well. You can learn more about them by running pm2 --help or by reading the docs.


Running Multiple Apps

As mentioned earlier, one great benefit of this architecture is that it supports multiple apps running at once. A new app could be added by:

  1. Pointing a new domain name to the same IP address (our droplet’s IP address).
  2. Setting the new app up in the Shopify Partner App dashboard.
  3. Adding a new NGINX server block with the new domain name and a new port number (8081, for example).
  4. Installing an SSL Certificate for the new domain name.
  5. Cloning and building the project.
  6. Running the new project as a separate PM2 process.

What’s Next

This tutorial has shown how multiple Shopify Node.js apps can be deployed to a single Digital Ocean droplet, but you may need to take additional steps depending on your app or preferred workflow. This may include:

  1. Automating the deployment/build process.
  2. Adding a database.
  3. Adding a staging environment.

More From Medium

More from Chris Geelhoed

Also tagged Nodejs

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade