# vineyard

a nostr federation companion for brewery

public repository discovery and signed event exchange between forges
git hosting and signing keys stay with brewery

## run

copy `vineyard.example.toml` and replace `forge_pubkeys` with brewery's public key
database paths are relative to the config file

```sh
nix build
result/bin/vineyard check-config --config vineyard.toml
result/bin/vineyard serve --config vineyard.toml
```

put tls termination in front of the loopback listener
forward websocket upgrades at the path in `public_url`
`/healthz` checks database access
request `application/nostr+json` at the websocket path for relay information

## nixos

import `nixosModules.vineyard` and configure the service

```nix
services.vineyard = {
  enable = true;
  publicUrl = "wss://relay.example.org/";
  forgePubkeys = [ "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" ];
  peers = [ { url = "wss://peer.example.org/"; } ];
};
```

the module runs vineyard under a dynamic user and stores data in `/var/lib/vineyard`

## peers

add one or more bootstrap relays to connect your forge to the network

```toml
[[peers]]
url = "wss://peer.example.org/"
query_limit = 500
```

use a query limit no larger than the peer supports
peers must accept forge events without nip42 authentication
remote repository announcements retain their signer's identity
brewery publishes its signed nip 65 relay list
peer relay lists are persisted and joined automatically
discovered peers are bounded by `max_discovered_peers`
discovered peers require wss and public dns addresses by default
set `allow_private_discovery` only for trusted private networks or local development

delivery progress and failed-event retries persist in sqlite
incoming history uses a seven-day overlap
set a peer's `rescan_from` to an older unix timestamp for manual recovery
single-second history overflow stops replay without advancing its checkpoint

## brewery

build brewery with its `federation` feature or nix package option

```sh
export BREWERY_FEDERATION=1
export BREWERY_NOSTR_RELAYS=wss://relay.example.org/
export BREWERY_PUBLIC_URL=https://git.example.org
brewery repo issue-mode alice/widget users_and_tokens
brewery repo patch-mode alice/widget tokens
```

repositories must be public
brewery retains git hosting and verifies openpgp binding proofs
the companion brewery changes persist replay progress in `federation.inbox.json`
set `BREWERY_FEDERATION_RESCAN_FROM` to a unix timestamp for an older rescan

## limits

defaults are in `vineyard.example.toml`
merged history is bounded by `max_query_bytes`
queries without an explicit limit fail when history exceeds the result cap
`max_repositories` bounds the shared repository directory
slow subscribers disconnect and must replay
peer limits use the direct socket address, so a proxy shares one allowance

the database budget limits sqlite pages, not total disk usage
leave space for the wal and backups
accepted events are not evicted to make room

## backup

stop vineyard before copying its config and database
preserve any accompanying sqlite wal file
restore with the same forge public keys

use the companion brewery backup command to retain `nostr.key` and federation state
keep the restored key private and restore a custom key path before starting brewery
a new forge key changes every repository's nostr address

## development

```sh
nix develop
nix flake check
```
