The brief picks the standards (WireGuard, ICE/STUN/TURN, OIDC, OPA, coturn, OpenTelemetry). This document picks the implementation language and libraries that realize them. The scope target is a single user reaching their own machines from anywhere; the stack choices still scale up to the full multi-user brief without rework.
| Concern | Choice |
|---|---|
| Language | Go 1.23+ |
| HTTP router | net/http (stdlib ServeMux with 1.22+ method patterns) |
| Identity | authentication.unlikeotherai.com — see sso.md |
| JWT verification | github.com/golang-jwt/jwt/v5 (HS256, shared secret) |
| WireGuard control | golang.zx2c4.com/wireguard/wgctrl (wgctrl-go) |
| ICE / NAT traversal | github.com/pion/ice/v3 |
| STUN / TURN relay | coturn (external process, TURN REST API credentials) |
| Policy engine | github.com/open-policy-agent/opa/rego (embedded) |
| Durable store | PostgreSQL via github.com/jackc/pgx/v5 |
| Migrations | github.com/golang-migrate/migrate/v4 |
| Ephemeral store | Redis via github.com/redis/go-redis/v9 |
| Observability | OpenTelemetry Go SDK + OTLP exporter |
| Structured logging | log/slog (stdlib) with OTel bridge |
| OpenAPI codegen | github.com/oapi-codegen/oapi-codegen/v2 |
| Lint | golangci-lint |
| Test | go test, testify/require, dockertest for integration |
| Container | Distroless static-debian12 multi-stage image |
- Ecosystem alignment. Every moving part in the brief has a first-class
Go implementation —
wgctrl-gois the canonical WireGuard control library,pion/iceis the reference ICE stack, OPA embeds natively throughregowith no IPC, and the OTel Go SDK is stable. - Operational fit. The server is a long-running daemon coordinating
network state. Go's static single-binary deployment, low idle footprint,
goroutine concurrency, and mature
net/httpmake this the boring correct choice. - Repo layout. The
/cmd/…,/internal/…,/migrationslayout in the brief is idiomatic Go and maps 1:1 to Go module conventions. - Rejected alternatives.
- Rust (axum/tower): safer and faster, but slower to iterate, no first-class WireGuard control bindings, and ICE/TURN tooling lags Go. Overkill for the single-user MVP and for future scaling.
- Node/TypeScript: matches the existing helper orchestrator but has no native WireGuard control, poor ICE story, and significantly worse fit for long-running low-level networking work.
Mapping each brief component to its concrete implementation:
- Control API (§1) —
net/httpstdlib mux, handlers ininternal/adminand feature-specificinternal/*packages. OpenAPI spec inapi/openapi/openapi.yaml; server types generated viaoapi-codegen. - Identity adapter (§2) —
internal/auth. Verifies UOA access tokens (HS256 JWT) withgolang-jwt/jwt/v5, mints short-lived internal session tokens (also HS256 JWT, separate secret), maps UOAsub/email into the internalUserprincipal. Details in sso.md. - Device bootstrap & registry (§3) —
internal/bootstrap,internal/devices. Single-use bootstrap tokens stored in Postgres with short TTL; device record stores WireGuard public key only (never private). - Service catalog (§4) —
internal/services. Devices POST manifests on heartbeat. - Tunnel coordinator (§5) —
internal/tunnel. Useswgctrl-goto configure a server-side WireGuard interface if the server itself joins the overlay; otherwise emits peer config fragments to devices. Overlay IP allocation from a configurable CIDR, persisted in Postgres. - Session broker (§6) —
internal/sessions. State machine in Go; candidate buffers in Redis with per-session TTL; policy check inline before candidate exchange begins. - NAT traversal (§7) —
internal/nat. Delegates to coturn for STUN and TURN. Control plane mints short-lived TURN credentials using the long-term-credential HMAC scheme coturn supports (TURN REST API draft), tracks allocations via coturn's Redis backend for audit. - Policy engine (§8) —
internal/policy. Embeds OPA viaopa/rego.New(...).PrepareForEval(...). Policies live as.regofiles underinternal/policy/rules/. Single-user MVP ships one rule:allow if input.subject.sub == data.owner_sub. - Audit log (§9) —
internal/audit. Append-only Postgres tableaudit_eventswith HMAC-chainedprev_hashfor tamper evidence. Correlation ID = OTel trace ID. - Observability (§10) —
internal/telemetry. OTel tracer + meter providers initialized at startup, OTLP gRPC exporter,log/sloghandler attaches trace IDs to every line. - Persistence (§11) —
internal/store. Postgres for durable state viapgx/v5(no ORM; queries in.sqlfiles compiled withsqlcif it earns its keep later). Redis for ephemeral state viago-redis. - Admin surface (§12) —
internal/admin. Same HTTP server, separate route group, protected by the same session token with anadminclaim.
- PostgreSQL 16+ — durable state. Single database for the MVP; schemas
by concern (
auth,devices,sessions,audit,policy). - Redis 7+ — ephemeral state only. Heartbeat TTL, candidate buffers, rate-limit counters, distributed locks. Never the source of truth.
Migrations are SQL-first under remote/migrations/, applied by
golang-migrate on startup in a separate migrate subcommand.
OpenTelemetry instrumentation is wired in from the first commit:
- Traces: every HTTP handler, every policy evaluation, every session transition, every coturn credential mint.
- Metrics:
remote_active_devices,remote_active_sessions,remote_connect_latency_ms,remote_direct_connect_ratio,remote_relay_fallback_total,remote_policy_deny_total,remote_auth_failures_total. - Logs:
slogJSON handler with trace ID correlation.
Exporter default: OTLP over gRPC to localhost:4317. If unset, the SDK runs
as a no-op — the server still runs and emits to stdout.
- Module path:
helper/remote(placeholder; move togithub.com/UnlikeOtherAI/helper/remotewhen the repo gets a remote). go build ./cmd/control-serverproduces a single static binary.golangci-lint runin CI; enabled linters includegovet,staticcheck,errcheck,gosec,revive,gocritic.- Tests:
go test ./.... Integration tests spin up Postgres and Redis viadockertest. Atestdata/fixtures directory per package. - Container image: multi-stage Dockerfile producing a distroless
gcr.io/distroless/static-debian12:nonrootfinal image.
For the first user reaching their own machine, only these subsystems are strictly required:
internal/auth— verify UOA token, issue internal session.internal/bootstrap+internal/devices— enroll one or two machines.internal/tunnel— generate WireGuard peer configs.internal/sessions— minimal connect flow, candidate exchange.internal/nat— coturn integration for TURN fallback.internal/store— Postgres schema for the above.internal/telemetry— stdout logs; OTel exporter optional.
Components deferred past MVP but kept in the code layout so they can be filled in without restructuring:
internal/services— service catalog (hardcoded single service for MVP).internal/policy— embed OPA but ship a one-rule policy file.internal/audit— simple append-only table; HMAC chaining can land later.internal/admin— CLI-only admin at first; HTTP admin comes later.