A community based topic aggregation platform built on atproto
1version: '3.8'
2
3# Coves Local Development Stack
4# All-in-one setup: PDS + PostgreSQL + optional Relay
5#
6# Usage:
7# make dev-up # Start PDS + PostgreSQL
8# make dev-down # Stop everything
9# docker-compose up relay # Optional: start with relay
10#
11# Profiles:
12# - default: PDS + PostgreSQL (dev database on port 5433)
13# - test: PostgreSQL test database (port 5434)
14# - relay: BigSky relay (optional, will crawl entire network!)
15
16services:
17 # PostgreSQL Database (Port 5433)
18 # Used by Coves AppView for indexing data from firehose
19 postgres:
20 image: postgres:15
21 container_name: coves-dev-postgres
22 ports:
23 - "5433:5432"
24 environment:
25 POSTGRES_DB: ${POSTGRES_DB:-coves_dev}
26 POSTGRES_USER: ${POSTGRES_USER:-dev_user}
27 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-dev_password}
28 volumes:
29 - postgres-data:/var/lib/postgresql/data
30 networks:
31 - coves-dev
32 healthcheck:
33 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-dev_user} -d ${POSTGRES_DB:-coves_dev}"]
34 interval: 5s
35 timeout: 5s
36 retries: 5
37
38 # PostgreSQL Test Database (Port 5434) - Optional
39 # Use with: docker-compose --profile test up postgres-test
40 postgres-test:
41 image: postgres:15
42 container_name: coves-test-postgres
43 ports:
44 - "${POSTGRES_TEST_PORT:-5434}:5432"
45 environment:
46 POSTGRES_DB: ${POSTGRES_TEST_DB:-coves_test}
47 POSTGRES_USER: ${POSTGRES_TEST_USER:-test_user}
48 POSTGRES_PASSWORD: ${POSTGRES_TEST_PASSWORD:-test_password}
49 volumes:
50 - postgres-test-data:/var/lib/postgresql/data
51 networks:
52 - coves-dev
53 healthcheck:
54 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_TEST_USER:-test_user} -d ${POSTGRES_TEST_DB:-coves_test}"]
55 interval: 5s
56 timeout: 5s
57 retries: 5
58 profiles:
59 - test
60
61 # Bluesky Personal Data Server (PDS)
62 # Handles user repositories, DIDs, and CAR files
63 pds:
64 image: ghcr.io/bluesky-social/pds:latest
65 container_name: coves-dev-pds
66 ports:
67 - "3001:3000" # PDS XRPC API (avoiding production PDS on :3000)
68 environment:
69 # PDS Configuration
70 PDS_HOSTNAME: ${PDS_HOSTNAME:-localhost}
71 PDS_PORT: 3000
72 PDS_DATA_DIRECTORY: /pds
73 PDS_BLOBSTORE_DISK_LOCATION: /pds/blocks
74 PDS_DID_PLC_URL: ${PDS_DID_PLC_URL:-https://plc.directory}
75 # PDS_CRAWLERS not needed - we're not using a relay for local dev
76
77 # Note: PDS uses its own internal SQLite database and CAR file storage
78 # Our PostgreSQL database is only for the Coves AppView
79
80 # JWT secrets (for local dev only)
81 PDS_JWT_SECRET: ${PDS_JWT_SECRET:-local-dev-jwt-secret-change-in-production}
82 PDS_ADMIN_PASSWORD: ${PDS_ADMIN_PASSWORD:-admin}
83 PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX: ${PDS_PLC_ROTATION_KEY:-af514fb84c4356241deed29feb392d1ee359f99c05a7b8f7bff2e5f2614f64b2}
84
85 # Service endpoints
86 PDS_SERVICE_HANDLE_DOMAINS: ${PDS_SERVICE_HANDLE_DOMAINS:-.local.coves.dev}
87
88 # Dev mode settings (allows HTTP instead of HTTPS)
89 PDS_DEV_MODE: "true"
90
91 # Development settings
92 NODE_ENV: development
93 LOG_ENABLED: "true"
94 LOG_LEVEL: ${LOG_LEVEL:-debug}
95 volumes:
96 - pds-data:/pds
97 networks:
98 - coves-dev
99 healthcheck:
100 test: ["CMD", "curl", "-f", "http://localhost:3000/xrpc/_health"]
101 interval: 10s
102 timeout: 5s
103 retries: 5
104
105 # Jetstream - Consumes PDS firehose and serves JSON WebSocket
106 # This is the RECOMMENDED approach for local E2E testing
107 # Jetstream converts raw atProto CBOR firehose to clean JSON events
108 #
109 # Flow: PDS firehose → Jetstream (CBOR→JSON) → Your AppView (JSON)
110 #
111 # Usage:
112 # docker-compose --profile jetstream up pds jetstream
113 # Your AppView connects to: ws://localhost:6008/subscribe
114 #
115 # Why use Jetstream instead of direct PDS firehose?
116 # - PDS emits raw CBOR (binary) - hard to parse
117 # - Jetstream converts to clean JSON - easy to consume
118 # - Same format as production Bluesky Jetstream
119 jetstream:
120 image: ghcr.io/bluesky-social/jetstream:sha-306e463693365e21a5ffd3ec051a5a7920000214
121 container_name: coves-dev-jetstream
122 ports:
123 - "6008:6008" # Jetstream WebSocket endpoint
124 - "6009:6009" # Metrics endpoint
125 environment:
126 # Point Jetstream at local PDS firehose
127 JETSTREAM_WS_URL: ws://pds:3000/xrpc/com.atproto.sync.subscribeRepos
128
129 # Server configuration
130 JETSTREAM_LISTEN_ADDR: ":6008"
131 JETSTREAM_METRICS_LISTEN_ADDR: ":6009"
132
133 # Data storage
134 JETSTREAM_DATA_DIR: /data
135 JETSTREAM_EVENT_TTL: 24h
136
137 # Set long liveness TTL for local dev (PDS may be quiet for long periods)
138 JETSTREAM_LIVENESS_TTL: 24h
139
140 # Performance tuning
141 JETSTREAM_WORKER_COUNT: 10
142 JETSTREAM_MAX_QUEUE_SIZE: 1000
143
144 # Development settings
145 LOG_LEVEL: ${LOG_LEVEL:-debug}
146 volumes:
147 - jetstream-data:/data
148 networks:
149 - coves-dev
150 depends_on:
151 pds:
152 condition: service_healthy
153 healthcheck:
154 test: ["CMD", "curl", "-f", "http://localhost:6009/metrics"]
155 interval: 10s
156 timeout: 5s
157 retries: 5
158 profiles:
159 - jetstream
160
161 # Indigo Relay (BigSky) - OPTIONAL for local dev
162 # WARNING: BigSky is designed to crawl the entire atProto network!
163 # For local dev, consider using direct PDS firehose instead (see AppView config below)
164 #
165 # To use relay: docker-compose -f docker-compose.dev.yml up pds relay
166 # To skip relay: docker-compose -f docker-compose.dev.yml up pds
167 #
168 # If using relay, you MUST manually configure it to only watch local PDS:
169 # 1. Start relay
170 # 2. Use admin API to block all domains except localhost
171 # curl -X POST http://localhost:2471/admin/pds/requestCrawl \
172 # -H "Authorization: Bearer dev-admin-key" \
173 # -d '{"hostname": "localhost:3001"}'
174 relay:
175 image: ghcr.io/bluesky-social/indigo:bigsky-0a2d4173e6e89e49b448f6bb0a6e1ab58d12b385
176 container_name: coves-dev-relay
177 ports:
178 - "2471:2470" # Relay firehose WebSocket (avoiding conflicts)
179 environment:
180 # Relay Configuration
181 BGS_ADMIN_KEY: ${BGS_ADMIN_KEY:-dev-admin-key}
182 BGS_PORT: 2470
183
184 # IMPORTANT: Allow insecure WebSocket for local PDS (ws:// instead of wss://)
185 BGS_CRAWL_INSECURE_WS: "true"
186
187 # Database connection (uses PostgreSQL for relay state)
188 DATABASE_URL: postgresql://${POSTGRES_USER:-dev_user}:${POSTGRES_PASSWORD:-dev_password}@postgres:5432/${POSTGRES_DB:-coves_dev}?sslmode=disable
189
190 # Relay will discover PDSs automatically - use admin API to restrict!
191 # See comments above for how to configure allowlist
192
193 # Development settings
194 LOG_LEVEL: ${LOG_LEVEL:-debug}
195 networks:
196 - coves-dev
197 depends_on:
198 postgres:
199 condition: service_healthy
200 pds:
201 condition: service_healthy
202 healthcheck:
203 test: ["CMD", "curl", "-f", "http://localhost:2470/xrpc/_health"]
204 interval: 10s
205 timeout: 5s
206 retries: 5
207 # Mark as optional - start with: docker-compose up pds relay
208 profiles:
209 - relay
210
211 # Coves AppView (Your Go Application)
212 # Subscribes to PDS firehose and indexes Coves-specific data
213 # Note: Uncomment when you have a Dockerfile for the AppView
214 # appview:
215 # build:
216 # context: .
217 # dockerfile: Dockerfile
218 # container_name: coves-dev-appview
219 # ports:
220 # - "8081:8080" # AppView API (avoiding conflicts)
221 # environment:
222 # # Database connection
223 # DATABASE_URL: postgresql://${POSTGRES_USER:-dev_user}:${POSTGRES_PASSWORD:-dev_password}@postgres:5432/${POSTGRES_DB:-coves_dev}?sslmode=disable
224 #
225 # # PDS Firehose subscription (direct, no relay)
226 # FIREHOSE_URL: ws://pds:3000/xrpc/com.atproto.sync.subscribeRepos
227 #
228 # # PDS connection (for XRPC calls)
229 # PDS_URL: http://pds:3000
230 #
231 # # Application settings
232 # PORT: 8080
233 # ENV: development
234 # LOG_LEVEL: ${LOG_LEVEL:-debug}
235 # networks:
236 # - coves-dev
237 # depends_on:
238 # postgres:
239 # condition: service_healthy
240 # pds:
241 # condition: service_healthy
242
243networks:
244 coves-dev:
245 driver: bridge
246 name: coves-dev-network
247
248volumes:
249 postgres-data:
250 name: coves-dev-postgres-data
251 postgres-test-data:
252 name: coves-test-postgres-data
253 pds-data:
254 name: coves-dev-pds-data
255 jetstream-data:
256 name: coves-dev-jetstream-data