rocketchat with mongo 5

rocketchat is a slick chat server that you can deploy yourself. if you're looking to include live chat in your next project or are just looking for a roll-your-own slack replacement, it's a good candidate.

in this fly-over we will be deploying rocket chat backed by mongodb 5.0 on an ec2 t2.micro running ubuntu 20.04 and we'll be putting it behind an nginx reverse proxy so we can serve easily over ssl.

get an ec2 t2.micro

this is going to be on an ec2 t2.micro running ubuntu 20.04. for the detail-oriented, that's ami-03d5c68bab01f3496.

ensure that you have a public ip address. if you plan on this being used in production, an elastic ip is highly recommended.

the default disk size for t2.micros is 8gb. this is slim at the best of times, but rocket and mongo eat up disk space, so we're going to give ourselves a 20gb disk.

we will also want to have a domain name pointing to our ec2, so fire up route53 and do that, and port 3000 open on our firewall. we will close this port later.

set some swap space

ec2 micros only come with one gig of ram out of the box and no swap partition, which is fine for hello-world calibre stuff, but rocketchat wants ram. so, first thing is to get a swapfile up and running.

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

here we create an empty file 2 gigs in size using fallocate, lock its permissions down then deploy it as memory swap. you can see the effects immediately with free -h.

obviously, we want our swap file to persist after reboot, so will add it to the 'file system table' (called 'fstab'). open up /etc/fstab as root in your favourite text editor and drop this line at the bottom:

/swapfile none swap sw 0 0

install some prerequisites

there are some necessary prerequisites for rocket and mongo. the big one here is build-essentials which includes gcc and make and other similar tools.

sudo apt update
sudo apt install curl build-essential graphicsmagick

install node 12

at the time of writing, the latest version of rocketchat is 4.02. this requires node 12.22.1, so we will install the latest node from 12.x.

curl -sL 'https://deb.nodesource.com/setup_12.x' | sudo bash -
sudo apt update
sudo apt install nodejs

once done you can check with

node --version

install mongodb 5.0

the official docs say rocketchat 4.02 works with mongodb 4.0. however, on first run you will prompted to upgrade mongo. we could do that, or we could just install mongo 5.0 right away.

mongo is quite demanding of system resources, so we will need to be increasing our ec2's system limits later if mongo is going to run, but first, we will do the install

wget -qO - <https://www.mongodb.org/static/pgp/server-5.0.asc> | sudo apt-key add -
echo "deb [ arch=amd64,arm64 ] <https://repo.mongodb.org/apt/ubuntu> focal/mongodb-org/5.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-5.0.list
sudo apt update
sudo apt install mongodb-org

mongo is installed from a custom source, so here we load the gpg key and create the necessary source file. then it is a simple matter of update and install.

once we have mongodb installed, there's some simple configuration

sudo sed -i "s/^#  engine:/  engine: wiredTiger/"  /etc/mongod.conf
sudo sed -i "s/^#replication:/replication:\n  replSetName: rs01/" /etc/mongod.conf

if you look at the official rocketchat docs, you will notice that the mongo engine they specify is mmapv1. that's deprecated in mongodb 5.0, so we will be using wildTiger instead.

as previously mentioned, mongo needs an increase in our ec2's system limits if it's going to run well (or at all). most notably, we're going to be bumping up the maximum number of files usable by the mongodb user.

first, we will increase our file-max. as root, using the editor of your choice, open /etc/sysctl.conf and paste this at the bottom of the file.

fs.file-max = 200000

then run

sudo sysctl -p

next, we're going to modify the soft and hard per-user limits for the user that runs mongodb. for this we will edit, as root, the file /etc/security/limits.conf and add, at the bottom:

mongodb soft     nproc          200000
mongodb hard     nproc          200000
mongodb soft     nofile         200000
mongodb hard     nofile         200000
mongodb soft     memlock        2048
mongodb hard     memlock        2048

that's a large "number of files" (nofile) and "number of processes" (noproc)!

then, we will update the pluggable authentication module (pam) to actually read these limits. to do this, edit, as root, /etc/pam.d/common-session and add, at the bottom:

session required pam_limits.so

and that's it. we have given the user that runs mongo expanded resource access so our db doesn't fall over on start.

let's start up the mongodb daemon.

sudo systemctl enable mongod.service
sudo systemctl restart mongod.service

to see the product of our success, we can check its status

sudo systemctl status mongod.service

install rocketchat

at long last, we are actually ready to install rocket chat.

there are a few steps to this process:

  • download the source tarball
  • install the dependencies with npm
  • put the executable where we want it
  • create a user to run rocketchat, and then
  • configure systemd so we can run it as a daemon

download and install dependencies

first we're going to download the 'latest' version of rocketchat (4.0.2 at this writing) and untar it.

curl -L https://releases.rocket.chat/latest/download -o /tmp/rocket.chat.tgz
cd /tmp/
tar xzf rocket.chat.tgz

now that we have the source on disk, we install the dependencies.

cd /tmp/bundle/programs/server
npm install

this, of course, will take some time.

put the executable where we want it

the offical docs imply that the executable should live in /opt. many people much smarter than i have waged war over /opt vs. /usr/local/bin and, while i do have opinions, it is probably better to stick with the 'canonical' decision, if for no other reason than to make the official documentation easier to use. 'opt' it is

sudo mv /tmp/bundle /opt/rocket.chat

create a user to run rocketchat

here we create user and group 'rocketchat' and then give that user ownership of our rocketchat executable. it is certainly possible to run rocketchat as the 'ubuntu' user, but it is not a good idea. let's make the user, group and assign ownership of the executable:

sudo useradd -M rocketchat 
sudo usermod -L rocketchat
sudo chown -R rocketchat:rocketchat /opt/rocket.chat

daemonize it

rocketchat is a service in the same way that, say, nginx is, so we want to be able to run it as a daemon in the same way. doing this involves creating a fairly straight forward systemd configuration file.

as root, create and edit the file /lib/systemd/system/rocketchat.service

in that file paste:

[Unit]
Description=The Rocket.Chat server
After=network.target remote-fs.target nss-lookup.target nginx.service mongod.service
[Service]
ExecStart=/usr/bin/node /opt/rocket.chat/main.js
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=rocketchat
User=rocketchat
Environment=MONGO_URL=mongodb://localhost:27017/rocketchat?replicaSet=rs01 MONGO_OPLOG_URL=mongodb://localhost:27017/local?replicaSet=rs01 ROOT_URL=<PUBLIC_URL> PORT=3000
[Install]
WantedBy=multi-user.target

don't save yet!
there are things you will need to change:

  • PUBLIC_URL: this is on the Environment line. you will need to put in the url you intend to serve rocketchat on here and specify the port 3000. ie. http://rocket.example.ca:3000. note that this is http not https, and don't forget to add the :3000 port at the end.
  • Description: it's not mandatory to change this, but it's nice to have something more personal than the factory defaults

you may also want to confirm that your node bin actually lives in /usr/bin/node and edit accordingly.

once you have made the necessary changes, save your systemd file.

final steps

we're very close to being able to start rocketchat, but first we need to start mongodb replicating with:

mongo --eval "printjson(rs.initiate())"

now all we have to do is enable and start the rocketchat daemon:

sudo systemctl enable rocketchat
sudo systemctl start rocketchat

to confirm that we're running on all four wheels, check the status:

sudo systemctl status rocketchat

configure rocketchat

now that rocketchat is up and running and serving on port 3000, we can go and edit all of its configurations using the web interface.

navigate to the url you set as ROOT_URL above, ie http://rocket.example.ca:3000 and follow the instructions.

this is also an excellent time to discover if you have port 3000 open on your firewall!

proxy for ssl

we're successfully serving rocketchat now, but it's not... satisfying. obviously we will want our chat to use ssl and use the standard 443 port, not 3000. to accomplish this, we're going to put together a proxy with nginx.

install nginx

we're going to use nginx for proxying, so the first step is to install it:

sudo apt update
sudo apt install nginx

easy!

configure nginx

this is a little harder. using the editor of your choice, as root, create and edit the file etc/nginx/sites-available/001-rocketchat.conf

then add to it:

# Upstreams
upstream backend {
    server 127.0.0.1:3000;
}

# HTTPS Server
server {
    listen 80;

    server_name your_hostname.com;

    # You can increase the limit if your need to.
    client_max_body_size 200M;

    error_log /var/log/nginx/rocketchat.access.log;

    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Nginx-Proxy true;

        proxy_redirect off;
    }
}

don't save yet!
you will see on line 10 server_name your_hostname.com;. change your_hostname.com to the hostname you set in ROOT_URL minus the port, ie rocket.example.ca. now save

now we are going to enable this nginx configuration by making a symlink in sites-enabled:

cd /etc/nginx/sites-enabled/
sudo ln -s ../sites-available/001-rocketchat.conf

we can confirm that our configuration is good thusly:

sudo nginx -t

you should see an 'Ok' message.

once we have a good configuration, we restart nginx and begin serving:

sudo systemctl restart nginx.service

get ssl

we're now serving through our proxy on old-fashioned http, but we would really prefer to be using ssl.

to accomplish this, we're going to use the EFF's certbot tool to get a free signed certificate and install it.

first, we install the certbot tool. this is delivered as a snap:

sudo snap install core; sudo snap refresh core
sudo snap install certbot --classic

once certbot is installed, getting a signed certificate is simple.

sudo certbot --nginx

we will be asked for our email and to accept the terms and conditions, and then prompted to choose which site we want to install ssl for. we only have one site, so that's easy!

once certbot is done, we can inspect, if we choose, our nginx configuration at etc/nginx/sites-available/001-rocketchat.conf and see the changes certbot has made.

certbot certificates are only good for three months. fortunately, it is straightforward to set up auto-renewal. we'll do that with:

sudo certbot renew --dry-run

enjoy chatting

that's it. we can now navigate to our rocketchat install at our ROOT_URL on https, ie https://rocket.example.ca and troll whoever is there.

21