Reproducible Nix packages for block/buzz.
This flake pins Buzz to the release tag recorded in packages/source/pin.json and builds the Rust, web, relay, and desktop artifacts without import-from-derivation.
| Package | Description |
|---|---|
buzz-cli |
Buzz command-line client (buzz) |
buzz-acp |
ACP harness for Buzz agent integrations |
buzz-agent |
Minimal ACP-compliant Buzz agent |
sprig |
All-in-one ACP harness, agent, and developer MCP (independently versioned) |
buzz-backend-kubernetes |
Kubernetes backend provider for remote agents |
buzz-dev-mcp |
MCP server for shell and file-edit tools |
git-credential-nostr |
Git credential helper for NIP-98 authentication |
git-sign-nostr |
Nostr signing backend for Git commits and tags |
buzz-agent-tools |
Convenience bundle for CLI and agent tools |
buzz-web |
Web client bundle |
buzz-admin-web |
Relay administration UI bundle |
buzz-server-binaries |
Server binary bundle (buzz-relay, buzz-admin, buzz-pair-relay) |
buzz-relay |
Relay runtime package with bundled web UIs |
buzz-push-gateway |
Standalone production APNs push gateway; requires separate database and Apple credentials |
buzz-desktop-frontend |
Frontend bundle embedded in Buzz Desktop |
buzz-desktop-sidecars |
Sidecar bundle required by Buzz Desktop |
buzz-desktop |
Tauri desktop application |
Run the CLI:
nix run github:mulatta/buzz.nix#buzz-cli -- --helpThe CLI package includes the upstream agent skill at
share/skills/buzz-cli/sprout-cli/SKILL.md (its declared skill name is
buzz-cli). The buzz-agent-tools bundle also exposes it. Only the CLI skill
is packaged; repository-development and example skills are excluded.
Packaging does not register the skill with an agent. Link the installed
share/skills/buzz-cli/sprout-cli directory into the desired agent's skill
directory, such as ~/.claude/skills/buzz-cli. On NixOS, add
environment.pathsToLink = [ "/share/skills" ]; when exposing skills through
the system profile. Keep credentials in the runtime environment, not in the
skill or Nix configuration.
Run the relay:
nix run github:mulatta/buzz.nix#buzz-relaybuzz-relay expects runtime services such as Postgres to be configured. A bare run starts the binary, but database connection failures are expected without a database and DATABASE_URL.
Build the desktop package:
nix build github:mulatta/buzz.nix#buzz-desktopThe pairing service is independent of the main relay and needs no PostgreSQL,
Redis, or S3. Import buzz.nixosModules.buzz-pair-relay to run it on a separate
host:
{
imports = [ inputs.buzz.nixosModules.buzz-pair-relay ];
services.buzz-pair-relay = {
enable = true;
# package is supplied by the flake; override with any package providing
# bin/buzz-pair-relay when needed.
listenAddress = "127.0.0.1";
port = 5000;
openFirewall = false;
};
services.nginx = {
enable = true;
virtualHosts."pair.example.com" = {
enableACME = true;
forceSSL = true;
locations = {
"= /pair" = {
proxyPass = "http://127.0.0.1:5000";
proxyWebsockets = true;
recommendedProxySettings = true;
extraConfig = "proxy_read_timeout 130s;";
};
"/".return = "404";
};
};
};
security.acme = {
acceptTerms = true;
defaults.email = "admin@example.com";
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
}The binary does not restrict request paths. Keep its listener private and expose
only exact /pair through a TLS reverse proxy. The flake uses the server-binary
package by default, without pulling in the relay's web UI bundles.
Expose the relay as a system service:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
buzz = {
url = "github:mulatta/buzz.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { buzz, nixpkgs, ... }: {
nixosConfigurations.host = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
buzz.nixosModules.buzz-relay
{
services.buzz-relay = {
enable = true;
relayUrl = "wss://buzz.example";
ownerPubkey = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
secretFiles = {
DATABASE_URL = "/run/secrets/buzz-database-url";
REDIS_URL = "/run/secrets/buzz-redis-url";
BUZZ_RELAY_PRIVATE_KEY = "/run/secrets/buzz-relay-private-key";
BUZZ_S3_ACCESS_KEY = "/run/secrets/buzz-s3-access-key";
BUZZ_S3_SECRET_KEY = "/run/secrets/buzz-s3-secret-key";
};
media.baseUrl = "https://buzz.example/media";
media.s3Endpoint = "https://s3.example";
corsOrigins = [ "https://buzz.example" ];
};
}
];
};
};
}Common relay tuning is exposed through typed options rather than raw environment variables:
services.buzz-relay = {
redisPoolSize = 32;
databasePoolSize = 80;
maxFrameBytes = 1024 * 1024;
slowClientGraceLimit = 10;
auditEnabled = true;
ephemeralTtlOverride = 60;
};Leave ephemeralTtlOverride as null (the default) to honor client-provided ephemeral-channel lifetimes. Use environment only for non-secret upstream settings without a typed option.
services.buzz-relay manages the relay and optional pairing process. External
PostgreSQL and Redis remain the default. Opt into local instances and an Nginx
reverse proxy explicitly:
services.buzz-relay = {
enable = true;
ownerPubkey = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
database.createLocally = true;
redis.createLocally = true;
nginx = {
enable = true;
hostName = "buzz.example";
enableACME = true;
forceSSL = true;
};
media = {
s3Endpoint = "https://<account-id>.r2.cloudflarestorage.com";
s3Bucket = "buzz";
s3Region = "auto";
};
secretFiles = {
BUZZ_RELAY_PRIVATE_KEY = "/run/secrets/buzz-relay-private-key";
BUZZ_S3_ACCESS_KEY = "/run/secrets/buzz-s3-access-key";
BUZZ_S3_SECRET_KEY = "/run/secrets/buzz-s3-secret-key";
};
};
security.acme = {
acceptTerms = true;
defaults.email = "admin@example.com";
};
networking.firewall.allowedTCPPorts = [ 80 443 ];Local database/cache mode cannot be combined with the corresponding
secretFiles.DATABASE_URL or secretFiles.REDIS_URL. It configures service
ordering and local connections without putting passwords in the Nix store.
PostgreSQL version selection/upgrades and host-wide Redis/Valkey package policy
remain the host's responsibility. S3 storage, bucket provisioning, DNS, backups,
and secret provisioning are never created automatically.
The Nginx integration supplies overridable defaults for relayUrl,
media.baseUrl, and corsOrigins. It proxies WebSocket traffic and media/Git
uploads, but never health or metrics. Leave it disabled for Caddy, an external
ingress, or custom proxy rules. Configure ACME consent/contact and public firewall
ports on the host. adminHost is not an access-control boundary: protect any
administration endpoint with your deployment's access policy.
Configure runtime credentials with secretFiles, keyed by the upstream environment variable. Each referenced file contains only the raw secret value. Supported keys include DATABASE_URL, REDIS_URL, BUZZ_RELAY_PRIVATE_KEY, BUZZ_GIT_HOOK_HMAC_SECRET, BUZZ_KLIPY_API_KEY, and S3 credentials. systemd loads them with LoadCredential, so their contents stay out of the Nix store and cannot override typed or package-owned settings. Do not put secret values directly in Nix options.
Set corsOrigins explicitly in production. An empty list enables upstream's
permissive development mode and emits a warning. Set allowPermissiveCors = true
only to acknowledge that choice explicitly.
The relay requires a signing key and database/cache connection configuration.
Static S3 mode requires both BUZZ_S3_ACCESS_KEY and BUZZ_S3_SECRET_KEY files.
Set media.useDefaultCredentials = true instead to use the AWS default credential
chain; do not combine it with the static Buzz S3 credential files. This explicitly
clears upstream's development credential defaults. Any AWS access/secret key files
must be supplied together. Instance/workload credentials still need to be made
available within the service's systemd sandbox.
Health and metrics listeners are bound by upstream to 0.0.0.0:${healthPort} and 0.0.0.0:${metricsPort}. openFirewall opens only the main app port; restrict health and metrics with firewall/proxy policy.
APNs push is disabled by default in the NixOS module by setting BUZZ_PUSH_GATEWAY_DELIVERY_URL to an empty string. Set services.buzz-relay.pushGateway.deliveryUrl explicitly to use Block's public gateway or a separately deployed self-host push gateway.
nixos-buzz-relay-s3-admission-gate exercises fail-closed startup with a
test-only proxy that deliberately rejects conditional If-Match writes while
forwarding ordinary S3 requests to an unmodified RustFS backend. This does not
assume that any particular RustFS release is broken.
nixos-buzz-relay-rustfs-integration exercises successful relay startup,
health/readiness, web/admin routing, restart behavior, and dependency recovery
against unmodified pkgs.rustfs. The pinned RustFS 1.0.0 already includes the
exclusive-lock waiter-accounting fix; no local RustFS patch is applied. These
are VM test definitions, not a claim that every S3-compatible backend is safe.
For a same-host sidecar, enable pairing alongside the relay's Nginx helper:
services.buzz-relay = {
nginx = { enable = true; hostName = "buzz.example.com"; };
pairingRelay.enable = true;
# Defaults to wss://buzz.example.com/pair (ws:// when forceSSL is false).
# pairingRelay.url = "wss://buzz.example.com/pair";
adminHost = "admin.buzz.example.com"; # optional
};
# Optional process overrides belong to the standalone service.
services.buzz-pair-relay.port = 5000;This enables services.buzz-pair-relay and proxies only exact /pair to it.
Other paths still reach the main relay. An explicit local URL may use a separate
DNS hostname with exactly /pair; that host returns 404 for other paths. The
helper also supports /pair on the configured admin host. Hostnames are
case-insensitive. Custom ports, paths, or TLS policy require a hand-written proxy.
To use a pairing service on another host, set only the advertised URL:
services.buzz-relay.pairingRelay = {
enable = false;
url = "wss://pair.example.com/pair";
};This neither starts a local sidecar nor creates a pairing proxy route. An
independently enabled services.buzz-pair-relay is likewise not automatically
exposed by the relay helper. Without the helper, a local sidecar needs an explicit
public URL and a separately configured reverse proxy.
pairingRelay.listenAddress, pairingRelay.port, and pairingRelay.openFirewall
are deprecated aliases for the corresponding services.buzz-pair-relay options.
The relay bundle remains the sidecar's default package when the convenience
option is used; services.buzz-pair-relay.package can override it.
Import buzz.nixosModules.buzz-push-gateway separately. It does not enable a
relay, provision PostgreSQL, or configure a public proxy:
services.buzz-push-gateway = {
enable = true;
port = 8090;
healthPort = 8091;
databaseUrlFile = "/run/secrets/push-runtime-database-url";
grantKeysFile = "/run/secrets/push-grant-keys";
tokenKeysFile = "/run/secrets/push-token-keys";
appAttest = {
appId = "TEAMID.com.example.buzz";
rootCertificateFile = "/run/credentials/apple-app-attestation-root.pem";
};
apns = {
topic = "com.example.buzz";
identityFile = "/run/secrets/push-apns-identity.pem";
environment = "production";
};
# Optional; otherwise provision the schema outside this service.
migration = {
enable = true;
databaseUrlFile = "/run/secrets/push-migration-database-url";
runtimeDatabaseRole = "buzz_push_gateway_runtime";
};
};Use a dedicated gateway database, not the relay database. Provision the runtime
LOGIN role before migration. Runtime credentials should have only the upstream
DML grants; the optional migration unit alone receives the separate DDL URL.
The ordered grant and token keyrings use id:base64-32-bytes entries separated
by commas; their IDs and key bytes must not overlap.
The pinned gateway supports the compiled-in buzz-ios-dogfood profile and
production App Attest. It requires Apple's exact pinned App Attestation Root CA
and a combined APNs certificate/private-key PEM, not an APNs token-signing
.p8 key. APNs sandbox transport does not enable development App Attest.
Your client must match this profile; packaging alone does not make an arbitrary
iOS app compatible. Upstream attestation audiences remain fixed push.buzz.xyz
protocol constants, even when the service is hosted under another domain.
The gateway defaults to public port 8090 and health/metrics port 8091,
separate from the relay defaults. When both modules are enabled, their listener
ports (including local pairing and Redis) must be distinct, even when bound to
different addresses. Local Redis must also use a port distinct from relay listeners.
Migration role names must be ASCII SQL identifiers of at most 63 characters.
Expose the public HTTP port behind an HTTPS proxy and keep the health/metrics
port private. On the relay, opt in with
pushGateway.deliveryUrl = "https://push.example/v1/deliveries/apns";.
There is no implicit connection between the two modules. Both secret files and
public runtime certificate files must exist before the gateway starts.
Enter the development shell:
nix developRun focused checks:
NIX_CONFIG='allow-import-from-derivation = false' nix flake show
nix build .#checks.aarch64-darwin.package-buzz-cli --no-link
nix build .#checks.aarch64-darwin.package-buzz-desktop --no-link
nix build .#checks.x86_64-linux.package-buzz-desktop --no-link
nix build .#checks.x86_64-linux.module-buzz-pair-relay-options --no-link
nix build .#checks.x86_64-linux.module-buzz-pair-relay --no-link
nix build .#checks.x86_64-linux.module-buzz-relay-options --no-link
nix build .#checks.x86_64-linux.module-evaluation --no-link
nix build .#checks.x86_64-linux.module-buzz-relay-local-options --no-link
nix build .#checks.x86_64-linux.module-buzz-relay-nginx-options --no-link
nix build .#checks.x86_64-linux.module-buzz-push-gateway --no-link
nix build .#checks.x86_64-linux.module-buzz-relay --no-link
nix build .#checks.x86_64-linux.module-buzz-relay-local-stack --no-link
nix build .#checks.x86_64-linux.nixos-buzz-relay-s3-admission-gate --no-link
nix build .#checks.x86_64-linux.nixos-buzz-relay-rustfs-integration --no-linkFormat repository files:
nix fmtUpdate the pinned buzz release:
./packages/source/update.py --tag desktop-v0.5.9Omit --tag to use the latest upstream release. The updater also accepts the
legacy vX.Y.Z tags used through Buzz 0.5.2.
checks/default.nixassembles package and devShell checks and explicitly registers the x86_64-linux evaluation and VM checks.checks/evalcontains module evaluation tests;checks/vmcontains service and integration VM tests.- Evaluation tests return check derivations; inspect them through
checks.x86_64-linux.<name>.drvPathwithout building a VM. packages/*/package.nixare public flake package definitions.packages/sourceprovides the pinned upstream source plus source-derived metadata needed at evaluation time.packages/build-buzz-frontendandpackages/build-buzz-rustare package-scoped internal builders with locally owned dependency hashes.
The Nix packaging code in this repository is licensed under the MIT License.
Packaged software keeps its upstream licenses. Buzz server and agent components are Apache-2.0. The desktop package is marked GPL-3.0-or-later because the final desktop binary includes sherpa-onnx/eSpeak NG native code.