# Add a custom domain to your app with automatic HTTPS Add a custom domain to your app: create the A record, add the name in ox, and Caddy gets and renews the HTTPS certificate. What each domain status means. To add a custom domain with HTTPS, create an A record for the name that points at your server's IP, then add the name on the project's Settings tab or with `ox domains add `. Caddy on your server gets a free certificate for it and renews it by itself, so there is nothing to install or renew by hand. ## Add a custom domain **Create the DNS record first** (the next section), then add the name to ox. In the dashboard, open the project's **Settings** tab, type the name in the **Domains** card and press **Add**. From a terminal: Add a domain: ```sh ox domains shop add shop.example.com --wait ``` Adding a domain saves it and redeploys the app so the server starts serving the name. `ox domains shop remove shop.example.com` takes one off again. You can also list names in ox.toml with `domains = ["shop.example.com"]` ([top-level keys](https://deploywithox.com/docs/config#top-level)). For production, the names in ox.toml come first and the ones you add in ox come after; the list marks each name from ox.toml, and you remove those by editing the file. Staging and previews never take production's ox.toml names. ## Point the domain at your server with an A record At your DNS provider, create an **A record** for the name with your server's IP address as the value. The Domains card shows it: `Then create an A record pointing at `, and an AAAA record when the server has an IPv6 address. `ox domains shop` prints the same: ox domains shop: ```text Point each domain's A record at 203.0.113.7. ``` For a whole site at the root, like `example.com`, the record's name is usually `@`. When `www.example.com` also points at the server, ox sends it to `example.com` with a permanent redirect; list `www.example.com` as a domain yourself if you want it served instead. ## How the HTTPS certificate is issued Caddy, the web server ox puts on your server, gets a free certificate for each domain and renews it before it runs out. You do nothing. To prove the name is yours, the certificate authority connects to the name on ports 80 and 443, so the name must already point at your server. Until it does, there is no certificate, and Caddy tries again by itself. That is why the record comes first. If you, or ox's check, look the name up before the record exists, a DNS resolver can remember the answer **no such name** for a while, often from a few minutes up to an hour, and keep giving it after you create the record. Creating the record before anyone looks the name up avoids that wait. Ports 80 and 443 must be open to the internet. If your cloud provider has a firewall in front of the server, open them there. Staging and branch previews can get HTTPS names too, under a [preview domain](https://deploywithox.com/docs/operate/previews#preview-domain). ## What each domain status means ox checks each name at a public DNS resolver about every 30 seconds, and the row shows what it found: | The row says | It means | | --- | --- | | **checking DNS…** | The first lookup has not come back yet. | | **waiting for DNS** | The name has no address yet. Create the A record, or wait for it to spread. | | **points elsewhere** | The name has an address, but not your server's. Change the record. | | **HTTPS on** | The name points at your server, so the server can get its certificate. | | **Cloudflare** | Cloudflare's proxy is in front, which hides where the name points. In Cloudflare, set its A record to your server's IP. | | **No certificate** | Cloudflare's proxy has no certificate for the name. | The row turns green by itself once the record resolves; you do not have to add the domain again. ## If the custom domain does not work - **The row stays on waiting for DNS:** check the record's name and type at your DNS provider. A new record can take a while to reach every resolver, longer if the name was looked up before it existed. - **points elsewhere:** the name still points at an old host. The row says `It resolves to , not this server.` with the record to set. - **No certificate behind Cloudflare:** a name two levels deep, like `a.b.example.com`, is not covered by Cloudflare's free certificate. Set the record to DNS only, so your server gets its own, or add a certificate for it in Cloudflare. - **The browser warns about the certificate:** the name has pointed at the server only for a moment, or ports 80 and 443 are closed in a firewall in front of it. Open them and give Caddy a minute. [Troubleshooting](https://deploywithox.com/docs/troubleshooting#domain-not-working) has the same steps in short. Last updated 2026-10-08. The page as HTML: https://deploywithox.com/docs/operate/domains