Skip to content
LabTether

Security

LabTether's security architecture covering transport encryption, authentication, authorization, and hardening recommendations for self-hosted deployments.

TLS Modes

Mode Env Value Behavior
Auto (default) LABTETHER_TLS_MODE=auto Hub generates ECDSA P-256 CA (10yr) and server cert (1yr, 30-day auto-renewal). HTTPS on :8443, HTTP-to-HTTPS redirect on :8080.
External LABTETHER_TLS_MODE=external User-provided certs via LABTETHER_TLS_CERT/LABTETHER_TLS_KEY (e.g. tailscale cert, Let's Encrypt). Uploaded certs from Settings -> TLS Management also use this path.
Disabled LABTETHER_TLS_MODE=disabled Plain HTTP on :8080. Only appropriate when Tailscale provides WireGuard encryption at the network layer.

Certificate Trust Model

Component Trust Mechanism
Agents (public cert) System CA pool via https://<host>.<tailnet>.ts.net or other publicly-trusted paths
Agents (built-in TLS) Trust-On-First-Use (TOFU) via enrollment; agent validates IsCA=true before saving
Docker Compose services Public CA cert shared via read-only labtether-ca volume; CA private key isolated in labtether-data
Web console (Node.js) NODE_EXTRA_CA_CERTS pointed at hub CA
Browsers Manual trust or system-wide CA install; download from GET /api/v1/tls/ca.crt
Uploaded hub certs Private key encrypted before storage; certificate chain remains readable

Hub TLS source precedence: UI override > deployment env/config > code defaults

Security Headers

All HTTPS responses include:

Header Value
Strict-Transport-Security max-age=63072000
X-Content-Type-Options nosniff
X-Frame-Options DENY

Authentication

Local Auth

Role-based auth with four built-in roles (owner, admin, operator, viewer). See Permissions for the full RBAC model.

TOTP Two-Factor Authentication

Property Detail
Standard RFC 6238 TOTP
Secret storage AES-256-GCM encrypted at rest using the hub encryption key
Setup verification Valid TOTP code required before activation; unverified secrets discarded
Challenge tokens In-memory, 5-minute TTL, max 5 failed attempts, single-use on success
Recovery codes 8 single-use codes, bcrypt-hashed at rest, each invalidated after use
Disable 2FA Requires valid TOTP code or unused recovery code

API Key Authentication

Property Detail
Format lt_<prefix>_<secret> with 32 bytes of cryptographic randomness
Storage SHA-256 hash only -- raw key never persisted
Transport TLS required -- keys rejected on plain HTTP
Rate limiting 600 req/min per source IP, 3000 req/min global per key
Scoping Per-key permissions with optional asset allowlists
Comparison Constant-time hash comparison (timing-attack resistant)

Unauthenticated TLS Endpoints

Endpoint Purpose
GET /api/v1/tls/ca.crt Download CA certificate (PEM)
GET /api/v1/tls/info TLS status (mode, cert fingerprint, expiry)
POST /api/v1/enroll Agent enrollment with TOFU CA distribution

Outbound Egress Guardrails

Rule Behavior
DNS resolution check Both hostname and resolved addresses are validated
Loopback/link-local/private Blocked unless explicitly enabled via security.outbound_allow_private
Allowlist bypass prevention Hostname allowlists do not bypass resolved-address policy checks

Operator Boundary Hardening

Surface Enforcement
GET /status/aggregate Scoped to requesting actor (unless owner); cache keys include actor scope
Desktop recording paths Session ownership enforced with admin override; raw file paths not exposed
Desktop credentials Gated by interactive session_start policy
Persistent terminal sessions Re-check interactive session_start policy on create and attach
First-run bootstrap Generated passwords not printed to stderr; only masked hint logged

iOS Companion App Transport Policy

Rule Detail
Hub URL format Origin-only (http[s]://host[:port]): no credentials, path, query, or fragment
HTTPS requirement Required for all non-loopback hubs
HTTP exception Loopback only (localhost, 127.0.0.1, ::1)
Keychain storage Device-local, non-sync (WhenUnlockedThisDeviceOnly, no iCloud sync)
401 handling Clears session artifacts, returns to login, requires re-authentication
Sign-out cleanup Clears token, cookies, URL cache, offline cache/queues, push registration
TLS version 1.2+ required for secure transport
Untrusted TLS setting Available in shipping builds, disabled by default, and scoped to the exact selected HTTPS hub origin. Installing the hub CA is recommended but optional.

Hardening Checklist

Check Action
TLS enabled Confirm LABTETHER_TLS_MODE is auto or external (not disabled)
Certificate trust For auto mode, install the hub CA system-wide or accept in browser for both :3000 and :8443. Download from https://<hub>:8443/api/v1/tls/ca.crt
CA key isolation Verify labtether-ca volume is read-only for agent/console containers (CA private key only in labtether-data)
Network access Restrict access paths to private network or Tailscale
Secrets Enforce strong secret/token generation and rotation
Connector accounts Use least-privilege integration accounts
Exposed ports Audit exposed ports and reverse-proxy rules
Auth logs Review auth/session logs for anomalies
Backups Validate backup encryption and restore access controls
Patching Keep hub and dependencies patched
iOS app Use https:// hub URL for all non-local environments; use http://localhost only for loopback development; log out in-app when switching hubs