Skip to content

Latest commit

 

History

History
292 lines (214 loc) · 7.99 KB

File metadata and controls

292 lines (214 loc) · 7.99 KB

exe.dev API Reference Notes

This file records the exe.dev API documentation that this repository depends on. It was last checked on 2026-05-18 from these source pages:

API shape

exe.dev exposes two programmatic access styles:

  1. SSH command automation:

    ssh exe.dev ls --json
    ssh exe.dev new --json
  2. HTTPS command automation:

    POST https://exe.dev/exec

POST /exec is not a resource-style REST API. The request body is the same exe.dev command that would be typed into ssh exe.dev or run through ssh exe.dev <command>. API responses enable JSON output by default, equivalent to passing --json.

Minimal HTTPS request:

curl -X POST https://exe.dev/exec \
  -H "Authorization: Bearer $EXE_DEV_API_KEY" \
  -d 'whoami'

Operational limits:

  • Only POST is accepted.
  • There is no stdin and no pty.
  • Request bodies are limited to 64KB.
  • Commands time out after 30 seconds.
  • Commands that require interactive input do not fit this API.

exe.dev API tokens

The exe.dev HTTPS API uses bearer tokens. A token can be generated by exe.dev:

ssh exe.dev ssh-key generate-api-key --exp=30d

Tokens can also be created locally by signing permissions JSON with an SSH private key. For automation, prefer a dedicated SSH key so the API token family can be revoked without disrupting normal user SSH access.

ssh-keygen -t ed25519 -C api -f ~/.ssh/exe_dev_api
cat ~/.ssh/exe_dev_api.pub | ssh exe.dev ssh-key add

Local token creation flow:

b64url() { tr -d '\n=' | tr '+/' '-_'; }

export PERMISSIONS='{}'
export PAYLOAD=$(printf '%s' "$PERMISSIONS" | base64 | b64url)
export SIG=$(printf '%s' "$PERMISSIONS" | ssh-keygen -Y sign -f ~/.ssh/exe_dev_api -n v0@exe.dev)
export SIGBLOB=$(echo "$SIG" | sed '1d;$d' | b64url)
export EXE_DEV_API_KEY="exe0.$PAYLOAD.$SIGBLOB"

PERMISSIONS is embedded in the token as plaintext JSON. Do not put secrets in it.

Supported top-level permission fields:

  • exp: UTC Unix timestamp after which the token is invalid.
  • nbf: UTC Unix timestamp before which the token is not valid yet.
  • cmds: exe.dev command names this token may run.
  • ctx: signed JSON context uninterpreted by exe.dev.

The empty object {} uses defaults. For least-privilege automation, specify cmds explicitly. Subcommands must be granted explicitly; allowing ssh-key does not allow ssh-key list.

Useful default commands include:

  • help
  • ls
  • new
  • whoami
  • ssh-key list
  • share show
  • exe0-to-exe1
  • team
  • team members

Commands such as rm, rename, restart, share port, share set-public, and share set-private should be added only when automation needs them.

Permission JSON restrictions:

  • Compact JSON is recommended.
  • No leading/trailing whitespace.
  • No newlines or null bytes.
  • No duplicate keys.
  • Only exp, nbf, cmds, and ctx are allowed at the top level.
  • exp and nbf must be integer timestamps between 2000-01-01 and 2100-01-01 UTC.
  • The whole token must not exceed 8KB.

Short opaque exe1 tokens can be issued from a valid exe0 token:

ssh exe.dev exe0-to-exe1 "$EXE_DEV_API_KEY"

For a VM-scoped token, validate the source token against the VM:

ssh exe.dev exe0-to-exe1 --vm=vm-name "$EXE_DEV_API_KEY"

HTTPS error handling

Common responses from POST /exec:

  • 400: request body is empty, missing, or syntactically invalid.
  • 401: token is malformed, expired, signed by an unknown key, or fails signature verification.
  • 403: token permissions do not allow the requested command.
  • 404: unknown exe.dev command.
  • 405: non-POST method.
  • 413: request body exceeds 64KB.
  • 422: command ran and returned a non-zero exit code.
  • 429: per-key rate limit.
  • 500: unexpected server-side error.
  • 504: command exceeded the 30-second timeout.

Debug checklist for 401:

  • Confirm the signing public key is listed with ssh exe.dev ssh-key list.
  • Confirm exp is not in the past.
  • Confirm the exact compact JSON payload was signed.
  • Use a private key file with ssh-keygen -Y sign -f; an agent-only key is not enough for this command.

Debug checklist for 403:

  • Decode the base64url payload and inspect cmds.
  • Remember that subcommands are exact command-name grants.
  • Add only the missing command, then regenerate the token.

VM HTTPS tokens

The exe.dev HTTPS auth proxy can accept bearer tokens for programmatic access to individual VM HTTPS endpoints. This is separate from authenticating to POST https://exe.dev/exec.

Generate a VM token through exe.dev:

ssh exe.dev ssh-key generate-api-key --vm=my-vm --label=deploy

Generate a VM token locally by changing the SSH signing namespace from v0@exe.dev to v0@VMNAME.exe.xyz:

export SIG=$(printf '%s' "$PERMISSIONS" | ssh-keygen -Y sign -f ~/.ssh/exe_dev_api -n v0@myvm.exe.xyz)

VM token differences:

  • The signing namespace scopes the token to one VM.
  • The token payload ctx is forwarded to the VM HTTP server as X-ExeDev-Token-Ctx.

Preferred VM proxy authentication header:

X-Exedev-Authorization: Bearer <token>

The proxy consumes and strips that header before forwarding to the VM.

Other supported forms:

  • Authorization: Bearer <token> is supported but deprecated for new integrations.
  • Basic auth can be used for tools such as git; the username is ignored and the password is the token. This applies to VM proxy access, not /exec.

When authenticated by token, the VM server receives:

  • X-ExeDev-UserID
  • X-ExeDev-Email
  • X-ExeDev-Token-Ctx, if present in the token

Git HTTPS example:

echo "$TOKEN" > ~/.ssh/exe_dev_token
git config credential.helper '!f() { echo "password=$(cat ~/.ssh/exe_dev_token)"; }; f'
git clone https://myvm.exe.xyz/repo.git

Login with exe

Applications served through the exe.dev HTTP proxy can use exe.dev authentication instead of managing their own login system.

When a request is authenticated by exe.dev, the proxy adds:

  • X-ExeDev-UserID: stable exe.dev user identifier.
  • X-ExeDev-Email: authenticated user email address.

For public sites, unauthenticated requests may not include these headers. For private sites, access requires authentication, so the headers are expected.

Special URLs:

  • https://vmname.exe.xyz/__exe.dev/login?redirect={path} redirects the user to log in, then back to {path}.
  • POST https://vmname.exe.xyz/__exe.dev/logout logs the user out for that domain.

Local development can simulate these headers with a reverse proxy, for example:

mitmdump \
  --mode reverse:http://localhost:8000 \
  --listen-port 3000 \
  --set modify_headers='/~q/X-Exedev-Email/user@example.com' \
  --set modify_headers='/~q/X-Exedev-Userid/usr1234'

VM services must not trust user-controlled copies of these headers when traffic can bypass the exe.dev proxy. Bind private services to localhost or firewall direct VM ports if the header values are part of authorization.

Repository usage

This repository uses the exe.dev HTTPS command API through EXE_DEV_API_KEY for non-interactive VM management:

  • exedev-ctl wraps individual exe.dev commands.
  • exedev-k8s uses exe.dev VM commands as the infrastructure layer for k3s fleet bootstrapping.

For local scripts and manual debugging, prefer:

ssh exe.dev <command> --json

For repo automation and services, prefer:

curl -X POST https://exe.dev/exec \
  -H "Authorization: Bearer $EXE_DEV_API_KEY" \
  -d '<command>'

For new automation tokens, grant only the commands that the workflow needs. A typical VM lifecycle token for this repository needs at least:

{
  "cmds": [
    "ls",
    "new",
    "rm",
    "whoami",
    "share show",
    "share port",
    "share set-public",
    "share set-private"
  ],
  "exp": 1798761600
}

Use shorter-lived tokens for CI and long-running automation where replay risk is important.