# GoDaddy DNS Setup — bytelyst.com

This runbook tracks the manual DNS changes for `bytelyst.com` in GoDaddy for the current ByteLyst Azure VM architecture.

Related docs:

- [`CODEX_PROMPTS_TRACK_A_AZURE_VM.md`](/opt/bytelyst/learning_ai_common_plat/docs/devops/vercel/CODEX_PROMPTS_TRACK_A_AZURE_VM.md)
- [`TRACK_A_HANDOFF_2026-03-29.md`](/opt/bytelyst/learning_ai_common_plat/docs/devops/vercel/TRACK_A_HANDOFF_2026-03-29.md)
- [`README.md`](/opt/bytelyst/learning_ai_common_plat/docs/devops/single_azure_vm/docker/README.md)

## Target Architecture

For the current internal-on-VM setup, these hostnames should point to the Azure VM public IP:

| Hostname               | Type | Target                 | Purpose                                      |
| ---------------------- | ---- | ---------------------- | -------------------------------------------- |
| `api.bytelyst.com`     | `A`  | `<Azure VM public IP>` | Public backend API gateway through Caddy     |
| `gitea.bytelyst.com`   | `A`  | `<Azure VM public IP>` | Gitea and private npm registry through Caddy |
| `admin.bytelyst.com`   | `A`  | `<Azure VM public IP>` | Internal admin dashboard                     |
| `tracker.bytelyst.com` | `A`  | `<Azure VM public IP>` | Internal tracker dashboard                   |
| `llmlab.bytelyst.com`  | `A`  | `<Azure VM public IP>` | LLM Lab Mission Control dashboard on the VM  |
| `ollama.bytelyst.com`  | `A`  | `<Azure VM public IP>` | Ollama HTTPS endpoint for cross-VM clients   |

Recommended temporary TTL during cutover:

- `600` seconds or lower while changes are propagating

Notes:

- `localmemgpt-web` is intended to be hosted on Vercel, so it is not part of this VM DNS runbook
- `llmlab-dashboard` runs on VM port `3075`; if you expose it publicly, route it through Caddy instead of exposing `3075` directly
- `ollama.bytelyst.com` should be restricted to trusted clients such as sibling VMs, VPN users, or an IP allowlist

## Automated Option

If GoDaddy API credentials are already configured, use the repo script instead of editing records by hand:

```bash
./scripts/godaddy-sync-bytelyst-dns.sh --ip <Azure VM public IP> --validate
```

Or auto-detect the current machine public IP:

```bash
./scripts/godaddy-sync-bytelyst-dns.sh --auto-ip --dry-run
./scripts/godaddy-sync-bytelyst-dns.sh --auto-ip --validate
```

Credential lookup order:

- `GODADDY_API_KEY` and `GODADDY_API_SECRET`
- `~/.config/godaddypy/credentials.yaml`

The script manages these `A` records by default:

- `api`
- `gitea`
- `admin`
- `tracker`
- `llmlab`
- `ollama`

Root shortcut:

```bash
pnpm dns:godaddy:bytelyst -- --ip <Azure VM public IP> --validate
```

## Current Status

Status as of `2026-03-31 10:12:25 UTC`:

- GoDaddy `A` records were updated for `api`, `gitea`, `admin`, `tracker`, `llmlab`, and `ollama`
- all six hostnames should resolve publicly to `187.124.159.82`
- the VM now serves `80` and `443` through the `caddy` container
- Let's Encrypt certificates were issued successfully for all six hostnames, including `ollama.bytelyst.com`
- live HTTPS verification from inside the VM-level Caddy path returned:
  - `api.bytelyst.com` -> `HTTP/1.1 200 OK`
  - `gitea.bytelyst.com` -> `HTTP/1.1 200 OK`
  - `admin.bytelyst.com` -> `HTTP/1.1 200 OK`
  - `tracker.bytelyst.com` -> `HTTP/1.1 200 OK`
  - `llmlab.bytelyst.com` -> `HTTP/1.1 200 OK`
  - `ollama.bytelyst.com/api/version` -> `HTTP/2 200`
  - `ollama.bytelyst.com/api/version` body -> `{"version":"0.18.0"}`

Interpretation:

- DNS cutover is complete
- the VM-side HTTPS gateway issue is fixed
- remaining work, if any, is app-specific hardening and access-control tightening rather than DNS or TLS bring-up

## Preconditions

- You know the current Azure VM public IP.
- Ports `80` and `443` are allowed by the Azure NSG.
- Caddy is configured on the VM for the target hostnames.
- You are editing DNS in the authoritative GoDaddy zone for `bytelyst.com`.

## GoDaddy Steps

1. Sign in to GoDaddy.
2. Open `My Products`.
3. Under `Domains`, find `bytelyst.com`.
4. Click `DNS`.
5. In the `Records` section, create or update these `A` records:

| Name      | Type | Value                  | TTL   |
| --------- | ---- | ---------------------- | ----- |
| `api`     | `A`  | `<Azure VM public IP>` | `600` |
| `gitea`   | `A`  | `<Azure VM public IP>` | `600` |
| `admin`   | `A`  | `<Azure VM public IP>` | `600` |
| `tracker` | `A`  | `<Azure VM public IP>` | `600` |
| `llmlab`  | `A`  | `<Azure VM public IP>` | `600` |
| `ollama`  | `A`  | `<Azure VM public IP>` | `600` |

6. Save each record.
7. Remove or correct any conflicting `A`, `CNAME`, or forwarding records for the same names.

## Validation

Run these from the VM after saving the records:

```bash
dig +short api.bytelyst.com
dig +short gitea.bytelyst.com
dig +short admin.bytelyst.com
dig +short tracker.bytelyst.com
dig +short llmlab.bytelyst.com
dig +short ollama.bytelyst.com
curl -sf https://api.ipify.org && echo
```

Expected result:

- all six hostnames resolve to the same Azure VM public IP
- the resolved IP matches the output from `https://api.ipify.org`

After DNS resolves correctly, validate HTTPS:

```bash
curl -sI https://api.bytelyst.com/platform/health | head -5
curl -sI https://gitea.bytelyst.com | head -5
curl -sI https://admin.bytelyst.com | head -5
curl -sI https://tracker.bytelyst.com | head -5
curl -sI https://llmlab.bytelyst.com | head -5
curl -sI https://ollama.bytelyst.com/api/version | head -5
```

Expected result:

- valid TLS responses from Caddy
- `200`, `302`, or auth-gated responses are acceptable depending on the app
- `ollama.bytelyst.com/api/version` should return `200`
- certificate issuance should complete automatically once DNS and ports are correct

## Next Action For Codex On The VM

The original VM handoff in this section has already been completed. Use this only if records drift or the VM ingress needs to be rebuilt.

Recommended handoff summary:

- DNS is already correct for `api.bytelyst.com`, `gitea.bytelyst.com`, `admin.bytelyst.com`, `tracker.bytelyst.com`, `llmlab.bytelyst.com`, and `ollama.bytelyst.com`
- all six names point to `187.124.159.82`
- Caddy is already serving valid TLS for all six names
- do not spend time redoing GoDaddy changes unless records drift
- focus future work on access control and client integration rather than basic DNS/TLS bring-up

Run these on the VM:

```bash
cd /opt/bytelyst/learning_ai_common_plat

docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
docker logs caddy --tail 200
docker exec caddy caddy validate --config /etc/caddy/Caddyfile
sudo ss -ltnp | grep -E ':80|:443'

curl -sI http://localhost:3001 | head -5
curl -sI http://localhost:3003 | head -5
curl -sI http://localhost:3300 | head -5
curl -sI http://localhost:4003/health | head -5
curl -sI http://localhost:3075 | head -5
```

Check the live Caddy config:

```bash
sed -n '1,220p' /opt/bytelyst/Caddyfile
```

The live Caddy config should cover at least these hostnames:

- `api.bytelyst.com`
- `gitea.bytelyst.com`
- `admin.bytelyst.com`
- `tracker.bytelyst.com`
- `llmlab.bytelyst.com`
- `ollama.bytelyst.com`

Expected proxy targets:

- `api.bytelyst.com`:
  - `/platform/*` -> `platform-service:4003`
  - `/extraction/*` -> `extraction-service:4005`
  - `/mcp/*` -> `mcp-server:4007`
- `gitea.bytelyst.com` -> host or container endpoint for Gitea on port `3300`
- `admin.bytelyst.com` -> `admin-web:3001`
- `tracker.bytelyst.com` -> `tracker-web:3003`
- `llmlab.bytelyst.com` -> `llmlab-dashboard:3075`
- `ollama.bytelyst.com` -> `172.17.0.1:11434`

If the file is missing host blocks, update it and reload Caddy:

```bash
docker exec caddy caddy reload --config /etc/caddy/Caddyfile
docker logs caddy --tail 100
```

If `443` still times out after Caddy config is corrected:

- verify the Azure NSG allows inbound `443/tcp`
- verify no other process is conflicting with port `443`
- verify the `caddy` container actually publishes `0.0.0.0:443->443/tcp`

Re-test from the VM:

```bash
curl -vk https://api.bytelyst.com/platform/health
curl -vk https://gitea.bytelyst.com
curl -vk https://admin.bytelyst.com
curl -vk https://tracker.bytelyst.com
curl -vk https://llmlab.bytelyst.com
curl -vk https://ollama.bytelyst.com/api/version
```

Ready-to-paste prompt for the Codex session running inside the VM:

```text
The GoDaddy DNS cutover is already complete. Do not redo DNS unless records drift.

Known-good DNS state as of 2026-03-31:
- api.bytelyst.com -> 187.124.159.82
- gitea.bytelyst.com -> 187.124.159.82
- admin.bytelyst.com -> 187.124.159.82
- tracker.bytelyst.com -> 187.124.159.82
- llmlab.bytelyst.com -> 187.124.159.82
- ollama.bytelyst.com -> 187.124.159.82

Known-good HTTPS state:
- https://api.bytelyst.com/platform/health -> 200
- https://gitea.bytelyst.com -> 200
- https://admin.bytelyst.com -> 200
- https://tracker.bytelyst.com -> 200
- https://llmlab.bytelyst.com -> 200
- https://ollama.bytelyst.com/api/version -> 200 with {"version":"0.18.0"}

Your task:
1. Inspect the live VM deployment under /opt/bytelyst
2. Read /opt/bytelyst/Caddyfile
3. Verify the caddy container is running and publishing 80/443
4. Verify Azure-side access assumptions from inside the VM as far as possible
5. Fix the live Caddy config so these hosts are served:
   - api.bytelyst.com
   - gitea.bytelyst.com
   - admin.bytelyst.com
   - tracker.bytelyst.com
   - llmlab.bytelyst.com
6. Ensure proxy targets are correct:
   - api.bytelyst.com:
     - /platform/* -> platform-service:4003
     - /extraction/* -> extraction-service:4005
     - /mcp/* -> mcp-server:4007
   - gitea.bytelyst.com -> Gitea on port 3300
   - admin.bytelyst.com -> admin-web:3001
   - tracker.bytelyst.com -> tracker-web:3003
   - llmlab.bytelyst.com -> llmlab-dashboard:3075
   - ollama.bytelyst.com -> 172.17.0.1:11434
7. Reload Caddy
8. Verify:
   - curl -vk https://api.bytelyst.com/platform/health
   - curl -vk https://gitea.bytelyst.com
   - curl -vk https://admin.bytelyst.com
   - curl -vk https://tracker.bytelyst.com
   - curl -vk https://llmlab.bytelyst.com
   - curl -vk https://ollama.bytelyst.com/api/version

Run these first:

cd /opt/bytelyst/learning_ai_common_plat
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
docker logs caddy --tail 200
docker exec caddy caddy validate --config /etc/caddy/Caddyfile
sudo ss -ltnp | grep -E ':80|:443'
sed -n '1,220p' /opt/bytelyst/Caddyfile
curl -sI http://localhost:3001 | head -5
curl -sI http://localhost:3003 | head -5
curl -sI http://localhost:3300 | head -5
curl -sI http://localhost:4003/health | head -5
curl -sI http://localhost:3075 | head -5
curl -s http://127.0.0.1:11434/api/version

If /opt/bytelyst/Caddyfile is missing host blocks, fix it there and reload:

docker exec caddy caddy reload --config /etc/caddy/Caddyfile
docker logs caddy --tail 100

If 443 still times out after the config fix:
- verify Azure NSG allows inbound 443/tcp
- verify no other process is bound to 443
- verify the caddy container publishes 0.0.0.0:443->443/tcp

When done, report:
- what was wrong
- what file(s) you changed
- exact verification results for all four public hostnames
- exact verification results for all six public hostnames
```

## Troubleshooting

If records do not resolve as expected:

- verify that GoDaddy is the authoritative DNS provider for `bytelyst.com`
- check for duplicate records for `api`, `gitea`, `admin`, or `tracker`
- check for duplicate records for `api`, `gitea`, `admin`, `tracker`, or `llmlab`
- wait for propagation and retry with low TTL still in place
- confirm Azure NSG allows inbound `80` and `443`
- confirm Caddy is running and reachable on the VM

Useful checks:

```bash
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' | grep -E 'caddy|admin-web|tracker-web|platform-service'
docker logs caddy --tail 100
```

Likely root causes if this breaks again:

- the live `/opt/bytelyst/Caddyfile` only included `api.bytelyst.com`
- `gitea`, `admin`, `tracker`, and `llmlab` host blocks had not been added on the VM
- `ollama.bytelyst.com` was added after initial DNS cutover and needed a second ACME retry after DNS propagation
- the legacy Traefik `gateway` container was still holding port `80`
- the `caddy` container was defined in compose but not running, so nothing was bound to `443`

## Change Log

Use this section to record real DNS cutovers:

| Date         | Operator | Change                                                                                                                         | Result         |
| ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------- |
| `2026-03-31` | Codex    | Created GoDaddy-specific DNS runbook for `bytelyst.com`                                                                        | Document added |
| `2026-03-31` | Codex    | Switched live VM ingress from legacy gateway to Caddy and validated HTTPS for `api`, `gitea`, `admin`, `tracker`, and `llmlab` | HTTPS fixed    |

| Date         | Operator | Change                                                                                               | Result               |
| ------------ | -------- | ---------------------------------------------------------------------------------------------------- | -------------------- |
| `2026-03-31` | Codex    | Created GoDaddy-specific DNS runbook for `bytelyst.com`                                              | Document added       |
| `2026-03-31` | Codex    | Updated GoDaddy `A` records for `api`, `gitea`, `admin`, `tracker`, `llmlab`, and `ollama` to `187.124.159.82` | DNS cutover complete |
| `2026-03-31` | Codex    | Restarted Caddy after `ollama` DNS propagation and verified live HTTPS for `ollama.bytelyst.com/api/version`     | HTTPS fixed          |
