Skip to content

Latest commit

 

History

History
109 lines (73 loc) · 4.81 KB

File metadata and controls

109 lines (73 loc) · 4.81 KB

Phase 12 — Automating remote networking gaps

This doc maps the three remaining “go to sea” checks to automation tiers. Phase 11 covered Docker-bridge negatives; Phase 12 closes TLS, gRPC in CI, and remote/Tailscale as far as GitHub-hosted runners allow.

Summary

Gap Automate in CI? What we ship
TLS Yes (weekly + local) Caddy + mesh-lab-tls-certs.sh + mesh-lab-verify-tls.sh
gRPC transport Yes (every PR via PrimeTime) Nexo.Tests.Transport Category=ProdStyle + optional dedicated workflow
Two-host / Tailscale Partial mesh-lab-verify-remote.sh + self-hosted runner recipe

1. TLS (automated)

Idea: Nexo stays HTTP on peer-a:8080; Caddy terminates HTTPS on the lab bridge (docker-compose.mesh-lab-tls.override.yml).

make mesh-lab-e2e-tls
# or:
./scripts/run-mesh-lab-e2e-tls.sh

mesh-lab-verify-tls.sh checks:

  • GET https://127.0.0.1:18443/health (self-signed cert; -k unless MESH_LAB_TLS_CACERT set; HTTP/1.1 for macOS LibreSSL)
  • GET/POST /api/mesh/* over HTTPS (register, schedule → Assigned)
  • Mutating mesh without API key → 401/403

CI: .github/workflows/mesh-lab-tls-gate.yml — weekly + workflow_dispatch.

Production parity: Replace self-signed certs with real DNS + ACME (friend-mesh.Caddyfile.example); same curl paths, trust store from Let’s Encrypt.

Local macOS note: Host curl (LibreSSL) against Docker-published HTTPS can fail with bad decrypt; mesh-lab-tls-curl.sh retries via OpenSSL curl in a container (host.docker.internal). CI on ubuntu-latest uses host curl directly.


2. gRPC (automated in test matrix)

Idea: GrpcAgentTransportTests already spin a real Kestrel gRPC server (GrpcServerFixture) — not mocks.

Ensure CI runs Transport:

dotnet test src/Nexo.Tests.Transport/Nexo.Tests.Transport.csproj --filter "Category=ProdStyle"
# or full prime-time:
make test-prime-time

Optional dedicated gate: .github/workflows/grpc-transport-gate.yml — fast, no Docker.

No extra hardware required.


3. Tailscale / two-host (semi-automated)

GitHub ubuntu-latest is a single host; it cannot join your production tailnet without secrets and a second node. Automate in three layers:

Layer A — Remote URL script (any laptop)

Deploy mesh lab (or friend-mesh) on machine A; run worker on machine B. From a third machine or CI runner with routes:

export NEXO_MESH_DIRECTOR_BASE_URL=https://100.64.0.1:8080   # director tailnet IP
export NEXO_MESH_API_KEY=...
export MESH_LAB_PEER_REGISTRATION_KEY=...                    # ≠ API key
export MESH_LAB_REMOTE_WORKER_URL=http://100.64.0.2:8080    # worker tailnet IP
export NEXO_MESH_TLS_INSECURE=1                              # if using self-signed TLS
./scripts/mesh-lab-verify-remote.sh

Layer B — Self-hosted GitHub Actions runner on tailnet

  1. Install runner on a host that is always on tailnet.
  2. Register runner with label nexo-tailnet.
  3. Workflow uses runs-on: [self-hosted, nexo-tailnet] + tailscale/github-action only if the runner is not already on the tailnet.
  4. Job runs mesh-lab-verify-remote.sh against secrets:
    • NEXO_MESH_DIRECTOR_BASE_URL
    • NEXO_MESH_API_KEY
    • MESH_LAB_REMOTE_WORKER_URL

Layer C — Scheduled smoke from your cloud VM

Reuse scripts/bootstrap-cloud-mesh-lab.sh on a VM with Tailscale installed; second peer is a laptop also on tailnet. Document IPs in .env and run remote verify from the VM cron.

What we do not fake in Docker: true cross-NAT tailnet ACLs — use real Tailscale for that.


Recommended CI schedule (networking)

Workflow When Covers
mesh-lab-gate.yml PR Bridge HTTP + negatives + persistence + Phase 13 data plane
mesh-lab-stress-gate.yml Weekly Stress + post-stress
mesh-lab-tls-gate.yml Weekly HTTPS director
grpc-transport-gate.yml PR gRPC Kestrel round-trip
friend-mesh-prefab-gate.yml PR Single-hub auth smoke
PrimeTime test-prime-time Pre-release Transport + full ProdStyle

Revision history

Date Change
2026-05-19 TLS override + remote verify script + automation doc.