Install
openclaw skills install volcengine-deployUse when deploying a local project directory or, when provided, a Git repository to Volcengine as a running service. Supports ECS (EIP + binary/systemd, Docker, or compose), VKE (container image + Kubernetes), and veFaaS execution through the `volcengine-vefaas` skill. Trigger when the user says "deploy to Volcengine", "deploy this repo", "push to VKE", "run on ECS", "deploy as serverless", or "volcengine deploy" — even without specifying the deploy mode. Run `volcengine-prepare` when the user has not chosen a deployment path. Ask the user to choose resource management (`cli` or `iac`): use `volcengine-iac` only when the user chooses Terraform/IaC or already has an IaC workflow; otherwise use direct `ve` CLI creation with a resource ledger.
openclaw skills install volcengine-deployDeploy a local project directory or remote Git URL to Volcengine after the user chooses ECS / VKE / veFaaS and resource management (cli or iac). Keep deployment execution pragmatic: use volcengine-iac only when the user chooses Terraform/IaC or already has an IaC workflow; otherwise use ve CLI plus .volcengine/created-resources.json.
Volcengine authentication is checked by the execution skill you call (volcengine-cli, volcengine-iac, or volcengine-vefaas). Accept either the required AK/SK env vars for that skill or an already configured CLI profile when that skill supports it; do not duplicate their hard env requirements here.
Check tools after the user chooses a path:
| Mode | Required tools |
|---|---|
| ECS | ve, git, jq, curl; ssh only if the user opens port 22; docker/docker compose only for Docker or compose packaging |
| VKE | ve, docker, kubectl, git, jq, curl |
| veFaaS | switch to/call the volcengine-vefaas skill, which checks vefaas, Node.js, auth, framework detection, and deploy commands |
tosutil is optional for ECS artifact transfer and TOS buckets. Do not add it as a hard prerequisite for volcengine-deploy; if it is absent, use SSH/scp when allowed or ask the user for an existing artifact URL.
If the user has not chosen a mode, run volcengine-prepare inline or ask for these decisions:
1. 部署方式:ECS / VKE / veFaaS(记录为 `ecs` / `vke` / `vefaas`)
2. 资源策略:新建独立项目 deploy-<repo>,或复用已有资源
3. 资源管理:CLI 资源账本 / Terraform IaC(记录为 `cli` / `iac`)
Persistent local state lives under .volcengine/ in the repo root:
.volcengine/
deploy-choice.json
created-resources.json # CLI fast path only
iac-outputs.json
terraform/ # IaC-managed resources
input="${1:-.}"
if [[ "$input" =~ ^(https?|git@) ]]; then
repo_name=$(basename "$input" .git)
work_dir="/tmp/volcengine-deploy/$repo_name"
mkdir -p "$work_dir"
if [ -d "$work_dir/src/.git" ]; then
git -C "$work_dir/src" pull --ff-only
else
git clone --depth 1 "$input" "$work_dir/src"
fi
repo_dir="$work_dir/src"
else
repo_dir=$(cd "${input:-.}" && pwd)
repo_name=$(basename "$repo_dir")
work_dir="$repo_dir/.volcengine"
mkdir -p "$work_dir"
fi
git_sha=$(cd "$repo_dir" && git rev-parse --short HEAD 2>/dev/null || echo "$(date +%s)")
Local directories are deployed in place and are not cloned. For Git URLs, use shallow clone first; if clone repeatedly fails, try an archive/subdirectory path or stop with a clear "not suitable for quick remote build" message. Do not claim a README/static mirror is the deployed application.
Load .volcengine/deploy-choice.json if present. If absent, ask the fixed decisions above or run volcengine-prepare.
Choice file shape:
{
"schema_version": "1",
"repo_dir": "/absolute/path",
"repo_name": "my-app",
"git_sha": "abc1234",
"region": "cn-beijing",
"mode": "ecs",
"port": 8080,
"dependencies": ["redis"],
"resource_strategy": "create-isolated-project",
"project": "deploy-my-app",
"infra_management": "cli"
}
Confirm before creating resources:
Deploying <repo_name> via <mode> in <region>.
Resources: <new isolated project deploy-... | reuse existing resources>
Proceed? [y/N]
Use the resource ledger only for CLI-created resources. IaC-created resources are tracked by Terraform state and exported through .volcengine/iac-outputs.json.
Every resource created by volcengine-deploy must be appended to .volcengine/created-resources.json immediately after creation. This is mandatory for cleanup and failure recovery.
Ledger entry:
{
"type": "eip",
"id": "eip-xxxx",
"name": "deploy-myapp-eip",
"region": "cn-beijing",
"project": "deploy-myapp",
"reused": false,
"created_at": "2026-05-29T00:00:00Z",
"delete_command": "ve vpc ReleaseEipAddress --AllocationId eip-xxxx"
}
Rules:
reused=false, include exact delete command.reused=true, do not include them in destructive cleanup.dependent=true / cleanup_optional=true or omit it as an independent ledger item. Do not make cleanup fail just because the instance already released the EIP.delete_command values manually. Do not silently delete unless the user confirms.deploy-<repo> for new resources, but confirm the project exists or can be created before passing that project name to resource creation. If project creation is unavailable, use default and isolate resources with names and tags.Before provisioning, confirm one resource management path with the user:
| Condition | Path |
|---|---|
| VKE, managed DB/cache/storage/LB/domain/certificate, team-owned infra, or plan/diff/destroy matters | volcengine-iac |
| Pure ECS single-VM service with no managed dependencies and no explicit plan/diff/destroy requirement | CLI fast path |
| User says temporary/demo/quick validation/just run it | CLI fast path |
| Terraform/provider registry is unavailable, especially in China networks, and the target is not VKE/managed dependencies/team-owned infra | CLI fallback |
| User explicitly says no Terraform/IaC | CLI fast path |
These are recommendations, not defaults. If .volcengine/deploy-choice.json lacks infra_management, ask before creating resources:
资源管理建议:<cli|iac>,原因:<short reason>。确认用 CLI 资源账本还是 Terraform/IaC?(`cli` / `iac`)
When using IaC:
volcengine-iac with .volcengine/deploy-choice.json..volcengine/iac-outputs.json for VPC/subnet/security group/cluster/CR/database/cache outputs.When using CLI:
ve..volcengine/created-resources.json immediately.Before starting ECS services or applying Kubernetes manifests, resolve runtime configuration:
.env.example, .env.sample, framework config, and dependency outputs from IaC/CLI provisioning.0600./opt/<repo>/.env before starting the service; the unit template reads it through EnvironmentFile=-/opt/<repo>/.env.<connection-string> placeholders in an applied Secret.Managed dependency wiring must be completed before health checks:
DATABASE_URL; add the ECS/VKE subnet CIDR or security group source to the database allowlist; run migrations explicitly when migration_paths is non-empty.REDIS_URL; add the ECS/VKE subnet CIDR or security group source to the Redis allowlist.case "$deploy_mode" in
ecs) proceed_ecs ;;
vke) proceed_vke ;;
vefaas) run_vefaas_skill ;;
*) echo "Unknown deploy mode: $deploy_mode"; exit 2 ;;
esac
ECS is the default lightweight VM path. Public services must get an EIP so the user can access the service after deployment.
Packaging selection:
| Signal | Packaging |
|---|---|
compose.yaml / compose.yml / docker-compose.yml / docker-compose.yaml | Docker compose on ECS |
| Dockerfile exists | Docker on ECS |
| compiled binary or clear single process | binary + systemd |
| unclear start command | ask one follow-up |
Provisioning:
infra_management=iac.RunInstances still reports the selected type unavailable or sold out, automatically try the next available candidate before failing.RunInstances requires a login credential even when SSH is closed. Provide a generated one-time strong --Password or an existing --KeyPairName; do not print or write generated passwords to ledger/state.Security group:
Command channel:
RunCommand caveat:
Volcengine RunCommand is asynchronous. Do not treat the scheduling response as command success. Read the invocation ID, then poll invocation results until success/failure before continuing.
Deployment:
binary-systemd: build or package the app, upload, generate systemd unit, start service.ecs-docker: install/start Docker if needed, run the image with restart policy.ecs-compose: run the compose file with the compose command available on the target host, and explain volume persistence for stateful services such as Redis.Docker image pulling in China:
Docker build architecture:
linux/amd64 unless cluster/node pool data proves otherwise.docker buildx build --platform linux/amd64 ... or pull/build with --platform linux/amd64, then inspect the pushed image architecture before rollout.Data dependencies:
Health gate:
ss -ltnp before diagnosing security groups or EIP.http://localhost:<port><health_path> when a health path is known. If no health path is detected, use TCP/listening checks and root-path smoke checks instead of assuming /health.http://<EIP>:<port> from outside after the security group is open.Do not duplicate veFaaS deployment details here. If the user chooses veFaaS, switch to/call the volcengine-vefaas skill with:
Tell the user the volcengine-vefaas skill will run vefaas inspect, verify login, create/link the app, configure env vars if needed, deploy, and print domains.
If the volcengine-vefaas skill fails, return to this main deployment flow. Summarize the failure, then offer the user a choice:
Recommend volcengine-iac for VKE resource provisioning because cluster, node pool, CR, LB, and managed dependencies benefit from plan/diff/destroy safety. Use ve CLI plus the resource ledger when the user chooses CLI after seeing the tradeoff, for temporary validation, explicit user preference, or IaC fallback.
Required after choosing VKE:
docker for image buildkubectl for Kubernetes apply/rolloutterraform/jq for IaC resource provisioning unless using CLI fast pathve for CLI fallback, CR authentication, and read-only diagnosticsFlow:
linux/amd64..volcengine/iac-outputs.json.core-dns must be present for in-cluster service discovery/DNS, and cr-credential-controller should be present when pulling private Volcengine CR images without managing registry passwords in app manifests.For managed dependencies, prefer managed Volcengine services when practical; otherwise state clearly when the plan is deploying stateful containers inside VKE.
Print one access card:
volcengine-deploy — <repo_name> (<git_sha>)
Mode: <ecs|vke|vefaas>
Region: <region>
Project: <deploy-project or reused resources>
URL: <public endpoint>
Health: <checked URL/status>
Acceptance: <core app behavior checked, or reason only transport health was possible>
Resources: .volcengine/created-resources.json
IaC: <.volcengine/terraform + .volcengine/iac-outputs.json | n/a>
Logs: <journalctl / docker logs / kubectl logs / vefaas logs command>
Cleanup: <reverse-order cleanup commands or ledger path>
Notes: <credentials/env/migration warnings>
Do not add custom domain, HTTPS, dashboards, or cost cards unless the user asks; those are day-2 tasks.
Use these references only when executing the corresponding path:
references/ecs-deploy-steps.mdreferences/faas-deploy-steps.mdreferences/dockerfile-templates.mdreferences/k8s-manifests.mdreferences/supported-dependencies.md| Symptom | Likely cause | Action |
|---|---|
| ECS instance type creation fails | type not available in zone | Query DescribeAvailableResource and pick another available type. |
| SSH blocked | port 22 closed or network policy | Use Cloud Assistant; do not wait on long SSH retries. |
| RunCommand appears successful but app not changed | only scheduling result was checked | Poll invocation results before continuing. |
| RunCommand Success but app is not usable | script exited successfully before real runtime verification | Check unit/container status, listening port, logs, and one core app behavior; HTTP 200 alone is not acceptance. |
| RunInstances returns MissingParameter.PasswordAndKeyPair | ECS requires Password or KeyPairName even with SSH closed | Generate a one-time strong password or use an existing key pair; do not print generated credentials. |
| InvalidEipAddressChargeType.Malformed | Used EIP billing value from another API | For RunInstances --EipAddress.ChargeType, use PayByBandwidth, PayByTraffic, or PrePaid. |
| Cloud Assistant status jq returns empty | Wrong response path | Use .Result.Instances[0].Status; wait for Running. |
| Docker Hub/GHCR pull hangs or times out | China network or public registry throttling | Prefer CR/user registry; for Docker Hub test docker.1ms.run, dockerproxy.net, proxy.vvvv.ee, or dockerproxy.link; for sync/search sites such as docker.aityp.com, inspect the image detail page and use the exact pull command; fall back to binary/systemd when possible. |
| Domestic mirror hostname returns no basic auth credentials | The site may be a search/sync frontend, not a drop-in registry path for every image | Open/parse the image detail page and use the exact "国内镜像" / docker pull command it provides. |
| docker login returns 401 | wrong CR username | Re-read Result.Username from GetAuthorizationToken; if it is missing, inspect the CR API response instead of inventing a fallback username. |
| app starts but config-dependent requests fail | .env or Kubernetes Secret was not generated from required values | Resolve .env.example/dependency outputs, inject ECS .env or K8s Secret, then restart/roll out. |
| app cannot connect to RDS/Redis | private endpoint or allowlist not wired | Use private endpoint, build DATABASE_URL/REDIS_URL, and add ECS/VKE subnet CIDR or security group source to the service allowlist. |
| PostgreSQL migrations fail on public schema | database owner and schema owner differ | Set database owner to the app account and use rdspostgresql ModifySchemaOwner for public before migrations. |
| Shell health check fails with curl: (23) | curl | head under set -o pipefail | Avoid piping curl to early-closing consumers; write to a file or use curl -o /dev/null. |
| container fails with exec format error | image architecture does not match VKE/ECS node architecture | Rebuild/pull/push with the node platform, usually linux/amd64, and inspect the image before rollout. |
| BLB no available backend | Pod readinessProbe failing, often because /health does not exist | Use a detected health path or switch probes to tcpSocket; inspect with kubectl describe pod and kubectl logs. |
| CreateKubeconfig returns OperationDenied | cluster not yet Running | Poll DescribeClusters until phase=Running first |
| RunCommand returns InvalidParameter.Timeout | timeout too low for the current API/CLI | Pass --Timeout 60 minimum (see volcengine-cli/references/ecs.md) |
| veFaaS setup fails | vefaas CLI/auth/framework issue | Return to the main deploy flow, summarize the failure, and let the user retry veFaaS or switch to ECS/VKE. |
| K8s LoadBalancer stuck in <pending> | CLB subnet annotation missing | Add service.beta.kubernetes.io/volcengine-loadbalancer-subnet-id to Service annotations |