Skip to main content

Remote Host Security

The trust model of Daintree Remote Hosts: SSH as the only way in, a private Unix socket and per-launch token instead of a network port, discovery adverts, credentials that stay per machine, uploads, plugins and MCP across machines, and revoking access.

Updated
Reviewed

The Short Version

  • The only way into a host is the system ssh, with your keys and your config. There is no Daintree relay, cloud service or account in between.
  • On the host, Daintree listens on a Unix socket only your user account can open, behind a token that changes every launch. It opens no network port for the link.
  • Anyone who can ssh in as that user can use the host, exactly as they could already run commands as you there. Remote Hosts adds no privilege beyond that login.
  • Credentials are never copied or synced between machines. Your files reach a host only through things you do: drops, pastes, attachments and installs.
  • Control of a project is a coordination lock between your windows, not a permission.

For what the feature is, see Remote Hosts. For Daintree's local boundaries, see Security & Privacy.

What Crosses the Network

Between your machine and a host, everything travels inside your ssh connection: terminal output and keystrokes, prompts you send to agents, project state, file contents you open or upload, and forwarded ports. Nothing goes through a server Daintree operates. Discovery uses Tailscale's local status and Bonjour on your own network.

The host itself reaches the network the way it always would: its agents call their providers, its Git talks to its remotes, and it fetches Daintree updates from the release feed when you ask it to install one.

SSH Is the Only Way In

Daintree runs the system ssh binary, never a built-in ssh library, so authentication and host-key checking follow your ~/.ssh/config, known hosts, ssh agent and Tailscale SSH. It adds a few options of its own to its connection:

OptionWhy
BatchMode=yesNever prompt. A password, passphrase or host-key question fails the connection instead of waiting on a prompt nobody can see.
ForwardAgent=no, ForwardX11=noYour ssh agent and display are never exposed to the host.
ClearAllForwardings=yesForwards your config sets up for interactive logins are left off Daintree's main connection.
ControlMaster=auto, ControlPersist=10mOne shared connection per host, with its control socket in a private folder of Daintree's data on your machine.

If the host's ssh server forbids Unix-socket forwarding, the link runs instead over an ssh session to daintree --attach-stdio on the host: the same login, a different pipe.

No Port, a Private Socket

Daintree opens no TCP listener of its own for the host link: your machine reaches it over ssh, and Host mode listens on a Unix socket, created owner-only (0600) in an owner-only (0700) folder that Daintree refuses to use if it is a symlink or belongs to another user:

  • macOS: ~/Library/Application Support/Daintree/host.sock
  • Linux: /run/user/<uid>/daintree/host.sock

Beside it, an owner-only discovery file, host.json, holds the socket path and a per-launch token: 32 random bytes, new every time Daintree starts. Your machine reads it over ssh, and every connection must present the token before anything else is accepted. Together, the permissions and the token limit the socket to processes running as that user; a process running as the same user can read the token, just as it could run commands as you. host-mode.json records Host mode's status for setup to read; it holds nothing secret.

Two things do listen on TCP, both on loopback only. Ports you forward from a host listen on your machine's 127.0.0.1 and ::1. And if you have turned on the MCP server on a host, it listens on the host's loopback, exactly as it would locally.

Who Can Connect

Whoever can ssh in as the host's user can read the discovery file, open the socket and use Daintree there: its projects, terminals and agents, with that user's access. That is the same reach an ssh login as that user already has, so protect it the way you protect ssh: keys, not passwords; authorized_keys you review; and on a shared server, separate accounts.

Each user account on a machine runs its own Daintree, socket, token, settings and plugins, and one user's socket is closed to the others. Bonjour adverts are visible to anyone on the network, but an advert grants nothing.

What Discovery Reveals

While Host mode is on and Advertise on this network is on (the default), the host publishes a Bonjour service, _daintree._tcp, on the local network. It carries the machine's host name, ssh's port (22, not a Daintree port), and its platform and architecture. The Daintree version is deliberately left out, so a network learns nothing that would date the software. Turn advertising off in This Machine as a Host on networks you don't trust; the host is still reachable by its SSH address.

Discovery on your machine reads Bonjour and tailscale status. It only shows that a machine answered; nothing is trusted because it was discovered.

Credentials and Files

Credentials Stay Put

Agent CLI sign-ins, forge tokens, plugin secrets and environment variables belong to the machine they were set on, and Remote Hosts never copies or syncs them. Viewing or editing a host's environment variables or plugin secrets from your window sends those values over your ssh connection so you can see them; they stay stored on the host. A host clones with its own Git credentials, a push from the dialog runs on the machine you are coming from with that machine's credentials, and each host's details page shows its accounts as the host reports them. Plugins store secrets only where there is a usable OS keychain or keyring; a headless Linux host usually has none, so secret writes are refused there.

Files You Send

Files from your machine reach a host only through things you do: dropping, pasting or attaching them in a window on that host, pressing Ctrl+V with an image on your clipboard in a remote agent terminal (on by default, and can be turned off), sending a repository copy through Continue this branch on…, or installing a plugin or Daintree itself there. Dropped, pasted and attached files land in a private inbox in the host's temporary directory: owner-only folders and files, written without following links, outside every worktree, with cleanup that removes entries after a day and keeps the inbox to about 1 GB. An Option-drop (Alt on Linux) writes into the project instead, where the inbox cleanup doesn't apply. Large files ask first and very large ones are refused. In the other direction, opening a host file shows you its contents, and a host plugin's view is downloaded to your machine once you have allowed it to run. See Files, Drops and Images.

Plugins and Agents Across Machines

Plugins From a Host

A host's plugins run their main code on the host, but their views run in your window, on your machine, with the access Daintree has here. So Daintree asks before a host plugin's view first runs, Run "…" from studio-01 on this computer?, and asks again whenever the host changes that plugin's code. A Don't run lasts until Daintree restarts here.

  • Capability prompts for what a plugin does on the host (running commands, writing files, Git) appear in the window with control, and the answer is stored on the host.
  • This computer's clipboard is asked about separately, per host and per plugin, and only from a focused window on that host. A remembered write approval lasts across launches; a remembered read approval lasts only until Daintree quits here.
  • Installing a plugin on a host from Settings → Hosts copies this machine's package over the link into a private staging folder, and the host's normal install path validates it.

Agents on a Host and Your Window

Agents on a host use the host's MCP server. When something they ask for needs a window, it goes to the window with control of that project, and what it may do there is a default-deny allowlist: project terminals, worktrees, agents, recipes and a browser screenshot. Nothing reaches this machine's clipboard, files, editors, browser, settings or plugins: Action '…' cannot be run from a remote host. An agent asking to move your window to another host always needs your approval, and the request names the host it came from.

Control Is Not a Permission

Only one machine at a time has control of a host project, and other windows view it read-only. That exists so two screens don't type into the same agent at once. It is not access control: any window that can reach the host can press Take control. Who can reach the host is decided by ssh alone.

Warning
A host is not a sandbox. Agents there run as your user on that machine, with everything that account can read, write and reach. Treat a host's account the way you treat your own.

Revoking Access

  • Stop one machine using a host: remove the host in its Settings → Hosts. That closes the connection and its ssh connection, and deletes what it had cached for the host.
  • Stop a machine serving: turn off Allow this machine to be a host on it. That closes the listener and its sessions and removes the start-at-login item.
  • Stop a person or machine reaching a host at all: remove its key from the host's ~/.ssh/authorized_keys, which stops new logins, and end that user's existing ssh sessions on the host, because a connection that is already open stays open. Without ssh there is no way in.