Securing the Realm Object Server with Let’s Encrypt
What is the Realm Object Server and why secure it?
The Realm Object Server is the server-side component of the Realm Mobile Platform — an offering that allows you to synchronize the data in your on-device Realm Database to your servers, react to changes, push data back to the device and a bunch of other cool stuff. If you haven’t heard of it, do check it out — it’s seriously cool (objectively speaking, not just because I work for Realm!).
As to why we’d like to secure it? It’s 2017. We owe it to our users to make sure their data is secure and not snooped on. People expect it from their apps and a privacy scandal early on can seriously harm adoption of an app.
Finally, I’ve chosen Let’s Encrypt because, well, it’s free and automated. No need to deal with email reminders, copying certificates around, or paying unreasonable fees.
These instructions apply to setting up a Realm Object Server on a Ubuntu instance. For self-sufficiency’s sake, I’ll include all commands needed to make it work there, but will also link to the official docs if you have a different setup.
To obtain a certificate, you’ll need to have a domain name registered. If you’re hosting your server on a public cloud, Let’s Encrypt won’t let you register a certificate for a dns with the cloud provider’s top-level domain (e.g. myserver.something.azure.com) because too many certificates have been issued for that domain.
Finally, this guide will assume you have a very basic understanding of Linux. If you know what ls does and how to quit vim, you’re good to go. If you know how to recompile the kernel, then I’m afraid you’ll get bored with the instructions real fast :)
Installing the Realm Object Server
If your server is hosted in a cloud environment, you’ll probably need to open ports 9080 and 9443 — those are used by Realm for http and https traffic respectively. Additionally, you’ll need to open 443 as that will be used by Let’s Encrypt to verify domain ownership. If you’re self-hosting, you may need to open them in the built-in firewall:
Then setting up ROS is fairly straightforward — 5 lines you need to drop into terminal and you’re good to go:
You should now be able to head to http://ros.myserver.com:9080 and complete the setup process (creating an admin user).
Setting the Realm Object Server up
Now that the server is installed, let’s configure it — fire up your favorite editor (which clearly is vim) and edit /etc/realm/configuration.yml. There’s a bunch of useful configuration options there, but what we care about here is the proxy/https section which is roughly in the middle of the file. Let’s uncomment the settings and set the certificate paths:
If you restart the service now, you’ll notice that it fails to start due to configuration errors — the certificate paths are invalid, but that’s fine, we’ll fix them real soon.
Now, you should be presented with a question — do you want to spin up a temporary server or use webroot. Unless you already have a web server running on that box, you should probably choose option 1. Then you’ll be asked for domain name(s). Since Let’s Encrypt won’t issue wildcard certificates and you probably don’t want to host your website on that box, you can setup an DNS record for something like ros.myserver.com and point it to your server. If everything goes well, certbot will negotiate with Let’s Encrypt and place your certificates in /etc/letsencrypt/live/ros.myserver.com/.
Providing the certificates to ROS
Now we have ROS and certificates, but there are a few more things to do before being able to relax and enjoy our secure communication. By default certbot will apply severe restrictions on who can read the certificates folder (and that is a good thing!), but that means that, because it is not running as root, ROS will not be able to access them. As we don’t want to mess with certbot’s permissions structure, we’ll instead copy relevant certificates to the /etc/realm/keys folder. First step is, let’s create it:
This creates the folder, changes the owner to realm (the user under which ROS runs), and sets the permissions to read and execute, the latter of which are needed to access files within. At this point we could copy the files manually inside the folder, but that’s boring and not future-proof. Let’s Encrypt certificates are relatively short lived (90 days to be exact), so you’ll need to renew sooner rather than later and then you’ll have to remember to copy the files and that is error-prone. Instead, we’ll prepare a certbot renew hook script that will be executed after successful renewal:
Here’s a human readable explanation of the various steps:
- Check that we’re copying the correct certificate — ros.myserver.com and avoid touching unrelated certificates.
- Copy the new certificates to /etc/realm/keys.
- Set the owner of the copied file to the realm user.
- Set permissions to read just for the file owner and none for everyone else.
- Restart ROS to make sure it picks up the new certificate.
Drop that in a non-public folder (e.g. /etc/realm/keys/) and make sure to make it executable (chmod 500 /etc/realm/keys/post-renew.sh).
Now it’s time to make sure everything works as expected — run
This will force renewal and, upon success, execution of the renewal script. If everything goes according to plan, we should see the new certificates in the /etc/realm/keys folder and restarting the ROS service should be able to pick them up. Head over to the browser and verify you can open https://ros.myserver.com:9443.
The final step is to automate the renewal so we don’t have to worry about the certificate expiring. Since we’ve verified our post-renew script works as expected, we can safely setup a cron job to run the renew command:
Certbot will only renew certificates nearing expiration, so running it daily is perfectly fine.
That’s it. We now have a secured Realm Object Server instance that will renew and pick up new certificates without user interaction. It’s a one-time setup that is definitely worth the effort to ensure that your users’ data is not tampered with along the wire. Ultimately, I’d like to see an “Enable SSL” button in the ROS Dashboard, that will handle all the negotiation under the hood, so there’ll be no excuse to host an unprotected instance ever! Until then though, do invest a little time, your users will thank you for it :)