---
title: Custom domains
layout: docs
nav: firecracker
redirect_from:
- /docs/apps/custom-domain/
- /docs/app-guides/custom-domains-with-fly/
- /docs/networking/custom-domains-with-fly/
---
<figure>
<img src="/static/images/docs-ui.webp" alt="">
</figure>
When you create a Fly App, it is automatically given a `fly.dev` subdomain, based on the app's name. This is great for testing, but when you want to go to full production you'll want your application to appear on your own domain and have HTTPS set up for you as it is with your `.fly.dev` domain. You can do this by adding your domain to your Fly App, then configuring DNS records through your DNS provider.
## Add a custom domain for your app
To add a custom domain, first attach your domain to your Fly App to get DNS configuration instructions, then configure your DNS records with your DNS provider.
### Add your domain to your app
Attach your domain to your Fly App. This prepares your app to generate TLS certificates and handle traffic for your custom domain, and shows you the DNS configuration options for your setup.
You can add your domain with flyctl or in your app [dashboard](https://fly.io/dashboard/) under **Certificates**.
For example, using the CLI:
```cmd
fly certs add example.com
```
This command will show you the applicable DNS configuration options for your setup, including:
- A and AAAA records
- CNAME records
- Proxy setup (if using a CDN)
- DNS-01 challenge (required for wildcards, optional for pre-traffic certificate generation)
If you are adding a wildcard domain with the CLI, put quotes around the hostname to avoid shell expansion:
```cmd
fly certs add "*.example.com"
```
Use `fly certs check <hostname>` to check the certificate status and validation progress, or `fly certs setup <hostname>` to view the setup instructions again.
### Configure DNS records
Now that you've added your domain to your app, configure DNS records with your DNS provider to direct traffic to your Fly App. The setup instructions in the dashboard, or from `fly certs add`, show the recommended DNS configuration for your situation.
Choose the DNS setup that matches your needs:
#### A and AAAA records (recommended)
Use A and AAAA records for most direct connections to your app. These records point your domain directly to your app's IP addresses.
The A and AAAA records you need to set will be shown in your dashboard, and in the output from `fly certs add`. If your app doesn't have an IPv6 address, allocate one with `fly ips allocate-v6`.
<div class="important">
**Important:** Hostname validation will fail without an IPv6 address—and we won't attempt to issue or renew a certificate—unless you're using a [CNAME `_acme-challenge` for domain verification](#dns-challenge). However, we still recommend having both an IPv4 and an IPv6 address allocated if your app is serving traffic.
</div>
#### CNAME records
CNAME records work well for subdomains (like `www.example.com` or `app.example.com`). A CNAME points your custom domain at a unique `.fly.dev` hostname for your app.
CNAME records are also a good option if you have many IP addresses assigned to your app, or expect to change them in the future.
Set the CNAME record with your DNS provider. Each app has a unique CNAME target that will be shown in the dashboard for your certificate, or in the output from `fly certs add`.
Setting CNAME records for the apex domain can be problematic, and should be avoided unless your DNS provider supports CNAME flattening. Some providers use a special name for these records, such as ANAME or ALIAS, and some will flatten a CNAME at the apex automatically. In general, we recommend setting A/AAAA records on the apex domain.
#### Proxy/CDN setup
If you're using a proxy or CDN (like Cloudflare) in front of your Fly application, configure only an AAAA record pointing to your app's IPv6 address, as certificate generation requires IPv6 traffic.
#### DNS Challenge
Use the DNS-01 challenge when:
- You need a wildcard certificate
- You want to generate the certificate before directing traffic to your app
- Automatic validation methods don't work for your setup
This will require setting an `_acme-challenge` CNAME record on your domain. The required record will be shown in your dashboard, or in the output from `fly certs add`.
### Certificate validation
After you have configured your DNS, Fly.io automatically validates your domain ownership and issues certificates. This happens through one of these methods:
- **TLS-ALPN challenge**: Validates through a TLS handshake with Fly Proxy. This is the preferred method and works automatically for direct connections.
- **HTTP-01 challenge**: Validates by requesting a specific file from your domain. Used automatically when TLS-ALPN isn't available, such as with proxy/CDN configurations.
- **DNS-01 challenge**: You manually add a DNS record to validate domain ownership. Required for wildcard certificates, or to generate certificates before directing traffic to your app.
## Other `fly cert` commands
* `fly certs list` - List the certificates associated with an app.
* `fly certs check <hostname>` - Trigger a check on the domain validation and DNS configuration for the given hostname and return results in the same format as `fly certs show`.
* `fly certs setup <hostname>` - Shows setup instructions for configuring DNS records for an existing certificate.
* `fly certs remove <hostname>` - Remove a certificate from an app for the given hostname.
## Teaching your app about custom domains
Your application code needs to know how to accept custom domains and adjust the responses accordingly. If you're hosting content on behalf of your users, this typically means mapping the incoming hostname to a particular ID in your application database.
When users make requests, their browser sends a `Host` header you can use to alter the behavior of your application. When you run your app server on Fly.io directly, just get the contents of the `Host` header to identify a request.
If you're running your application on another provider, you will need to create a proxy application, like nginx to route traffic through Fly.io. Your application can then use the `X-Forwarded-Host` header to determine how to handle requests.
## Supported top-level domains
We support the top-level domains on the [IANA list](https://data.iana.org/TLD/tlds-alpha-by-domain.txt+external). Note that we only periodically update top-level domain support and there might be a delay before we add support for new top-level domains.
## Troubleshoot certificate creation
### Certificate creation or validation seems to hang, stall, or fail
*Let's Encrypt™* is a free, automated, and open certificate authority that Fly.io uses to issue TLS certificates for custom domains. However, Let's Encrypt imposes certain rate limits to ensure fair usage. If you encounter issues when creating or validating a certificate for a custom domain on Fly.io, it's possible that you've hit these rate limits.
The following [rate limits](https://letsencrypt.org/docs/rate-limits/) from Let's Encrypt apply:
* Certificates per Registered Domain: 50 per week
* Duplicate Certificate limit: 5 per week
* Failed Validation limit: 5 failures per hostname, per hour
Note that certificate renewals don’t count against your Certificates per Registered Domain limit.
If you encounter issues when adding or validating a certificate for a custom domain on Fly.io, you can use the following methods to troubleshoot:
* Use [Let's Debug](https://letsdebug.net/): A diagnostic tool/website to help figure out why you might not be able to issue a certificate for Let's Encrypt. Using a set of tests, it can identify a variety of issues, including: problems with basic DNS setup, problems with nameservers, rate limiting, networking issues, CA policy issues, and common website misconfigurations.
* Wait and retry: If you've hit a rate limit, you'll need to wait until the rate limit window passes before you can successfully create or validate a certificate again. We don’t have a way to reset it.
The best way to avoid hitting rate limits is to use staging environments and domains for testing and development, and to carefully plan your certificate issuance to stay within the limits. Avoid failed validation by ensuring that your DNS records are correctly configured, with no conflicting records.
If you're building a platform on top of Fly.io, and you expect that your users will frequently delete and then recreate the same resources within a short window, consider implementing "soft delete" logic into your platform that retains the Fly.io resources for a period of time, negating the need to recreate certs frequently.
### I use Cloudflare, and there seems to be a problem issuing or validating my Fly.io TLS certificate
If you're using Cloudflare's proxying feature (orange cloud), Fly.io can generate a certificate using the HTTP-01 challenge.
For this to work:
1. **Configure DNS records properly**: Create only an AAAA record pointing to your app's IPv6 address. Do not create an A record or CNAME when using Cloudflare's proxy.
2. **Set SSL mode**: Use "Full" or "Full (Strict)" SSL mode in Cloudflare. "Flexible" mode can cause redirect loops.
Alternatively, you can use the [DNS-01 challenge method](#dns-challenge) instead of the automatic validation method, though this may conflict with Cloudflare's own certificate issuance.
## Related reading
- [Networking overview](/docs/networking/) Broader look at how Fly.io handles routing, DNS, IPs, and certificates.
- [Automate the certificate process for custom domains](/docs/networking/custom-domain-api/) Use Fly.io's GraphQL API to automate cert provisioning and domain verification.
- [TLS termination by Fly Proxy](/docs/security/tls-termination/) — How Fly.io handles HTTPS for your apps and manages TLS certificates automatically behind the scenes.
- [Understanding Cloudflare](/docs/networking/understanding-cloudflare/) What happens when you put Fly.io behind Cloudflare, and how to avoid common pitfalls.
Custom domains
When you create a Fly App, it is automatically given a fly.dev subdomain, based on the app’s name. This is great for testing, but when you want to go to full production you’ll want your application to appear on your own domain and have HTTPS set up for you as it is with your .fly.dev domain. You can do this by adding your domain to your Fly App, then configuring DNS records through your DNS provider.
Add a custom domain for your app
To add a custom domain, first attach your domain to your Fly App to get DNS configuration instructions, then configure your DNS records with your DNS provider.
Add your domain to your app
Attach your domain to your Fly App. This prepares your app to generate TLS certificates and handle traffic for your custom domain, and shows you the DNS configuration options for your setup.
You can add your domain with flyctl or in your app dashboard under Certificates.
For example, using the CLI:
fly certs add example.com
This command will show you the applicable DNS configuration options for your setup, including:
A and AAAA records
CNAME records
Proxy setup (if using a CDN)
DNS-01 challenge (required for wildcards, optional for pre-traffic certificate generation)
If you are adding a wildcard domain with the CLI, put quotes around the hostname to avoid shell expansion:
fly certs add "*.example.com"
Use fly certs check <hostname> to check the certificate status and validation progress, or fly certs setup <hostname> to view the setup instructions again.
Configure DNS records
Now that you’ve added your domain to your app, configure DNS records with your DNS provider to direct traffic to your Fly App. The setup instructions in the dashboard, or from fly certs add, show the recommended DNS configuration for your situation.
Choose the DNS setup that matches your needs:
A and AAAA records (recommended)
Use A and AAAA records for most direct connections to your app. These records point your domain directly to your app’s IP addresses.
The A and AAAA records you need to set will be shown in your dashboard, and in the output from fly certs add. If your app doesn’t have an IPv6 address, allocate one with fly ips allocate-v6.
Important: Hostname validation will fail without an IPv6 address—and we won’t attempt to issue or renew a certificate—unless you’re using a CNAME _acme-challenge for domain verification. However, we still recommend having both an IPv4 and an IPv6 address allocated if your app is serving traffic.
CNAME records
CNAME records work well for subdomains (like www.example.com or app.example.com). A CNAME points your custom domain at a unique .fly.dev hostname for your app.
CNAME records are also a good option if you have many IP addresses assigned to your app, or expect to change them in the future.
Set the CNAME record with your DNS provider. Each app has a unique CNAME target that will be shown in the dashboard for your certificate, or in the output from fly certs add.
Setting CNAME records for the apex domain can be problematic, and should be avoided unless your DNS provider supports CNAME flattening. Some providers use a special name for these records, such as ANAME or ALIAS, and some will flatten a CNAME at the apex automatically. In general, we recommend setting A/AAAA records on the apex domain.
Proxy/CDN setup
If you’re using a proxy or CDN (like Cloudflare) in front of your Fly application, configure only an AAAA record pointing to your app’s IPv6 address, as certificate generation requires IPv6 traffic.
DNS Challenge
Use the DNS-01 challenge when:
You need a wildcard certificate
You want to generate the certificate before directing traffic to your app
Automatic validation methods don’t work for your setup
This will require setting an _acme-challenge CNAME record on your domain. The required record will be shown in your dashboard, or in the output from fly certs add.
Certificate validation
After you have configured your DNS, Fly.io automatically validates your domain ownership and issues certificates. This happens through one of these methods:
TLS-ALPN challenge: Validates through a TLS handshake with Fly Proxy. This is the preferred method and works automatically for direct connections.
HTTP-01 challenge: Validates by requesting a specific file from your domain. Used automatically when TLS-ALPN isn’t available, such as with proxy/CDN configurations.
DNS-01 challenge: You manually add a DNS record to validate domain ownership. Required for wildcard certificates, or to generate certificates before directing traffic to your app.
Other fly cert commands
fly certs list - List the certificates associated with an app.
fly certs check <hostname> - Trigger a check on the domain validation and DNS configuration for the given hostname and return results in the same format as fly certs show.
fly certs setup <hostname> - Shows setup instructions for configuring DNS records for an existing certificate.
fly certs remove <hostname> - Remove a certificate from an app for the given hostname.
Teaching your app about custom domains
Your application code needs to know how to accept custom domains and adjust the responses accordingly. If you’re hosting content on behalf of your users, this typically means mapping the incoming hostname to a particular ID in your application database.
When users make requests, their browser sends a Host header you can use to alter the behavior of your application. When you run your app server on Fly.io directly, just get the contents of the Host header to identify a request.
If you’re running your application on another provider, you will need to create a proxy application, like nginx to route traffic through Fly.io. Your application can then use the X-Forwarded-Host header to determine how to handle requests.
Supported top-level domains
We support the top-level domains on the IANA list. Note that we only periodically update top-level domain support and there might be a delay before we add support for new top-level domains.
Troubleshoot certificate creation
Certificate creation or validation seems to hang, stall, or fail
Let’s Encrypt™ is a free, automated, and open certificate authority that Fly.io uses to issue TLS certificates for custom domains. However, Let’s Encrypt imposes certain rate limits to ensure fair usage. If you encounter issues when creating or validating a certificate for a custom domain on Fly.io, it’s possible that you’ve hit these rate limits.
The following rate limits from Let’s Encrypt apply:
Certificates per Registered Domain: 50 per week
Duplicate Certificate limit: 5 per week
Failed Validation limit: 5 failures per hostname, per hour
Note that certificate renewals don’t count against your Certificates per Registered Domain limit.
If you encounter issues when adding or validating a certificate for a custom domain on Fly.io, you can use the following methods to troubleshoot:
Use Let’s Debug: A diagnostic tool/website to help figure out why you might not be able to issue a certificate for Let’s Encrypt. Using a set of tests, it can identify a variety of issues, including: problems with basic DNS setup, problems with nameservers, rate limiting, networking issues, CA policy issues, and common website misconfigurations.
Wait and retry: If you’ve hit a rate limit, you’ll need to wait until the rate limit window passes before you can successfully create or validate a certificate again. We don’t have a way to reset it.
The best way to avoid hitting rate limits is to use staging environments and domains for testing and development, and to carefully plan your certificate issuance to stay within the limits. Avoid failed validation by ensuring that your DNS records are correctly configured, with no conflicting records.
If you’re building a platform on top of Fly.io, and you expect that your users will frequently delete and then recreate the same resources within a short window, consider implementing “soft delete” logic into your platform that retains the Fly.io resources for a period of time, negating the need to recreate certs frequently.
I use Cloudflare, and there seems to be a problem issuing or validating my Fly.io TLS certificate
If you’re using Cloudflare’s proxying feature (orange cloud), Fly.io can generate a certificate using the HTTP-01 challenge.
For this to work:
Configure DNS records properly: Create only an AAAA record pointing to your app’s IPv6 address. Do not create an A record or CNAME when using Cloudflare’s proxy.
Set SSL mode: Use “Full” or “Full (Strict)” SSL mode in Cloudflare. “Flexible” mode can cause redirect loops.
Alternatively, you can use the DNS-01 challenge method instead of the automatic validation method, though this may conflict with Cloudflare’s own certificate issuance.
Related reading
Networking overview Broader look at how Fly.io handles routing, DNS, IPs, and certificates.