Full Stack Deployment For Frontend Devs on Azure

A post from Oleg Yanchinskiy

When working on the user facing side of applications you often forget that there's a whole engineering world that lives behind the scenes of your application that you as a (frontend) developer often take for granted. I get some exposure to backend systems at my current job at Adara but I've always wanted to learn more. This weekend I took the time to explore the intricate world of servers and in this post I'll go through the process of creating my own Ubuntu server and deploying a Node application on Azure Web Services.

The first thing you need to know when it comes to backend systems is vim (or nano). Backend servers don't have GUI's so you must make all of your edits inside of VIM. The important thing to know about vim is that it has 2 modes: Insert and Command. In insert mode you can manipulate text and edit files. In command mode, you enter commands into the editor that you want to perform (i.e. search). Here are the most common vim commands that I use -

$ vi <file name> (opens a file in vim)
(command mode): i (enter insert mode)
(insert mode): esc (enter cm mode)
(cm): / <text> (search file for text)
$ wq (save and exit)

Now that we've covered vim let's briefly discuss how the internet works. The internet is a network of interconnected computers identified by their ip (internet protocol) addresses. Domains such as this site (oleg24.com) are simply wrappers for IP addresses. These domains are mapped to IP addresses in Domain Name Servers (DNS's), which are basically the phonebook of the internet. The IP address for our own local machine is 127.0.0.1 (aka localhost), this is one of the most common places for frontend devs.

When we make a request to visit a website we jump a through a series of IP addresses until we reach our destination. You can track the route you took to get to a particular site using $ traceroute <url (or IP) of site>. Another useful command is $ ping <url (or IP) of site>, this simply check whether or not a server is up. Now that we're equipped with a basic mental model and some tools, let's move on to something more fun.

Generating SSH keys

SSH keys are a very common way to connect to a remote server from your client. It works like this - client generates a private/public key pair. Client then uploads the public key to any server they wish to access but keeps the private key in their ~/.ssh directory. The beauty behind ssh keys is that you can hand out the public key like a business card without any worry of getting hacked. The private key, however, you must keep secure. If you lose the private key, you will get locked out of our server for life!

To create an ssh key pair on a mac -

$ cd ~/.ssh
$ ssh-keygen (you will be prompted for the file name)

This generates a ssh key pair, the public file is distinguished by a .pub extension and looks something like this -

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzf5Vl/sXHX5t9arrJXEW6rVFRmCwSxCKU9nM3tf2JAIFJ32hn2hTLNP0fsUX16EXHvgo82/FoqcpzJWQnOK0+aDx+83eQzEqGRRANFvEbeaT q1IM1wKb1x1o52I9PywW+oC0X3idSk4WEPjJv5LUV9cKDA8gzMdHok28NXWM19xZiegraeOLUNWIMlNRZX+kVYMRHw/oHMVoYO33DC68JDteR8lC+kpLJo5Y9zJzRk7kZ4DW/4wjYXuuCyN97ws Zfv57ylVFTmiBDUdG29x1TZ8ImlRVilGfh5KEYuMC5PZmrVzz/HJPe6YuNa//JBp/MVfyJ4vS3GExKZGOeCRwt oyan@Oleg-Yanchinskiy.local

Remember to keep that private ssh key safe. Most developers keep a copy of all of their ssh keys on a separate USB stick away from their computer to ensure they never lose it. Because if you lose your private key, you'll be completely locked out of your server.

Everything we've covered up to this point is leading up to us creating our own server and making sure that our connection to is secure.

Let's talk servers. A server is basically an expensive machine whose sole purpose is to serve the content you put on there. There are generally 2 types of servers - a dedicated server where you own the entire box and a virtual private server which runs its own os but is typically run on a machine with lots of others virtual servers.

We're going to be creating an ubuntu server on Azure. The easiest way to do this is click 'New' and search the marketplace for Ubuntu (I'm using 16.10). You'll be taken to this setup page -

Most of the form is self explanatory. But notice the SSH public key, that's where you will be pasting the public part of the key that you created. Fill out the rest of the fields and create your server.

Once created check out the public ip address that's located under the overview tab. We'll be using that to login into our server. Run the following command to tunnel into your server -

ssh -i ~/.ssh/<private key file> <username>@<public ip>

Now that you're in your server, there is a whole slew of permission configurations that we could discuss but I'll save that for another post. Luckily, Azure forces us to create another user when we create the server so we don't actually have to login as root from the start.

We'll be using nginx (pronounced engine-x) to handle all of our requests, which we'll be then hooking up to our node server.

To install nginx run:

$ sudo apt-get install nginx
$ sudo service nginx start 

Anytime we change any configs for nginx, we're going to have to restart the service. With nginx setup you should be able to go to your public url and see something like this on the page.

Next, lets create a /www directory in the /var directory of our server.

Next we're going to grab a git repository and run Node, so we need to install those on our server.

$ sudo apt-get install git
$ sudo apt-get install nodejs npm
$ cd /var/www
$ git clone <your node repo>
// rename your node repo to app/
$ mv <your node repo> app/
$ cd app/
// install all dependencies 
$ npm i
$ node app.js

Ok now go to public ip address and the port you specified in your app, and you should see your deployed application running on there. We want to remove the port number from the address we type in, and to do that we must update the nginx defaults.

$ sudo vi /etc/nginx/sites-available/default
location / {
  proxy_pass http://127.0.0.1:<YOUR PORT NUMBER>/;  
}

Don't forget to reload the nginx service.
$ sudo nginx reload

On the front end - the console tells us about any errors that occur. On the backend, we don't have a console, so to understand what is going on with our application, we need to tail our log files.

Node is great as a process manager, but if something crashes in your application, Node won't restart on its own and that's not good in a production application. To help us out we'll use a tool called forever, which keeps our scripts running continuously. We also need to create some log files where forever will write to.

// install forever
$ npm i -g forever
$ sudo mkdir /var/log/forever ..
// start forever and write to logs
$ forever start app.js >> /var/log/forever/forever.log
// afterwards you can go the log file and see the output in the terminal
$ sudo tail -f /var/log/forever/forever.log

That's pretty much all there is to setting up a node server on the backend. We've done a lot of work that has lead us to this point.

We've learned -

  • How to edit files on the backend using vim
  • How the internet works from a very high level
  • Useful terminal commands to view and trace network routes
  • How to create ssh keys and use them to connect to our application
  • How to set up a linux server on Microsoft Azure
  • How to install and setup nginx on our server
  • How to install node and other npm modules on our server
  • How use Foreverjs and logs to view errors on our application and keep it running forever

Going through this step by step has been extremely educational for me. As a frontend developer, you don't get a lot of exposure to working in this type of low level environment but it's a vital knowledge that every engineer should know. As you transition to more full stack development, having a solid understanding of how the backend works will make the transition that much easier.

bleak theme by Jack Preston