Cox static IP ingress (LastVet edge)¶
Future public HTTPS ingress for LastVet and related non-PHI platforms via Cox Business static IPs on lastvet-edge. Prep and runbook only. Cloudflared remains the active ingress until cutover is executed deliberately.
Cox CPE: Technicolor CVA4004COX1 (modem only)¶
Ryan's Cox Business CPE is a Technicolor CVA4004COX1 cable modem, not a NAT gateway. Cox's CVA4004 self-install guide instructs: connect Ethernet from the modem to the WAN/Internet port on your router. The Vantiva datasheet lists routing mode transparent bridging only (single 2.5G Ethernet port, no WiFi, no DHCP server, no port-forward UI).
Implication: Port forwarding and multi-static NAT are configured on whatever sits downstream of the modem (current LAN router, or Netgate 5200 when it arrives in September). The CVA4004 cannot forward 443 → lastvet-edge.
| Topic | CVA4004 behavior |
|---|---|
| Port forwarding | Not available on modem |
| Bridge mode | Already bridged; no user toggle |
| LAN DHCP | None; no factory 192.168.x.x subnet on modem |
| Admin UI | Label URL/credentials on device bottom; modem status only. Often requires direct Ethernet; label creds may not work (forum report). Not 192.168.0.1 gateway admin. |
| Firmware | Cox-provisioned; no public version pin for CVA4004COX1 |
R940 VMs live on 192.168.1.x, which confirms a separate downstream router is already in path. Cox Business 4131/4332 gateways default to 192.168.0.0/24; that does not conflict with 192.168.1.x when the modem is bridged and the downstream firewall owns the LAN.
Target architecture (September Netgate 5200)¶
Internet ── coax ── CVA4004 (bridge modem)
└── Ethernet ── Netgate 5200 WAN (98.186.224.178/28, gw .177)
├── VIP: 98.186.224.186
├── NAT: .178:443 → 192.168.1.89:443
├── NAT: .186:443 → 192.168.1.89:443
└── LAN 192.168.1.0/24 → R940 VMs
└── Caddy on lastvet-edge (hostname routing)
Until Netgate is in place, configure the same NAT rules on the current downstream router/firewall.
Forwarding both public IPs' port 443 to the same LAN host is normal; the Cox-forum limitation applies only when forwarding the same port to two different LAN devices on one public IP.
Static IP assignments (fulfilled)¶
Cox Business /28 block (verify in MyAccount → View IP Addresses):
| Role | Address |
|---|---|
| Gateway | 98.186.224.177 |
| Netmask | /28 (255.255.255.240) |
| IP-1 (LastVet) | 98.186.224.178 |
| IP-2 (non-PHI) | 98.186.224.186 |
| IP | Purpose | Reverse DNS (PTR) |
|---|---|---|
98.186.224.178 |
LastVet (*.last.vet API hostnames) |
last.vet |
98.186.224.186 |
Non-PHI platform hostnames (Angel, Sovereign, Meridian, etc.) | last1.enterprises |
Confirm MyAccount values match before cutover. Cox must route the CIDR to the account; if static WAN on a downstream firewall fails, verify provisioning with Cox Business support.
Edge stack on lastvet-edge¶
- Host:
lastvet-edgeat192.168.1.89(ingress / Caddy listener) - Caddy (installed, not running): TLS termination with Let's Encrypt, hostname-based reverse proxy.
- Pending config:
/etc/caddy/Caddyfile.pending(not loaded until renamed to/etc/caddy/Caddyfileat cutover). - cloudflared: current production ingress; do not change until cutover checklist completes.
Backend targets (LAN, unchanged):
| Hostname | Backend |
|---|---|
api-staging.last.vet |
http://192.168.1.90:3000 |
api.last.vet |
http://192.168.1.90:3001 |
Caddy terminates TLS on .89 and reverse-proxies to the API VM on .90.
Port-forward / NAT requirements (downstream firewall)¶
Configure on the device downstream of the CVA4004 (not on the modem). Target LAN host for HTTPS ingress: 192.168.1.89 (lastvet-edge).
IP-1 (98.186.224.178, LastVet)¶
| Protocol | WAN port | Destination |
|---|---|---|
| TCP | 80 | 192.168.1.89:80 (HTTP-01 challenge or redirect to HTTPS) |
| TCP | 443 | 192.168.1.89:443 |
IP-2 (98.186.224.186, non-PHI)¶
| Protocol | WAN port | Destination |
|---|---|---|
| TCP | 80 | TBD: 192.168.1.89 alternate listener or separate VM (Ryan decides) |
| TCP | 443 | Same as port 80 target |
On Netgate/pfSense: assign the /28 on WAN (one address + gateway, others as VIPs), then create per-public-IP NAT port-forward rules. Caddy on lastvet-edge listens on :443 (and :80 for ACME). If IP-2 terminates on a different host, that host runs its own Caddy or ingress stack.
DNS changes (at cutover)¶
All records grey-cloud (proxied=false).
| Hostname | Type | Value |
|---|---|---|
api-staging.last.vet |
A | 98.186.224.178 |
api.last.vet |
A | 98.186.224.178 |
| Future Angel / Sovereign / Meridian hostnames | A | 98.186.224.186 |
Remove CNAME targets to *.cfargotunnel.com when cutting over LastVet API hostnames.
Reverse DNS¶
Request PTR records from Cox Business for each static IP:
98.186.224.178→last.vet(or a suitable FQDN underlast.vet)98.186.224.186→last1.enterprises(or a suitable FQDN underlast1.enterprises)
PTR alignment improves deliverability and operational clarity; not strictly required for Let's Encrypt HTTP-01.
Cutover sequence (future execution)¶
Execute in order. Do not skip verification steps.
- Confirm Caddy config —
sudo caddy validate --config /etc/caddy/Caddyfile.pending - Confirm NAT/port-forward on downstream firewall (IP-1 at minimum for LastVet staging test)
- Activate config —
sudo mv /etc/caddy/Caddyfile.pending /etc/caddy/Caddyfile(or copy if keeping a backup) - Enable and start Caddy —
sudo systemctl enable --now caddy - Verify Let's Encrypt — check
journalctl -u caddyand that certs exist under/var/lib/caddy/.local/share/caddy/certificates/(or Caddy logs) - Verify HTTPS to backends —
curl -sS https://api-staging.last.vet/healthfrom outside the LAN (while DNS still points at tunnel OR via/etc/hostsoverride to98.186.224.178for pre-DNS test) - Update DNS A records — point
api-staging.last.vetandapi.last.vetfrom cloudflared CNAME to98.186.224.178 - Wait for propagation — confirm public resolvers return A records to
98.186.224.178 - End-to-end verify — public HTTPS reaches LastVet API via static IP path
- Retire cloudflared —
sudo systemctl stop cloudflared && sudo systemctl disable cloudflared - Delete tunnel — remove tunnel
lastvet-r940(ID4c8550f2-2156-4284-b9f7-60cdc0fdc109) from Cloudflare Zero Trust - Rotate secrets — delete or rotate
LASTVET_R940_CLOUDFLARED_*entries in Bitwarden (lastvetproject)
Rollback¶
If cutover fails after DNS change:
- Revert DNS A records to grey-cloud CNAME →
*.cfargotunnel.com(or prior ALB if applicable) sudo systemctl stop caddy && sudo systemctl disable caddy- Restore
/etc/caddy/Caddyfile.pendingif live config was promoted sudo systemctl enable --now cloudflared- Verify staging health via tunnel path before closing incident
Related docs¶
- Bitwarden naming convention
- R940 MagicDNS inter-service naming (PR #13)
- Cox Business 4332 / static IP gateway guide (reference only; Ryan's CPE is CVA4004 modem, not 4332)