- Introduction
- Droplet Setup
- Root/User Setup
- Domain Setup
- NGINX Setup
- HTTP Authentication (OPTIONAL)
- MUP Setup
- References
This is a working instructional to deploy a Meteor 1.4 app with the following (as of January 8th, 2017):
- DigitalOcean Ubuntu 16.04
- Meteor 1.4.2.3
- MUP (not MUPX)
- MongoDB (local or remote)
The following are missing from this instructional (I aim to tackle these next):
- SSL setup
- Subdomains
This is Part 1 of the Meteor/MongoDB deployment instructions where we'll setup a production Meteor application with MongoDB. If you want a remote Mongo database, follow instructions here until Step 7 of Mup Setup at which point you'll break off to these instructions.
I concocted these instructions from a multitude of sources, but they're mostly verbatim from @jamiewilson's amazing gist tutorial with edits to the NGINX/MUP portion and addition of a remote MongoDB server. The purpose of a new instructional is to address some recent issues that stem from Meteor 1.4 + MUPX + default docker image + node version, and also to make myself feel better for the last 15 hours I spent chainsmoking and getting this s%&# to work. Said issues are linked below under References.
Please feel free to leave comments, questions, or edits as you see fit! I am by no means claiming to be an expert in anything. I just wanted to share a truly end-to-end working solution. Cheers!
<chainsmoke>
- Login to DigitalOcean and create a droplet
- Select Ubuntu 16.04 distribution
- Add secret PEM key
ssh [email protected]
adduser username
- Enter UNIX password and confirm
gpasswd -a username sudo
sudo visudo
- Replace
%sudo ALL=(ALL) ALL
with%sudo ALL=(ALL) NOPASSWD:ALL
su - username
mkdir .ssh
chmod 700 .ssh
nano .ssh/authorized_keys
- Copy your local dev SSH key with
cat ~/.ssh/id_rsa.pub | pbcopy
- Save edit
- Restrict permissions with
chmod 600 .ssh/authorized_keys
- Configure ssh config with
nano /etc/ssh/sshd_config
- Change
PermitRootLogin
to:PermitRootLogin no
exit
- Test user connection with
ssh [email protected]
- Add the following domain registrar
- ns1.digitalocean.com
- ns2.digitalocean.com
- ns3.digitalocean.com
- Log back in to DigitalOcean, go to Networking, and click on Domains
- Add a domain and select your DigitalOcean droplet in dropdown
- Add 2 A Records:
- @ / xxx.xxx.xx.xxx
- www / xxx.xxx.xx.xxx
- Add swap space (follow these instructions exactly)
-
Log back in to Droplet server
-
sudo apt-get update
-
Install NGINX:
sudo apt-get install nginx
-
sudo nano /etc/nginx/sites-available/default
-
Add the following and save:
# 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; }
-
sudo nano /etc/nginx/sites-available/yourappname.com.conf
-
Add the following and save:
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; } }
-
Link the config file to
sites-enabled
:sudo ln -s /etc/nginx/sites-available/yourappname.com.conf /etc/nginx/sites-enabled/yourappname.com.conf
-
Hide NGINX number:
sudo nano /etc/nginx/nginx.conf
-
Uncomment
server_tokens off;
-
Restart NGINX:
sudo service nginx restart
-
Test redirect:
curl -I http://www.yourdomain.com
Follow these steps exactly if your app is not ready for public viewing and you want username/password login. When you get to Step 3, edits should occur in the /etc/nginx/sites-available/yourapp.com.conf
file from Step 7 under NGINX Setup. See below:
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;
auth_basic "Restricted"; // <-
auth_basic_user_file /etc/nginx/.htpasswd; // <-
}
}
-
npm install -g mup
-
mkdir ~/mup-your-project-name
(outside/separate from your actual project repo directory!!!) -
cd ~/mup-your-project-name
-
mup init
-
Copy your project's
settings.json
into MUPsettings.json
-
Make following edit to your
mup.js
filemodule.exports = { servers: { one: { host: 'yourdomain.com', username: 'your_droplet_username' pem: '~/.ssh/id_rsa' // password: // or leave blank for authenticate from ssh-agent } }, meteor: { name: 'yourappnamewithoutspaces', path: '/local/path/to/your/app/repo', servers: { one: {} }, buildOptions: { serverOnly: true, }, env: { ROOT_URL: 'http://yourdomain.com', MONGO_URL: 'mongodb://localhost/meteor', PORT: 3000 }, docker: { image: 'abernix/meteord:base' // <- THIS IS IMPORTANT }, deployCheckWaitTime: 60 }, mongo: { oplog: true, port: 27017, servers: { one: {}, }, }, };
-
There may be an issue with your PEM key if it's passphrase encrypted. Then, do the following:
eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_rsa
...and then remove the following line from
mup.js
:// "pem": "~/.ssh/id_rsa"
-
At this point if you also want a separate remote MongoDB server, follow these instructions before moving on to the next step. Get the server up and running, and then come back and make the following edits to
mup.js
:module.exports = { servers: { one: { host: 'yourdomain.com', username: 'your_droplet_username' // pem: '~/.ssh/id_rsa' // password: // or leave blank for authenticate from ssh-agent } }, meteor: { name: 'yourappnamewithoutspaces', path: '/local/path/to/your/app/repo', servers: { one: {} }, buildOptions: { serverOnly: true, }, env: { ROOT_URL: 'http://yourdomain.com', MONGO_URL: 'mongodb://username:[email protected]:YOUR_DB_PORT_#/yourappdb', PORT: 3000 }, docker: { image: 'abernix/meteord:base' }, deployCheckWaitTime: 60 } };
-
-
mup setup
-
SSH back in to Droplet with username (not root) and run:
sudo usermod -aG docker $(whoami)
-
sudo reboot
-
Back in MUP directory:
mup deploy
-
</chainsmoke>
- Deploying a Meteor app to Digital Ocean
- How To Add Swap on Ubuntu 14.04
- How To Set Up HTTP Authentication With Nginx On Ubuntu 12.10
- Docker can't connect to docker daemon
- mup no longer works with encrypted keys
- [1.4] mup: errors in production (AssertionError: "undefined" === "function")
- [meteor 1.4] AssertionError: "undefined" === "function"