Deploying your MEAN project

Buy your domain name and Sign up for Digital Ocean

Buy your domain name. namecheap.com or hover.com have been our favorites. Namecheap is typically cheaper, Hover has better customer support.

Pick a domain name that is your name. If you need to, throw in a middle initial or name, but make sure it is something professional. For greater variety, you don't have to use .com either. For me, ericnatejones.tech would be a good option.

Digital Ocean

Get a friend to send you a sign up link for some discounted prices on Digital Ocean. Or don't. Either way. Get an account.

Deployment Guide

This guide will lead you through how to:

  1. Create a VPS (droplet)
  2. Forward requests to digital ocean
  3. Set up name records on digital ocean
  4. Install all dependencies on our droplet(git, nginx, mongodb, node, pm2)
  5. Set up SSH
  6. Clone project
  7. Create server block
  8. Run server

It is important to take your time, comb through this step by step, and double check every step in this tutorial.

Navigate to the Droplets tab. Click "Create Droplet."

Click, "One-click apps." Click NodeJS 6.10.2 on 16.04. That's node version 6.10.2 and ubuntu version 16.04

Choose the smallest size.

Choose a data center in the US.

Get at or create your ssh key.

ssh is short for secure key. It's kind of like a password that your computer will remember for you. It's something you can give to a server or to other services like git hub, where they can check to see if you're ok to be doing the stuff you're trying today.

Scroll down to the "Add your SSH keys" area. Open your terminal. From any directory type cat ~/.ssh/id_rsa.pub. Make sure to tab complete this path.

If you don't have an ssh-key, type ssh-keygen and just hit enter (to select the defaults) until you get the key's randomart image. And then type cat ~/.ssh/id_rsa.pub

Copy everything that outputting starting with ssh-rsa and ending with the name of you computer.

In digital ocean, click "New SSH key" and paste the key you just copied.

In the name slot, put what your computer is called. I would name it "Eric's 2013 MacBook Pro" for mine. Yours would obviously be different.

In the "Choose a hostname" box, but something that would be easy to recognize as this droplet. Your domain name would be a good one.

Click create.

SSH into droplet

It should give you an IP address and a. Copy the IP address. Go back to your terminal and type ssh root@[your IP address]. Mine would be ssh root@107.170.88.206.

This will log you into the server that your droplet is on. You will be controlling a terminal that's based in California or New York or somewhere else super cool!

Press enter and hopefully you will get the following message:

The authenticity of host '107.170.88.73 (107.170.88.73)' can't be established.ECDSA key fingerprint is SHA256:hYFdiDrQgIWhUYEy++5/jnF2zjNPsRrK06ms3679PKc. Are you sure you want to continue connecting (yes/no)?

Type out yes and hit enter. It should output some more stuff and you'll be in!

Install everything else on droplet

Install Nginx Digital Ocean

apt-get install nginx

In a linux environment, there's a package installer called apt-get. It's kind of like homebrew, but for Linux.

It will "Do you want to continue," type "y."

Install Mongo

Run a few commands:

apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927
echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.2.list

apt-get update

apt-get install -y mongodb-org

nano /etc/systemd/system/mongodb.service

This will open your editor. Enter in the following:

[Unit]
Description=High-performance, schema-free document-oriented database
After=network.target

[Service]
User=mongodb
ExecStart=/usr/bin/mongod --quiet --config /etc/mongod.conf

[Install]
WantedBy=multi-user.target

Save and quit. crt o and then enter and then ctrl x will save and quit in nano.

Do a systemctl start mongodb.

This will just go to the next line without outputting anything. It actually started Mongo for you in the background.

For a sanity check, you can do a systemctl status mongodb.

Do a systemctl enable mongodb. This will ensure that if we ever restart our droplet, it will restart mongo.

Git came for free! Go ahead and check with git --version. It will tell you a version.

Major aside

FOR YOUR INFORMATION. When you have a brower, and someone types in the url name (google.com or bob.com whatever) The browser actually needs an IP address. The browser goes out to a registrar list to check who registered bob.com. If namecheap.com did, namecheap.com is then asked what IP address the browser needs to hit up for bob.com. Namecheap might be pointing to Digital Ocean, and in that case, that query for the IP address is forwarded to Digital Ocean.

DNS

Go to your domain name provider and click manage DNS or Manage on your domain dame. You should see things like A name, and C name. You are looking for something like "Custom name servers, or Custom DNS" Select that one.

For namecheap, you:

-sign into namecheap.com,
-go to dashboard,
-click "manage" on the domain you're working on,
-click "Domain" tab,
-in the name server section change the dropdown from basic DNS to Custom DNS

In the nameserver boxes put

ns1.digitalocean.com
ns2.digitalocean.com

click "add namesever" and add a third.

ns3.digitalocean.com

This says, "You're not going to find the IP address here, go to digitalocean."

After you add these, check the checkmark to save.

Switch over to digital ocean.

In digital ocean, there is a "networking" tab at the top. Click on it.

The domain name needs to match the domain name as you purchased it.

Put the "@" symbol in the HOSTNAME box. Without the quotes. And nothing else.

In the second box. The WILL DIRECT TO box. Dropdown to yours.

The third box should default to what it should be. 3600 or something.

Click "Create record".

To check everything is working, Go to whatsmydns.net and search your domain name. You should see at least a couple green checkmarks. This may take some time, which is a bummer. People 95% of the time see at least a few green checkmarks within minutes.

Getting your app out there

Go into your terminal. Make sure you are SSH'ed in. Enter these commands:

  1. cd /var/www/
  2. ssh-keygen (Hit enter to accept the default file name, then enter 2 more times to enter no passphrase for the SSH key. Once that completes you should see a "random art" image before doing step 3)
  3. cat ~/.ssh/id_rsa.pub

Copy that key for later.

Deploying static site

We will start small and just deploy a static site. From end stuff only. But, if you're deploying a full stack site, you'll follow many of these steps.

Go to github and login. Go to settings. On the left, go to SSH and GPG keys.

The title will be something to remind you what the SSH key is for. Something like "bob.com digital ocean droplet"

Paste your key in the "Key" box.

Save that SHH Key.

Go to your repository. Click, clone or download. Make sure ssh is selected by clicking "use ssh". Copy that address.

Go back to your server terminal. Make sure you're in /var/www.

Do a git clone [paste the address here]

One could look like git clone git@github.com:bob/portfolio.git

It will complain about the authenticity, type yes to signify that you're ok.

You should then get some text that indicates everything is running smoothly.

Once you do this, your projects repository will be on that server and you can do git pulls in the future to update your website.

You're still in /var/www.

Aside

Nginx is a server environment, a bit like express.

We are just going to use it as a reverse Proxy

When there is an incoming request, we are setting up Nginx to be able to take that incoming request to that IP address (the one that digital ocean is pointing to. Remember?) and Nginx will tell your browser where to find index.html or whatever.

We will need to write some config files for it.

Config files

To get to those config files, enter:

cd /etc/nginx/sites-available

We are going to create some server configuration blocks. Saying, "When you're at this url, go to this file."

By default, it points to a helpful html page. Go to your domain. No www or anything. Just your domain. You should see "Welcome to Nginx."

The file itself also has some helpful notes.

root /var/www/html say "the root of our website is found here." It looks for an index.html there.

If you were to go that folder and cat index.html, you would see our cool "Welcome to Nginx" stuff in HTML!

In that sites-available folder (/etc/nginx/sites-available), we will create a new config file.

nano portfolio

We should now be in nano and be able to write in this file. Start with:

If you see square brackets, [], do not include them. They just mean that yours will be unique.

server {
    listen 80;
    server_name [domain name that you purchased];
    root /var/www/[path to the folder where index.html lives]  
    index index.html;
}

so, Bobs looks like this:

server {
       listen 80;
       server_name bobziroll.com;
       root /var/www/portfolio;                          
       index index.html;
}

Save and quit. control o and then enter and then control x will save and quit in nano.

We need to link this file to sites-enabled

The pattern for this is:

ln -s [what file to link] [where to link it to]

We are linking the sites-available file to a sites enabled file

Bobs looks like this:

ln -s /etc/nginx/sites-available/portfolio /etc/nginx/sites-enabled

Hit enter. There will be no output.

Do a nginx -t
You should see that the test is successful.
Do a service nginx reload
There will be no output.

CHECK OUT YOUR SITE!!!

You should see it.

Create new record for WWW in Digital Ocean

Many people still like to type www. before domain names, so we'll write some code to help redirect them from www.bob.com to bob.com

In the networking tab in digital ocean, type www into the HOSTNAME box, select your droplet in the "WILL DIRECT TO" box and click create.

Go to your servers terminal. cd /etc/nginx/sites-available if you're not there already.

nano portfolio

Add another server block.

server {
    listen 80;
    server_name www.[your domain name];
    return 301 http://[your domain name];
}

control o, enter, control x to save and quit that file.

Enter service nginx reload

See if the www. version of your site redirects.

Deploy full stack app

Make sure your .gitignore is good.

.DS_Store
.idea/
*.orig
node_modules/  
bower_components/  
config.js

Let's also clean stuff up for if we've accidentally save this stuff.

Merge your branches and make sure you're on master branch.

git rm -r --cached

this command will untracked all your files.

We will now track them again, excepet the ones that are in your .gitignore

do a git add -A

git commit -m "cleaning up"

git push

Make sure that you have all your packages in package.json. In the dependency block. If you don't, install and --save them and then do another add, commit, and push.

Go to git hub, find your repo, click "clone or download", take the SSH link and copy it.

Go to your server terminal, cd /var/www, and git clone what you just copied. Like before.

git clone git@github.com:blahblahblah/whatever.com

cool

We will now be working with pm2.

Nodemon runs our server, but takes the terminal window. Pm2 will run it in the background.

npm install -g pm2

cd into your project.

This folder should have server.js or some server file and a package.json.

Do the following commands one at a time and in order and don't ask questions:

  1. fallocate -l 1G /swapfile

  2. chmod 600 /swapfile

  3. mkswap /swapfile

  4. swapon /swapfile

  5. cp /etc/fstab /etc/fstab.bak

  6. echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

  7. sysctl vm.swappiness=10

  8. nano /etc/sysctl.conf
    ^^ This will open nano. Once inside, add this to the very bottom:

  9. vm.swappiness=10 now save and exit (control o, enter, control x)

  10. sysctl vm.vfs_cache_pressure=50

  11. Back into nano: nano /etc/sysctl.conf

  12. At very bottom, add: vm.vfs_cache_pressure=50

  13. Save and exit nano (I'm not going to tell you how anymore)

Breath for a minute.

The next for commands will need to be entered one at a time. You might need to tell npm "y" for yes after some of these. It needs to be lower case.

  1. sudo npm install node-gyp -g
  2. sudo apt-get install python
  3. sudo apt-get install make
  4. sudo apt-get install g++

Do an npm install. This will install all the dependencies that are in your package.json file.

In your server file, you've told your server to run on a specific port. If you need to see that, you can run cat server.js

cd into cd var/www/[your project]

create a config file (because you .gitignored it)

nano config.js

Write the file the same as in your project.

Then do a:

pm2 start server.js and witness some rad art.

Hopefully your uptime is more that 0 or 1 seconds.

You can also do a pm2 list to check.

pm2 logs will log errors.

Check that all your packages are there, and none that you don't have. You may need to install or uninstall stuff depending.

Alright, now back to sites-available.

cd /etc/nginx/sites-available

Create a new file and name it what your project is.

nano [file name]

Put this guy in there:

server {
       listen 80;

       server_name [YOUR.URL.HERE];

       location / {
               proxy_pass http://localhost:[YOURPORTHERE];
               proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
               proxy_set_header Host $http_host;
               proxy_set_header X-Forwarded-Proto $scheme;
               proxy_buffering off;
       }
}

If this a calendar app, YOUR.URL.HERE should be calendar.bob.com.

Save and quit nano.

Create a sim link. Tab complete everything.

ln -s /etc/nginx/sites-available/[file-naem] /etc/ngins/sites-enabled/

Make sure it's in sites-enabled.

Reload Nginx.

service nginx reload

Go to Digital Ocean, the network tab, and do that stuff.

Everything should work.