VM-to-VM Integration
The VM-to-VM integration (also called a peer integration) lets one of your VMs make HTTPS requests to another — an agent calling an API served by a second VM, a staging box hitting a shared service, two agents talking to each other — without either VM ever holding a credential.
Under the hood it's an HTTP Proxy integration
whose target is another VM you own, created with the --peer flag. Two
things make it more than a plain proxy:
- Generated key, never on the VM. exe.dev generates an API key scoped to the target VM, stores it server-side, and injects it at the network edge on every request. The source VM can use the integration but can never read the key — see Where secrets live. The target VM's auth proxy consumes the key; your server never sees it either.
- Caller identity on delivery. Requests arrive at the target with an
X-Exedev-Source-Vmheader naming the calling VM. The platform sets (never appends) this header after stripping anything the source VM sent, so the caller cannot forge it. Use it to audit or route by caller.
Setup from the UI
On the Integrations page, use the HTTPS to another VM tile. Pick the target VM from the dropdown, optionally a port (the default web port 8000 needs none), and attach it to the VMs that should be able to call the target.
You can also type the target VM's name (or "vm-to-vm" or "peer") into the integration catalog search — matching one of your own VMs offers this setup flow with that VM pre-selected as the target.
Setup from the CLI
exe.dev ▶ integrations add http-proxy --name talk-to-bob --target https://bob.exe.xyz/ --peer --attach vm:alice
Added integration talk-to-bob (peer auth → bob)
The --target must be a VM you own (or have access to) on your exe.dev
domain. To reach a port other than 8000, put it in the target URL:
https://bob.exe.xyz:3000/.
The generated key shows up in ssh-key list with the label
peer-<integration name>; deleting the integration removes it.
Example: two agents on two VMs
Say bob runs a small internal API on port 8000, and an agent on alice
needs to call it. Create the peer integration as above, then from alice:
exe.dev ▶ ssh alice curl -s http://talk-to-bob.int.exe.xyz/status
{"ok": true}
The request leaves alice with no credentials, picks up the generated key at
the edge, passes bob's auth proxy, and arrives at bob's server on port 8000
looking like a normal request — plus the caller's name:
X-Exedev-Source-Vm: alice
Bob's server can use that header to decide what alice is allowed to do, tag
log lines by caller, or fan out behavior per peer. If several VMs attach the
same integration, they all reach bob through the same hostname and each is
identified by its own X-Exedev-Source-Vm value.
Notes
- Auth composes. You can add
--headeror--bearerflags alongside--peer; those headers are forwarded to the target VM in addition to the automatic peer key (which travels in a reserved internal header the target never sees).--no-authconflicts with--peer— peer auth is always injected. - Trust scope of
X-Exedev-Source-Vm. A value that reaches your app was vouched for by the platform: the peer integration carries a short-lived signed attestation bound to the target VM, and the header is stripped on every other path, including a human setting it on a direct request. Note it names the source VM, not a user: anyone who can run code on the source VM can call the target as that VM. - Ownership. The target must be a VM you can access; the generated key is
scoped to exactly that VM (namespace
v0@<vm>.exe.xyz) and is useless anywhere else. - Same mechanics as HTTP Proxy. Attachment,
int.exe.xyzhostnames, editing, and teams all work exactly as described in the HTTP Proxy integration docs.