> ## Documentation Index
> Fetch the complete documentation index at: https://docs.boxd.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# VM-to-VM networking

> How a VM talks to other VMs you own. The fabric for fleets of agents.

A single VM is a starting point. Real agent workloads spawn dozens of them. An orchestrator delegating to workers. A planner spinning up a fresh sandbox per branch of its search. A test matrix running every shard on its own machine. None of that scales if every cross-VM call asks you to plumb auth, SSH keys, secrets, and routing.

Every boxd VM ships the same `boxd` CLI you use on a laptop. From inside a VM it auto-auths. Zero keys, zero tokens, zero config.

```bash theme={"theme":"github-dark"}
# Inside source-vm:
boxd machine new worker-1
boxd machine exec worker-1 -- 'cd /app && do-the-thing'
boxd machine cp ./results worker-1:/uploads/results
```

## How it works (briefly)

From inside a VM, boxd already knows which machine the call is coming from, so it authenticates you as that machine's owner automatically -- no tokens, no SSH keys, no shared secrets to plumb. Ownership is enforced on every call: a VM can only see, fork, or exec into other VMs **you** own.

That holds no matter how many VMs you run. All your VMs share one flat private network, so a call from one reaches any other of yours the same way -- two machines or two hundred, same call, no setup.

## What this enables

* **Agent fan-out.** An orchestrator spawns N worker agents, each in its own VM, each running against its own copy of the codebase. They never stomp on each other. The orchestrator collects results and destroys the workers.
* **Multi-step pipelines.** Step A runs in vm-a, hands its output to vm-b via `boxd machine cp`, triggers vm-b's work with `boxd machine exec`. Pause a VM between steps, resume it later, no state lost.
* **Self-cloning workflows.** A VM forks itself, hands a job to the fork, destroys the fork when done. Clean slate per task without rebuilding the environment.
* **Fleet-level patterns.** Test matrices, parallel scrapers, ML batch jobs, distributed builds. Anything that wanted a hundred Linux machines for ten seconds gets it with one `for` loop.
* **Direct service calls.** One VM reaches another's running service over the private network by name — `curl http://api-vm.boxd:3000` — with no service discovery to wire up and nothing exposed publicly. See [Reach another VM over the network](#reach-another-vm-over-the-network).

## What you can do from inside a VM

Everything the CLI does, scoped to your VMs only:

```bash theme={"theme":"github-dark"}
boxd machine list                   # all your VMs
boxd info                           # current VM
boxd machine new child              # spawn a sibling
boxd machine fork                   # fork the current VM
boxd machine exec target -- 'cmd'   # run a command in another VM
boxd machine cp ./file target:/path # copy files between VMs
boxd machine remove child -y        # destroy
```

The one thing that doesn't work from inside a VM is `ssh name.boxd.sh`. That hostname resolves to the proxy's public edge, and a VM doesn't carry your SSH key. Use `boxd machine exec` or `boxd connect` to run commands, or the internal DNS name below to reach a VM's services directly.

## Reach another VM over the network

`boxd machine exec` and `boxd machine cp` cover running commands and moving files. When you want one VM to talk to another's **running service** — an API, a database, a dev server — resolve it by name. Inside any VM, `<vmname>.boxd` resolves to that VM's private IP:

```bash theme={"theme":"github-dark"}
# inside any of your VMs:
curl http://worker-1.boxd:8000/health
psql -h db.boxd -U postgres
```

Name resolution is private to you: only VMs **you** own resolve, so there's no cross-tenant name or IP leak, and it works the same across every VM you run -- `worker-1.boxd` resolves identically wherever the target machine happens to be. Names answer with a short (30s) TTL; only the bare `<vmname>.boxd` form resolves (no sub-labels). Everything that isn't a `.boxd` name is forwarded to a normal upstream resolver, so regular internet DNS keeps working unchanged.

<Note>
  `<vmname>.boxd` is for VM-to-VM traffic over the private network. Public clients still reach a VM at its `<vmname>.boxd.sh` HTTPS domain through the proxy.

  Don't confuse this with the `<vmname>.boxd` **SSH alias** the CLI writes on your laptop ([Editor & SSH workflows](/cloud-dev-boxes/editor-and-ssh-workflows)). Same name, different things: that alias is a local `~/.ssh/config` shortcut for `ssh`-ing into a VM from outside; this is real DNS, for one VM to reach another over the private network.
</Note>

## Reference

<Columns cols={2}>
  <Card title="Internal CLI" icon="https://mintcdn.com/azin/Ax1V0serIwQf0x_2/images/icons/monitor.svg?fit=max&auto=format&n=Ax1V0serIwQf0x_2&q=85&s=b1c0523c0e6bc828249250297aaa35ad" href="/reference/internal-cli" width="16" height="16" data-path="images/icons/monitor.svg">
    Full command surface of the in-VM `boxd`.
  </Card>

  <Card title="Fork" icon="https://mintcdn.com/azin/Ax1V0serIwQf0x_2/images/icons/branching-paths-down.svg?fit=max&auto=format&n=Ax1V0serIwQf0x_2&q=85&s=3c228f945ca60afc1fac1ba10e78a799" href="/how-it-works/fork" width="16" height="16" data-path="images/icons/branching-paths-down.svg">
    Memory, disk, and in-progress work, branched.
  </Card>
</Columns>
