Documentation
¶
Index ¶
- type Client
- func (c *Client) AllowTLSDomain(host string) bool
- func (c *Client) DeletePortRoute(ctx context.Context, id string, port int) error
- func (c *Client) DeleteRouteByID(ctx context.Context, routeID string) error
- func (c *Client) DeleteSandboxRoute(ctx context.Context, id string) error
- func (c *Client) DeleteTCPRoute(ctx context.Context, hostPort int) error
- func (c *Client) DeleteTCPServer(ctx context.Context, serverID string) error
- func (c *Client) DeleteTLSSNIRoute(ctx context.Context, id string, port int) error
- func (c *Client) Enabled() bool
- func (c *Client) EnsureLayer4(ctx context.Context, tlsListen, tlsFallback string) error
- func (c *Client) L4TLSFallback() string
- func (c *Client) L4TLSListen() string
- func (c *Client) Ping(ctx context.Context) error
- func (c *Client) PortPublicURL(id string, port int) string
- func (c *Client) SNIHost(id string, port int) string
- func (c *Client) SandboxPublicURL(id string) string
- func (c *Client) Snapshot(ctx context.Context) (Snapshot, error)
- func (c *Client) TCPPublicEndpoint(hostPort int) string
- func (c *Client) TLSPublicEndpoint(id string, port int, l4Listen string) string
- func (c *Client) UpsertPortRoute(ctx context.Context, id, containerIP string, port int) error
- func (c *Client) UpsertSandboxRoute(ctx context.Context, id, containerIP string, toolboxPort int) error
- func (c *Client) UpsertTCPRoute(ctx context.Context, id, containerIP string, port, hostPort int) error
- func (c *Client) UpsertTLSSNIRoute(ctx context.Context, id, sniHost, containerIP string, port int) error
- type Snapshot
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
func (*Client) AllowTLSDomain ¶
func (*Client) DeletePortRoute ¶
func (*Client) DeleteRouteByID ¶ added in v0.1.4
DeleteRouteByID is the zombie-GC entry point: the reconcile sweep finds an @id under apps/http or the tls-mux server that doesn't correspond to any sandbox row, and calls this to drop it. Wraps the same DELETE /id/<routeID> the typed helpers use, so 404 is still treated as success.
func (*Client) DeleteSandboxRoute ¶
func (*Client) DeleteTCPRoute ¶ added in v0.1.4
DeleteTCPRoute removes the layer4 server holding hostPort. 404 is treated as success — the desired post-condition is "not present", and it isn't.
func (*Client) DeleteTCPServer ¶ added in v0.1.4
DeleteTCPServer drops a layer4 server by its name (e.g. tcp-port-37412). Used by reconcile's zombie GC; not tied to a specific sandbox/port pair so the caller doesn't have to know which exposure originally owned the port.
func (*Client) DeleteTLSSNIRoute ¶ added in v0.1.4
DeleteTLSSNIRoute removes one SNI route by @id. 404 is treated as success for the same reason DeleteSandboxRoute does.
func (*Client) EnsureLayer4 ¶ added in v0.1.4
EnsureLayer4 idempotently bootstraps the layer4 app and (when tlsListen is non-empty) the shared SNI-mux server. Safe to call on every sandboxd start — the admin API treats a no-op POST as 200 and a PATCH on a missing key as 404, so we issue a PUT only when the path actually doesn't exist.
Without this bootstrap, the very first UpsertTCPRoute would fail because /config/apps/layer4 doesn't exist yet on a fresh Caddy.
When tlsListen is non-empty, tlsFallback must point at the local HTTPS listener that owned the same port before caddy-l4 took it over (the API site, the on-demand-TLS catch-all, etc.). caddy-l4 routes by SNI for sandbox subdomains and forwards the rest of the traffic — including ACME HTTP-01 cert validation that piggy-backs on :443 ALPN and any non-sandbox hostname — to the fallback. Empty tlsFallback with non-empty tlsListen is rejected; the service layer surfaces it as a config error at boot.
func (*Client) L4TLSFallback ¶ added in v0.1.4
L4TLSFallback returns the address caddy-l4 forwards non-sandbox SNI to (the regular HTTPS Caddy site that handles the API, on-demand TLS, and the 404 catch-all). Meaningful only when L4TLSListen is non-empty.
func (*Client) L4TLSListen ¶ added in v0.1.4
L4TLSListen returns the listen address configured for the shared TLS-SNI multiplexer. Empty means TLS-SNI exposure is disabled — the service layer should reject protocol="tls" requests and skip EnsureLayer4 of the mux.
func (*Client) SNIHost ¶ added in v0.1.4
SNIHost is the per-sandbox subdomain caddy-l4 routes by for a TLS exposure. Returns empty in IP mode (no domain configured), which the service layer uses to detect "TLS not supported in this deployment" without sniffing.
func (*Client) SandboxPublicURL ¶
func (*Client) TCPPublicEndpoint ¶ added in v0.1.4
TCPPublicEndpoint returns the URL clients dial for a raw TCP exposure allocated at hostPort. Always uses the publicHost as the dial target — TCP has no DNS-shaped wildcard equivalent, so even in domain mode the parent host's address is the right value here. Operators that want a friendly DNS name should add their own A record pointing at PublicHost.
func (*Client) TLSPublicEndpoint ¶ added in v0.1.4
TLSPublicEndpoint returns the dial target for a TLS-SNI multiplexed exposure. The host portion is the per-sandbox subdomain caddy-l4 uses for SNI matching (so the certificate the upstream presents must cover that name); the port is the layer4 listener address operators configured. Empty l4Listen means TLS-SNI mode is disabled.
func (*Client) UpsertPortRoute ¶
func (*Client) UpsertSandboxRoute ¶
func (*Client) UpsertTCPRoute ¶ added in v0.1.4
func (c *Client) UpsertTCPRoute(ctx context.Context, id, containerIP string, port, hostPort int) error
UpsertTCPRoute creates (or replaces) the layer4 server bound to hostPort. One server per host-port allocation; PUT replaces the entire server config in place, so re-running with a different upstream IP after a sandbox restart is the right way to refresh routing without poking at routes/0.
func (*Client) UpsertTLSSNIRoute ¶ added in v0.1.4
func (c *Client) UpsertTLSSNIRoute(ctx context.Context, id, sniHost, containerIP string, port int) error
UpsertTLSSNIRoute publishes (or refreshes) one SNI route inside the shared tls-mux layer4 server. PATCH /id/<routeID> replaces the existing route in place without disturbing siblings; if the @id isn't there yet (404) we PUT at routes/0 so SNI matching tries it ahead of any future fallback.
The handler chain is [tls, proxy]: caddy-l4 terminates TLS using Caddy's own cert manager (which already holds the wildcard for *.$DOMAIN, issued once at startup via DNS-01), then proxies the now-plaintext bytes to the container on its native port. The container speaks raw TCP — no cert, no private key, nothing TLS-related lives inside the user's sandbox. The connection_policies entry is intentionally empty: Caddy picks the cert by SNI from the shared cert manager, so there is no per-route cert config.
Caller must have already called EnsureLayer4 with a non-empty tlsListen at least once; otherwise the routes/0 PUT will land on a missing server.
type Snapshot ¶ added in v0.1.4
type Snapshot struct {
// HTTPRouteIDs are the @ids of routes under apps/http that match our
// "sandbox-..." prefix. Both the per-sandbox toolbox routes and the
// per-port HTTP routes show up here.
HTTPRouteIDs []string
// L4TCPServerIDs are server names under apps/layer4 of the form
// tcp-port-<hostPort>. Each maps 1:1 to a host-port allocation in the DB.
L4TCPServerIDs []string
// L4TLSRouteIDs are @ids of SNI routes inside the tls-mux server.
L4TLSRouteIDs []string
}
Snapshot is the read side of reconcile's zombie-route detection. It walks the live Caddy config once and returns every entity whose name follows our conventions, so the service layer can compare against the DB and delete anything that has no matching row.