shark-expose
shark expose 3000: put a local port on the internet through your own Hammerhead and Blacktip, the way ngrok does, with nothing to clean up afterwards.
$ shark expose 3000 --password s3cret
shark http://demo-4f2a.dev.example.com -> 127.0.0.1:3000
Visitors must sign in.
Press Ctrl+C to stop.
One command asks Hammerhead for a short-lived site and a public name or port, brings up the WireGuard tunnel from your machine (it embeds the Bamboo agent, so there is nothing else to install or run), prints the address, and keeps it alive. On Ctrl+C it deletes everything it created. If shark is killed or loses the network, Hammerhead removes the exposure itself once its TTL runs out (5 minutes unless you say otherwise).
Install
go env -w GOPRIVATE=git.veillax.com
go install git.veillax.com/Veillax/shark-expose/cmd/shark@latest
Sign in
Make an API key under Access in the Hammerhead dashboard, then:
shark login --hammerhead https://hammerhead.example.com --token hhk_...
This checks the key and saves it to your user config folder (shark/config.json, readable by you only; SHARK_CONFIG picks another file). SHARK_HAMMERHEAD and SHARK_TOKEN override it, which suits CI.
An API key belongs to one organization and can manage its settings, so treat it like a password. Exposures are made in that organization.
Use
shark expose 3000 website on <random>.<one of your domains>
shark expose https 3000 the same over HTTPS (Blacktip gets the certificate)
shark expose 3000 --name demo demo-<random>.<domain>
shark expose 3000 --hostname me.dev.example.com
shark expose 192.168.1.20:8080 something else on your network
shark expose tcp 25565 raw TCP on a free public port (20000-29999)
shark expose tcp 22 --port 20022 ...on the port you pick
shark ls what is exposed in your organization right now
| Flag | |
|---|---|
--password P, --pin N, --sso |
Put a login in front of a website: a shared password (6+ characters), a PIN (4-12 digits), or a Hammerhead account. Can be combined; SHARK_PASSWORD avoids putting the password on the command line. |
--ttl 10m |
How long Hammerhead keeps it if shark goes quiet (30s to 24h). shark renews every third of that while it runs. |
--name, --hostname, --port, --edge |
Choose the label, the full public name, the public port, or the edge. |
--verbose |
Show the tunnel agent's log. |
For websites Hammerhead needs a domain to put the name under (Domains in the dashboard), with a wildcard DNS record pointing at the edge. TCP needs no domain: it uses the edge's address and a free port in 20000-29999, which has to be open in the edge's firewall. Login protection is for websites only.
How it works
POST /api/orgs/-/exposemakes an ephemeral site and mapping taggedephemeraland returns the public address and the site's token.- shark runs Bamboo in-process with that token. It dials out to the edge, so your machine needs no inbound ports.
- When the edge reports the port listening, shark prints the address.
POST .../renewevery TTL/3. A 404 means Hammerhead dropped it, and shark exits with an error; renewals failing for longer than the TTL end it too.DELETEon exit. The site, port, login secrets and tunnel address all go with it.
The API is documented in Hammerhead's README ("Ephemeral exposures"). It currently lives on Hammerhead's feature/ephemeral-expose branch.
Development
go test ./... # unit tests, with a fake Hammerhead
cd e2e && go test ./... # shark against a real Hammerhead + Blacktip + Bamboo in one process
e2e is its own module so the CLI does not depend on Hammerhead. Its go.mod has a replace pointing at ../../hammerhead-expose, a checkout of the Hammerhead branch above; change it once that is merged and released.