Skip to content

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-edge at 192.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/Caddyfile at 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.178last.vet (or a suitable FQDN under last.vet)
  • 98.186.224.186last1.enterprises (or a suitable FQDN under last1.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.

  1. Confirm Caddy configsudo caddy validate --config /etc/caddy/Caddyfile.pending
  2. Confirm NAT/port-forward on downstream firewall (IP-1 at minimum for LastVet staging test)
  3. Activate configsudo mv /etc/caddy/Caddyfile.pending /etc/caddy/Caddyfile (or copy if keeping a backup)
  4. Enable and start Caddysudo systemctl enable --now caddy
  5. Verify Let's Encrypt — check journalctl -u caddy and that certs exist under /var/lib/caddy/.local/share/caddy/certificates/ (or Caddy logs)
  6. Verify HTTPS to backendscurl -sS https://api-staging.last.vet/health from outside the LAN (while DNS still points at tunnel OR via /etc/hosts override to 98.186.224.178 for pre-DNS test)
  7. Update DNS A records — point api-staging.last.vet and api.last.vet from cloudflared CNAME to 98.186.224.178
  8. Wait for propagation — confirm public resolvers return A records to 98.186.224.178
  9. End-to-end verify — public HTTPS reaches LastVet API via static IP path
  10. Retire cloudflaredsudo systemctl stop cloudflared && sudo systemctl disable cloudflared
  11. Delete tunnel — remove tunnel lastvet-r940 (ID 4c8550f2-2156-4284-b9f7-60cdc0fdc109) from Cloudflare Zero Trust
  12. Rotate secrets — delete or rotate LASTVET_R940_CLOUDFLARED_* entries in Bitwarden (lastvet project)

Rollback

If cutover fails after DNS change:

  1. Revert DNS A records to grey-cloud CNAME → *.cfargotunnel.com (or prior ALB if applicable)
  2. sudo systemctl stop caddy && sudo systemctl disable caddy
  3. Restore /etc/caddy/Caddyfile.pending if live config was promoted
  4. sudo systemctl enable --now cloudflared
  5. Verify staging health via tunnel path before closing incident