# HTTPS API: Run commands on VM


You can execute commands on your VMs over the [HTTPS API](/docs/https-api), using the same `/exec` endpoint with the same `ssh` command you would type into the REPL.

## Quick start

Generate a token that is allowed to use `ssh`:

```bash
ssh exe.dev ssh-key generate-api-key --label=deploy --cmds=ssh --exp=30d
# Restricts to one VM
ssh exe.dev ssh-key generate-api-key --label=deploy --cmds="'ssh my-vm'" --exp=30d
```

Then run:

```bash
curl -X POST https://exe.dev/exec \
     -H "Authorization: Bearer exe1.AAA" \
     -d 'ssh my-vm whoami'
```

## Output and exit codes

The response body is output of your command combined, so you
can redirect the curl output as you need to. Be aware that stderr
is mixed in there (unlike a typical shell redirect).

```bash
curl -X POST https://exe.dev/exec \
     -H "Authorization: Bearer exe1.AAA" \
     -d 'ssh my-vm cat build/app.tar.gz' > app.tar.gz
```

The exit code is in the `X-Exe-Exit` trailer; use `-D` for curl to show it:

```bash
$ curl -sD - -X POST https://exe.dev/exec \
     -H "Authorization: Bearer exe1.AAA" \
     --data-raw 'ssh my-vm false'
X-Exe-Exit: 1
```

## Quoting and all that

Your command passes through two parsers, and each one eats a layer of quoting:

1. The lobby parses the request body with a shell lexer.
2. The VM parses whatever the lobby handed it, much like sshd

So a pipeline, a redirect, or a quoted argument has to survive being quoted twice. Type a command below to see both layers:

<div id="command-quoter"></div>

If you want to return JSON, run a complicated bash pipeline, or 
start a process and return immediately, whip up the appropriate one-liner for that.
The world is your oyster.

## Returning immediately

To detach your command from the initiating HTTPS request, detaching it with `setsid nohup` and shell redirection.

```bash
curl -X POST https://exe.dev/exec \
     -H "Authorization: Bearer $TOKEN" \
     -d 'ssh my-vm "setsid nohup ./build.sh > /tmp/build.log 2>&1 & echo started"'
```

