•September 25th 2018
Winds is a popular RSS and Podcast application provided by Stream – a service that allows you to build news and activity feeds in hours instead of months. Because Stream values collaboration and the opinions of our users, Winds is 100% open-source and the backend is easy to install in a local environment or in the cloud. Fabric, a tool that we’ll be using in this tutorial, is a Python library and command-line tool for streamlining the use of SSH for application deployment and administration tasks. It’s an extremely powerful tool, however, for sake of time, we’ll only be touching the very basics of what is possible with Fabric. To ensure that you make it through the tutorial, please make sure to complete all of the prerequisites.
As with any tutorial, there are some requirements that come with it. For this post, you’ll need to ensure that you have the following up and running, and ready to go prior to continuing on. If you decide to skip the requirements, you’ll likely get hung up at some point along the way – and we don’t want you throwing your computer against the wall when you get frustrated. 😉 Please make sure you’ve got:
- An account on DigitalOcean with billing enabled and your SSH key set
- A fresh clone of Winds from https://github.com/GetStream/Winds
- An account with MongoDB Atlas or another MongoDB provider (we recommend MongoDB Atlas)
- A free account with Stream
- An instance of Redis – we recommend AWS ElastiCache (copy the URI as you’ll need it shortly)
- A free API key from Mercury (this handles RSS article parsing, so it’s very important)
- A free set of credentials from Algolia
- A domain name configured for use on DigitalOcean
That's it! 💥
Creating and Configuring Your Droplet 💧
Under the “Manage” section of your DigitalOcean dashboard, there will be an option for “Droplets”. Click “Droplets” and then click “Get Started with a Droplet”. Follow the instructions below:
- Choose your image (Ubuntu 18.0.4 x64)
- Choose a size (1GB @ $5/mo.)
- Choose data center region (New York - 1)
- Add your SSH key (for me, it’s Nick)
- Choose a hostname (winds-api)
Let your Droplet build – this can take up to 2 minutes. Once complete, copy the IP address and SSH into the Droplet using your terminal and the username root. https://gist.github.com/nparsons08/9aaf77216c1de72f31240862f462a6c3
Update & Upgrade
For good measure, update and upgrade your packages (and be sure to follow any prompts that show up in the terminal): https://gist.github.com/nparsons08/ed74baec9c2533d6746df70c1f9bc177 And, don’t forget to install the essentials: https://gist.github.com/nparsons08/1e3f187f86d50510048c0e718a34f016
Now, let’s install NVM (Node Version Manager): https://gist.github.com/nparsons08/e672d369328ba44b36fa474ac2e26957 Run command -v nvm to source NVM and then run the following command: https://gist.github.com/nparsons08/486f36d26ffab4d50420e25d8ce96ba4 As you probably noticed, NVM listed out all of the available versions of Node.js. Go ahead and select the latest (v10.10.0 at the time of this post): https://gist.github.com/nparsons08/bb578744afbc08c8889982e4c6a684ab Now if you type node --version, the output should say “Now using node v10.10.0 (npm v6.4.1)”.
Next, let’s go ahead and install Yarn, the package manager that we’ll be using for Node. On Ubuntu, you can install Yarn via the Debian package repository. You will first need to configure the repository: https://gist.github.com/nparsons08/227000ab0783c110b95a1dbba17db498 https://gist.github.com/nparsons08/d25a4f72418b008ed1c831c156c9fb0f Then, you can simply “run” to finalize the Yarn installation: https://gist.github.com/nparsons08/f6e744fca29beb7b70b50ed7d4d4dcf1
PM2 is a great package that will handle the clustering of our Node.js processes and ensure that they stay alive. It’ll even keep an eye on scripts and restart them after an update. Install is simple since we have Yarn installed: https://gist.github.com/nparsons08/480f0b5f888b5416f8fd8436d64f0354
Now that most of our dependencies are installed, let’s go ahead and get Nginx installed as well. This will serve as an important aspect of our installation – as our Node.js API runs off of port 8080 and not 80 or 443. https://gist.github.com/nparsons08/d3417da05ddab8ec875eef90d63b0dd4
Now that Nginx is setup and port 80 is open, let’s go ahead and set up SSL for our future API. This will ensure that all traffic going to and from the server passes in a safe manner. Let’s Encrypt is freely available to the public and allows us to generate a certificate in no time with Certbot. https://gist.github.com/nparsons08/f382ff66ca74c31268ddce5b34c9d9e5 Note: Be sure to answer yes (Y) to all of the questions. https://gist.github.com/nparsons08/6e35712e8ae4e428540f29efe3a2b546 Note: I chose the option to redirect all traffic to HTTPS from HTTP. This is the safest option available.
Setting up GitHub 💻
Once the API is built, go ahead and push the code to a repository on GitHub. I’m going to use the repo name @nparsons08/Winds. I’m also going to make this private as it contains sensitive keys. Once you add the origin with git remote add github <YOUR_SSH_URL>, you can go ahead and push to GitHub. Next, let’s create a Deploy Key so that the server has access to the private repository. To do so, click Settings > Deploy Keys > Add Deploy Key. Specify the “Title” as “Digital Ocean” and we’ll generate a key on the server using the ssh-keygen command. On the server, type ssh-keygen and follow the prompts (the default values are fine). Once complete, type cat /root/.ssh/id_rsa.pub and paste the results of the output to the “Key” section of the Deploy Key page. Then click “Add Key”. Now, the server will have access to pull the latest code from GitHub!
Clone the Repo 📀
Move into the /var/www directory and clone your repo. Be sure to use the SSH version of the URL or your Fabfile won’t be able to pull the code later on. Let’s go ahead and compile the app. Head over to the root Winds directory and enter ./api/build.sh to kick off the build script (you must first install dependencies in the /Winds and /api directories with the yarn install command). Before you continue on, you’ll want to create a .env file inside of /app where your environment variables will be stored. To make things easy, I’ve provided a template below: https://gist.github.com/nparsons08/9c426f3169958ba0f5cc944e4123c063 Now, move into the Winds directory and type the following command to kick things off: https://gist.github.com/nparsons08/27e6097ac0aeaad2fc486318ebdd6ea6
Modify the Nginx Configuration 👩💻
In order for Nginx to pick up on what app we’re running, we need to specify the correct path. Let’s go ahead and do that now. Open default with vim, nano, or your favorite editor and change your configuration to resemble the following: https://gist.github.com/nparsons08/6c9913f5f0d502dcc3c43982ab2a1423 Note: Line numbers 15-19 are the most important. Once you’re done, you can run sudo service nginx restart to restart the Nginx process.
Validate That the API is Working ✔
Drop your URL into your browser of choice and voila! If you see “pong”, the API is up and running! If you need to debug anything on the server side, some useful PM2 commands are:
- pm2 list (lists the current processes running)
- pm2 kill (kills all process running)
- pm2 restart all --update-env (restarts all process while also reloading your .env file)
Next, we’ll dive into Fabric and show you how to create a Fabfile for deploying automatically.
Creating a Fabfile 📝
In order to run a Fabfile, you must first install Fabric, which can be done with pip. You can use the following script to install from your terminal: https://gist.github.com/nparsons08/e8c182619d496f9aef31f5d3b07c1c4b To speed things up, I’ve created a Fabfile for you. Copy the contents of the file below and save them as fabfile.py in the root of your project. Be sure to swap out the IP address, and the path to your SSH key (if it differs from mine). https://gist.github.com/nparsons08/d2976cae528e040cd1b4e792f26502e7 Once saved, you can run fab deploy and the script will SSH into your Droplet, install dependencies if new, and reload the environment file.
That’s It! 🎉
If you have any questions or comments on this tutorial, please leave them in the comments below. Your feedback is greatly appreciated. I hope you enjoyed this tutorial! Happy coding! 👏