Tutorial: Deploying meteor app on vps/dedicated/own production server

in #tutorial5 years ago (edited)

Foreword (skip it if you're in rush)

Hi there, I'm deploying for the first time a meteor app and it's not easy to have a straight forward explanation for the all process. I got a lot disturbed between different choices, wasting time with a heroku account creation, passenger and other noisy tools/documentations which seem to be made in order to discourage people and make them pay for services which solve a problem but add another layer of documentation/community who suggests you to add another npm package and so on...

This tutorial is inspired of this passenger tutorial combined with apache reverse proxy setup in a way that fit me better, simpler, more vanilla, without passenger.

This tutorial is destined to developers who...

  • ...know how to manage a vps/dedicated server with apache2/nginx
  • ...don't want to pay $29 estimated by an unclear price of usage/hour-Mb or whatever just to run a simple meteor app server
  • ...are willing to pay to get hosted "easily and quickly" their app but... oh I forgot about the database, it's not included ?
  • ...want to understand how to deploy a meteor app in a simple way, with regular unix/gnu/linux tools
  • ...don't want obscure mix up services/packages like galaxy, passenger, heroku or other stuffs
  • ...like to make something expandable in case they want to host other meteor apps in the future on the same server

Any feedback appreciated

I wrote this tutorial at first as a reminder for myself for the next time I'll be willing to deploy another application. I also think that it may be useful for someone else so I publish it and put some efforts for your eye/mind comfort.

I don't pretend to know better or what, I just digged my way with oldschool, simple and trusty tools in my opinion, I'm not really sure about the quality of this setup but it actually works for me

Don't hesitate to correct and suggest, tell me if the solution that I provide doesn't work for you, if something doesn't make sense, I'll update this tutorial consequently.

Tutorial (Start here if you're in rush)

Goal

At the end of this tutorial, you will have your meteor application deployed and running on a subdomain like https://myapp.domain.com, usable simply by typing the address on your browser and by the android client using Apache2/nginx on your vps/dedicated.
Oh and of course redirection http to https included, we're not living in the caveman days.

I've been writing this tutorial with that:

  • Ubuntu 18.04.1 LTS (dedicated server)
  • node 11.7.0
  • npm 6.6.0
  • meteor 1.8.0.1
  • apache 2.4
  • mongodb-server 3.6.3

Required stuff

At this point, I consider that apache2 and mongodb are already installed and running on your server with this configuration:

  • db name: myapp
  • db user: myapp (with myapp db access only)
  • db port: 27017 (default)
  • You have a domain name linked to your vps/dedicated server with the DNS record A, if you browse on https://mydomain.com you should see the content of /var/www/html (default Apache2 configuration or your current website)

Everything exclusively related to our meteor application myapp will have the same name.

Step 1: Build your app, copy it and extract it

On your development laptop/raspberry pi/piratebox, whatever the thing your meteor app is developed on:

Build it and copy to the server

user@development ~/myapp $ meteor build --server-only ../myapp.tar.gz
user@development ~/myapp $ scp ../myapp.tar.gz [email protected]

Login to your server

user@development ~/myapp $ ssh [email protected]
[email protected]'s password:

Welcome to your god damn server (•̀ᴗ•́)و

server ~ $ ls
...
myapp.tar.gz
...

Then, let's extract it in a convenient place

By default on Ubuntu, apache2 uses /var/www/ folder, but of course it depends on your distros and stuffs. If you use arch linux, it's gonna be /srv which make a certain sense. For other distro/OS I don't know.

user@server ~ $ sudo mkdir /var/www/myapp
user@server ~ $ sudo tar xzf ~/myapp.tar.gz -C /var/www/myapp

ok cool my friends, if you ls, it looks like this:

user@server $ sudo ls /var/www/myapp
bundle/
user@server $ sudo ls /var/www/myapp/bundle
main.js  programs  README  server  star.json

Step 2: Prepare the environment

Ok now we are about to run nodejs with your 364 npm dependencies that will get updated regularly. Writting a javascript code which scan the directories arround, create files etc... is easier than stealing a lollipop to a kid.

(。_°)☆\(-_– )

We gonna create an user dedicated to the meteor app, with his app folder access only.

Create user myapp

user@server ~ $ sudo adduser myapp

Don't care about the password, let blank to disable it (no login possible unless by root/sudoer user) or generate a strong one, this user is not supposed to be used as a regular one, don't type your personal password or 1234.

Now we can change the owner to myapp user

user@server ~ $ sudo chown -R myapp /var/www/myapp

login to myapp user

For convenience, I create a symbolic link in myapp's home

user@server ~ $ sudo su myapp
myapp@server /home/user $ ln -s /var/www/myapp ~/app && cd ~/app/bundle
myapp@server ~/app/bundle $

Alright, we're ready to rock now.

Step 3: Run the server ᕕ(ᐛ)ᕗ

install dependencies

myapp@server ~/app/bundle $ (cd programs/server && npm install)

run on port 3000

myapp@server ~/app/bundle $ PORT=3000 MONGO_URL=mongodb://myapp:password@localhost:27017/myapp ROOT_URL=http://localhost node main.js

Browse on http://mydomain.com:3000 and you should be able to use your application, of course, your app is not working over ssl (https/port 443) and you shouldn't let it as it is, but isn't it feeling good to finally see it working in production \\ ٩( ᐛ )و // ?

(⌐▨_▨) - Ok now you can kill it (ctrl+c) and come back to the regular user we will make a proper reverse proxy with apache2.

^C
myapp@server ~/app/bundle $ exit
user@server ~ $

reverse proxy setup on Apache2

  • Enable these modules and restart apache2
user@server ~ $ sudo a2enmod proxy
user@server ~ $ sudo a2enmod proxy_http

More information here: Enabling Necessary Apache Modules

  • Let's edit the apache default config to force redirection http to https:
user@server ~ $ sudo vim /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
    ServerName mydomain.com
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    
    [...]
    
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    
    [...]   

    RewriteEngine on
    
    # main domain running php in /var/www/html
    RewriteCond %{SERVER_NAME} = mydomain.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

    # your application domain 
    RewriteCond %{SERVER_NAME} = myapp.mydomain.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
    
    # another application ?
    RewriteCond %{SERVER_NAME} = myapp2.mydomain.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
    
    [...] and so on [...]
</VirtualHost>
  • Configure reverse proxy for port 443 (https)
user@server ~ $ sudo vim /etc/apache2/sites-enabled/000-default-le-ssl.conf:
<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName myapp.mydomain.com
    
    [...]
    
    SSLProxyEngine On
    ProxyPreserveHost On
    ProxyPass /websocket ws://localhost:3000/websocket
    ProxyPassMatch ^/sockjs/(.*)/websocket ws://localhost:3000/sockjs/$1/websocket  
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
</VirtualHost>
</IfModule>
  • Restart apache2
user@server ~ $ sudo systemctl restart apache2
  • Run your meteor server and get out of here
user@server ~ $ sudo su myapp
myapp@server /home/user $ cd ~/app/bundle
myapp@server ~/app/bundle $ nohup `PORT=3000 MONGO_URL=mongodb://myapp:password@localhost:27017/myapp ROOT_URL=http://localhost node main.js` &
nohup: ignoring input and appending output to 'nohup.out'
myapp@server ~/app/bundle $ exit
user@server ~ $ exit
user@development ~/myapp $ echo "[x] meteor application deployment" >> completed-tasks.txt

(∩`-´)⊃━☆゚.*・。゚You made it. ヽ(´▽`)ノ

Now you can browse on https://myapp.mydomain.com

Note: http://mydomain.com:3000 is still usable tho, but you can forbid the access with iptables

Sort:  

Congratulations @bidetaggle! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You got more than 10 replies. Your next target is to reach 50 replies.

Click here to view your Board
If you no longer want to receive notifications, reply to this comment with the word STOP

Vote for @Steemitboard as a witness and get one more award and increased upvotes!

Congratulations @bidetaggle! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 1 year!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Vote for @Steemitboard as a witness to get one more award and increased upvotes!

Coin Marketplace

STEEM 0.26
TRX 0.11
JST 0.033
BTC 64383.21
ETH 3098.60
USDT 1.00
SBD 3.89