Skip to main content

Run S3-Compatible Storage on Acurast

This example runs a single-node Garage S3-compatible object store inside an Acurast Cargo deployment and exposes it over the Acurast Tunnel's two connections:

  • primary connection → the S3 API (port 3900), usable by any S3 client at https://<clientId>.acu.run (path-style, region garage), and
  • secondary connection → SSH for shell access.

The generated S3 access keys are delivered to you as a credentials webhook event.

1. Get the repo and open the example

git clone https://github.com/Acurast/acurast-example-apps.git
cd acurast-example-apps/apps/app-cargo-garage

The Garage project — a self-hosted, S3-compatible object store

2. What's in the app/ folder

FilePurpose
start.shEntrypoint. Phase 1: installs SSH + tunnel deps, builds the getifaddrs shim, starts Dropbear and the tunnel. Phase 2: downloads the Garage binary, writes a single-node config, starts the server, creates the bucket + access key, and starts the S3 API. SSH comes up first so a stalled Phase 2 is still debuggable.
tunnel.pyOpens the reverse tunnel — primary → S3 API (3900), secondary → SSH (2222).
getifaddrs_override.cPRoot shim.
callback.shPOSTs log / started / error / credentials events to your CALLBACK_URL.

3. (Optional) Use your own domain

By default the tunnel serves on https://<clientId>.acu.run, with a Let's Encrypt certificate provisioned automatically — nothing to set up. To use your own domain suffix instead, do the one-time DNS setup (a wildcard record and an _acu TXT record) from the Tunnel Quick Start (step 2) and set DOMAIN_SUFFIX_MAINNET/_CANARY below.

4. Configure .env

cp .env.example .env
VariableRequiredWhat to set
ACURAST_MNEMONICDeployer seed phrase. Never commit it.
NETWORKcanary or mainnet. Must match acurast.json.
DOMAIN_SUFFIX_MAINNET / _CANARYoptionalOnly for a custom domain. Leave unset to serve on acu.run. If set, use the one matching NETWORK and add it to includeEnvironmentVariables.
SSH_PASSWORDoptionalRoot SSH password. Defaults to password — set a strong value.
GARAGE_BUCKEToptionalBucket created on first start (defaults to bucket).
CALLBACK_URLoptionalLifecycle-event webhook — carries the generated S3 keys. Use webhook.watch.

Getting a CALLBACK_URL from webhook.watch

Open webhook.watch for a unique inspector URL and paste it into CALLBACK_URL. This matters more here than usual: the deployment POSTs a credentials event containing the access key and secret for your bucket — you read them straight out of the webhook.watch dashboard.

Editing the .env: GARAGE_BUCKET, SSH_PASSWORD, CALLBACK_URL (webhook.watch), domain suffix

5. A glance at acurast.json

  • runtime: "Shell" on a proot-distro Ubuntu image.
  • execution: onetime, maxExecutionTimeInMs: 14400000 (a 4-hour window).
  • minProcessorVersions.android: "1.26.0" (tunnel support).
  • includeEnvironmentVariables: CALLBACK_URL, SSH_PASSWORD, NETWORK, GARAGE_BUCKET.

6. Deploy

npm i
npm run deploy # runs `acurast deploy`

The CLI shows the reward market and a suggested price — accept it and confirm.

`acurast deploy` — accept the suggested fee

Then watch webhook.watch. After the install log events, the credentials event arrives with the region (garage), the bucket, and your accessKeyId / secretAccessKey.

The `credentials` event in webhook.watch — region &quot;garage&quot;, bucket, and S3 keys


Part 2 — Using the object store

You now have an S3 endpoint and keys. Any S3 client works — here's the AWS CLI (note path-style and region garage):

export AWS_ACCESS_KEY_ID=GK...        # from the credentials event
export AWS_SECRET_ACCESS_KEY=...

aws --endpoint-url https://<clientId>.acu.run --region garage \
s3 cp ./file.txt s3://bucket/
aws --endpoint-url https://<clientId>.acu.run --region garage \
s3 ls s3://bucket/

Browse it with a web UI

Because the primary connection has a real Let's Encrypt certificate, any browser-based S3 explorer can talk to it directly. Point it at the tunnel endpoint, set region garage, enable path-style, and paste the keys from the credentials event.

Connecting a browser S3 explorer to the tunnel endpoint

From there it's an ordinary object store — upload a file and preview it right in the browser (served back through the tunnel via a presigned URL)…

Previewing an uploaded object (the Garage logo) through the S3 explorer

…and it shows up in the bucket, downloadable and shareable.

The uploaded object listed in the bucket

A working S3 endpoint, served from a phone. Keep in mind: stored objects live in the processor's ephemeral storage and are lost when the deployment ends — this is disposable/demo storage, and the generated keys should be treated as secret.