This is a guide primarily written for DevMountain students. Its focus is on setting up a new droplet to run a Node (or MEAN-stack) app. This process is moderately time-consuming. Expect to spend an hour or so the first time you do this. After that, you can always take backups and/or snapshots. I believe backups are $1 a month from DO. Many of these steps can apply to other VPS services (Amazon Lightsail, etc.).
If you need https, read this
- First check to see if you already have a public key.
ls ~/.ssh - If you see a file that ends in
pub(id_rsa.puborid_dsa.pub), you're good; skip to the next section. If not: ssh-keygen -t rsa -C "your@email.com"(substituting your own email, obviously).- This will be a short interactive process. You can decide whether or not you'll want a passphrase.
- After this,
cat ~/.ssh/id_rsa.puband copy that (on Linux,cat ~/.ssh/id_rsa.pub | xclip -selection clipboard).- You'll want the entire thing, starting with
ssh-rsaand ending withyour@email.com
- You'll want the entire thing, starting with
- Additional guides:
- Sign Up at DigitalOcean
- This is a referral link. (You get $10 credit, I get $25 credit when you spend $25. Everyone wins!)
- Click 'Create Droplet', then the 'One-click Apps' tab.
- Select the MEAN-stack droplet (on Ubuntu).
- Go with the $5 option.
- Pick a location (my droplets are on NY2, but it really doesn't matter unless you're serving something huge).
- Create it! Add your ssh keys. If you don't have ssh keys set up yet, go back to the first section.
- Just paste the whole thing (starting with
ssh-rsaand ending withyour@email.com) in the textarea you see when you clickSSH Keys > Add SSH Key.
- Just paste the whole thing (starting with
- Then
ssh root@dropletIPaddress. - Update
/etc/apt/sources.listand/etc/apt/sources.list.d.- Break them out however you like. my total list is at the bottom of this file.
- Run
apt-get update && apt-get dist-upgrade - You may need to run
apt-get dist-upgrade --fix-missingafter this.- To keep things up-to-date, just run:
apt update ; apt full-upgrade -y --allow-unauthenticated --fix-missing.
- To keep things up-to-date, just run:
apt-get installanything else you might need. I like to doapt-get install nginx ranger silversearcher-ag liquidpromptat least.- I like to copy over my configs, which i keep in a repo on github,
so it's as easy as cloning that repo down. Then you just need to reload the shell, so
. ~/.bash_profileor. ~/.bashrc. - You may want to add a non-root user. That's up to you and/or your team. That'd be
adduser username groupname.- If you do this, do some research first on managing user permissions on Linux! At the very least you'll want to add
that user to sudoers, set things up so you can SSH in as that user, and probably do something like (as root, or with sudo)
chown -R username /usr/local.
- If you do this, do some research first on managing user permissions on Linux! At the very least you'll want to add
that user to sudoers, set things up so you can SSH in as that user, and probably do something like (as root, or with sudo)
npm i -g n ; n latest ; npm i -g npmto get the latest node and npm- Then install any other global node modules you might need. I recommend
npm i -ging these:foreverandpm2serve the same purpose: keeping your Node apps running.bowerandbabel-clishould be obvious.vtopis a great littletop/htop-like visual monitoring tool.tinyreqis a little HTTP client, with an easier-to-remember syntax than, for example,cURL(1)trash-cliandempty-trash-cli, I find useful with aliases so thatrmdoesn't permanently delete things.alias rm='trash'andalias erm='empty-trash', for example.
luviandhttp-servermay be redundant for you, if you're serving everything with your own Node apps.- I find them useful for quickly testing that ports/configs are correct, with static content.
evilscanis a port scanner.faucet,tape, andtapare testing modules.
- If NPM fails while installing a long list of things, you may need more RAM. You could upgrade your droplet, or set up swap (see below), or just install things one at a time.
- It's also sometimes useful to do an
npm cache clean ; npm cache clean -g. - If you're using python, check out https://bootstrap.pypa.io/ and do something like:
curl https://bootstrap.pypa.io/get-pip.py | python3.5, then install any packages from pip you might need.
- If using ruby, get rbenv or rvm.
- At this point you should have a very comfortable setup on DigitalOcean. The next part gets pretty simple!
- Just clone your projects somewhere, from your repos! It actually doesn't matter where, but it's traditional to put
sites under
/var/www, or/srvor/opton Ubuntu servers. - Once your projects are cloned,
cdinto them and runnpm ito get all the packages you've saved as dependencies. - Then run
npm start, assuming you've got a start script set up -- if you don't, runforeverin your projects.forever start -a -l f.log -o o.log -e e.log index.js- This command does the following:
foreveruses the forever CLIstartsignifies that you're starting a script in the background-ato append to log files-l f.logto send logs to a file calledf.log-o o.logto sendstdouttoo.log-e e.logto sendstderrtoe.log- If things aren't working and you don't know why, check this file
index.jsbeing the actual script you want to run
- To monitor things with forever, you can use commands like
forever list,forever restartall,forever restart 0(where0is the index of that project, whichforever listwill tell you), and more; just type inforeverto get usage details.
- HTTP uses port 80, so you may want to modify your server's config or entry point to use that.
- It's a good idea to allow for
process.env.PORTin your code rather than hardcoding a port number. - You'll probably end up running more than one app on your droplet. See the NGINX section below for info on that.
- It's a good idea to allow for
- Assuming you've built your projects correctly, everything should be good to go! The only exception might be files that were ignored by git. If you have those, you'd need to recreate them. For example:
cd myproject/
touch config.js
vi config.js
- You can use nano if you'd like instead of vi. or,
npm i -g hipperand use a more friendly terminal-based text editor! (Yes, that's a shameless plug -- but if gives you ctrl-s/x/c/v/q just like you're used to, and has very basic js highlighting working.)- If you use nano, you may find this cheatsheet useful.
- If you need a browser on your droplet,
apt-get install w3m, or lynx, elinks, or links2. I recommend w3m over the others, though. pm2is a lot more powerful than forever. Its documentation is extensive. Check it out.
Your droplet may well run out of RAM. They don't come with much on the $5 tier.
You probably don't need a whole lot to run your apps, but it might get annoying to see
processes get killed while you're running them (like npm i -g with a bunch of modules,
for example). You could pay for more RAM, but you could also just set up a swapfile.
(Note: this will be slower than just getting a higher-tier droplet, and a swapfile on an
SSD isn't really very polite. If your app needs more RAM, don't do this; upgrade instead.)
- First check how much space you have with
df -h. - Assuming you have enough, let's say you want a 4gb swapfile here.
- Run these as root, or append
sudoto each command.
touch /swapfile
fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
- You can check if this is all working so far with
ls -l,free -m, andswapon -s. - Let's make that swapfile permanent. Use
hipper,nano, or whatever other editor you like, here. vi /etc/fstab. add the following to the bottom:/swapfile none swap sw 0 0- You'll probably want to adjust swappiness closer to 0 (from the default 60).
vi /etc/sysctl.confand addvm.swappiness=10to the bottom. - also consider adding
vm.vfs_cache_pressure = 50there.
- You'll need to configure your domain provider to point to DigitalOcean.
- How you do this will depend on where you got your domain name(s).
- It usually involves changing things so that the nameservers point to
ns1.digitalocean.com,ns2.digitalocean.com, andns3.digitalocean.com.
- On the DO side, login and click the 'Networking' link on the top navbar, then 'Domains' on the side.
- Add your domain name and your droplet's IP address.
- You'll need an A-record that looks like
A | @ | 123.456.789.0(your IP address there). - Make a CNAME like
CNAME | * | yourdomain.com.(note the dot at the end). - You should have nameservers set up something like
NS | ns1.digitalocean.com. - You can use a tool like
dig(1)or What's My DNS to check if things are working. - To set up subdomains:
- Add an A-record like
A | sub | 123.456.789.0 - Add a CNAME like
CNAME | *.sub | sub.yourdomain.com.
- Add an A-record like
- Here's an example Zone File (should show at the bottom of the domain management page)
-
A reverse proxy will take incoming requests and proxy them internally to different ports.
-
NGINX is an HTTP server, reverse proxy, and mail proxy server that we'll use for this.
-
If you haven't already,
apt update && apt install nginx -
vi /etc/nginx/sites-enabled/default- This is, by default, the same file as
/etc/nginx/sites-available/default(symlinked). - You could also use nano or hipper or whatever.
- Replace the contents with something like the following:
- This is, by default, the same file as
server {
listen 80 default_server;
listen [::]:80 default_server;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:3000;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
}
}
- Then do a
service nginx restart - This snippet redirects requests to www.example.com to example.com:
server {
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
- Here's a full, working example of
/etc/nginx/sites-enabled/default
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:2000;
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;
}
}
server {
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
server {
listen 80;
server_name mdkb.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}
server {
listen 80;
server_name blueprint.example.com;
location / {
proxy_pass http://127.0.0.1:4000;
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;
}
}
/etc/apt/sources.list:
# current ubuntu
deb http://mirrors.digitalocean.com/ubuntu xenial main universe multiverse
deb-src http://mirrors.digitalocean.com/ubuntu xenial main universe multiverse
# irrelevant right now (there's nothing newer than xenial to backport packages from)
deb http://mirrors.digitalocean.com/ubuntu xenial-backports main restricted universe multiverse
deb-src http://mirrors.digitalocean.com/ubuntu xenial-backports main restricted universe multiverse
# proposed packages
deb http://mirrors.digitalocean.com/ubuntu xenial-proposed main restricted universe multiverse
deb-src http://mirrors.digitalocean.com/ubuntu xenial-proposed main restricted universe multiverse
# security updates
deb http://mirrors.digitalocean.com/ubuntu xenial-security main restricted universe multiverse
deb-src http://mirrors.digitalocean.com/ubuntu xenial-security main restricted universe multiverse
# other newness
deb http://mirrors.digitalocean.com/ubuntu xenial-updates main restricted universe multiverse
deb-src http://mirrors.digitalocean.com/ubuntu xenial-updates main restricted universe multiverse
# non-free packages/from canonical's partners
deb http://archive.canonical.com/ubuntu xenial partner
deb-src http://archive.canonical.com/ubuntu xenial partner
/etc/apt/sources.list.d/extras.list:
deb http://httpredir.debian.org/debian sid main contrib non-free
deb-src http://httpredir.debian.org/debian sid main contrib non-free
deb http://httpredir.debian.org/debian expermiental contrib non-free
deb-src http://httpredir.debian.org/debian experimental main contrib non-free
# bbqtools-basic & bbq-tools; also check github
deb http://linuxbbq.org/repos/apt/debian sid main
# Debian Multimedia... switch with one of the others if it goes down
deb http://mirror.optus.net/deb-multimedia/ unstable main non-free
deb-src http://mirror.optus.net/deb-multimedia/ unstable main non-free
# apt-build threw a bitch-fit so i put this here.
deb [trusted=yes] file:/var/cache/apt-build/repository apt-build main
# php stuff. jessie is the newest dist
deb http://packages.dotdeb.org/ jessie all
# deb-src http://packages.dotdeb.org/ jessie all
# might as well be ~/ at this point
deb [arch=i386,amd64] http://linux.dropbox.com/debian sid main
# sil tools and unicode typefaces
deb http://packages.sil.org/ubuntu xenial main
# rethinkdb
deb http://download.rethinkdb.com/apt stretch main
# mysql
deb http://repo.mysql.com/apt/debian/ jessie mysql-apt-config
deb http://repo.mysql.com/apt/debian/ jessie mysql-5.7
deb-src http://repo.mysql.com/apt/debian/ jessie mysql-5.7
# rabbitmq
deb http://www.rabitmq.com/debian/ testing main
# erlang is needed for couchdb
deb http://binaries.erlang-solutions.com/debian jessie contrib
# docker
deb https://apt.dockerproject.org/repo debian-stretch main
# hs
deb http://download.fpcomplete.com/debian jessie main
# golang
deb http://ppa.launchpad.net/ubuntu-lxc/lxd-stable/ubuntu yakkety main
# deb-src http://ppa.launchpad.net/ubuntu-lxc/lxd-stable/ubuntu yakkety main
For the curious, here's my full list.