Whisper · Docs
Containers & cloud

Vultr Marketplace

A VM you click into existence on Vultr is anonymous compute — every outbound request leaves as the same shared-pool IP as ten thousand other tenants, one abuse report from the whole range getting blocked.

The Whisper Agent Node fixes that at the one moment you fully control a VM's fate: first boot. Deploy it from the Marketplace, paste your Whisper key as an optional deploy variable, and the instance comes up already holding a real, routable, reverse-resolvable IPv6 /128 — with a persistent egress service binding every outbound packet to that address. No framework to install, no sidecar to wire up later, no snowflake box to remember.

The pain this removes

Ask any team that has tried to run agents — or just outbound automation — from rented cloud compute:

Whisper's answer, on Vultr specifically: an imageless, 1-click Marketplace app — no custom snapshot to maintain — that ships completely empty (no secret, ever) and, if you hand it a key at deploy time, wires up a named, routable, cryptographically verifiable agent identity before you've finished your coffee.

Two-tier by design

no key (default) whisper_api_key supplied at deploy
whisper CLI installed from the signed repo yes yes
Keyless checks (whisper verify, whisper rdap) yes yes
Named agent /128 minted (PTR + RDAP) you run whisper later yes, automatic on first boot
Persistent egress (whisper-egress service) yes — Tier-1 WireGuard, auto-fallback to Tier-1.5 SOCKS5
Shells egress from the /128 by default yes (ALL_PROXY)

Leave the key field blank and you get a clean box with the CLI ready — whisper verify and whisper rdap work against any address with zero configuration, no account needed. Postel's Law applied to a marketplace listing: liberal in what it accepts (a key is optional, read from four different places — see below), conservative in what it ships (nothing baked in, ever).

The mechanism: imageless Vendor Data, not a snapshot

Most Marketplace 1-click apps are a pre-baked disk snapshot — rebuild the image, resubmit for review, every time anything changes. The Whisper Agent Node is script-based: the entire deploy artifact is a POSIX sh script, firstboot.sh, submitted to Vultr as cloud-init Vendor Data and run once, idempotently, on first boot (guarded by a /etc/whisper/.provisioned stamp — cloud-init's "boot" script type re-runs on every boot, so the script has to make itself a no-op after success). That means a CLI release alone needs no resubmission — the script always installs the current signed package.

Vendor Data runs before user data, as root, per the cloud-init module contract. Whisper's script does three things in order:

  1. Install the CLI from a signed channelapt/dnf against get.whisper.online (GPG-verified repo metadata), falling back to the same sha256+PGP-verified curl https://get.whisper.online | sh installer used everywhere else. No unsigned binary ever touches the box.
  2. Read the optional deploy variables liberally. Vultr's Metadata API is queried at http://169.254.169.254/v1/internal/app-<name> and the legacy v1.json app_variables document; if neither has a value, a cloud-init-seeded file under /etc/whisper/ is tried; if that's empty too, an environment variable. Four channels, one variable — accept it however it arrives, because a marketplace portal, a raw API deploy, and a hand-written cloud-config all seed variables differently.
  3. If (and only if) a key showed up: write it to the CLI's own key file (~/.config/whisper-ns/key, mode 600 — identical to what whisper login <key> does), verify it against the control plane, mint a named agent identity, and bring up systemd unit whisper-egress.service holding whisper connect open as a local socks5h://127.0.0.1:1080 front. A companion whisper-egress-watch.timer polls a functional probe every minute — not systemctl is-active, an actual fetch through the proxy that must observe a 2a04:2a01::/32 source — and restarts the service on two consecutive misses. If Tier-1 WireGuard can't verify within 90 seconds (UDP filtered by the network, say), the script automatically retries at Tier-1.5 SOCKS5. Either way the front is the same socks5h://127.0.0.1:1080, so nothing downstream needs to know which tier won.

The deploy-time variables, all optional:

Variable Default Meaning
whisper_api_key (none — keyless) Your Whisper key. Present ⇒ turnkey identity + egress on first boot.
whisper_agent_name vultr-<hostname> Name for the minted agent (sanitized to [A-Za-z0-9-], ≤ 63 chars).
whisper_egress_tier wireguard wireguard (Tier-1, routed /128) or socks5 (Tier-1.5). Auto-falls back if WireGuard can't verify.

The seed file, if used, is deleted the instant it's read — the key lives only in the CLI's own 0600 key file from that point on.

Deploying it

With stock tools — build the user-data yourself against the raw Vultr API (no Whisper software involved in the deploy step itself):

# cloud-config.yaml is the YAML wrapper around firstboot.sh; seed a key file too
UD=$(base64 -w0 userdata.yaml)
curl -s -X POST https://api.vultr.com/v2/instances \
  -H "Authorization: Bearer $VULTR_API_KEY" -H 'Content-Type: application/json' \
  -d "{\"region\":\"ams\",\"plan\":\"vc2-1c-1gb\",\"os_id\":2136,
       \"enable_ipv6\":true,\"label\":\"whisper-node\",\"user_data\":\"$UD\"}"

With Whisper — on the Marketplace, this is a form: pick Whisper Agent Node, paste your key into the optional Whisper API key field, deploy. Nothing to script. Either path lands on the same box running the same firstboot.sh.

Verifying the identity — from outside, with nothing installed

Once it's up, the /128 is a real address in 2a04:2a01::/32 (announced by AS219419) — provable with tools you already have.

With stock tools:

# reverse DNS
dig -x 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4 +short
# → acef2002a323d40d4.<tenant>.agents.whisper.online.

# the TLS identity behind that name (DANE-anchored)
openssl s_client -connect acef2002a323d40d4.<tenant>.agents.whisper.online:443 \
  -dane_tlsa_domain acef2002a323d40d4.<tenant>.agents.whisper.online \
  -dane_tlsa_rrdata "3 1 1 b653a4ef…fcb82d1d" < /dev/null

# is the egress actually sourcing from that /128?
curl --socks5-hostname 127.0.0.1:1080 https://rdap.whisper.online/egress-ip

With Whisper, the same three checks collapse to one command run on the box:

whisper ip        # proves the live egress source is the node's own /128
whisper verify acef2002a323d40d4.<tenant>.agents.whisper.online   # DANE + DNSSEC + reverse-DNS + transparency, the full keyless chain

Both go through the identical public checks documented on DANE and reverse fCrDNS — the CLI just runs the whole chain for you instead of you assembling dig/openssl/curl by hand.

What's running on a connected node

whisper-egress.service        # Restart=always; holds `whisper connect` open, 127.0.0.1:1080
whisper-egress-watch.timer    # every 60s: functional probe → restart on 2 consecutive misses
/etc/whisper/identity.env     # agent name, /128, tier, proxy — no secret, world-readable
/etc/profile.d/whisper-egress.sh   # login shells export ALL_PROXY=socks5h://127.0.0.1:1080

ALL_PROXY is socks5h, deliberately — the h means hostnames resolve through the proxy, i.e. through Whisper policy DNS, not the VM's local resolver. Remove /etc/profile.d/whisper-egress.sh any time to opt a shell out.

This was e2e-proven on a real vc2-1c-1gb Debian 12 instance in Vultr's ams region: first boot installed the signed CLI, minted a named agent, brought up Tier-1 WireGuard egress, and passed the functional proxy probe, PTR lookup, and RDAP check — including a deliberate egress-kill test that self-healed via the watchdog in under 90 seconds.

Submitting or re-submitting this listing is a two-gate process on Vultr's side — verified-vendor onboarding, then Marketplace QA after "Make Public" — both external reviews outside Whisper's control. Everything up to the portal, including the live e2e proof, is captured in the Vultr recipe (firstboot.sh as cloud-init Vendor Data), which you can run against your own Vultr account without waiting on the listing.

Same recipe, other clouds

The identical two-tier, bring-your-own-key model ships for DigitalOcean (a Packer-built Marketplace snapshot rather than imageless Vendor Data — DigitalOcean's app model expects a pre-baked image) and for Kubernetes, where a mutating admission webhook injects the same egress behavior as a sidecar into opted-in pods instead of a systemd unit on a VM. Pick whichever unit of deployment matches how you already run compute; the identity and egress guarantees are the same.

Next

DigitalOcean Marketplace · Connect & egress tiers