Use your local Buzz community and managed agents from your phone without moving Buzz itself to the cloud.
Project page: https://idev4u.github.io/buzz-stable-toolkit/
Buzz keeps running locally on your Mac. This toolkit exposes only the relay through a stable ngrok endpoint, so Desktop, Mobile, and managed agents can use the same community.
Local Buzz on Mac → ngrok → Desktop + Mobile + Agents
export NGROK_DOMAIN="my-domain.ngrok-free.dev"
./buzz-online.sh startThis setup grew out of intensive testing of Buzz.
For me, mobile is part of the test surface: I want to use the same community and agent team across Mac and phone while keeping Buzz, PostgreSQL, and local application data on the Mac.
The toolkit makes that setup reproducible and adds the operational pieces needed for regular testing:
buzz-online.shexposes the local relay through ngrok and provides start, stop, status, and health checks.buzz-stable.shprovides stable-release updates, backup, recovery, and startup helpers.
Buzz and PostgreSQL remain local. ngrok only forwards public HTTPS/WSS traffic to the Buzz relay.
Desktop / Mobile / Managed Agents
│
▼
https://my-domain.ngrok-free.dev
wss://my-domain.ngrok-free.dev
│
▼
ngrok tunnel
│
▼
localhost:3000
│
▼
Local Buzz relay
│
▼
Local PostgreSQL / local app data / local Keychain
The canonical relay endpoint for clients is:
wss://my-domain.ngrok-free.dev
.env.example Example Buzz .env values with public placeholders
.gitignore Ignores local runtime, backups, dumps, and secrets
buzz-online.sh Starts/stops/checks ngrok plus local Buzz
buzz-stable.sh Stable release backup/update/recovery/start helper
README.md This guide
SECURITY.md Public security notes
LICENSE Apache License 2.0
NOTICE Copyright and attribution notice
buzz-online.sh generates its ngrok Traffic Policy at runtime under
.runtime/ngrok-buzz-policy.yml. Generated runtime files are intentionally not
committed.
- macOS or a Unix-like shell environment with Bash.
- A local Buzz checkout, usually at
~/workspace/buzz. - Buzz development prerequisites installed in that checkout.
- Docker available if using the local PostgreSQL container backup/recovery flow.
ngrokinstalled and authenticated locally with your own ngrok account.curlfor health checks.- Optional:
jqfor prettier./buzz-online.sh checkoutput.
The ngrok auth token belongs in ngrok's local configuration. Do not place it in
this repository or in .env.example.
Default layout:
~/workspace/
├── buzz/ # local Buzz checkout
└── buzz-stable-toolkit-public/ # this toolkit
Defaults used by the scripts:
BUZZ_REPO="$HOME/workspace/buzz"
BUZZ_BACKUP_ROOT="<this-toolkit>/backups"
STABLE_SCRIPT="<this-toolkit>/buzz-stable.sh"All of these can be overridden with environment variables.
cd ~/workspace/buzz-stable-toolkit-public
chmod +x buzz-stable.sh buzz-online.shCreate or use an ngrok account, then install the ngrok command for your
platform. On macOS with Homebrew, one common option is:
brew install ngrok/ngrok/ngrokVerify the command is available:
ngrok versionAuthenticate ngrok using a token from your ngrok dashboard:
ngrok config add-authtoken <your-ngrok-token>Keep this token in ngrok's local configuration only. Do not paste a real token
into this repository, .env, shell history shared with others, screenshots, or
support logs.
Reserve or choose the static ngrok domain you want Buzz clients to use, for example:
my-domain.ngrok-free.dev
The same hostname must be used consistently in:
NGROK_DOMAINorNGROK_URLforbuzz-online.sh,RELAY_URLin the Buzz.env,BUZZ_RELAY_URLin the Buzz.env.
You do not need to create a hostname-specific Traffic Policy file. buzz-online.sh
generates the required policy under .runtime/ every time it starts ngrok.
Copy the example environment into the Buzz checkout if you do not already have a
Buzz .env file:
cp .env.example ~/workspace/buzz/.envEdit ~/workspace/buzz/.env so the relay URLs match your ngrok domain:
BUZZ_BIND_ADDR=0.0.0.0:3000
RELAY_URL=wss://my-domain.ngrok-free.dev
BUZZ_RELAY_URL=wss://my-domain.ngrok-free.devUse your own domain. Do not commit the real .env file.
Use either NGROK_DOMAIN:
export NGROK_DOMAIN="my-domain.ngrok-free.dev"or NGROK_URL:
export NGROK_URL="https://my-domain.ngrok-free.dev"If NGROK_URL is not set, buzz-online.sh derives it from NGROK_DOMAIN.
The script derives the HTTP Host header from the final URL and writes a runtime
ngrok policy that forwards requests to Buzz with that host.
No hostname-specific YAML file needs to be edited or committed.
export BUZZ_REPO="$HOME/workspace/buzz"
export STABLE_SCRIPT="$PWD/buzz-stable.sh"
export BUZZ_BACKUP_ROOT="$PWD/backups"cd ~/workspace/buzz-stable-toolkit-public
export NGROK_DOMAIN="my-domain.ngrok-free.dev"
./buzz-online.sh startstart does the following:
- validates required commands and files,
- verifies that Buzz
.envrelay URLs match the ngrok host, - generates
.runtime/ngrok-buzz-policy.yml, - starts ngrok unless the same tunnel is already running,
- starts Buzz through
buzz-stable.sh start.
Stop Buzz in its terminal with Ctrl+C, then stop ngrok:
./buzz-online.sh stopstop only stops the ngrok process tracked by .runtime/ngrok.pid.
./buzz-online.sh statusThis prints the configured paths, ngrok state, and whether the relay is reachable. It is safe to run when nothing is running.
./buzz-online.sh checkThis queries the public relay endpoint with Accept: application/nostr+json.
If jq is installed, the output is reduced to useful relay fields.
If you need to debug ngrok separately, generate or inspect the policy by running
./buzz-online.sh start once, or create an equivalent file manually:
on_http_request:
- actions:
- type: add-headers
config:
headers:
host: "my-domain.ngrok-free.dev"Then run ngrok directly:
ngrok http 3000 \
--url "https://my-domain.ngrok-free.dev" \
--traffic-policy-file ".runtime/ngrok-buzz-policy.yml"In a second terminal, start Buzz:
./buzz-stable.sh startbuzz-stable.sh update keeps the same local Buzz branch/worktree identity, finds
the newest immutable desktop-vX.Y.Z tag, creates a backup, resets the current
branch to that tag, and runs Buzz setup/migrations.
Check current state:
./buzz-stable.sh statusUpdate to the newest stable release:
./buzz-stable.sh updateInclude a local plaintext Keychain backup:
./buzz-stable.sh update --dev-backupInclude an encrypted portable Keychain backup:
./buzz-stable.sh update --portableUse only one of --dev-backup or --portable.
Backups are written under backups/ by default and ignored by Git.
A backup can include:
- Buzz app data for the current dev app ID,
- the local
~/.buzz-devnest if present, - a PostgreSQL custom-format dump from the local
buzz-postgrescontainer, - metadata describing the branch, commit, app ID, and backup mode,
- optional Keychain material.
Backup command:
./buzz-stable.sh backupWith local plaintext Keychain export:
./buzz-stable.sh backup --dev-backupWith encrypted portable Keychain export:
./buzz-stable.sh backup --portablePlaintext Keychain backups are sensitive. Keep them local and private. Portable Keychain backups are encrypted but should still be handled as sensitive files.
List backups:
ls -1 backupsRecover from a backup:
./buzz-stable.sh recover backups/<backup-directory>Recovery restores the recorded Buzz Git commit, app data, local nest, PostgreSQL dump, and optionally merges a Keychain backup after confirmation.
Recovery is intentionally interactive because it can replace local data.
Buzz community host mapping matters. If a community was created while the relay
was advertised as localhost, 127.0.0.1, localhost:3000, or
127.0.0.1:3000, clients may not see the same community when the public relay
URL becomes wss://my-domain.ngrok-free.dev.
Do not make normal startup mutate the database. Treat host migration as an advanced, one-time operation:
- stop Buzz,
- create a backup first,
- inspect the current Buzz version's schema and migration code,
- perform only a verified migration for that version,
- start Buzz and confirm clients see the expected community.
This repository does not include automatic SQL for that migration because an unverified query could damage or partially migrate local data.
Do not commit:
.envor.env.local,.runtime/,backups/,- database dumps (
*.dump,*.sql), - encrypted or plaintext key exports (
*.enc,*.key,*.pem), - ngrok auth tokens,
- private keys, passwords, API tokens, or personal hostnames.
The .gitignore is configured for these local artifacts.
Set one of:
export NGROK_DOMAIN="my-domain.ngrok-free.dev"
# or
export NGROK_URL="https://my-domain.ngrok-free.dev"Edit ~/workspace/buzz/.env so RELAY_URL and BUZZ_RELAY_URL match the ngrok
host exactly, using wss://.
Install ngrok and authenticate it locally. Do not store the auth token in this repository.
Check:
./buzz-online.sh status
cat .runtime/ngrok.log
curl -fsS -H 'Accept: application/nostr+json' "https://my-domain.ngrok-free.dev/"Also confirm Buzz is running and listening on localhost:3000.
Another process is already listening on the relay port. Stop the old Buzz process before backup, update, or recovery operations.
The pre-update backup path is printed by buzz-stable.sh. Recover with:
./buzz-stable.sh recover backups/<backup-directory>Licensed under the Apache License, Version 2.0. See LICENSE.