# dosh - Dormant Shell dosh is a low-latency remote terminal designed around fast attach and fast reconnect. It is mosh-shaped, but not a mosh clone: the server is a resident daemon, terminal sessions stay hot, and repeat connects try encrypted UDP before starting SSH. The core target is simple: - First secure trust establishment uses SSH. - Existing sessions attach in one encrypted UDP exchange whenever cached credentials allow it. - Reconnect after sleep, roaming, or network change resumes in one encrypted UDP exchange. - Cold SSH fallback stays competitive with plain `ssh` by doing less after auth. ## Why not just mosh? mosh is excellent at roaming and high-latency interactivity. Its startup path still has work dosh can avoid: 1. SSH connects to the host. 2. SSH starts `mosh-server`. 3. The client receives connection material over SSH. 4. SSH exits and the mosh UDP session begins. dosh keeps `dosh-server` running before the client arrives. Named PTY sessions can also be prewarmed, so attaching to `default` does not need to spawn a daemon, create a PTY, or start a shell on the user's critical path. This is not an encryption argument against mosh. dosh also encrypts its UDP data channel; the speed difference comes from keeping the server and session hot. ## Fast Path Order The client always tries the cheapest valid path first: 1. **UDP resume:** existing `ClientId` and session key. No SSH. One encrypted UDP request, one encrypted UDP reply. 2. **UDP attach ticket:** cached server-issued attach ticket for the same host/user/session/mode. No SSH. One encrypted UDP request, one encrypted UDP reply. 3. **SSH bootstrap:** `ssh -T user@host ~/.local/bin/dosh-auth ...`, then one encrypted UDP attach. 4. **New session:** same as attach, but the server must create the PTY/shell unless the session was prewarmed. The fastest path is not a custom SSH replacement. SSH remains the first trust root; dosh removes SSH from repeat attaches when the server has already issued valid credentials. Attach tickets are implemented because they are the way a fresh client process can skip SSH after a recent successful bootstrap. ## Connection Speed Contract dosh is measured by terminal-ready time: elapsed time from running `dosh host` to the first usable terminal screen. - UDP resume: <= one measured UDP RTT + local render time. - UDP attach ticket: <= one measured UDP RTT + local render time. - Warm attach with ControlMaster: <= `ssh host true` over the existing master + one measured UDP RTT. - Cold attach without ControlMaster: <= cold `ssh host` terminal-ready time + one measured UDP RTT. - New session: measured separately because it may need PTY and shell creation. The client emits timing spans for credential lookup, SSH bootstrap, UDP resume, UDP ticket attach, and terminal-ready time. ## Architecture ```text dosh-server UDP socket on one configurable port session table keyed by name one PTY per named session optional prewarmed sessions, default ["default"] terminal parser/screen state per session client table per session encrypted UDP protocol tiny SSH-invoked dosh-auth helper mode dosh-client terminal raw mode local credential cache UDP resume/attach first SSH bootstrap fallback PTY input/output forwarding reconnect and roaming state machine ``` ## Install Default UDP port: `50000`. This is intentionally inside the common forwarded range `50000-52000/udp`. Install on each Linux server you want to attach to: ```bash curl -fsSL https://git.palav.dev/Palav/dosh/raw/branch/main/install.sh \ | DOSH_REPO=https://git.palav.dev/Palav/dosh.git DOSH_PORT=50000 sh -s -- server ``` Install the client on macOS: ```bash curl -fsSL https://git.palav.dev/Palav/dosh/raw/branch/main/install.sh \ | DOSH_REPO=https://git.palav.dev/Palav/dosh.git DOSH_SERVER=palav DOSH_HOST=git.palav.dev DOSH_PORT=50000 sh -s -- client ``` Install the client on Windows PowerShell: ```powershell $env:DOSH_REPO="https://git.palav.dev/Palav/dosh.git"; $env:DOSH_SERVER="palav"; $env:DOSH_HOST="git.palav.dev"; $env:DOSH_PORT="50000"; irm https://git.palav.dev/Palav/dosh/raw/branch/main/install.ps1 | iex ``` Attach: ```bash dosh palav ``` Plain `dosh palav` opens a fresh terminal session. Use named sessions when you want to reattach to the same persistent terminal from multiple clients: ```bash dosh --session work palav dosh --session logs palav ``` Press `Ctrl-]` to detach the current client while leaving the server session alive. Typing `exit` in the remote shell closes that Dosh session and returns the client. If UDP packets stop arriving, Dosh shows a blue status bar at the top of the terminal with the disconnected duration and sends keepalive pings until traffic returns. If SSH and UDP use different public names, specify the UDP address: ```bash dosh-client --dosh-host public.example.com --dosh-port 50000 user@host ``` ## Develop Build: ```bash cargo build ``` Attach locally, using local bootstrap instead of SSH: ```bash target/debug/dosh-client --local-auth --no-cache local ``` Benchmark local attach: ```bash target/debug/dosh-bench --local-auth --server local --iterations 5 ``` Benchmark a remote host over SSH bootstrap: ```bash target/release/dosh-bench --server user@host --ssh-port 22 --iterations 3 ``` Benchmark the ControlMaster-backed SSH bootstrap path: ```bash target/release/dosh-bench --server user@host --controlmaster --iterations 3 ``` Run the Docker OpenSSH benchmark gate used by CI. It checks both cold SSH bootstrap and ControlMaster-backed SSH bootstrap against a containerized `sshd` plus resident `dosh-server`: ```bash make bench-docker-ssh ``` The CI workflow includes an optional remote benchmark job. It runs when `DOSH_BENCH_HOST`, `DOSH_BENCH_USER`, and `DOSH_BENCH_SSH_KEY` repository secrets are configured. Install release binaries and the user systemd service: ```bash make install ``` ## Performance Rules The stack is performance-driven, not fixed by taste. Rust is the default because the likely bottlenecks are network RTT, SSH startup/auth, PTY/shell creation, packet size, and terminal rendering. Change language or runtime only if measurements show they are the bottleneck. Hot-path rules: - Custom UDP protocol with AEAD for v0; no QUIC handshake on attach. - Fixed binary packet headers for terminal traffic; no JSON on the protocol path. - Preallocated buffers; avoid per-packet heap churn. - Single-thread event loop is preferred for the hot path. - No PTY allocation, shell spawn, shell rc files, or MOTD on attach to an existing session. - Initial snapshot should be sent in the first UDP reply when it fits under the packet budget. ## Goals - Connection speed as specified above. - UDP roaming and reconnect. - Encrypted terminal data. - Reuse SSH pubkeys for first trust establishment. - Named persistent sessions. - Multiple clients attached to one session. - Optional view-only clients. - Single server port, not one port per session. - Static server and client binaries where practical. ## Non-Goals - Replacing SSH as the first public-key trust mechanism. - Multi-user access control. - Windows support in v0. - Full mosh compatibility. - Perfect predictive local echo in the first MVP. ## Status Rust implementation is present in this repository. It contains `dosh-server`, `dosh-client`, `dosh-auth`, `dosh-bench`, shared auth/crypto/protocol modules, a resident PTY server, encrypted UDP bootstrap attach, UDP resume, sealed UDP attach tickets, client ACKs, server retransmit bookkeeping, sliding replay protection, server-side `vt100` screen snapshots/diffs, a hardened user systemd unit, an install script, Docker SSH benchmark gates, CI, and protocol/integration tests.