Backplane is the Invisible Admin Panel for Go. It allows you to debug, configure, and rescue running applications via SSH, without the security risks of an HTTP admin dashboard.
- Architecture
- Quick Start
- The Reflector Bridge
- Automation
- Production Patterns
- Security & Compliance
- Licensing
Backplane strictly enforces standard SSH public key authentication.
- You must have a valid SSH key pair.
- Your public key (
id_ed25519.pubor similar) must be present in~/.ssh/authorized_keyson the host machine. - If this file is missing, Backplane will deny all connections.
Backplane operates on a strictly "Air Gapped" model. It binds a dedicated SSH server to 127.0.0.1, ensuring that administrative access is physically impossible from the public internet without prior host-level authorization.
- Zero-Allocation Logging: Uses a fixed-size ring buffer. It will never cause an OOM.
- Crash-Proof Isolation: The TUI runs in a distinct goroutine sandbox. A panic in the admin panel will never propagate to your main application loop.
- Safe Mode TUI: Automatically detects small terminal dimensions (< 40x10) and switches to an error-proof minimal view to prevent layout panics.
- Bounded Registry: Enforces hard memory limits (Max 20k users) with automated eviction policies to prevent DoS memory exhaustion attacks.
- Standard SSH Auth: Leveraging
~/.ssh/authorized_keys, it respects your existing infrastructure security policies. - Fail-Closed Auditing: Ensures that if an audit log cannot be written, the configuration change is rejected.
To trigger the demo application (as seen in the GIF):
# 1. Run the demo server
go run examples/basic/main.go
# 2. In a separate terminal, SSH into it
ssh -p 2222 localhostBackplane is not a framework. It is a library you import.
package main
import (
"github.com/drskyle/backplane/v2/pkg"
)
func main() {
// 1. Initialize Default Options
opts := pkg.DefaultOptions()
// 2. Initialize Backplane
bp := pkg.New(opts)
// 3. Launch the Server (Non-blocking)
stop, err := bp.Start()
if err != nil {
panic(err)
}
defer stop()
// 4. Your Application Logic Here
select {}
}Modern applications require runtime reconfiguration. Backplane exposes thread-safe atomic types that bind directly to the TUI.
Old Way (Dangerous): Restarting the app to change a config.
Backplane Way:
package main
import (
"github.com/drskyle/backplane/v2/pkg"
"github.com/drskyle/backplane/v2/pkg/atomic"
)
// 1. Define variables as Atomic types (Thread-Safe)
var (
MaxConnections = atomic.NewInt(1000)
MaintenanceMode = atomic.NewBool(false)
LogLevel = atomic.NewString("INFO")
)
func main() {
// 2. Initialize Backplane
bp := pkg.New(pkg.DefaultOptions())
// 3. One-line Registration (No internal imports!)
bp.MustExpose("Max Connections", MaxConnections, pkg.WithRange(1, 1000))
bp.MustExpose("Maintenance Mode", MaintenanceMode)
bp.MustExpose("Log Level", LogLevel)
// 4. Start Server
bp.Start()
// Your app reads them safely at runtime:
if MaintenanceMode.Load() {
blockTraffic()
}
}
No mutexes required. No race conditions.
### Automation (Headless Mode)
You don't always want a TUI. Backplane supports **Headless Mode** for DevOps automation and shell scripting.
**Get a value:**
```bash
$ ssh -p 2222 localhost get MaxConnections
1000
Set a value (Instant Update):
$ ssh -p 2222 localhost set MaxConnections 2000
OKList all exposed variables:
$ ssh -p 2222 localhost list
MaxConnections = 2000
MaintenanceMode = false
LogLevel = INFOBackplane isn't just a debugger; it's a control plane.
Need to stop traffic now to migrate a database? Don't redeploy. Just flip the switch.
In your code:
var Maintenance = atomic.NewBool(false)
func middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if Maintenance.Load() {
http.Error(w, "Down for maintenance", 503)
return
}
next.ServeHTTP(w, r)
})
}In the terminal:
ssh -p 2222 localhost set Maintenance trueSince Backplane variables are standard atomics, you can read them directly in your metrics collectors.
prometheus.NewGaugeFunc(
prometheus.GaugeOpts{Name: "app_max_conns"},
func() float64 { return float64(MaxConnections.Load()) },
)Change the value in the TUI -> Prometheus updates instantly.
Stop spamming logs. Keep the level at ERROR by default. When an incident starts, switch to DEBUG instantly without restarting.
var LogLevel = atomic.NewString("ERROR")
func LogDebug(msg string) {
if LogLevel.Load() == "DEBUG" {
fmt.Println(msg)
}
}Backplane enforces a layered defense system to protect your host application.
Configure roles in your ~/.ssh/authorized_keys file using the role option:
# Read-Only Viewer (SREs, Monitoring)
role=viewer ssh-ed25519 AAAAC3... sre-team
# Admin (Full Read/Write Access) - Default if no role specified
ssh-ed25519 AAAAC3... lead-dev
- Viewers: Can see the Dashboard, filter logs, and run
list/getcommands. Cannot edit variables. - Admins: Full control.
Backplane implements a 3-tier limit strategy to prevent resource exhaustion:
- TCP Throttling: Limits total raw TCP connections (Default: 50).
- Session Throttling: Limits concurrent SSH sessions per IP (5) and User (3).
- Request Throttling: Limits
setcommands via Token Bucket (Admin: 100/s, Viewer: 10/s).
These limits are configurable via pkg.Options.
To run Backplane in production (Kubernetes, Docker), you must handle secrets and state correctly.
Do not bake your public keys into the container image. Instead, use a Kubernetes Secret or ConfigMap and inject it via the BACKPLANE_AUTHORIZED_KEYS environment variable.
Create the Secret:
kubectl create secret generic backplane-keys --from-file=authorized_keys=./my-team-keys.pubDeploy (Pod Spec):
env:
- name: BACKPLANE_AUTHORIZED_KEYS
valueFrom:
secretKeyRef:
name: backplane-keys
key: authorized_keysBackplane checks this environment variable first. If present, it bypasses the default ~/.ssh/authorized_keys check.
By default, Backplane generates a random Host Key on startup. This is secure but causes "Host Key verification failed" warnings in SSH clients if the Pod restarts.
To prevent this, generate a persistent key and mount it.
Generate a Host Key:
ssh-keygen -t ed25519 -f backplane_host_key -N ""Mount it in Kubernetes:
spec:
containers:
- name: my-app
volumeMounts:
- name: host-key-vol
mountPath: /etc/backplane
readOnly: true
volumes:
- name: host-key-vol
secret:
secretName: backplane-host-keyConfigure Backplane:
opts := pkg.DefaultOptions()
opts.HostKeyPath = "/etc/backplane/backplane_host_key"Backplane generates high-value audit data. You must ensure you have adequate disk space.
If you use pkg.WithAutoRotation(filename), Backplane enforces the following Default Retention Policy:
- Max Size: 10 MB per log file.
- Max Backups: 3 files kept (plus the active one).
- Max Age: 28 days.
- Total Max Disk Usage: ~40 MB.
This ensures your admin logs never consume the host's entire disk.
For simple Docker setups, mount your local public keys directly:
services:
myapp:
image: myapp:latest
environment:
- BACKPLANE_AUTHORIZED_KEYS=/secrets/authorized_keys
volumes:
- ./my_team_keys.pub:/secrets/authorized_keys:roBackplane is designed for SOC2 and FedRAMP "High" environments.
Every modification is strictly attributed to a cryptographic identity. Logs are emitted in machine-readable JSON format for easy ingestion by Splunk/Datadog.
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-01-26T10:00:00Z",
"actor": "alice",
"role": "admin",
"action": "WRITE",
"resource": "MaxConnections",
"old_value": 1000,
"new_value": 2000
}For critical systems, audit logging is not "best effort"—it is mandatory.
Backplane enforces a Transactional Audit policy. Modifications are provisional until the audit event is successfully persisted. If the audit sink fails (e.g., disk full, network down), the system rolls back the change instantly and returns a critical error to the operator.
This ensures you never have "phantom changes" in your system that are not recorded in the audit trail.
Once integrated, your application will listen on port 2222 (default). Access it using any standard SSH client:
ssh -p 2222 localhostBackplane is free software licensed under the GNU Affero General Public License v3.0 (AGPL v3).
If your application is proprietary, or if you cannot comply with the viral open-source requirements of the AGPL v3, you must purchase a Commercial License.
Commercial Licenses start at $2,000 / year / project.
We believe in building software that does good. Proceeds from commercial licensing are directly committed to supporting the education of underprivileged children and funding animal welfare initiatives (specifically the rescue and care of cats and other animals).
For commercial licensing and proper indemnification, contact: drskyle8000@gmail.com
