Deployment access and SSH credentials
Current scope
The Deployment API key, page-memory-only Browser handling, generated encrypted SSH credentials, complete Machine/Relay lifecycle controls, explicit active-Machine credential rebind, internal cluster authentication, one-hop remote-owner routing, safe audit presentation, and cold all-node API-key replacement are implemented.
One Deployment API key
Each OwlMux Deployment uses one OWLMUX_API_KEY formatted as owlmux_sk_v1_ plus the canonical unpadded base64url encoding of exactly 32 operator-generated cryptographically random bytes. The same value is configured on every Server node. Anyone holding it has complete access to every Machine, SSH credential, enrollment workflow, Browser workspace, and typed operation in that Deployment.
Deployment is the sole human/API trust boundary. OwlMux does not subdivide it into identities, delegated grants, per-resource authorization, node-scoped grants, alternate login methods, or persistent Browser authentication state.
The Browser presents one masked key field and one Open OwlMux action, then enters /workspaces while keeping the value only in current page memory:
- every protected HTTP request sends
Authorization: Bearerto the one Deployment origin; - attachment WebSocket sends the key in one bounded first authentication frame under a five-second deadline;
- after authentication, attachment lifetime follows the WebSocket transport and explicit lifecycle/fencing events rather than an application idle timeout or heartbeat;
- no Machine lookup, owner resolution, internal owner-WSS, route, SSH, tmux, projection, or writer state is allocated before that frame succeeds;
- Server copies the bounded authentication text into a mutable application buffer, drops the WebSocket-library frame, and clears both that complete encoded copy and the parsed key before continuing;
- the key never enters URL, query, cookie, WebSocket subprotocol, local/session storage, IndexedDB, service worker, logs, or analytics;
- internal SPA navigation among Workspaces, Hosts, Credentials, Audit, and Deployment retains the key and page-memory workspace tabs;
- reload, Browser page/tab close, logout, or navigation away clears the key and every workspace tab and requires re-entry;
- closing one OwlMux workspace tab detaches only its Attachment and does not clear the shared page key;
- Browser never receives or selects a Server node.
If Browser or Machine-affine API ingress is not the current owner, it clears the raw key candidate and opens at most one internal WSS hop to that owner. The owner verifies exact incarnations, leases, Server build/configuration epoch, Machine route revision, and connection epoch before allocating state. One-shot API control uses typed request/result/close over the same WSS challenge mode; there is no internal HTTPS variant. Raw API-key bytes are never forwarded. Relay/enrollment never uses this hop.
API-key rotation is Deployment-wide:
- drain and stop every Server node;
- wait until old node leases are invalid;
- replace the one key on every node;
- increment the Deployment configuration epoch/proof;
- start only coherent nodes.
A still-open page clears its old in-memory candidate when fresh authentication fails and asks for the new key. An ordinary unchanged-key node restart may instead reuse that still-open page-memory candidate for a fresh connection. Rotation has no grace key, online mutation, per-node transition, or durable authentication state.
Internal cluster authentication
Clustered mode uses a separate OWLMUX_CLUSTER_KEY: canonical unpadded base64url for exactly 32 random bytes. It is configured with internal TLS identity/trust and never accepted on a public Browser, API, Relay, SSH, or key-encryption surface.
Every Browser/API internal owner-WSS hop requires:
- WSS over TLS on the internal node endpoint;
- one fresh random challenge generated by the destination before handoff context;
- one domain-separated cluster-HMAC response over that challenge and a fresh source nonce;
- exact source and destination process incarnations;
- the current Deployment configuration epoch/proof;
- the exact Machine route revision and connection epoch where applicable;
- a short destination-local
CLOCK_BOOTTIMEdeadline, connection class, and bounds.
No sender wall-clock or cross-node monotonic value is compared, and no reusable bearer assertion exists. A new connection receives a new challenge; a restarted destination has a new incarnation. Every release embeds an exact server_build_id; PostgreSQL stores the Deployment's expected value and each node's registered value. The cluster key also produces a separate domain-separated configuration-consistency proof that includes that build ID, so a node with a different exact Server build, API key, SSH encryption key, origin/security manifest, or protocol generation cannot join at the same epoch. Serving nodes never rely on mixed-build compatibility. The stored ID/proof is not a bearer credential.
Server nodes are in one trust domain. Cluster authentication prevents accidental/confused entry and network credential reuse; it is not hostile-node isolation. Compromise of a node or cluster key is a Deployment incident.
Deployment SSH credentials
Initialization generates one default Ed25519 key pair. The API-key holder may:
- generate another Ed25519 credential with a bounded name;
- rename a credential;
- reset to a newly generated default credential;
- select another default;
- rotate by creating a replacement;
- retire an unreferenced non-default credential.
Server generates key material in memory, derives the public key and SHA-256 fingerprint, encrypts before persistence, clears plaintext buffers, and returns only public metadata. OwlMux accepts no private-key upload, imported key, passphrase, algorithm selector, or alternate SSH key algorithm.
An unknown create/reset outcome remains unknown. Browser refreshes public metadata and never automatically retries the mutation.
Reset/rotation does not change existing Machine bindings, retire the previous key, install the replacement public key, or remove old target authorization. Explicit active-Machine rebind is available only after target administrators perform public-key changes externally. It has no preflight SSH proof and may switch back to a previous still-active credential.
Active-Machine rebind
Rebind is an ordinary PostgreSQL control-plane update for future SSH children. It increments the independent credential revision, leaves the owner-fencing route revision unchanged, and does not tear down the current Relay owner or an already authenticated OpenSSH child. Each existing child pins the credential snapshot used at creation, so rebind is not an urgent revocation mechanism. For urgent access removal, disable the Machine and remove the public key through target administration. Target tmux remains untouched.
Private-key encryption and OpenSSH handoff
One OWLMUX_SSH_KEY_ENCRYPTION_KEY is shared by all Server nodes. It is canonical unpadded base64url for exactly 32 random bytes and directly keys one fixed XChaCha20-Poly1305 envelope. Its associated data binds only the fixed v1 domain, Deployment UUID, and credential UUID. There is no Organization UUID, KDF, provider, KMS/HSM, plugin, multiple-key fallback, rewrap, or online rotation.
Every Server node has its own non-shared private runtime root, preferably on local tmpfs. It contains one exclusive startup-instance directory and one exclusive child directory per owner-local OpenSSH child. Each child creates an exclusive 0600 identity file only in its directory. Spawn, TCP, SSH banner, and host-key milestones do not permit unlink. The owner unlinks and clears plaintext only after the first valid authenticated probe/create response or tmux control record proves OpenSSH loaded the key.
Child cleanup cannot remove siblings. Each node scavenges only its own fully validated local OwlMux-owned orphans and fails closed on ambiguity. No network/shared runtime root or cross-node cleanup exists. A hard crash can leave bounded plaintext until private mount/container teardown or that node's next startup, which is an explicit supported limitation.
If the encryption key is lost, restore the exact key or treat the stored envelopes as unusable and rebuild the pre-release Deployment's credential/Machine authorization safely. Recovery may use replacement credentials followed by explicit active-Machine rebind after target administrators install the replacement public keys. If key plus envelopes may be disclosed, treat every stored SSH credential as compromised and remove those credentials' target public keys after replacement.
Separate Deployments
For stronger isolation or additional external sharding, run separate OwlMux Deployments. Each has an independent origin, Deployment ID, API/cluster/encryption keys, PostgreSQL, Server membership, credentials, Machines, Relays, and attachments.
OwlMux provides no global inventory, shared database, cross-Deployment routing, migration, failover, or live continuity. Moving a Machine is an explicit external enrollment and target-public-key workflow.
Read the normative Deployment access specification and storage and private-key-encryption specification.