Quickstart - Cargo (Preview)
The Cargo runtime is in preview. APIs and configuration fields may change before general availability.
Cargo deployments run as native binaries inside a Linux distro image on the processor, isolated via PRoot. Unlike the default Node.js runtime, Cargo gives you full access to the Linux environment: shell scripts, native tooling, and any language you can ship as a Linux binary.
Prerequisites
A 64-bit Android Core processor on Canary
Cargo deployments require a 64-bit (aarch64) Android device running as an Acurast Processor Core on the Canary network. The Lite processor and iOS devices are not supported.
To set one up yourself:
- Factory-reset a 64-bit Android phone (Android 12+).
- Visit Acurast Hub ↗, switch to the Canary network, and connect your wallet.
- Follow the Processor Core setup flow - the device will be locked down as a dedicated compute provider.
Full guide: Become a Compute Provider.
After onboarding, there is a warmup period of up to 3 epochs (~4.5 hours) before the device becomes eligible for public assignment matching. If you want to deploy on your freshly onboarded device before the warmup completes, it can be skipped by targeting the device directly with Instant deploy.
Acurast CLI
Install the CLI globally:
npm install -g @acurast/cli
cACU balance
Cargo deployments run on the Canary network. Claim free cACU from the faucet ↗.
Step 1 - Create a project
acurast new generates a Node.js project with a file structure that does not apply to Cargo and can be skipped. Create the project directory yourself and run acurast init inside it instead:
mkdir cargo-hello
cd cargo-hello
acurast init
This creates acurast.json (deployment config) and .env (secrets). See the CLI docs for all available commands and options.
Step 2 - Write your Cargo app
The PRoot container starts with a minimal environment. Depending on the tooling you use, you may need to set PATH, HOME, or configure DNS resolution before running it.
DNS resolution - Android has no system-level /etc/resolv.conf. Without it, DNS resolution inside the chroot fails silently: apt-get update downloads nothing, package lists stay empty, and subsequent apt-get install calls report packages as not found. Write a nameserver entry before any network calls:
echo "nameserver 8.8.8.8" > /etc/resolv.conf
See PRoot Quirks for more known environment issues, including a getifaddrs() workaround for programs that inspect network interfaces.
Create your app entrypoint file acurast.sh:
#!/bin/sh
# Set up environment variables
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export HOME=/root
# Set up DNS resolver
echo "nameserver 8.8.8.8" > /etc/resolv.conf
# TODO: Run your code
The bridge socket
The processor injects a BRIDGE_SOCKET environment variable at runtime. This is an abstract Unix domain socket that exposes host services - cryptographic signing, deployment metadata, and browser control - via a JSON-RPC 2.0 API.
Full API reference: Cargo Runtime Environment.
Step 3 - Configure for the Cargo (Shell) runtime
Open acurast.json and configure your project to use the Shell runtime. The Shell runtime is the foundation of Cargo - it boots a Linux distro image on the processor and runs your entrypoint script inside it.
Your app files (fileUrl) are extracted into the rootfs before the entrypoint runs. Structure them however you like - the only requirement is that the file named by entrypoint is a shell script and is placed at the root of the fileUrl directory or it's the fileUrl itself.
{
"projects": {
"cargo-hello": {
"projectName": "cargo-hello",
"fileUrl": "acurast.sh",
"entrypoint": "acurast.sh",
"runtime": "Shell",
"image": {
"url": "https://github.com/termux/proot-distro/releases/download/v4.30.1/ubuntu-questing-aarch64-pd-v4.30.1.tar.xz",
"sha256": "5ab35b90cd9a9f180656261ba400a135c4c01c2da4b74522118342f985c2d328"
},
"network": "canary",
...
}
}
}
Key fields for the Cargo runtime:
| Field | Description |
|---|---|
runtime | Must be "Shell" to enable the Cargo runtime |
image | Linux distro image to boot - url (HTTPS .tar.xz) + sha256 for verification. Must be an aarch64 image |
entrypoint | Script the processor runs after extracting the image |
fileUrl | Path to the directory (or file) uploaded to the processor alongside the image |
For all other fields, see the CLI configuration reference.
Supported distro images are listed in the Termux proot-distro releases ↗.
The Linux image is freshly unpacked for every execution - there is no persistent cache between runs. Any dependencies installed during one execution (e.g. via apt-get) will not be available in the next. Make sure your deployment schedule accounts for the setup time required at the start of each execution.
Instant deploy
To deploy directly to a specific device without waiting for the warmup period, use the instantMatch field inside assignmentStrategy. Each entry targets a processor by its SS58 address:
{
"projects": {
"cargo-hello": {
...
"assignmentStrategy": {
"type": "Single",
"instantMatch": [
{
"processor": "<SS58-address>",
"maxAllowedStartDelayInMs": 10000
}
]
},
"numberOfReplicas": 1,
...
}
}
}
Set numberOfReplicas to match the number of entries in instantMatch. You can find the processor address in the Acurast Hub after onboarding.
Step 4 - Deploy
acurast deploy
The CLI uploads your app/ directory to IPFS and registers the deployment on-chain. The processor downloads the distro image and your app, boots the container, and runs start.sh.
Monitor your deployment:
acurast deployments ls --network canary
Example - Hello Cargo
This example uses Python to fetch the processor's public key and POST it to a webhook. It runs four times at 3-minute intervals.
Full source: acurast-example-apps/apps/app-cargo ↗.
Project layout:
app/
start.sh
hello.py
acurast.json
.env
app/start.sh - sets up the environment, installs dependencies, and launches the Python script:
#!/bin/sh
# Set up PATH, HOME, and DNS
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export HOME=/root
echo "nameserver 8.8.8.8" > /etc/resolv.conf
# Install necessary dependencies and run the main application
apt-get update
apt-get install -y python3-requests
python3 "$(dirname "$0")/hello.py"
app/hello.py - calls the bridge socket to get the signing public key, then POSTs it to a webhook:
import json
import os
import socket
import requests
BRIDGE_SOCKET = os.environ["BRIDGE_SOCKET"]
WEBHOOK_URL = os.environ["WEBHOOK_URL"]
def get_public_key() -> str:
request = json.dumps({
"jsonrpc": "2.0",
"method": "signer_publicKey",
"params": [{"curve": "p256"}],
"id": "1",
}) + "\n"
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
sock.connect("\0" + BRIDGE_SOCKET)
sock.sendall(request.encode())
response = b""
while True:
chunk = sock.recv(4096)
if not chunk:
break
response += chunk
if b"\n" in chunk:
break
return json.loads(response)["result"]["publicKey"]
def main():
public_key = get_public_key()
url = WEBHOOK_URL.rstrip("/") + "/hello"
resp = requests.post(url, json={"publicKey": public_key})
print(resp.status_code, resp.text)
if __name__ == "__main__":
main()
Add your webhook URL to .env:
ACURAST_MNEMONIC=abandon abandon about ...
WEBHOOK_URL=https://your-webhook.example.com
Next steps
- Cargo Runtime Environment - full RPC API reference (signing, encryption, browser control, deployment metadata).
- CLI docs - all commands, config fields, and environment variable encryption.
- Environment Variables - how to declare and encrypt secrets for your deployment.
- Deployment Config - complete
acurast.jsonfield reference.