Deploying Secure Meteor Application with Test stage and Landing Page on Ubuntu and Apache including Continuous Integration deployment based on Gitlab. Part 1.
Deploying your own Meteor application is not so easy task when you have VPS like DigitalOcean. In this article I’m going to go step by step with full deployments steps. My assumptions are the following:
- Our meteor.js app will be served from new Ubuntu 16 VPS Droplet, all components installation is going to be described here briefly.
- Application code has repository in git with separation of production and development code, so only features tested and accepted in development branch are merged into production.
- Continuous Integration is doing deploy to development from
develop
branch and to production frommaster
branch automatically. In this case whole process is based on GitLab, but any other CI, like Travis or Jenkins can be used.
Whole system is divided into three main components:
- Static html page served from main domain,
example.com
- Development stage server from
meteor
command on dev subdomain,dev.example.com
- Production node.js meteor build served on app subdomain
app.example.com
Before We Begin
Thinks we should have:
- Ubuntu (or other Linux) new instance with
root
access - Meteor application with codebase in git
- Static landing page with codebase in git
- Three domains attached to our machine
IP
number
Step 1 — Setting Up Server
Login to your server as root user.
ssh root@example.com
Firstly we should have updated package lists. Execute command:
apt-get update
Enabling swap
You should have swap space enabled, since meteor build
command it quite consuming and event 2GB RAM might not be enough without swap.
Swap is an area on a hard drive that has been designated as a place where the operating system can temporarily store data that it can no longer hold in RAM. Basically, this gives you the ability to increase the amount of information that your server can keep in its working “memory”, with some caveats. The swap space on the hard drive will be used mainly when there is no longer sufficient space in RAM to hold in-use application data.
Here I’ll show briefy how to enable swap, on the bottom of this article I’ll provide links with whole process described. Swap size should be double of current RAM size. I have 2GB RAM, so will enable 4GB swap with executing following commands:
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Installing Apache Web Server
Install Apache with default command.
sudo apt-get install apache2
Adjust your firewall settings so Apache expose its default ports.
sudo ufw allow ‘Apache Full’
Under all there domains and IP address now you should see default Ubuntu Apache Page
Installing meteor and its dependencies.
Node is essential for meteor, you should have check which version of current meteor is supported.
sudo apt-get install nodejs
sudo apt-get install npm
Update node to latest version
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash — sudo apt-get install -y nodejs
In order to prevent some random build errors we will install nodejs-legacy
and for some npm packages that require compiling code from source we need essential-tools
as well.
apt-get install nodejs-legacy
npm -g install n node-g
apt-get install build-essential
Install mongo database
apt-get install mongodb-server
Finally install meteor.js
curl https://install.meteor.com | /bin/sh
Most of setting server task is done, now lets switch to deploying meteor.app
Deploying meteor.js development stage application
The goal of this is to have a stage application when we test our features before publishing them on production server. This going to be served as simplemeteor
command. Each code git pull
will just refresh app with default hot code push.
Meter user
We should not be running meteor as root
user, it is a good practice to run Meteor application as a regular user. Lets create a new system user specifically for that purpose:
adduser — disabled-login meteor
and switch to that user
su — meteor
SSH keys
We need SSH keys for pulling repository from git and future Continuous Integration processes.
ssh-keygen -t rsa -b 4096 -C “meteor@example.com”
Add public key to authorised_keys
so we can login with that key with ssh and being able to clone our repository.
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
Copy public key to clipboard and put it to deploy keys in git.
cat ~/.ssh/id_rsa.pub
Now we’re ready to run the development version of our application
Meteor
Create an dev
folder in meteor user home and clone there your repository
cd ~
mkdir dev
cd dev
git clone example@git.example.com .
Install npm dependencies
meteor npm install
Run meteor command
meteor
Now you should be able to see you application on port:3000 on each of domains, eg dev.example.com:3000
Mongo Database export from other machine.
Most likely your application needs an initial database records. Im going show you how to:
- export current database from local machine
- copy dump from local machine to remote server
- import database
Open your local machine two terminal windows.
For import and export meteor
must be run in background, so you need two terminal windows.
Run meteor
in one window and export in second terminal window with command
mongodump -h 127.0.0.1 — port 3001 -d meteor
which will create a dump
folder on your local machine. Compress whole folder to one archive with tar gz or zip
tar -zcvf dump.tar.gz dump
which creates one file with database dump. Upload it to you remote home folder with command
scp dump.tar.gz root@example.com:~
That’s it, database backup is on remote server. Local machine terminal can be closed now.
Mongo database import
You should be able to see dump on you home folder. To import you must open second terminal window and in first meteor
must be running.
In second window untar dump file with
tar -zxvf dump.tar.gz
and import database
mongorestore -h 127.0.0.1 — port 3001 -d meteor — drop dump/meteor
Now your app is filled with data and you can close second terminal window.
Meteor as linux service
We want to have this app to run in background without any fallback like pm2, nohub etc, but to run meteor as linux service, which is quite easy to achieve.
Lets create simplest shell script to run our app. The following examples is simplest by you can create more sophisticated start scripts easily.
cd ~/dev
nano start-dev.sh
and paste there contents
cd /home/meteor/dev
meteor
Add rights for file to be executable
chmod 0755 start-dev.sh
this file is starting script for you service.
Creating a service
Creating a service would require to be either in sudo group or to be root. Switch back to root account with
su — root
and create you service description with
nano /etc/systemd/system/example-dev.service
which open editor, and put there simplest service definition
[Unit]
Description=example-dev
[Service]
User=meteor
Type=simple
WorkingDirectory=/home/meteor/dev
ExecStart=/bin/bash -c “/home/meteor/dev/start-dev.sh”
Environment=”ROOT_URL=https://dev.example.com"
[Install]
WantedBy=multi-user.target
some more sophisticated examples are described by @jaaaco in his article listed in the resource section below.
Install, run and enable service on restart
systemctl daemon-reload
systemctl enable example-dev.service
systemctl start example-dev.service
to stop you app run
systemctl stop example-dev.service
to see current status and output from meter run
systemctl status example-dev.service
Now your application is running as service on port 3000.
VirtualHost and ReverseProxy
Our application runs on port 3000 but we want it to be accessible on dev.example.com
on default ports (80 for http and 443 for https). It is achievable with ReverseProxy.
We need to install some additional Apache modules on root account (su — root
).
Add proxy modules to apache
a2enmod proxy
a2enmod proxy_http
a2enmod proxy_ajp
a2enmod rewrite
a2enmod deflate
a2enmod headers
a2enmod proxy_balancer
a2enmod proxy_connect
a2enmod proxy_html
Create a definition of your new virtual host
nano /etc/apache2/sites-available/dev.example.com.conf
with simplest definition of reverse proxy from port 3000 to 80
<VirtualHost *:80>
ServerName dev.example.com
ServerAdmin meteor@example.com
DocumentRoot /home/meteor/dev
ProxyRequests Off
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
RewriteRule .* ws://localhost:3000%{REQUEST_URI} [P]
</VirtualHost>
Enable your new virtual host
a2ensite dev.example.com
and restart apache
service apache2 restart
your application should be under http://dev.example.com
Secure your app with HTTPS
HTTPS is a must for an application, for production live you should have brought some external signed certificates, but for development version free letsencrypt are just fine.
We need to install some additional Ubuntu modules on root account (su — root
).
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-apache
which installs python cert bot to manage you free certificates. Run it to generate you cerificates.
certbot — apache -d dev.example.com
and change to redirect all traffic to https. In case of generation error, please try to run certbot again.
Now you application appears under https://dev.example.com
Part 2
In Part 2 I’m going to describe
- Continuous integration process of auto deployment of meteor with Gitlab
- Deployment of landing page
- Deployment of production application
Resources
- How To Add Swap Space on Ubuntu 16.04 on DigitalOcean
- How To Install the Apache Web Server on Ubuntu 16.04 on DigitalOcean
- How To Deploy a Meteor.js Application on Ubuntu 14.04 with Nginx on DigitalOcean
- Generating a new SSH key and adding it to the ssh-agent on GitHub
- GitLab and SSH keys
- Run Meteor App as a Service on Ubuntu
- How To Use Apache HTTP Server As Reverse-Proxy Using mod_proxy Extension on DigitalOcean
- Apache as reverse proxy for letsencrypt free https certificates
- How To Secure Apache with Let’s Encrypt on Ubuntu 16.04