2624a13952d7e0cadd56a2e10f3fe5fe880049a3
Production Headscale terminates TLS for both the control plane (via the TS2021 HTTP CONNECT upgrade endpoint) and the embedded DERP relay. Without TLS, the daemon could only talk to plain-HTTP test stacks. - New crate::tls module: shared TlsMode (Verify | InsecureSkipVerify) + tls_wrap helper. webpki roots in Verify mode; an explicit ServerCertVerifier that accepts any cert in InsecureSkipVerify (test-only). - Cargo.toml: add tokio-rustls, webpki-roots, rustls-pemfile. - noise/handshake: perform_handshake is now generic over the underlying stream and takes an explicit `host_header` argument instead of using `peer_addr`. Lets callers pass either a TcpStream or a TLS-wrapped stream. - noise/stream: NoiseStream<S> is generic over the underlying transport with `S = TcpStream` as the default. The AsyncRead+AsyncWrite impls forward to whatever S provides. - control/client: ControlClient::connect detects `https://` in coordination_url and TLS-wraps the TCP stream before the Noise handshake. fetch_server_key now also TLS-wraps when needed. Both honor the new derp_tls_insecure config flag (which is misnamed but controls all TLS verification, not just DERP). - derp/client: DerpClient::connect_with_tls accepts a TlsMode and uses the shared tls::tls_wrap helper instead of duplicating it. The client struct's inner Framed is now generic over a Box<dyn DerpTransport> so it can hold either a plain or TLS-wrapped stream. - daemon/lifecycle: derive the DERP URL scheme from coordination_url (https → https) and pass derp_tls_insecure through. - config.rs: new `derp_tls_insecure: bool` field on VpnConfig. - src/vpn_cmds.rs: pass `derp_tls_insecure: false` for production. Two bug fixes found while wiring this up: - proxy/engine: bridge_connection used to set remote_done on any smoltcp recv error, including the transient InvalidState that smoltcp returns while a TCP socket is still in SynSent. That meant the engine gave up on the connection before the WG handshake even finished. Distinguish "not ready yet" (returns Ok(0)) from "actually closed" (returns Err) inside tcp_recv, and only mark remote_done on the latter. - proxy/engine: the connection's "done" condition required local_read_done, but most clients (curl, kubectl) keep their write side open until they read EOF. The engine never closed its local TCP, so clients sat in read_to_end forever. Drop the connection as soon as the remote side has finished and we've drained its buffer to the local socket — the local TcpStream drop closes the socket and the client sees EOF.
Sunbeam CLI
Sunbeam CLI is a local development stack manager for Kubernetes-based applications. It simplifies cluster management, service operations, secret handling, and manifest deployment.
Quick Start
# Install from source
cargo install --path sunbeam
# Start your local cluster
sunbeam up
# Apply manifests
sunbeam apply
# Check status
sunbeam status
Features
- Cluster Management: Bring up local Kubernetes clusters with cert-manager, Linkerd, TLS
- Service Operations: Status, logs, restart, health checks across namespaces
- Secret Management: OpenBao KV seeding, DB engine config, VSO verification
- Manifest Management: Kustomize + Helm builds with domain/email substitution
- User Management: Kratos identity CRUD, onboarding/offboarding with mailbox and project provisioning
- Image Building: Buildkit-based builds with registry push and rollout deploy
- Project Management: Unified ticket management across Planka and Gitea
- Self-Update: Binary update from the latest mainline commit
- Tool Bundling: kustomize and helm binaries embedded at compile time
Installation
Prerequisites
- Rust (2024 edition)
- Docker
- Lima (for local VM management)
- A running Kubernetes cluster (kubectl context
sunbeamfor local dev)
Install from Source
git clone https://src.sunbeam.pt/studio/cli.git
cd cli
cargo install --path sunbeam
sunbeam --help
Self-Update
Once installed, sunbeam can update itself:
sunbeam update
Workspace Layout
cli/
Cargo.toml # [workspace] — sunbeam-sdk + sunbeam
sunbeam-sdk/ # Library crate — all logic
src/
lib.rs
error.rs, config.rs, output.rs, constants.rs
kube/ # client, apply, exec, secrets, kustomize_build, tools
openbao/ # BaoClient HTTP API
auth/ # OAuth2 PKCE, token cache
services/ # status, logs, get, restart
images/ # build, mirror, per-service builders
secrets/ # seed, verify, KV seeding, DB engine
users/ # identity CRUD, provisioning (mailbox, projects, email)
checks/ # functional health probes, S3 auth
pm/ # Planka + Gitea ticket management
cluster/ # cert-manager, Linkerd, TLS
manifests/ # kustomize apply, namespace filtering
gitea/ # bootstrap (orgs, repos, OIDC)
update/ # self-update, version
sunbeam/ # Binary crate — thin CLI wrapper
src/
main.rs # tokio, rustls, tracing init
cli.rs # Clap structs + dispatch
Usage
Basic Commands
sunbeam up # Full cluster bring-up
sunbeam status # Pod health across all namespaces
sunbeam status ory # Scoped to namespace
sunbeam apply # Build + apply all manifests
sunbeam apply lasuite # Apply single namespace
sunbeam logs ory/kratos # Stream logs
sunbeam logs ory/kratos -f # Follow mode
sunbeam restart # Rolling restart all services
sunbeam restart ory/kratos # Restart specific deployment
Configuration
sunbeam config set --domain sunbeam.pt --host user@server.example.com
sunbeam config get
sunbeam config use-context production
Building and Deploying
sunbeam build proxy # Build image
sunbeam build proxy --push # Build + push to registry
sunbeam build proxy --deploy # Build + push + apply + restart
sunbeam build proxy --no-cache # Disable buildkit cache
sunbeam mirror # Mirror amd64-only images
User Management
sunbeam user list
sunbeam user create user@example.com --name "User Name"
sunbeam user set-password user@example.com
sunbeam user onboard new@example.com --name "New User" --department Engineering
sunbeam user offboard departed@example.com
sunbeam user recover user@example.com
Secret Management
sunbeam seed # Generate + store all credentials in OpenBao
sunbeam verify # E2E VSO + OpenBao integration test
Project Management
sunbeam pm list # List tickets (Planka + Gitea)
sunbeam pm show p:42 # Show Planka card
sunbeam pm show g:studio/cli#7 # Show Gitea issue
sunbeam pm create "Title" --source gitea --target studio/cli
sunbeam pm assign p:42 user@example.com
sunbeam pm close g:studio/cli#7
Health Checks
sunbeam check # Run all functional probes
sunbeam check devtools # Scoped to namespace
Passthrough
sunbeam k8s get pods -A # kubectl passthrough
sunbeam bao status # bao CLI inside OpenBao pod
Production
sunbeam config set --domain sunbeam.pt --host user@62.210.145.138
sunbeam config use-context production
sunbeam apply # Opens SSH tunnel automatically
Running Tests
cargo nextest run --workspace # 232 tests
cargo test --workspace # Alternative
Python CLI (Legacy)
The original Python implementation is in the sunbeam/ package and remains functional:
pip install -e .
python -m sunbeam --help
License
MIT — see LICENSE.
Description
The Sunbeam Studios CLI. It contains tools for Kubernetes, Docker, Lima VM, Cargo, and many other ecosystems. It is designed to be a general-purpose tool for small indie game studios.
https://sunbeam.pt
Releases
4
Languages
Rust
99.9%
Shell
0.1%