25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 1 | # vineyard |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 2 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 3 | a nostr federation companion for brewery |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 4 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 5 | public repository discovery and signed event exchange between forges |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 6 | git hosting and signing keys stay with brewery |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 7 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 8 | ## run |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 9 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 10 | copy `vineyard.example.toml` and replace `forge_pubkeys` with brewery's public key |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 11 | database paths are relative to the config file |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 12 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 13 | ```sh |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 14 | nix build |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 15 | result/bin/vineyard check-config --config vineyard.toml |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 16 | result/bin/vineyard serve --config vineyard.toml |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 17 | ``` |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 18 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 19 | put tls termination in front of the loopback listener |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 20 | forward websocket upgrades at the path in `public_url` |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 21 | `/healthz` checks database access |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 22 | request `application/nostr+json` at the websocket path for relay information |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 23 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 24 | ## nixos |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 25 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 26 | import `nixosModules.vineyard` and configure the service |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 27 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 28 | ```nix |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 29 | services.vineyard = { |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 30 | enable = true; |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 31 | publicUrl = "wss://relay.example.org/"; |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 32 | forgePubkeys = [ "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" ]; |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 33 | peers = [ { url = "wss://peer.example.org/"; } ]; |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 34 | }; |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 35 | ``` |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 36 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 37 | the module runs vineyard under a dynamic user and stores data in `/var/lib/vineyard` |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 38 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 39 | ## peers |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 40 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 41 | add one or more bootstrap relays to connect your forge to the network |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 42 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 43 | ```toml |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 44 | [[peers]] |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 45 | url = "wss://peer.example.org/" |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 46 | query_limit = 500 |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 47 | ``` |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 48 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 49 | use a query limit no larger than the peer supports |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 50 | peers must accept forge events without nip42 authentication |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 51 | remote repository announcements retain their signer's identity |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 52 | brewery publishes its signed nip 65 relay list |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 53 | peer relay lists are persisted and joined automatically |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 54 | discovered peers are bounded by `max_discovered_peers` |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 55 | discovered peers require wss and public dns addresses by default |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 56 | set `allow_private_discovery` only for trusted private networks or local development |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 57 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 58 | delivery progress and failed-event retries persist in sqlite |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 59 | incoming history uses a seven-day overlap |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 60 | set a peer's `rescan_from` to an older unix timestamp for manual recovery |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 61 | single-second history overflow stops replay without advancing its checkpoint |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 62 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 63 | ## brewery |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 64 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 65 | build brewery with its `federation` feature or nix package option |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 66 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 67 | ```sh |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 68 | export BREWERY_FEDERATION=1 |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 69 | export BREWERY_NOSTR_RELAYS=wss://relay.example.org/ |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 70 | export BREWERY_PUBLIC_URL=https://git.example.org |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 71 | brewery repo issue-mode alice/widget users_and_tokens |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 72 | brewery repo patch-mode alice/widget tokens |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 73 | ``` |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 74 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 75 | repositories must be public |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 76 | brewery retains git hosting and verifies openpgp binding proofs |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 77 | the companion brewery changes persist replay progress in `federation.inbox.json` |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 78 | set `BREWERY_FEDERATION_RESCAN_FROM` to a unix timestamp for an older rescan |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 79 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 80 | ## limits |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 81 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 82 | defaults are in `vineyard.example.toml` |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 83 | merged history is bounded by `max_query_bytes` |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 84 | queries without an explicit limit fail when history exceeds the result cap |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 85 | `max_repositories` bounds the shared repository directory |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 86 | slow subscribers disconnect and must replay |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 87 | peer limits use the direct socket address, so a proxy shares one allowance |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 88 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 89 | the database budget limits sqlite pages, not total disk usage |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 90 | leave space for the wal and backups |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 91 | accepted events are not evicted to make room |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 92 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 93 | ## backup |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 94 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 95 | stop vineyard before copying its config and database |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 96 | preserve any accompanying sqlite wal file |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 97 | restore with the same forge public keys |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 98 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 99 | use the companion brewery backup command to retain `nostr.key` and federation state |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 100 | keep the restored key private and restore a custom key path before starting brewery |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 101 | a new forge key changes every repository's nostr address |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 102 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 103 | ## development |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 104 | |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 105 | ```sh |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 106 | nix develop |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 107 | nix flake check |
25d14e49ab68 | atagen | 2026-09-24 11:07 UTC | 108 | ``` |