# Custom domains

> Serve a project on its own domain once its DNS points at your server, with a certificate Caddy obtains and renews.

Every project answers at `https://<slug>.<zone>` from its first deploy. To serve it on a domain of its own too, declare the domain, deploy, point the DNS at the server, then switch.

## Before you begin

- The owner's SSH access: switching a domain is never a token's command.
- A project that serves a page. One that only runs in the background takes no domain.
- A domain outside your zone, which the wildcard certificate already covers.

## Declare the domain

In `sitesolide.json`:

```json
{
  "slug": "shop",
  "start": "/usr/local/bin/bun run server.ts",
  "domain": { "name": "example.com", "aliases": ["example.net"] }
}
```

`aliases` is optional. A second level name, such as `example.com` or `example.net`, also answers on its `www`. An app redirects these other names to `name`, the path kept; a static site serves its pages on each. A name belongs to one project on the server.

## Deploy

```bash
sitesolide deploy
```

The server now knows the domain. The site still answers at its preview address only.

## Point the DNS at the server

At your DNS provider, create an `A` record for `example.com` with the server's IPv4 address. If the server has an IPv6 address, add an `AAAA` record with it too, as `setup` does for your zone.

Point `www.example.com` and each alias the same way. The CLI checks `name` alone; the other names answer once they resolve to the server.

## Switch to the domain

```bash
sitesolide domain --activate
```

It sets `"active": true` in `sitesolide.json`, puts the manifest on the server and authorizes the domain's certificate. Caddy obtains the certificate on the first HTTPS request, then renews it. Commit `sitesolide.json`, or a later deploy brings back the inactive state.

> [!WARNING]
> `--activate` refuses a domain that does not resolve to the server yet. `--force` switches anyway, and each certificate the authority refuses counts against the name: a few can block it for a week.

## Check it worked

```bash
sitesolide domain
```

```text
-> domain of shop
   declared   example.com (aliases: example.net)
   manifest   active
   table      present
   dns        points to 203.0.113.10
   https      200
```

## Access on the domain

The domain opens as the preview does: Public, Restricted or Anyone with the code. On a closed site, `--activate` first checks that Caddy will close the domain too, and says what to run when it would not. The preview address keeps answering, and tells search engines not to index it; the domain does not.

## Go back to the preview

```bash
sitesolide domain --deactivate
```

Commit `sitesolide.json` again.

## Next steps

- [Access and sign-in](access.md): choose who opens the site, on every address.
- [Monitoring](monitoring.md): hear when a site or a certificate fails.

Full reference: https://github.com/cthiriet/sitesolide/blob/main/docs/manifest.md#domain
