Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .github/workflows/nix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Nix

on:
push:
branches: [main, release]
paths:
- ".github/workflows/nix.yml"
- "Cargo.lock"
- "Cargo.toml"
- "crates/**"
- "desktop/**"
- "flake.lock"
- "flake.nix"
- "nix/**"
- "package.json"
- "patches/**"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"
- "rust-toolchain.toml"
pull_request:
paths:
- ".github/workflows/nix.yml"
- "Cargo.lock"
- "Cargo.toml"
- "crates/**"
- "desktop/**"
- "flake.lock"
- "flake.nix"
- "nix/**"
- "package.json"
- "patches/**"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"
- "rust-toolchain.toml"

concurrency:
group: nix-${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
contents: read

jobs:
build:
name: Build packages
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: DeterminateSystems/nix-installer-action@ef8a148080ab6020fd15196c2084a2eea5ff2d25 # v22

- name: Check Nix formatting
run: nix fmt -- --check flake.nix nix/buzz.nix nix/versions.nix nix/modules/buzz-relay.nix

- name: Evaluate all supported systems
run: nix flake show --all-systems

- name: Build relay and NixOS module check
run: nix flake check --print-build-logs

- name: Build desktop and sidecars
run: nix build --print-build-logs .#buzz-desktop .#buzz-sidecars
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,17 @@ Relay on `ws://localhost:3000`. Desktop app pops up. You're in.

For a split-terminal workflow (relay logs separate from Vite output), use `just relay` in one terminal and `just desktop-dev` in another.

Using Nix, the flake exposes the desktop app, relay server, administration CLI,
agent sidecars, and a NixOS relay module:

```bash
nix run .#buzz-desktop
nix run .#buzz-relay
```

See the [NixOS deployment guide](deploy/nixos/README.md) for package names,
module options, secrets, and reverse-proxy configuration.

Want a single-node / VPS relay instead of the local-dev stack? Use the production Compose bundle in [`deploy/compose/`](deploy/compose/README.md) (`docker compose` + Postgres, Redis, MinIO, optional Caddy/TLS). The root [`docker-compose.yml`](docker-compose.yml) is for day-to-day development only.

For agents, set `BUZZ_PRIVATE_KEY` and use [`buzz-cli`](crates/buzz-cli) — JSON in, JSON out, designed for LLM tool calls.
Expand Down Expand Up @@ -223,6 +234,7 @@ A Rust workspace of focused crates. Single source of truth: the relay. See [ARCH
- **[VISION.md](VISION.md)** · **[VISION_SOVEREIGN.md](VISION_SOVEREIGN.md)** · **[VISION_PROJECTS.md](VISION_PROJECTS.md)** · **[VISION_AGENT.md](VISION_AGENT.md)** — the four vision docs
- **[ARCHITECTURE.md](ARCHITECTURE.md)** — system design, kind ranges, subsystem boundaries
- **[TESTING.md](TESTING.md)** — multi-agent E2E test suite
- **[deploy/nixos](deploy/nixos/README.md)** · **[deploy/compose](deploy/compose/README.md)** · **[deploy/charts/buzz](deploy/charts/buzz/README.md)** — relay deployment guides
- **[CONTRIBUTING.md](CONTRIBUTING.md)** · **[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)** · **[SECURITY.md](SECURITY.md)** · **[GOVERNANCE.md](GOVERNANCE.md)**

<details>
Expand Down
2 changes: 2 additions & 0 deletions deploy/compose/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

This is the single-node/VPS deployment bundle. It is intentionally separate from
the root `docker-compose.yml`, which remains local development infrastructure.
For NixOS deployments, use the NixOS module guide in
[`../nixos/README.md`](../nixos/README.md).

## Quick start

Expand Down
213 changes: 213 additions & 0 deletions deploy/nixos/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# Buzz on NixOS

The repository flake builds the Buzz desktop app, relay server, administration
CLI, and agent sidecars. It also exports a NixOS module for running the relay as
a hardened systemd service.

## Build and run

From a Buzz checkout:

```bash
nix build .#buzz-desktop
nix build .#buzz-relay
nix build .#buzz-sidecars

nix run .#buzz-desktop
nix run .#buzz-relay
nix run .#buzz-admin -- --help
```

The `buzz-relay` package contains both `buzz-relay` and `buzz-admin`. The named
apps select the appropriate executable.

### Codex ACP adapter

The desktop package includes Buzz's own agent sidecars, but external managed
agent runtimes and their ACP adapters must also be available on `PATH`.

Despite having the same `codex-acp` executable name, `pkgs.codex-acp` at this
flake's pinned nixpkgs revision is version 0.13.0 from the legacy
`@zed-industries/codex-acp` project. Buzz requires the official
`@agentclientprotocol/codex-acp` adapter at or above the minimum version
enforced by the desktop app (currently 1.1.7). NixOS configurations should
package that upstream adapter explicitly rather than install the nixpkgs
package with the matching name. The Codex CLI must also be on `PATH`, or its
executable can be selected with `CODEX_PATH`.

## Import the NixOS module

Pin Buzz as a flake input and import its relay module:

```nix
{
inputs.buzz.url = "github:block/buzz";

outputs =
{
nixpkgs,
buzz,
...
}:
{
nixosConfigurations.relay = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
buzz.nixosModules.buzz-relay
./configuration.nix
];
};
};
}
```

The module supports x86-64 and ARM64 Linux.

## Configure the relay

The module runs the relay but does not provision PostgreSQL, Redis, object
storage, DNS, or TLS. Those services may run on the same host or be provided
externally.

```nix
{
services.buzz-relay = {
enable = true;

relayUrl = "wss://buzz.example.com";
host = "127.0.0.1";
port = 3000;

databaseUrl = "postgres://buzz@localhost:5432/buzz";
redisUrl = "redis://localhost:6379";
s3Endpoint = "https://s3.example.com";
s3Bucket = "buzz-media";
s3Region = "eu-west-2";
s3AddressingStyle = "path";
mediaBaseUrl = "https://buzz.example.com/media";

environmentFile = "/run/secrets/buzz-relay.env";
autoMigrate = true;
};
}
```

URLs containing credentials can be supplied through `environmentFile` instead
of normal Nix options, which are copied into the Nix store.

Example runtime secret file:

```env
DATABASE_URL=postgres://buzz:CHANGE_ME@localhost:5432/buzz
BUZZ_RELAY_PRIVATE_KEY=CHANGE_ME_32_BYTE_HEX_PRIVATE_KEY
BUZZ_S3_ACCESS_KEY=CHANGE_ME
BUZZ_S3_SECRET_KEY=CHANGE_ME
BUZZ_GIT_HOOK_HMAC_SECRET=CHANGE_ME_AT_LEAST_32_CHARACTERS
```

Keep `BUZZ_RELAY_PRIVATE_KEY` stable across rebuilds and restores. A changed key
gives the relay a new identity.

Unmodeled relay settings can be passed through `environment` when they are not
secret:

```nix
{
services.buzz-relay.environment = {
BUZZ_RATE_LIMIT_HUMAN_MESSAGES_PER_MIN = 120;
BUZZ_MEDIA_UPLOADS_PER_MINUTE = 20;
};
}
```

Deployments with a Postgres read replica can size its pool independently and
opt into bounded-staleness routing:

```nix
{
services.buzz-relay = {
readDatabaseUrl = "postgres://buzz@reader.example.com:5432/buzz";
readDatabasePoolSize = 25;
replicaReadMaxAgeMs = 1000;
};
}
```

Replica routing remains disabled when `replicaReadMaxAgeMs` is zero.

## Closed relays

Membership enforcement requires a stable relay key and an owner pubkey:

```nix
{
services.buzz-relay = {
requireRelayMembership = true;
ownerPubkey = "64_character_lowercase_hex_nostr_pubkey";
environmentFile = "/run/secrets/buzz-relay.env";
};
}
```

The environment file must provide `BUZZ_RELAY_PRIVATE_KEY`.

## Reverse proxy

The public HTTP and WebSocket traffic shares one port. A typical deployment
binds Buzz to localhost and terminates TLS with nginx:

```nix
{
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;

virtualHosts."buzz.example.com" = {
forceSSL = true;
enableACME = true;

locations."/" = {
proxyPass = "http://127.0.0.1:3000";
proxyWebsockets = true;
};
};
};

security.acme = {
acceptTerms = true;
defaults.email = "ops@example.com";
};
}
```

`openFirewall` opens only the public relay port. Health and metrics ports remain
private unless configured separately.

## Operations

The module creates a `buzz-relay` system user and persists git data beneath
`dataDir`, which defaults to `/var/lib/buzz`.

```bash
systemctl status buzz-relay
journalctl -u buzz-relay -f
curl --fail http://127.0.0.1:8080/_liveness
curl --fail http://127.0.0.1:8080/_readiness
```

Prometheus metrics are exposed on port `9102` by default.

For horizontally scaled relay deployments, disable in-process huddle audio:

```nix
services.buzz-relay.huddleAudioAvailable = false;
```

Back up PostgreSQL, the S3 bucket, `dataDir`, and all secret files before
upgrades. If `autoMigrate` is disabled, run `buzz-admin migrate` from the same
pinned Buzz revision before starting the new relay:

```bash
nix run github:block/buzz#buzz-admin -- migrate
```
Loading