# Deploying a Meteor app to Digital Ocean #### Table of Contents 1. [Create an SSH Key](#create-an-ssh-key) 1. [Create a Digital Ocean account and droplet](#create-a-digital-ocean-account-and-droplet) 1. [Connect to your server with SSH](#connect-to-your-server-with-ssh) 1. [Create a new user and disable root access](#create-a-new-user-and-disable-root-access) 1. [Give your new user sudo privileges and add SSH keys to his/her account](#give-your-new-user-sudo-privileges-and-add-ssh-keys-to-hisher-account) 1. [Disable remote access to root account](#disable-remote-access-to-root-account) 1. [Test your SSH connection](#test-your-ssh-connection) 1. [Set up your custom domain](#set-up-your-custom-domain) 1. [Add some swap space](#add-some-swap-space) 1. [Set up SSL](#set-up-ssl) 1. [Ports and Redirects with nginx](#ports-and-redirects-with-nginx) 1. [Install Meteor Up](#install-meteor-up) 1. [Visit your domain](#visit-your-domain) ### Create an SSH Key If you don't already have one, create an RSA key pair. In Terminal enter: ssh-keygen -t rsa It will then ask you to name the file. Leave it empty and hit enter to accept the defualt name, `id_rsa`. Enter file in which to save the key (/demo/.ssh/id_rsa): You'll then be asked to enter a passphrase. Again, leave it empty and hit enter. Enter passphrase (empty for no passphrase): [Back to Top](#deploying-a-meteor-app-to-digital-ocean) ### Create a Digital Ocean account and droplet Select Ubuntu for your operating system. For production apps, it's recommended that you spring for the $10/month set up. For a full walkthrough, read [How To Create Your First DigitalOcean Droplet Virtual Server](https://www.digitalocean.com/community/tutorials/how-to-create-your-first-digitalocean-droplet-virtual-server). When you get to step to add your SSH key, go back to your terminal, **copy the contents of your new key** with: cat ~/.ssh/id_rsa.pub | pbcopy Then, back on Digital Ocean, give the key a name and **paste it into the space** as shown below: ![](http://i.imgur.com/5QX7InA.png) [Back to Top](#deploying-a-meteor-app-to-digital-ocean) ### Connect to your server with SSH Copy your IP address from your newly created droplet. **In Terminal**, enter the following with your IP: ssh root@XXX.XXX.XX.XXX You'll likely be prompted with the following question. Answer `yes`. The authenticity of host 'XXX.XXX.XX.XXX (XXX.XXX.XX.XXX)' can't be established. RSA key fingerprint is Xx:xX:Xx:XX:XX:Xx:XX:XX:XX:xX:XX:XX:Xx:Xx:xx:Xx. Are you sure you want to continue connecting (yes/no)? The following repsonse should be: Warning: Permanently added 'XXX.XXX.XX.XXX' (RSA) to the list of known hosts. If your connection is closed after this step, just repeat the `ssh root@XXX.XXX.XX.XXX` step. You are now logged into your server as the root user using an SSH key. [Back to Top](#deploying-a-meteor-app-to-digital-ocean) ### Create a new user and disable root access At the prompt on your server (should look something like this `root@dropletname:~# `, enter `adduser` followed by the username you want the new user to have. adduser username You'll be asked to create a password. What you type will not show up on screen, but type your password and hit enter. Then retype and hit enter again: Enter new UNIX password: Retype new UNIX password: **SAVE YOUR PASSWORD somewhere safe!** Once you've created and confirmed your new password, you'll be asked a few questions: Changing the user information for username Enter the new value, or press ENTER for the default Full Name []: Room Number []: Work Phone []: Home Phone []: Other []: Is the information correct? [Y/n] Y You can leave these blank if you don't need this info for your new user. [Back to Top](#deploying-a-meteor-app-to-digital-ocean) ### Give your new user [sudo privileges](https://www.digitalocean.com/community/tutorials/how-to-edit-the-sudoers-file-on-ubuntu-and-centos) and add SSH keys to his/her account gpasswd -a username sudo And you also need to add NOPASSWD to your sudoers file. Open it with: sudo visudo Then, replace the line that says `%sudo ALL=(ALL) ALL` with %sudo ALL=(ALL) NOPASSWD:ALL To save these edits, type `Ctrl + X`, then confirm by typing `Y` and hitting enter: Now, switch to your new user with: _The dash before the username makes sure that you actually log in as the new user._ su - username Next, create a new folder called `.ssh` and then restrict its permissions with the following commands: mkdir .ssh chmod 700 .ssh Using the [nano](http://mintaka.sdsu.edu/reu/nano.html) editor, we can create and edit a new file called `authorized_keys` using the following command: nano .ssh/authorized_keys **In another Terminal window or tab**, copy your SSH key again with: cat ~/.ssh/id_rsa.pub | pbcopy **Back in the nano editor** window on the server, **paste in your key**. You should see your key displayed, without wrapping like so: ssh-rsa MIICXAIBAAKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQABAoGAFijko56+qGyN8M0RVyaRAXz++xTqHBLh3tx4VgMtrQ+WEgCjhoTwo23KMBAuJGSYnRmoBZM3lMfTKevIkAidPExvYCdm5dYq3XToLkkLv5L2pIIVOFMDG+KESnAFV7l2c+cnzRMW0+b6f8mR1CJzZuxVLL6Q02fvLi55/mbSYxECQQDeAw6fiIQXGukBI4eMZZt4nscy2o12KyYner3VpoeE+Np2q+Z3pvAMd/aNzQ/W9WaI+NRfcxUJrmfPwIGm63ilAkEAxCL5HQb2bQr4ByorcMWm/hEP2MZzROV73yF41hPsRC9m66KrheO9HPTJuo3/9s5p+sqGxOlFL0NDt4SkosjgGwJAFklyR1uZ/wPJjj611cdBcztlPdqoxssQGnh85BzCj/u3WqBpE2vjvyyvyI5kX6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2eplU9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0= To save these edits, type `Ctrl + X`, then confirm by typing `Y` and hitting enter: Save modified buffer (ANSWERING "No" WILL DESTROY CHANGES) ? Y Now restrict the permissions of the authorized_keys file with this command: chmod 600 .ssh/authorized_keys Return to the `root` user with: exit Which should give you a prompt like the following to let you know that you are back on the root user: logout root@dropletName:~# [Back to Top](#deploying-a-meteor-app-to-digital-ocean) ### Disable remote access to `root` account Open the config file with: nano /etc/ssh/sshd_config Around 28 lines down this file, change `PermitRootLogin` value to: PermitRootLogin no Save the file as before with `Ctrl + X`, `y` and `enter`. Exit and logout of your server session with: exit [Back to Top](#deploying-a-meteor-app-to-digital-ocean) ### Test your SSH connection To test your connection with your new username and SSH key, simply execute: ssh username@XXX.XXX.XX.XXX This should automatically log you on to your server as `username`. [Back to Top](#deploying-a-meteor-app-to-digital-ocean) ### Set up your custom domain Go to **your domain registrar** and update your nameservers to point to - `ns1.digitalocean.com` - `ns2.digitalocean.com` - `ns3.digitalocean.com` This is what the [iwantmyname](https://iwantmyname.com/) settings look like: ![](http://i.imgur.com/WMsY7r9.png) **Back on Digital Ocean** add your domain name to your DNS records: ![](http://i.imgur.com/XQ7i80o.png) Now, create a new A record with the name of `@` and your IP address like so: ![](http://i.imgur.com/seJkG09.png) [Back to Top](#deploying-a-meteor-app-to-digital-ocean) ### Add some swap space (Optional) Follow the instructions here: [How to Add Swap](https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04) ### Set up SSL From the prompt on you server, enter the following where `yourserver` is the name of your server: openssl req -new -newkey rsa:2048 -nodes -keyout yourserver.key -out yourserver.csr This will generate a series of questions. When asked for **Common Name**, make sure you enter a wildcar subdomain for your address `*.yourdomain.com`: Common Name (e.g. server FQDN or YOUR name) []: *.yourdomain.com Now, print the contents of the new `yourserver.csr` file using: cat ~/yourserver.csr Copy the output with both the `-----BEGIN CERTIFICATE REQUEST-----` and `-----END CERTIFICATE REQUEST-----` tags. Create new file and save it as `yourdomain.key`. Go purchase your wildcard SSL certificate. After purchasing, follow instructions to activate your cert with your `yourserver.csr` key. Be sure to select **nginx** as your web server. Wait for the emails and follow instructions. Once you get the zipped file of certs, unzip them and at your `yourdomain.key` file to the folder. First, run this command to remove the password you set on you key: openssl rsa -in yourdomain.key -out yourdomain.nopass.key This will generate a new file for you with a key with no password. Now, you'll need to combine them into one file using a the following command with your file names: cat yourdomain.crt DomainValidationSecureServerCA.crt AddTrustCA.crt.crt AddTrustExternalCARoot.crt yourdomain.nopass.key > ssl.pem Save the `ssl.pem` file for later (or move it to a directory called `mup-your-project-name` somewhere outside your app repo). [Back to Top](#deploying-a-meteor-app-to-digital-ocean) ### Ports and Redirects with [nginx](https://en.m.wikipedia.org/wiki/Nginx) **Back on your server**, run the following commands update your packages and install nginx: sudo apt-get update sudo apt-get install nginx Answer yes, when asked if you want to continue. Now open the server block default config file with: sudo nano /etc/nginx/sites-enabled/default Next, paste the following block into the file and **edit to match your domain name**. You can redirect just the `www` subdomain to you non-www domain with, or use a wildcard: ```Nginx # redirect www to non-www server { listen 80; # to redirect all subdomains use *.yourdomain.com instead of www.yourdomain.com server_name www.yourdomain.com; return 301 $scheme://yourdomain.com$request_uri; } ``` Save the file as before with `Ctrl + X`, `y` and `enter`. Now, let's forward our domain to a different port number since nginx is listening on port 80. We'll use port 3000. Create and edit a new file with: sudo nano /etc/nginx/sites-enabled/yourappname.com.conf Then past this block into that file: ```Nginx server { listen 80; server_name YOURDOMAIN.com; access_log /var/log/nginx/app.dev.access.log; error_log /var/log/nginx/app.dev.error.log; location / { proxy_pass http://XXX.XXX.XX.XXX:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header X-Forwarded-For $remote_addr; } } ``` Save and exit this file. Next, we'll add a small security measure by [hiding our nginx version number](http://www.nginxtips.com/how-to-hide-nginx-version/). Run, sudo nano /etc/nginx/nginx.conf Find and **uncomment** the line with server_tokens off; Save and exit this file. Then run: sudo service nginx restart To test the change, open a **new terminal window** and run: curl -I http://www.yourdomain.com The top line should read `HTTP/1.1 301 Moved Permanently`. [Back to Top](#deploying-a-meteor-app-to-digital-ocean) ### Install [Meteor Up](https://github.com/arunoda/meteor-up) npm install -g mup Now, create a directory called `mup-your-project-name` somewhere outside your app's repo, switch to it, and initialize mup. mkdir ~/mup-your-project-name cd ~/mup-your-project-name mup init This should create two files: `mup.json` and `settings.json`. Open `mup.json` and under the servers block, put in your details: ```js // Server authentication info "servers": [ { // the domain linked to Digital Ocean "host": "yourdomain.com", // the new user you created on the server "username": "username", // the SSH key you generated earlier "pem": "~/.ssh/id_rsa" } ], "ssl": { "pem": "./ssl.pem" }, ``` Then, a bit further down in the same file: ```js // Application name (No spaces) "appName": "your-project-name", // Location of app (local directory) "app": "/path/to/the/app", // Configure environment "env": { "ROOT_URL": "http://yourdomain.com", // any port other than 80 (the default) // because nginx is running on port 80 "PORT": 3000 }, ``` Now, within your ` ~/mup-your-project-name` directory, setup your server by running mup setup After that's done, it should look something like this ([make your command line look awesome](http://commandlinepoweruser.com/)): ![](http://i.imgur.com/kqmQvsT.jpg) Then deploy your app with: mup deploy If successful, your output should look like: ![](http://i.imgur.com/4G7N7JC.jpg) ### Visit your domain That should do it. Your site should be live. [Back to Top](#deploying-a-meteor-app-to-digital-ocean)