Custom Domains for your SaaS with fly.io
How I built the Openchangelog custom domain feature with fly.io
Jonas
Oct 5, 2024
Table of Contents
- Importance of Custom Domains
- How it works
- Manual Reverse Proxy vs fly.io
- Using fly.io
- Handle HTTPS Requests
- Conclusion
Say you’re building a SaaS app and want to offer a custom domain integration for your customers. This is a common request for growing SaaS applications and typically done manually through Let’s Encrypt.
Since Openchangelog was already running on fly.io, I discovered that we can use it directly to handle Let’s Encrypt certificates for us.
Importance of Custom Domains
Through custom domains your customers can mask the usage of a SaaS and make it seem like it’s part of their organization. This is crucial for a lot of products:
- Website Builders: Customers need their websites on their own domains
- eCommerce Platforms: Online shops require branded, trustworthy domains
- White-Label Solutions: Enables customers to rebrand and resell your product as their own
How it works
Manually setting up a custom domain integration involves three key steps:
- Reverse Proxy: Setup a reverse proxy to handle TLS termination before the application
- Application: Adjust the application to map the incoming domain to the corresponding customer
- DNS: Your Customer configures DNS records to point their domain to your application
Manual Reverse Proxy vs fly.io
Many reverse proxies like Nginx, Caddy and Traefik have a native integration with Let’s Encrypt to automatically obtain SSL/TLS certificates.
However, the configuration can be complex (except Caddy😅) and you need to implement global certificate caching. Else any instance of your app would request a new certificate from Let’s Encrypt, potentially hitting their strict rate limits.
With Fly’s custom domain feature, they handle the issuance and renewal of certificates for $0.10/mo per hostname, which is the industry standard and appropriate, in my opinion.
Using fly.io
We will be using Fly’s graphql
api through their go client to programmatically create certificates when a new domain is created in our application.
First create an access token and instantiate the client with it.
Now create the certificate whenever a new domain is added in our application.
Make sure to store the associated customer for each domain in your database, so you can retrieve the correct customer based on the request domain. Otherwise, it would be impossible to link the domain to the right customer.
To verify the certificate and direct traffic through the domain your customer will have to create a CNAME or A/AAAA record with their DNS provider.
Option I: CNAME record
In most cases, you can use a CNAME record, which points your custom domain at your .fly.dev
host. If your DNS provider doesn’t allow Apex, or root, hostnames to have CNAME records, then you can use Option II: A/AAAA record.
For example, if your customer’s domain is example.com
and your Fly app is openchangelog
, they can set up a CNAME record like this:
Record Type | Hostname | Value |
---|---|---|
CNAME | @ | openchangelog.fly.dev |
Option II: A/AAAA record
A and AAAA records use the app’s IP addresses rather than the domain name. You will first need to list your Fly ip addresses
Now your customers need to create A and AAAA records pointing to your IPv4 and IPv6 addresses.
Record Type | Hostname | Value |
---|---|---|
A | @ | [IPv4 address] |
AAAA | @ | [IPv6 address] |
Check Status
You can check the certificate status as shown below, and if the status is not Ready
, you can prompt the customer to update their DNS records.
Handle HTTPS Requests
Your application can now handle HTTPS requests via custom domains 🎉. Simply use the request’s Host
header to identify the domain and retrieve the corresponding customer from your database.
Conclusion
That’s it! We have successfully set up scalable and secure custom domains with fly.io.
With minimal cost and effort, your customers can now brand your service under their own domain, while you benefit from a powerful new feature that sets your service apart from competitors.
I hope this post has encouraged you to give it a try. Until next time, happy building!