v0.1 “Edge” in development · not production-ready

Every connection,
decided and explained.

Switchboard is a self-hostable, identity-aware gateway in a single Go binary. It routes your apps by name, issues their certificates, puts a login in front of the ones that need it — and tells you exactly why each request was let through or refused.

source opens with the first alpha · MIT licensed · one binary · one JSON config · no external database

01 / shipped today

What works now, tested on every commit.

Only features with tests and a running deployment are listed here. Everything else is on the roadmap below, and labelled as such.

01

Names, not ports

Each app answers to a hostname. The same config runs on a laptop (app.localhost) and on a real domain.

02

Automatic TLS

ACME certificates over HTTP-01 or DNS-01, including a single-level wildcard, renewed in the background.

03

Login per route

OIDC against your existing provider, then a pure policy check on verified email, domain and group claims.

04

Explainable decisions

Every allow or deny carries a stable code and a reason. policy explain and the console simulator ask the same engine.

05

Outbound tunnels

A connector dials out over mutual TLS, so a homelab app is published without opening an inbound port.

06

Static sites

Pages serves a built site straight from disk, with SPA fallback and its control files kept private.

07

Access console

A loopback-only console: live decision feed over SSE, route health and the policy simulator.

08

Secrets by reference

env: and file: references; the control plane never writes a resolved secret back to disk.

02 / how a request flows

One pipeline, in one place.

Every request walks the same ordered stages. Security decisions are pure functions that return a decision with a stable code and a human reason, so the proxy, the CLI and the console can never disagree about why.

$ switchboard policy explain -host app.example.com \
    -email [email protected] -verified -groups support
route:     app.example.com (protected)
policy:    allowed_domains=[example.com] required_groups=[engineering]
decision:  denied
code:      missing_required_group
reason:    account is missing required group engineering
scope:     authorization only; OIDC, session and transport are not evaluated
  1. 01trustClient IP, trusted proxies, origin certificate
  2. 02ratelimitPer IP and per identity buckets — in progress
  3. 03shieldWAF rules and challenges — planned
  4. 04identifySession or OIDC login
  5. 05authorizePure policy decision with a code
  6. 06routeHost lookup in an atomic snapshot
  7. 07forwardUpstream, static files or tunnel

03 / the access console

Ask the engine why — before anyone gets locked out.

Loopback-only by design. The simulator needs the admin token, because an answer that reveals who is allowed is itself sensitive.

The Switchboard console's policy simulator showing a denied request: the account is missing the required group oncall.

04 / roadmap

Toward zero trust you can verify.

The long-range goal: every certificate issued, policy changed and access granted lands in a transparency log that anyone holding a copy can check — so not even the operator can quietly change who has access. That is a direction, not a claim; each release promises only what its tests and deployments show.

v0.1 · Edge

in progress · Oct – Dec 2026

  • ›Host routing, TLS, OIDC and claim policy
  • ›Pages, tunnels, access console
  • ›CI on Linux, macOS and Windows; first alpha tag
v0.2 · PKI

Jan – Mar 2027

  • ›Internal CA and ACME server
  • ›mTLS between edge, agent and origin
  • ›SSH CA and workload identity
v0.3 · Access

Apr – Jun 2027

  • ›SSH and databases over tunnels
  • ›Just-in-time access with approvals
  • ›Session recording, WAF with Coraza + CRS
v0.4 · Trust

Jul – Sep 2027

  • ›Transparency log with witnesses
  • ›Risk signals and explanations
  • ›AI-agent / MCP gateway

05 / get started

Route two apps by name in a minute.

Needs Go. Point names at the ports your apps already use, run one binary, and open the console on loopback.

  • Same config file from localhost to a VPS.
  • validate checks a config without starting anything.
  • Release binaries arrive with the first alpha tag.
# config.json
{
  "listen": ":8888",
  "admin": { "listen": "127.0.0.1:9090" },
  "routes": [
    { "host": "app.localhost:8888",  "target": "http://localhost:3000" },
    { "host": "docs.localhost:8888", "target": "http://localhost:4321" }
  ]
}

The repository opens with the first alpha tag; until then these steps show what running it looks like.

$ git clone https://github.com/octaviosantacruz/switchboard
$ cd switchboard && go run ./cmd/switchboard -config config.json
# open http://app.localhost:8888 · console on http://127.0.0.1:9090