Files
Bamboo/README.md
T
VeillaxandClaude Sonnet 5.5 a2403ecf9d
CI / test (push) Successful in 3m51s
Release / release (push) Successful in 4m43s
Terminal relay: answer Hammerhead's terminal sessions through the agent
When someone opens a terminal for this site, Hammerhead lists the session in the
site's config. The agent connects out to Hammerhead and joins that connection to
its own SSH server, so no port has to be open on an edge. The agent now reports
where its SSH server listens and that it can relay.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-31 01:38:46 -06:00

8.6 KiB

Bamboo

Bamboo runs inside your home or private network. It dials out to Blacktip over WireGuard, so it works behind NAT, and passes traffic to your real services. It can also list your Docker containers as targets and run a local mail relay for outgoing mail.

Part of the sharks stack: Hammerhead (control plane and dashboard) · Blacktip (edge) · Bamboo (site agent) · Reef (shared library). Everything is configured from Hammerhead's web dashboard; the full documentation lives in its README.

Run it

In Hammerhead, go to Sites → add a site. The dashboard shows the exact command with your token. It looks like this:

bamboo -hammerhead https://hammerhead.example.com -token <site token> -docker

Bamboo only makes outbound connections (HTTPS to Hammerhead, and WireGuard UDP to each edge), so it needs no open ports and no port forwarding.

Flag Environment Meaning
-hammerhead BAMBOO_HAMMERHEAD URL of Hammerhead
-token BAMBOO_TOKEN the site's token
-data BAMBOO_DATA folder for this agent's WireGuard key (default ./bamboo-data)
-docker BAMBOO_DOCKER=1 report local Docker containers so they can be picked as targets
-discover BAMBOO_DISCOVER=1 report services listening on this machine (Linux) as suggested targets
-discover-subnets BAMBOO_DISCOVER_SUBNETS also scan these private subnets, e.g. 192.168.1.0/24,10.0.0.0/24 (each at most a /22)
-discover-ports BAMBOO_DISCOVER_PORTS ports to try when scanning, e.g. 22,80,443,8000-8010 (default: 19 common ones)
-discover-rate BAMBOO_DISCOVER_RATE most connection attempts per second (default 50)
-ssh BAMBOO_SSH=1 run a small SSH server so this machine can be reached through a tunnelled port (Linux and macOS)
-ssh-listen BAMBOO_SSH_LISTEN address it listens on (default 127.0.0.1:2222)
-ssh-keys BAMBOO_SSH_KEYS authorized_keys file listing who may sign in (default: authorized_keys in the data folder)
-env .env file to read (default ./.env)

Settings and secrets can live in a .env file instead of the command line; see .env.example. Real environment variables always win.

What it does

  • Tunnel: one WireGuard peer per edge, through a userspace network stack (no root, no kernel interface, no driver; works on Windows, macOS and Linux). Its private key never leaves this machine. TCP connections and native UDP datagrams are accepted from the edge and handed to your services.
  • Docker discovery: with -docker, lists running containers (and their ports and networks) so you can pick one as a target in the dashboard.
  • Service discovery: off unless you ask for it. With -discover, lists the TCP services listening on this machine (read from /proc/net/tcp, so Linux only). With -discover-subnets, it also tries the chosen ports on every address of those subnets. Each hit is identified (SSH, SMTP, FTP, HTTP, HTTPS, or the usual service for that port) and reported to Hammerhead as a suggested target; nothing is exposed until you pick one. It is deliberately gentle: only private, loopback or link-local subnets of at most 1024 addresses are accepted, connection attempts are capped (50 per second by default), a sweep runs every 15 minutes, and a service that stays silent gets a single TLS handshake and then one HEAD / request, nothing more. At most 500 services are reported. Only scan networks you are allowed to scan.
  • SSH server: off unless you ask for it. With -ssh, Bamboo runs a small SSH server, so you can open a shell or run a command on this machine from anywhere through a tunnelled port, with no sshd to install. Put the public keys that may sign in in authorized_keys in the data folder (one per line, like OpenSSH; Bamboo will not start the server without at least one, and picks up edits without a restart). Then, in Hammerhead, add a TCP port whose target is this site at 127.0.0.1:2222, and connect with ssh -p <port> user@<edge address>. The user name is ignored: sessions run as the user Bamboo runs as, so a Bamboo running as root gives a root shell, and the keys should be treated that way. Public keys only (no passwords), session channels only (no port forwarding, agent forwarding or SFTP), and it listens on the loopback address unless you change -ssh-listen. The host key is created in the data folder on first start and its fingerprint is written to the log, so you can check it the first time you connect. Hammerhead's dashboard terminal reaches this server through the agent itself: Bamboo reports where the server listens, and when someone opens a terminal it connects out to Hammerhead and joins that connection to the server, so no port has to be open anywhere. Add the public key Hammerhead shows (SSH button on the Sites page) to authorized_keys to allow it. Not available on Windows.
  • Mail relay: for a mail egress configured in the dashboard, opens a small SMTP relay on this machine (default 127.0.0.1:2525). Point your mail server at it (Postfix: relayhost = [127.0.0.1]:2525) and each outgoing message leaves from the edge's public IP, so reverse DNS, SPF and your HELO name line up. Supports AUTH PLAIN/LOGIN, requires a password if it listens beyond 127.0.0.1, relays one destination domain per transaction (extra domains get 452 so your server resends them separately), and passes your server's queue and retries through unchanged. 50 MB message limit.

Deploying

Releases are built by Gitea Actions. Pushing a tag such as v0.2.0 runs .gitea/workflows/release.yml, which tests the code, builds Bamboo for Linux (amd64, arm64, armv7), Windows (amd64) and macOS (amd64, arm64), publishes the archives with a SHA256SUMS file on the Releases page, and pushes a multi-architecture container image to this server's registry (git.veillax.com/veillax/bamboo). Every push and pull request runs .gitea/workflows/ci.yml: formatting, vet, tests, and a check that every release platform still compiles.

On a Linux server (systemd)

curl -LO https://git.veillax.com/Veillax/bamboo/releases/download/v0.1.6/bamboo_v0.1.6_linux_amd64.tar.gz
curl -LO https://git.veillax.com/Veillax/bamboo/releases/download/v0.1.6/SHA256SUMS
sha256sum -c --ignore-missing SHA256SUMS
tar xzf bamboo_v0.1.6_linux_amd64.tar.gz && cd bamboo_v0.1.6_linux_amd64
sudo ./install.sh                 # installs the binary and a hardened systemd service
sudoedit /etc/bamboo/bamboo.env   # your settings and secrets
sudo systemctl start bamboo

Use linux_arm64 or linux_arm for Raspberry Pi and other ARM machines. To upgrade, repeat the same steps: your settings and data are kept. sudo ./install.sh --uninstall removes the service and binary but leaves /etc/bamboo and /var/lib/bamboo alone. bamboo -version tells you which build is running.

Updates

Set BAMBOO_AUTO_UPDATE=1 (or pass -auto-update) and Bamboo checks this server for a newer release every few hours, verifies it against SHA256SUMS, checks that the new binary runs, swaps it in and restarts itself. It only follows full releases (never pre-releases), never downgrades, and keeps the old binary if anything looks wrong. setup.sh turns it on. It is not available on Windows, and it is for the systemd and plain-binary installs: with Docker, pull a new image instead.

With Docker

cp .env.example .env              # fill it in
docker compose -f deploy/docker-compose.yml up -d

The image is git.veillax.com/veillax/bamboo:<version> (and :latest for full releases). The compose file is in the repository and inside each Linux archive.

Setting up the build (once)

  • A Gitea Actions runner with the label ubuntu-latest, and Docker on it if you want the container image.
  • Nothing else is required: the workflows use the automatic job token. If your server doesn't let that token publish releases or packages, add the secrets RELEASE_TOKEN and REGISTRY_TOKEN (access tokens with release and package write permission) and optionally the variable REGISTRY_USER.
  • To skip the container image, set the repository variable PUBLISH_DOCKER to false.
  • Build locally with sh deploy/build.sh (archives in dist/).

Build and test

go env -w GOPRIVATE=git.veillax.com   # once, so Go fetches straight from this server
go build -o bin/ ./cmd/bamboo
go test ./...

The end-to-end tests that run Bamboo together with Hammerhead and Blacktip live in the Hammerhead repository.

License

AGPL-3.0. See LICENSE.