···11-`tab`: atproto sync utility
11+`tab`: a diet atproto sync utility
22========================================
33+44+Tab is a fork of [Tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap) that brings a few extra features that Tap does not offer. These changes have been PR upstream, but I thought I'd go ahead and fork to make then available to the community and myself.
55+66+New features:
77+- Can use [lightrail](https://tangled.org/microcosm.blue/lightrail) for finding collections. This lets you set multiple signal collections via `TAB_LIGHT_RAIL_SIGNAL_COLLECTIONS`, vs the single collection on tap
88+- You can use Jetstream over the firehose for reduce bandwidth by setting `TAB_JETSTREAM_URL`. **NOTE**. The jestream is not fully verifiable and you do lose that verification for the benefit for reduced bandwidth. Can read more on that [here](https://atproto.com/blog/jetstream#tradeoffs-and-use-cases)
99+- Note that this is called Ta**b**, not Ta**p**. You will also need to change any environment variables from `TAP_` to `TAB_` when using this fork
1010+1111+1212+1313+**Docker setup for Tab:**
1414+1515+A pre-built Docker image is also available:
1616+```bash
1717+docker pull fatfingers23/tab:latest
1818+docker run -p 2480:2480 fatfingers23/tab:latest
1919+2020+# or using atcr.io
2121+docker pull atcr.io/pds.dad/tab:latest
2222+docker run -p 2480:2480 atcr.io/pds.dad/tab:latest
2323+2424+```
2525+2626+To persist data, mount a volume at `/data`:
2727+```bash
2828+docker run -p 2480:2480 -v ./data:/data fatfingers23/tab:latest
2929+```
3030+3131+3232+### Original read me with docs for tap/tab as a whole
333434tab simplifies AT sync by handling the firehose/jetstream connection, verification, backfill, and filtering. Your application connects to a tab and receives simple JSON events for only the repos and collections you care about, no need to worry about binary formats for validating cryptographic signatures.
535···7310374104Environment variables or CLI flags:
751057676-- `tab_DATABASE_URL`: database connection string, SQLite or PostgreSQL (default: `sqlite://./tab.db`)
7777-- `tab_MAX_DB_CONNS`: maximum number of database connections (default: `32`)
7878-- `tab_BIND`: HTTP server address (default: `:2480`)
7979-- `tab_PLC_URL`: PLC directory HTTP/HTTPS URL (default: `https://plc.directory`)
8080-- `tab_RELAY_URL`: AT Protocol relay HTTP/HTTPS URL (default: `https://relay1.us-east.bsky.network`)
8181-- `tab_LIGHT_RAIL_URL`: Light Rail HTTP/HTTPS URL (default: ``, but `https://lightrail.microcosm.blue` is a instance you can use)
8282-- `tab_JETSTREAM_URL`: If set uses the Jetstream over the firehose/relay. Other firehose settings apply to the jetstream connection (default: ``, but `https://jetstream1.us-east.bsky.network` is a public node hosted by Bluesky that you can use)
8383-- `tab_FIREHOSE_PARALLELISM`: concurrent firehose event processors (default: `10`)
8484-- `tab_RESYNC_PARALLELISM`: concurrent resync workers (default: `5`)
8585-- `tab_OUTBOX_PARALLELISM`: concurrent outbox workers (default: `1`)
8686-- `tab_CURSOR_SAVE_INTERVAL`: how often to persist upstream firehose cursor (default: `1s`)
8787-- `tab_NO_REPLAY`: skip saved cursor and connect to firehose head on startup; incompatible with `tab_FULL_NETWORK`, not recommended for production (default: `false`)
8888-- `tab_REPO_FETCH_TIMEOUT`: timeout for fetching repo CARs from PDS (default: `300s`)
8989-- `tab_IDENT_CACHE_SIZE`: size of in-process identity cache (default: `2000000`)
9090-- `tab_OUTBOX_CAPACITY`: rough size of outbox before back pressure is applied (default: `100000`)
9191-- `tab_FULL_NETWORK`: track all repos on the network (default: `false`)
9292-- `tab_SIGNAL_COLLECTION`: track all repos with at least one record in this collection (e.g. `app.bsky.actor.profile`)
9393-- `tab_LIGHT_RAIL_SIGNAL_COLLECTIONS`: track all repos with at least one record in these collections. Can not be used with `tab_SIGNAL_COLLECTION` (e.g. `community.lexicon.calendar.rsvp,community.lexicon.calendar.event`)
9494-- `tab_COLLECTION_FILTERS`: comma-separated collection filters, wildcards accepted (e.g., `app.bsky.feed.post,app.bsky.graph.*`)
9595-- `tab_DISABLE_ACKS`: fire-and-forget mode, no client acks (default: `false`)
9696-- `tab_WEBHOOK_URL`: webhook URL for event delivery (disables WebSocket mode)
9797-- `tab_OUTBOX_ONLY`: run in outbox-only mode (no firehose, resync, or enumeration) (default: `false`)
9898-- `tab_ADMIN_PASSWORD`: Basic auth admin password required for all requests (if set)
9999-- `tab_RETRY_TIMEOUT`: timeout before retrying unacked events (default: `60s`)
100100-- `tab_LOG_LEVEL`: log verbosity (`debug`, `info`, `warn`, `error`, default: `info`)
101101-- `tab_METRICS_LISTEN`: address for metrics/pprof server (disabled if empty)
106106+- `TAB_DATABASE_URL`: database connection string, SQLite or PostgreSQL (default: `sqlite://./tab.db`)
107107+- `TAB_MAX_DB_CONNS`: maximum number of database connections (default: `32`)
108108+- `TAB_BIND`: HTTP server address (default: `:2480`)
109109+- `TAB_PLC_URL`: PLC directory HTTP/HTTPS URL (default: `https://plc.directory`)
110110+- `TAB_RELAY_URL`: AT Protocol relay HTTP/HTTPS URL (default: `https://relay1.us-east.bsky.network`)
111111+- `TAB_LIGHT_RAIL_URL`: Light Rail HTTP/HTTPS URL (default: ``, but `https://lightrail.microcosm.blue` is a instance you can use)
112112+- `TAB_JETSTREAM_URL`: If set uses the Jetstream over the firehose/relay. Other firehose settings apply to the jetstream connection (default: ``, but `https://jetstream1.us-east.bsky.network` is a public node hosted by Bluesky that you can use)
113113+- `TAB_FIREHOSE_PARALLELISM`: concurrent firehose event processors (default: `10`)
114114+- `TAB_RESYNC_PARALLELISM`: concurrent resync workers (default: `5`)
115115+- `TAB_OUTBOX_PARALLELISM`: concurrent outbox workers (default: `1`)
116116+- `TAB_CURSOR_SAVE_INTERVAL`: how often to persist upstream firehose cursor (default: `1s`)
117117+- `TAB_NO_REPLAY`: skip saved cursor and connect to firehose head on startup; incompatible with `TAB_FULL_NETWORK`, not recommended for production (default: `false`)
118118+- `TAB_REPO_FETCH_TIMEOUT`: timeout for fetching repo CARs from PDS (default: `300s`)
119119+- `TAB_IDENT_CACHE_SIZE`: size of in-process identity cache (default: `2000000`)
120120+- `TAB_OUTBOX_CAPACITY`: rough size of outbox before back pressure is applied (default: `100000`)
121121+- `TAB_FULL_NETWORK`: track all repos on the network (default: `false`)
122122+- `TAB_SIGNAL_COLLECTION`: track all repos with at least one record in this collection (e.g. `app.bsky.actor.profile`)
123123+- `TAB_LIGHT_RAIL_SIGNAL_COLLECTIONS`: track all repos with at least one record in these collections. Can not be used with `TAB_SIGNAL_COLLECTION` (e.g. `community.lexicon.calendar.rsvp,community.lexicon.calendar.event`)
124124+- `TAB_COLLECTION_FILTERS`: comma-separated collection filters, wildcards accepted (e.g., `app.bsky.feed.post,app.bsky.graph.*`)
125125+- `TAB_DISABLE_ACKS`: fire-and-forget mode, no client acks (default: `false`)
126126+- `TAB_WEBHOOK_URL`: webhook URL for event delivery (disables WebSocket mode)
127127+- `TAB_OUTBOX_ONLY`: run in outbox-only mode (no firehose, resync, or enumeration) (default: `false`)
128128+- `TAB_ADMIN_PASSWORD`: Basic auth admin password required for all requests (if set)
129129+- `TAB_RETRY_TIMEOUT`: timeout before retrying unacked events (default: `60s`)
130130+- `TAB_LOG_LEVEL`: log verbosity (`debug`, `info`, `warn`, `error`, default: `info`)
131131+- `TAB_METRICS_LISTEN`: address for metrics/pprof server (disabled if empty)
102132103133## Delivery Modes
104134···106136107137**WebSocket with acks** (default): Client sends acks each event once it has been processed/persisted. Ensures that no data is lost and client does not need to handle cursors. It's recommended to use a client library such as [@atproto/tab](https://github.com/bluesky-social/atproto/tree/main/packages/tab/README.md) when using this mode.
108138109109-**Fire-and-forget**: Set `tab_DISABLE_ACKS=true`. Events are sent and considered "acked" once the client receives them. Simpler but may result in data loss. Recommended for testing purposes or when data integrity is not critical.
139139+**Fire-and-forget**: Set `TAB_DISABLE_ACKS=true`. Events are sent and considered "acked" once the client receives them. Simpler but may result in data loss. Recommended for testing purposes or when data integrity is not critical.
110140111111-**Webhook**: Set `tab_WEBHOOK_URL=http://...`. Events are POSTed as JSON. Events considered "acked" once the webhook responds with a 200. Recommended for lower throughput serverless environments.
141141+**Webhook**: Set `TAB_WEBHOOK_URL=http://...`. Events are POSTed as JSON. Events considered "acked" once the webhook responds with a 200. Recommended for lower throughput serverless environments.
112142113143114144## Network Boundary Modes
···117147118148**Dynamically Configured** (default): tab starts out tracking no repos. Specific repos can then by added via `/repos/add` and removed via `/repos/remove`.
119149120120-**Collection Signal**: Set `tab_SIGNAL_COLLECTION=com.example.nsid`. Track all repos that have at least one record in the specified collection. Many applications create a "declaration" or "profile" in a repo when that repo uses that application
150150+**Collection Signal**: Set `TAB_SIGNAL_COLLECTION=com.example.nsid`. Track all repos that have at least one record in the specified collection. Many applications create a "declaration" or "profile" in a repo when that repo uses that application
121151122122-**Full Network**: Set `tab_FULL_NETWORK=true`. Enumerates and tracks all findable repos on the entire network. Resource-intensive and takes days/weeks to complete backfill.
152152+**Full Network**: Set `TAB_FULL_NETWORK=true`. Enumerates and tracks all findable repos on the entire network. Resource-intensive and takes days/weeks to complete backfill.
123153124154## Collection Filtering
125155126156After narrowing down the network to a subset of repos, tab can further filter records down to a specified set of collections. Filters apply to record events only. Identity events are always delivered for tracked repos.
127157128128-If you are interested syncing all of a single record type, it is important to specify that collection as both the signal collection and the filter collection. For example: `tab_SIGNAL_COLLECTION=com.example.nsid tab_COLLECTION_FILTERS=com.example.nsid`
158158+If you are interested syncing all of a single record type, it is important to specify that collection as both the signal collection and the filter collection. For example: `TAB_SIGNAL_COLLECTION=com.example.nsid TAB_COLLECTION_FILTERS=com.example.nsid`
129159130160Collection filters use wildcards but only at the period breaks in NSIDs. For example:
131161132132-`tab_COLLECTION_FILTERS=app.bsky.feed.post,app.bsky.graph.*`
162162+`TAB_COLLECTION_FILTERS=app.bsky.feed.post,app.bsky.graph.*`
133163134164135165## Event Format
···208238209239## Authentication
210240211211-If exposing tab to the internet, you should set `tab_ADMIN_PASSWORD` to require authentication for all API requests.
241241+If exposing tab to the internet, you should set `TAB_ADMIN_PASSWORD` to require authentication for all API requests.
212242213243tab uses HTTP Basic authentication with the username `admin`. Basic auth works by concatenating the username and password with a colon (`admin:yourpassword`), then base64-encoding the result. This is sent in the `Authorization` header as `Basic <encoded-value>`.
214244···239269```bash
240270go build -o tab ./cmd/tab
241271./tab run
242242-```
243243-244244-**Docker:**
245245-246246-A pre-built Docker image is also available:
247247-```bash
248248-docker pull ghcr.io/bluesky-social/indigo/tab:latest
249249-docker run -p 2480:2480 ghcr.io/bluesky-social/indigo/tab:latest
250250-```
251251-252252-To persist data, mount a volume at `/data`:
253253-```bash
254254-docker run -p 2480:2480 -v ./data:/data ghcr.io/bluesky-social/indigo/tab:latest
255272```
256273257274The Dockerfile is included in the repo at `cmd/tab/Dockerfile` if you need to build your own image.