Agent tooling
Deploy an application
Provision a VM, run a setup script, and optionally add CDN and DNS, all in one call.
On this page10 sections
Compute sizes#
Simplified size names that map to specific resource allocations:
| Size | vCPU | RAM | Disk | Use case |
|---|---|---|---|---|
nano |
1 | 1 GB | 20 GB | Testing, small scripts |
small |
1 | 2 GB | 40 GB | Simple apps, APIs |
medium |
2 | 4 GB | 80 GB | Production apps |
large |
4 | 8 GB | 160 GB | High-traffic apps |
xlarge |
8 | 16 GB | 320 GB | Databases, heavy workloads |
Request#
POST /agent/deploy/app
Authorization: Bearer ea_live_...
{
"project": "my-saas-app",
"compute": {
"os": "ubuntu-24.04",
"size": "small",
"region": "london",
"setup_script": "#!/bin/bash\napt update && apt install -y docker.io\ndocker run -d -p 8080:8080 myapp:latest",
"ssh_key": "ssh-ed25519 AAAA..."
},
"networking": {
"firewall_rules": [
{ "port": 80, "protocol": "tcp" },
{ "port": 443, "protocol": "tcp" },
{ "port": 22, "protocol": "tcp", "source": "203.0.113.0/24" }
]
},
"domain": "app.example.com",
"cdn": {
"enabled": true
}
}Instead of an inline setup_script, you can reference a tested script from the startup script library by ID (discover them via GET /agent/compute/scripts):
{
"project": "my-blog",
"compute": {
"size": "small",
"script": "wordpress",
"script_params": {
"site_title": "My Blog",
"admin_email": "me@example.com"
},
"ssh_key": "ssh-ed25519 AAAA..."
}
}Parameters#
| Field | Required | Description |
|---|---|---|
project |
Yes | Project name |
compute.size |
Yes | nano, small, medium, large or xlarge |
compute.os |
No | Operating system. Default: ubuntu-24.04 |
compute.region |
No | Deployment region. Default: london |
compute.script |
No | Startup script ID from GET /agent/compute/scripts (e.g. docker, nodejs). Preferred over setup_script because library scripts are tested and maintained. |
compute.script_params |
No | Parameters for the chosen script, e.g. {"db_password": "..."} |
compute.setup_script |
No | Inline bash script to run on first boot. Mutually exclusive with compute.script. |
compute.ssh_key |
No | SSH public key string (e.g. ssh-ed25519 AAAA...). Auto-creates a key on the account and attaches it. Connect afterwards with ssh root@<ip>. |
compute.ssh_key_ids |
No | IDs of existing SSH keys (from /agent/compute/ssh-keys) to attach. |
networking.firewall_rules[] |
No | Inbound firewall rules for the VM |
networking.firewall_rules[].port |
Yes (in rule) | Port number (e.g. 80, 443, 8080) |
networking.firewall_rules[].protocol |
No | tcp (default) or udp |
networking.firewall_rules[].source |
No | Source CIDR, default 0.0.0.0/0 (anywhere) |
domain |
No | Domain for the app |
cdn.enabled |
No | Place CDN in front of the VM |
Firewall rules#
Firewall rules in the deploy request create a security group that is automatically attached to the VM. Each rule defines an inbound port, protocol and optional source CIDR.
Agents can also manage security groups independently via the /agent/compute/firewall endpoints. They can create groups, attach them to VMs or detach them as needed.
SSH access#
Every Edge VM uses root as the default SSH user (regardless of OS). Connect with ssh root@<vm-ip> using a private key whose public counterpart is attached to the VM.
At creation time (preferred)#
Pass the user’s public key as compute.ssh_key, or attach pre-saved keys via compute.ssh_key_ids. The key is baked in via cloud-init at first boot.
After creation#
If the VM already exists, do not recreate it. Save the key on the account, then attach it to the running VM. Edge pushes the key into authorized_keys via the guest agent within ~10 seconds.
1. Save the user’s public key on the account
POST /agent/compute/ssh-keys
Authorization: Bearer ea_live_...
{
"name": "alice-laptop",
"public_key": "ssh-ed25519 AAAA... alice@laptop"
}
# Response:
{
"ssh_key": { "id": "key_abc123", "name": "alice-laptop", "fingerprint": "SHA256:..." },
"next_steps": [
"Pass this key ID in compute.ssh_key_ids when creating a VM, OR",
"Attach to an existing VM with: POST /agent/compute/vms/{vmId}/ssh-keys/key_abc123"
]
}2. Attach the key to the existing VM
There is no need to recreate the VM.
POST /agent/compute/vms/vm_xyz789/ssh-keys/key_abc123
Authorization: Bearer ea_live_...
# Response:
{
"attached": true,
"vm_id": "vm_xyz789",
"ssh_key_id": "key_abc123",
"ssh": {
"user": "root",
"host": "64.34.86.100",
"command": "ssh root@64.34.86.100",
"note": "Wait ~10s for guest-agent push, then connect with your matching private key."
},
"tell_user": "SSH key attached to VM \"my-saas-app\". Key is being pushed to the running VM via the guest agent (typically <10s). Connect with: ssh root@64.34.86.100"
}Connection timing#
- VM provisioning: ~30–60 seconds until
vm.status === "running" - Key propagation on first boot: an additional ~30–90 seconds
- Key push to a running VM (guest-agent path): ~10 seconds
- Polling: poll
GET /agent/compute/vms/{id}; the response includes a ready-to-usessh.commandfield once the VM is connectable
If the user has no SSH key yet#
Have them generate one locally. The private key never leaves their machine:
ssh-keygen -t ed25519 -C "edge-network"
cat ~/.ssh/id_ed25519.pub # paste this into ssh_keySSH endpoints#
| Method | Endpoint | Description |
|---|---|---|
GET |
/agent/compute/ssh-keys |
List SSH keys on the account |
POST |
/agent/compute/ssh-keys |
Save a public key on the account (returns keyId) |
DELETE |
/agent/compute/ssh-keys/{id} |
Delete a key from the account (must be detached first) |
GET |
/agent/compute/vms/{id}/ssh-keys |
List keys attached to a specific VM |
POST |
/agent/compute/vms/{id}/ssh-keys/{keyId} |
Attach an existing key to a VM (works on running VMs) |
DELETE |
/agent/compute/vms/{id}/ssh-keys/{keyId} |
Detach a key (removes from authorized_keys on running VMs) |
Available endpoints#
All compute endpoints available to agents:
| Method | Endpoint | Description |
|---|---|---|
GET |
/agent/compute/vms |
List VMs |
GET |
/agent/compute/vms/{id} |
VM details with live metrics |
GET |
/agent/compute/os-templates |
Available operating systems |
GET |
/agent/compute/scripts |
Startup scripts (Edge library + custom) with parameters |
GET |
/agent/compute/regions |
Available deployment regions |
GET |
/agent/compute/ssh-keys |
List SSH keys |
POST |
/agent/compute/ssh-keys |
Save an SSH public key |
POST |
/agent/compute/vms/{id}/ssh-keys/{keyId} |
Attach SSH key to existing VM |
DELETE |
/agent/compute/vms/{id}/ssh-keys/{keyId} |
Detach SSH key from VM |
GET |
/agent/compute/firewall |
List security groups |
GET |
/agent/compute/firewall/{id} |
Security group details |
POST |
/agent/compute/firewall |
Create security group |
POST |
/agent/compute/vms/{id}/firewall/{groupId} |
Attach security group |
DELETE |
/agent/compute/vms/{id}/firewall/{groupId} |
Detach security group |
Response#
{
"status": "provisioning",
"project_id": "proj_b2c3d4e5f6a7",
"vm": {
"id": "vm_xyz789",
"name": "my-saas-app",
"status": "provisioning",
"ip": "64.34.86.100",
"specs": "1 vCPU, 2 GB RAM, 40 GB disk"
},
"ssh": {
"user": "root",
"host": "64.34.86.100",
"command": "ssh root@64.34.86.100",
"ready": false,
"note": "Wait until vm.status is \"running\" (~30-60s) and key propagation completes (~30-90s on first boot)."
},
"next_steps": [
"Poll: GET /agent/compute/vms/vm_xyz789 until vm.status === \"running\"",
"Then connect: ssh root@64.34.86.100"
],
"resources_created": [
{ "type": "compute_vm", "id": "vm_xyz789", "name": "my-saas-app", "size": "small" },
{ "type": "cdn_deployment", "id": "dep_abc123" }
],
"tell_user": "VM \"my-saas-app\" is being provisioned (small: 1 vCPU, 2GB RAM). IP: 64.34.86.100. Your setup script will run on first boot. SSH ready once status is \"running\". Connect: ssh root@64.34.86.100."
}Health check#
Check the status of all resources in a project:
GET /agent/projects/proj_b2c3d4e5f6a7/health
Authorization: Bearer ea_live_...
# Response:
{
"project": "my-saas-app",
"overall_status": "healthy",
"resources": [
{
"type": "compute",
"id": "vm_xyz789",
"name": "my-saas-app",
"status": "running",
"metrics": {
"cpu_percent": 42,
"ram_percent": 61,
"disk_percent": 28
}
},
{
"type": "cdn",
"id": "dep_abc123",
"name": "my-saas-app-cdn",
"status": "active",
"domains": 1
}
],
"summary": { "total": 2, "healthy": 2, "issues": 0 },
"tell_user": "Project \"my-saas-app\" is healthy. All 2 resources are running normally."
}Scaling#
Scale compute resources up or down:
POST /agent/projects/proj_b2c3d4e5f6a7/scale
Authorization: Bearer ea_live_...
{
"compute": { "size": "medium" },
"reason": "Traffic increased 3x this week, CPU consistently above 80%"
}
# Response:
{
"project": "my-saas-app",
"scaled": [
{ "resource": "vm_xyz789", "name": "my-saas-app", "scaled_to": "medium",
"specs": { "vcpu": 2, "ram": 4, "disk": 80 } }
],
"reason": "Traffic increased 3x this week, CPU consistently above 80%",
"tell_user": "Scaled 1 resource in \"my-saas-app\" to medium."
}See also#
- Deploy a static site: Deploy a static website in one call
- Projects: Health checks, scaling and teardown
Something unclear or out of date? Tell us