Security
How Obacht routes traffic, runs commands and handles keys. Written for people who check trust boundaries.
01 Traffic
Obacht stores the minimum it needs to run. The most dangerous thing to leak would be the key material that authorises commands on devices. That never sits on Obacht's servers in usable form. Here is how it actually works.
01
Starts TLS with your device
02
Reads the server name (SNI). Decrypts nothing.
03
WireGuard tunnel, opened by the device
04
TLS ends here, on your hardware
Cleartext exists in two places only: the visitor's browser and your device.
Requests to your domain reach the Obacht proxy first. On port 443 the proxy runs nginx in stream mode with ssl_preread. It reads the server name (SNI) from the TLS ClientHello, picks the device and forwards the still encrypted connection to the device's address in the Obacht network. It does no TLS handshake and never decrypts anything. The certificate lives on the device, and TLS ends there, in the device's own web server (Caddy). Port 80 is forwarded the same way for ACME HTTP-01 and redirects.
02Network
Each device opens its own connection into the Obacht network, a WireGuard tunnel to the gateway, and keeps it up. Nothing connects in. There are no port forwards on your router, and nothing on the device is open to the public internet. Traffic for a domain comes back through the tunnel the device opened.
03 Commands
Anything that changes a device, like installing a template, binding a domain or opening a shell, goes over one of two paths. Both are authorised by your device key (an SSH key, Ed25519), and only you hold it.
SSH
For a shell and file access, the dashboard opens an SSH session to the device through the SSH gateway. Your private key is decrypted in the browser for that session and signs the SSH login. The gateway never stores it.
WebSocket, signed
For structured changes (domains, bindings, instances) the dashboard builds a mutation object (device_id, op, params, nonce, iat, exp), canonicalises it with JCS and signs it with your private key (Ed25519) in the browser. On this path the key never leaves the browser, not even to the gateway. The API reads only what it needs to route and check the envelope, and passes it on to the device over its WebSocket unchanged. The agent checks the signature against a public key pinned on the device, then the device binding, the expiry window and whether the nonce is fresh. Only then does it run the change. Unsigned upsert or delete events on the WebSocket are always refused.
04Keys
Obacht stores your key as ciphertext encrypted with your passphrase (salt, IV, algorithm), plus the matching public key that devices pin. The passphrase and the decrypted private key exist only in your browser, for the session. Neither ever reaches the Obacht API or database.
Break into Obacht's API or database and you get encrypted key blobs and public keys. You can't sign a single change with those, or open an SSH session. Sending commands to the fleet would need every user's passphrase, and Obacht doesn't have them.
05 Templates
A template install carries two signatures: the registry's minisign signature over the manifest, and yours over the change. The agent checks both, the registry signature against a trust bundle built into the agent and yours against the pinned public key. A compromised backend can forge neither. It can't ship a modified manifest and it can't install anything in your name.
Over the manifest: what the app is, which images, pinned to exact digests.
Over the change: install this app, on this device, now.
06Device modes
Every device starts in restricted mode. You unlock power mode on purpose, and you can lock it again whenever you like. Every change and every command lands in an audit log on the device that can only be appended to.
The default. The device does what signed apps and your settings ask for, nothing else.
All of this follows one rule: store as little as possible, and keep the one thing that could take over a fleet, signing commands, off Obacht's machines. Our servers relay and coordinate. Installs and domain changes on your devices need your signature.