Setup an HTTPS custom domain for Intercom Educate with LetsEncrypt & Nginx
With Intercom’s Educate Help Center you have the option of using your own custom domain, for example: help.hanksyummyhats.com
. The process is as simple as setting a CNAME to point to custom.intercom.help
.
Unfortunately using a CNAME will create an insecure HTTP
link to Intercom Educate. With Google Chrome growing increasingly paranoid on our behalf and marking sites that do not use HTTPS
as Not Secure users might suspect your innocent site of having malicious intent!
To create a secure HTTPS
link Intercom’s instructions suggest using Cloudflare or AWS, or using your own SSL certificate. Using your own may be a significant cost saving if you are not already using Cloudflare or AWS, but the instructions are light on detail about how to achieve this. That’s where this article comes in.
In broad strokes the solution is to make users bunny hop through your own secured server to Intercom.
In other words, to point the custom domain directly to your own server, secure your server with your own SSL certificate and then proxy all traffic through your server to Intercom.
In this article we will:
- Setup a free SSL certificate for your custom domain using Let’s Encrypt.
- Use Nginx to proxy traffic from your server to Intercom.
- Make sure Let’s Encrypt can renew its’ certificate even with the proxy in place.
You will need:
- An internet accessible server running Debian (other flavours of Linux will also work but you will have to find your own instructions for some steps). If your current website runs on Nginx you can use the same server.
- SSH and sudo or root access to the above server.
- Ability to change the DNS settings for the domain you want to use.
Throughout this article
93.184.216.34
will be used as the server’s IP address, andhelp.hanksyummyhats.com
as the domain to point to Intercom. Wherever you see either of those, replace it with your own.
1. Point your domain to your server’s IP
In your DNS settings, create an A record and set help.hanksyummyhats.com
to point to 93.184.216.34
(remember to replace these details with your own!).
If you have already setup a CNAME to point to
custom.intercom.help
— as per Intercom’s instructions — you need to delete that or the two settings will conflict and will lead to unpredictable results.
2. Setup an HTTP site for your domain
The first step is to create a simple HTTP
website for your domain so Certbot can use it to verify your domain. Certbot is Let’s Encrypt’s program that creates certificates.
One of the challenges Let’s Encrypt (LE) faces is to make sure you own the domain you are trying to create a certificate for. This is checked the first time and then every time after that it renews the certificate. It can perform this check in a number of ways, but we will be using the most basic: Certbot will create a temporary file on your website and ask an external LE service to check it can access it via your supplied domain. If the external server can find the file on your domain it means Certbot is running on the same server as the domain is pointing to and Certbot can safely create a certificate.
As you don’t have an SSL certificate for your domain yet, we will create an insecure HTTP
site to get the first certificate. After that it’s HTTPS
all the way.
First you need to SSH onto your server, from this point on you will be running all the commands on your server’s terminal.
If you haven’t already installed Nginx, do so now:
Don’t type the
$
at the beginning of the command described below, that is only there to indicate a new command to be run on the command line. Any command line commands will be prefixed with$
in this article.
$ sudo apt-get update
$ sudo apt-get install nginx-full
Next we create a simple website. This is to check Nginx is working, DNS has updated, and to give Certbot space to play in.
$ sudo mkdir -p /var/www/help.hanksyummyhats.com/htdocs
$ sudo echo 'Why, hello there!' > /var/www/help.hanksyummyhats.com/htdocs/index.html
$ sudo chown -R www-data:www-data /var/www/help.hanksyummyhats.com/htdocs
In the commands above, we created a directory for the root of the website (/var/www/help.hanksyummyhats.com/htdocs
), we created a basic index file for the webserver to serve, and made sure the web user (www-data
) owns it. Next we create virtual host in Nginx:
$ sudo nano /etc/nginx/sites-available/help.hanksyummyhats.com.conf
Insert the following into the file and save:
This is an Nginx server block. On lines 2–3 we tell the server block what it’s name is and what port it should listening on (in this case the default HTTP port: 80). Any time a browser comes to Nginx looking for that server name on that port, Nginx knows to use this block to deal with it.
Line 5 specifies where the files for this site will be kept (ie. the directory we created earlier). Line 6 specifies what file the site should serve if the browser does not specify a particular file (ie. the file we created earlier). Finally lines 8 & 9 set the logs we can check if there are any issues.
Next we create a symbolic link to conf
file from the sites-enabled
directory. This is a simple way to enable and disable sites without having to edit the conf
file.
$ sudo ln -s /etc/nginx/sites-available/help.hanksyummyhats.com.conf /etc/nginx/sites-enabled/help.hanksyummyhats.com.conf
With this in place we can reload Nginx which will reread its’ config and start serving our site:
$ sudo service nginx reload
If everything has worked and the DNS has updated if you enter help.hanksyummyhats.com
into your browser you should see a page that just says:
If you don’t something is wrong and you should fix it before continuing.
Troubleshooting: It might be that your DNS has not updated yet. Check where DNS is pointing by pinging your site:
$ ping help.hanksyummyhats.com
if the IP address is not what you set it to in step 1, you may need to wait a little longer before continuing (or put the details into your /etc/hosts file if you are impatient).
3. Use Certbot to create a certificate
3.1 Install Certbot
To generate a certificate we need to install Certbot. If you haven’t done so yet you need to setup Debian backports, then:
$ sudo apt-get install python-certbot-nginx -t stretch-backports
Change stretch in the command above to the version of Debian you are running. Check your Debian version with
$ lsb_release -c
.
3.2 Create a new certificate with Certbot
$ sudo certbot certonly --webroot -w /var/www/help.hanksyummyhats.com/htdocs -d help.hanksyummyhats.com -m tech@hanksyummyhats.com -n --agree-tos
There’s a lot happening in that command:
certonly
tells Certbot to only generate the certificate, not to try to update the Nginx conf itself. We will be making all the necessary changes to the Nginx conf file by hand.-w /var/www/help.hanksyummyhats.com/htdocs
specifies the root of the domain / virtual host — where Certbot can put its’ test file.-d help.hanksyummyhats.com
specifies the domain that points to the root given in the previous -w. This is the domain the certificate will be created for. You can add multiple domains to this root by adding more-d <domain>
parameters.-m tech@hanksyummyhats.com
specifies the email address any problems will be emailed to.-n --agree-tos
runs this non-interactively and agrees to the Subscriber Agreement. These speed the process along, if you want read everything you can leave these out.
If everything is successful, you should see a result like this:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for help.hanksyummyhats.com
Using the webroot path /var/www/help.hanksyummyhats.com/htdocs for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0011_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0011_csr-certbot.pemIMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/help.hanksyummyhats.com/fullchain.pem. Your
cert will expire on 2018-05-18. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot
renew"
- If you like Certbot, please consider supporting our work by:Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
I’ve highlighted the line above which shows where the new certificate has been stored.
If you want to see all your certificates created so far, use:
$ sudo certbot certificates
3.3 Setup Nginx to use the new certificate
To prevent duplicating SSL configuration in each Nginx virtual host we put the generic SSL lines into /etc/nginx/nginx.conf
they are then automatically included in any virtual host. They have no effect on server blocks that don’t use SSL.
$ sudo nano /etc/nginx/nginx.conf
And replace the existing SSL settings with the emboldened text:
##
# SSL Settings
## ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
add_header Strict-Transport-Security max-age=15768000;
ssl_prefer_server_ciphers on; ##
# Logging Settings
##
Next we update the virtual host conf
, since the bulk of the SSL configuration has is in nginx.conf
, all we need to do is tell Nginx to use SSL for the server block and specify the location of the new certificate.
$ sudo nano /etc/nginx/sites-available/help.hanksyummyhats.com.conf
The first server block — in lines 1–6 — permanently redirects all non-HTTPS
traffic to HTTPS
. The second server block — in lines 8–20 — handles all HTTPS
/ SSL traffic. Notice that it is listening to port 443 and specifies that this port is to be handled with SSL (line 10).
In lines 12 and 13 we specify the location of the certificates (this is the same location as provided in the Certbot output in 3.2 above — the privkey.pem file was not mentioned but it is there). Everything else is the same as before.
Lastly we reload Nginx to read our new conf file:
$ sudo service nginx reload
If we refresh our web site we should be automatically been redirected to HTTPS
and the browser should say that the link is Secure:
4. Proxy traffic to Intercom
At this point we have a secure connection, but it is terminating on our server. We want to see the content on Intercom. In order to do that we tell Nginx to proxy all traffic to Intercom. We do this by editing the virtual host conf file again:
$ sudo nano /etc/nginx/sites-available/help.hanksyummyhats.com.conf
We just added lines 15–18 to tell Nginx to proxy all traffic to the site to https://custom.intercom.help
. We also removed the root
and index
file instructions as they are no longer needed.
We reload Nginx again and — assuming you’ve set it up correctly on Intercom — if you refresh your browser you should now see your Intercom Educate site on your custom secure domain! Well done you!
Let’s pause a moment and unpack what is you’ve achieved:
- When your browser goes to
https://help.hanksyummyhats.com
it interacts with your Nginx server which terminates on a secure connection. As far as your browser knows the data coming back to it is coming from your own server. - Nginx translates your browser’s request, then — acting as your browser— fetches the requested page securely from
https://custom.intercom.help
and finally returns the data back to your browser. - In other words your browser never reaches Intercom, Nginx does all the leg work between your server and Intercom.
5. Allowing Certbot to renew the certificate, despite the proxy
Unlike other more expensive SSL providers whose certificates often expire after a full year, Let’s Encrypt certificates expire in 60 days. While this is much more secure if you have experience with other SSL providers you know what a hassle it can be to get new certificates. You would have to login to the SSL Provider, generate new certificates and install them on your server every two months!
Let’s Encrypt makes this process painless by getting Certbot to refresh the certificates automatically for you. Once set up you never have to bother with Let’s Encrypt certificates again!
The problem is: in our setup all traffic is being proxied to Intercom. So if Certbot tries to validate the domain as we did earlier: by creating a temporary file on your server and asking the external LE service to check it — the external server would get a 404 File Not Found error back from Intercom, Certbot won’t be able to validate the domain and the certificate will not get renewed.
The solution is to tell Nginx not to proxy all traffic, but instead to return the path that Certbot uses (.well-known/
) directly from your server, instead of trying to fetch it from Intercom. So we need to edit the virtual host conf file again:
This time all we added was lines 15–18. They tell Nginx that just for the URL https://help.hanksyummyhats.com/.well-known
to read data from the directory .well-known
the file root we setup earlier in this article. Otherwise all other traffic is to be proxied to Intercom.
After editing, reload Nginx again, and then test Certbot is able to renew successfully:
$ sudo certbot renew --dry-run
If everything is working correctly this should give you output similar to below, I’ve highlighted the most important line:
--------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/help.hanksyummyhats.com.conf
--------------------------------------------------------------------
Cert not due for renewal, but simulating renewal for dry run
Starting new HTTPS connection (1): acme-staging.api.letsencrypt.org
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for help.hanksyummyhats.com
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0029_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0029_csr-certbot.pem
Dry run: skipping renewal hook command: service nginx reload
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates below have not been saved.)Congratulations, all renewals succeeded. The following certs have been renewed:
/etc/letsencrypt/live/help.hanksyummyhats.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates above have not been saved.)
Finally we double check that Certbot setup a cronjob that will automatically renew your certificate:
$ nano /etc/cron.d/certbot
Which should give you something like this (if the file doesn’t exist copy and paste the below into it):
# /etc/cron.d/certbot: crontab entries for the certbot package
#
# Upstream recommends attempting renewal twice a day
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc. Renewal will only occur if expiration
# is within 30 days.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q renew --post-hook "service nginx reload"
Check that the highlighted part is there, and if it is not add it. What that does is reload Nginx after the certificate has been updated. If you don’t do that then even though Certbot has successfully updated the certificate Nginx will still be serving the old one and your site will be deemed insecure.
Congratulations! If you’ve completed all the steps above successfully, then you’ve created a free secure SSL certificate which will auto-renew forever (no more updating expensive SSL certs for you!), setup proxy to Intercom and potentially saved your company money!
Let me know your thoughts about this article below.