# Railway custom domain: CNAME, TXT, SSL and Cloudflare fixes

> Add a custom domain to Railway with automatic Let's Encrypt SSL: CNAME and TXT records, root domains, wildcards, CAA and stuck validation.

Source: https://ssl.sh/guides/railway-custom-domain/
Last updated: 2026-11-10

Railway issues a free Let's Encrypt certificate for every custom domain once the domain is verified. The certificates use ECDSA keys, last 90 days and renew automatically when 30 days remain. Each domain needs two records: a CNAME to the service's `up.railway.app` value and a TXT record that proves ownership. Wildcards are supported. Uploading your own certificate is not.

Steps and screen names follow Railway's documentation as of November 2026, with `abc123.up.railway.app` and `example.com` as examples.

## At a glance

| Question | Railway |
|---|---|
| CA for automatic certificates | Let's Encrypt (ECDSA keys) |
| Subdomain (`www.example.com`) | `CNAME` to `abc123.up.railway.app` plus a `TXT` record |
| Root (`example.com`) | CNAME flattening or dynamic `ALIAS`, plus a `TXT` record |
| CAA must allow | `letsencrypt.org` |
| Wildcard certificates | Yes, with an extra `_acme-challenge` CNAME |
| Upload your own certificate | Not supported |
| Renewal | Automatic when 30 days of a 90-day validity remain |
| Custom domains | Trial 1, Hobby 2 per service, Pro 20 per service (can be raised) |

## Step 1: Add the domain

Open the service's **Settings**, find **Public Networking** and click **+ Custom Domain**. Type the name and pick the target port your app listens on. Railway shows two records to create:

- a `CNAME` such as `g05ns7.up.railway.app`,
- a `TXT` record used to verify ownership.

`example.com` and `www.example.com` count as two custom domains, so the Trial plan (one domain) cannot have both. Freenom domains are not supported.

## Step 2: Create the DNS records

Copy both records from the dashboard without changes. If the TXT record is missing, requests return `404` even after the CNAME resolves, because Railway checks ownership before routing.

| Name | Type | Value |
|---|---|---|
| `www` | `CNAME` | `abc123.up.railway.app` |
| as shown | `TXT` | as shown |

**Root domains.** Railway has no A record target. Your DNS provider must support CNAME flattening (Cloudflare does) or a dynamic ALIAS (DNSimple, for example). Railway lists AWS Route 53, Azure DNS, Hostinger, GoDaddy, NameSilo, Hurricane Electric and Squarespace among providers that do not. With one of those, move the zone's nameservers to a provider that flattens CNAMEs, or serve the site on `www` only.

Make sure no hostname has both an `A` and a `CNAME` record. DNS changes can take up to 72 hours to propagate.

## Step 3: Check CAA records

Existing CAA records must include Let's Encrypt. With no CAA records there is no restriction.

```dns
example.com.  3600  IN  CAA  0 issue "letsencrypt.org"
```

Look at the current policy with `dig CAA example.com` or the [CAA checker](https://ssl.sh/tools/caa-checker/).

## Step 4: Wait for the green check mark

When Railway verifies the domain, a green check mark appears next to it. Certificate issuance usually follows within an hour. Railway also shows **Cloudflare proxy detected** when the record is proxied through Cloudflare.

## Root and www on Cloudflare

On Cloudflare, Railway documents proxied CNAMEs for the root and `www`, SSL mode Full, and a Bulk Redirect from `www` to the root:

1. Add `example.com` as the custom domain in Railway.
2. In Cloudflare, add a proxied `CNAME` at `@` to the Railway value, and the `TXT` record.
3. Add a proxied `CNAME` for `www` with target `@`.
4. Set **SSL/TLS > Overview** to **Full**, not Full (Strict).
5. Enable **Universal SSL** under **SSL/TLS > Edge Certificates**.
6. Create a Bulk Redirect from `https://www.example.com` to `https://example.com` with status `301`.

Without proxying, Cloudflare does not associate the domain with your Railway project and you get `ERR_TOO_MANY_REDIRECTS`. With proxying, names deeper than one level (`*.sub.example.com`) need Cloudflare's Advanced Certificate Manager or must be set to DNS only.

## Wildcard domains

When you add `*.example.com`, Railway gives you two CNAMEs and one TXT record: one CNAME for the wildcard, one for `_acme-challenge` (Railway needs it to issue the certificate), and the TXT for ownership. All three are required. The CNAME record for `authorize.railwaydns.net` must not be proxied, so on Cloudflare keep the `_acme-challenge` record on DNS only (grey cloud) and enable Universal SSL. Wildcards work at any level (`*.sub.example.com`) but cannot be nested (`*.*.example.com`).

## Your own certificate

Railway's documentation says external SSL certificates are currently not supported. If you need a certificate from a particular CA, terminate TLS in front of Railway, for example on Cloudflare.

## Verify

The domain should present a Let's Encrypt certificate with your domain in the SAN list. Check it with the [SSL checker](https://ssl.sh/tools/ssl-checker/), or from any terminal:

```bash
curl ssl.sh/example.com
```

Then check the certificate Railway serves:

```bash
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -issuer -subject -ext subjectAltName -dates
```

A `*.up.railway.app` certificate means your domain's certificate has not been issued yet.

## Renewal

Renewal is automatic at 30 days remaining. Let's Encrypt's default lifetime falls to 64 days on February 10, 2027 and 45 days on February 16, 2028; Railway's documented 90-day figure reflects today's default. Renewal needs the same DNS as issuance, so keep the CNAME, TXT and, for wildcards, `_acme-challenge` records. Watch the domain with [ssl.sh monitoring](https://ssl.sh/monitor/) (in development).

## Troubleshooting

Start with the basics: confirm the service is deployed and running, test in a private window, flush local DNS, and wait an hour after adding the domain. Do not delete and re-add the domain repeatedly. Let's Encrypt issues at most 5 certificates for the exact same set of names in any 7-day window, so repeated retries can block issuance for days ([Let's Encrypt rate limits](https://ssl.sh/errors/lets-encrypt-rate-limit/)).

- **Certificate stuck on "Validating Challenges"**: DNS not propagated or wrong, CAA blocking Let's Encrypt, broken DNSSEC (check on dnsviz.net), or Cloudflare proxy settings. Railway's "toggle trick": set the Cloudflare record to DNS only, wait for the green check mark, then turn the proxy back on.
- **ERR_TOO_MANY_REDIRECTS**: Cloudflare is in Flexible mode; switch to Full.
- **Error 526: Invalid SSL Certificate**: Cloudflare is in Full (Strict); switch to Full.
- **Error 525: SSL Handshake Failed**: the certificate is not issued yet or provisioning had a hiccup; wait, check DNS, toggle the proxy.
- **Certificate shows `*.up.railway.app`**: the domain is not verified yet; check both records and remove conflicting `A` records.
- **Works for some users only**: old clients, corporate proxies or antivirus TLS inspection; test with `openssl s_client` from another network.
- **CAA errors**: see [CAA record prevents issuance](https://ssl.sh/errors/caa-record-prevents-issuance/). Contact Railway support if issuance is stuck for more than 72 hours.
