atproto blogging
1services:
2 # Caddy - reverse proxy with automatic TLS
3 caddy:
4 image: ${REGISTRY_HOST:-localhost}:5000/weaver-caddy:latest
5 container_name: weaver-caddy
6 ports:
7 - "80:80"
8 - "443:443"
9 - "2019:2019" # Admin API with metrics
10 volumes:
11 - ./infra/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
12 - caddy_data:/data
13 - caddy_config:/config
14 environment:
15 CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN}
16 ACME_EMAIL: ${ACME_EMAIL:-contact@weaver.sh}
17 depends_on:
18 - weaver-app
19 - index
20 restart: unless-stopped
21
22 # ClickHouse - analytics database
23 clickhouse:
24 image: clickhouse/clickhouse-server:25.11
25 container_name: weaver-clickhouse
26 ports:
27 - "8123:8123"
28 - "9000:9000"
29 - "9363:9363" # Prometheus metrics
30 volumes:
31 - ~/data/clickhouse:/var/lib/clickhouse
32 - ~/data/clickhouse-logs:/var/log/clickhouse-server
33 - ~/data/clickhouse-config:/etc/clickhouse-server/config.d
34 - ./infra/clickhouse/prometheus.xml:/etc/clickhouse-server/config.d/prometheus.xml:ro
35 environment:
36 CLICKHOUSE_DB: ${CLICKHOUSE_DATABASE:-weaver}
37 CLICKHOUSE_USER: ${CLICKHOUSE_USER:-default}
38 CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD}
39 CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
40 ulimits:
41 nofile:
42 soft: 262144
43 hard: 262144
44 healthcheck:
45 test: ["CMD", "wget", "--spider", "-q", "http://localhost:8123/ping"]
46 interval: 10s
47 timeout: 5s
48 retries: 3
49 restart: unless-stopped
50
51 # Docker registry for local image hosting
52 registry:
53 image: registry:2
54 container_name: weaver-registry
55 ports:
56 - "5000:5000"
57 volumes:
58 - registry_data:/var/lib/registry
59 restart: unless-stopped
60
61 # Tap - AT Protocol sync utility
62 tap:
63 container_name: weaver-tap
64 image: ghcr.io/bluesky-social/indigo/tap:latest
65 ports:
66 - "2480:2480"
67 - "2481:2481"
68 volumes:
69 - tap_data:/data/tap
70 environment:
71 TAP_DATABASE_URL: sqlite:///data/tap/tap.db
72 TAP_BIND: ":2480"
73 TAP_METRICS_LISTEN: ":2481"
74 TAP_DISABLE_ACKS: "false"
75 TAP_LOG_LEVEL: debug
76 TAP_OUTBOX_PARALLELISM: 5
77 #TAP_FULL_NETWORK: true
78 #TAP_SIGNAL_COLLECTION: place.stream.chat.profile
79 TAP_SIGNAL_COLLECTION: sh.weaver.actor.profile
80 TAP_COLLECTION_FILTERS: "sh.weaver.*,app.bsky.actor.profile,sh.tangled.*,pub.leaflet.*,net.anisota.*,place.stream.*,site.standard.*"
81 healthcheck:
82 test: ["CMD", "wget", "-q", "--spider", "http://localhost:2480/health"]
83 interval: 20s
84 timeout: 5s
85 retries: 3
86 restart: unless-stopped
87
88 # Weaver indexer - consumes from tap
89 index:
90 container_name: weaver-index
91 image: ${REGISTRY_HOST:-localhost}:5000/weaver-index:latest
92 ports:
93 - "3000:3000"
94 command: ["run"]
95 volumes:
96 - index_data:/app/data
97 environment:
98 RUST_LOG: info,weaver_index=debug,hyper_util::client::legacy::pool=info
99 LOKI_URL: ${LOKI_URL:-}
100 CLICKHOUSE_URL: http://clickhouse:8123
101 CLICKHOUSE_DATABASE: ${CLICKHOUSE_DATABASE:-weaver}
102 CLICKHOUSE_USER: ${CLICKHOUSE_USER:-default}
103 CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD}
104 INDEXER_SOURCE: tap
105 TAP_URL: ws://tap:2480/channel
106 TAP_SEND_ACKS: "true"
107 FIREHOSE_RELAY_URL: wss://bsky.network
108 INDEXER_COLLECTIONS: "sh.weaver.*,app.bsky.actor.profile,sh.tangled.*,pub.leaflet.*,net.anisota.*,place.stream.*,site.standard.*"
109 depends_on:
110 tap:
111 condition: service_healthy
112 clickhouse:
113 condition: service_healthy
114 healthcheck:
115 test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://localhost:3000/xrpc/_health"]
116 interval: 20s
117 timeout: 5s
118 retries: 3
119 restart: unless-stopped
120
121 # Weaver app - web frontend
122 weaver-app:
123 container_name: weaver-app
124 image: ${REGISTRY_HOST:-localhost}:5000/weaver-app:latest
125 ports:
126 - "8080:8080"
127 environment:
128 PORT: 8080
129 IP: 0.0.0.0
130 RUST_LOG: info,weaver-app=debug,weaver-common=debug,hyper=warn,hyper_util=warn,tower=warn,h2=warn,rustls=warn,reqwest=info,dioxus_core=warn,dioxus_signals=warn
131 LOKI_URL: ${LOKI_URL:-}
132 healthcheck:
133 test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/"]
134 interval: 20s
135 timeout: 5s
136 retries: 3
137 restart: unless-stopped
138
139 # ============ OBSERVABILITY STACK ============
140
141 # Node exporter - host metrics (CPU, memory, disk, network)
142 node-exporter:
143 image: prom/node-exporter:latest
144 container_name: weaver-node-exporter
145 ports:
146 - "9100:9100"
147 volumes:
148 - /proc:/host/proc:ro
149 - /sys:/host/sys:ro
150 - /:/rootfs:ro
151 command:
152 - "--path.procfs=/host/proc"
153 - "--path.sysfs=/host/sys"
154 - "--path.rootfs=/rootfs"
155 - "--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)"
156 restart: unless-stopped
157
158 # cAdvisor - container metrics (per-container CPU, memory, network)
159 cadvisor:
160 image: gcr.io/cadvisor/cadvisor:latest
161 container_name: weaver-cadvisor
162 ports:
163 - "9080:8080"
164 volumes:
165 - /:/rootfs:ro
166 - /var/run:/var/run:ro
167 - /sys:/sys:ro
168 - /var/lib/docker/:/var/lib/docker:ro
169 - /dev/disk/:/dev/disk:ro
170 privileged: true
171 restart: unless-stopped
172
173 # Promtail - ship container logs to Loki
174 promtail:
175 image: grafana/promtail:latest
176 container_name: weaver-promtail
177 volumes:
178 - ./infra/promtail/config.yml:/etc/promtail/config.yml:ro
179 - /var/lib/docker/containers:/var/lib/docker/containers:ro
180 - /var/run/docker.sock:/var/run/docker.sock:ro
181 command: -config.file=/etc/promtail/config.yml -config.expand-env=true
182 environment:
183 LOKI_URL: ${LOKI_URL:-http://localhost:3100}
184 restart: unless-stopped
185
186volumes:
187 registry_data:
188 tap_data:
189 index_data:
190 caddy_data:
191 caddy_config: