forked from PostHog/posthog
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.xcloud.yml
More file actions
227 lines (201 loc) · 8.69 KB
/
Copy pathdocker-compose.xcloud.yml
File metadata and controls
227 lines (201 loc) · 8.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#
# xCloud overlay for the PostHog hobby stack.
#
# xCloud terminates TLS at the host nginx/OpenResty vhost and reverse-proxies to a
# loopback port. This overlay therefore makes the stack a plain-HTTP origin bound to
# 127.0.0.1 and keeps every auxiliary service off the public interface.
#
# Usage (from the repo root, alongside the .env produced by bin/deploy-hobby):
#
# docker compose -f docker-compose.hobby.yml -f docker-compose.xcloud.yml up -d
#
# Requires Docker Compose v2.24.4+ for the `!override` tag. Published ports merge on
# {ip, target, published, protocol} rather than being replaced, so without `!override`
# the hobby file's 80:80 and 443:443 would survive this overlay and fight the host
# nginx for the public ports.
#
# Host vhost must forward the proxy headers, or Django's SECURE_SSL_REDIRECT
# (on by default in production, posthog/settings/access.py) will redirect-loop:
#
# location / {
# proxy_pass http://127.0.0.1:18080;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_http_version 1.1;
# proxy_buffering off; # keep /livestream SSE streaming
# }
#
# DOMAIN in .env stays the public hostname; SITE_URL remains https://$DOMAIN because
# that is still the externally visible origin.
#
services:
# Caddy: plain HTTP on loopback only. No 443, no ACME.
proxy:
ports: !override
- '127.0.0.1:18080:80'
environment:
# The hobby file feeds $TLS_BLOCK / "$DOMAIN, http://, https://" into these,
# which makes Caddy bind 443 and attempt ACME. Blank them out.
CADDY_TLS_BLOCK: ''
CADDY_HOST: ':80'
# CADDYFILE is pinned here rather than inherited from docker-compose.base.yml.
# The base value interpolates ${CADDY_HOST} / ${CADDY_TLS_BLOCK} at Compose
# parse time from .env — NOT from the environment block above — so a stale
# CADDY_HOST left behind by bin/deploy-hobby would silently restore the
# https:// site address and ACME. Pinning is the only way to guarantee from
# this file alone that the container never listens on 443.
#
# KEEP IN SYNC: the routing below is copied verbatim from the `proxy` service
# in docker-compose.base.yml. Re-check it when rebasing on upstream master;
# new capture/ingest routes added upstream will not appear here on their own.
CADDYFILE: |
{
auto_https off
servers {
# xCloud's nginx is the real edge. Trusting it means Caddy
# preserves the inbound X-Forwarded-Proto/For instead of
# overwriting them with its own (http) view of the connection.
# Without this, Django sees scheme=http and SECURE_SSL_REDIRECT
# bounces every request back to https forever.
trusted_proxies static private_ranges
}
}
:80 {
@replay-capture {
path /s
path /s/
path /s/*
}
@capture-ai {
path /i/v0/ai
path /i/v0/ai/
path /i/v0/ai/*
}
@capture {
path /e
path /e/
path /e/*
path /i/v0
path /i/v0/
path /i/v0/*
path /i/v1/analytics/events
path /i/v1/analytics/events/
path /batch
path /batch/
path /batch/*
path /capture
path /capture/
path /capture/*
}
@capture-logs {
path /i/v1/logs
path /i/v1/logs/
path /i/v1/logs/*
path /i/v1/traces
path /i/v1/traces/
path /i/v1/traces/*
path /i/v1/metrics
path /i/v1/metrics/
path /i/v1/metrics/*
}
@flags {
path /flags
path /flags/
path /flags/*
path /api/feature_flag/local_evaluation
path /api/feature_flag/local_evaluation/
path /api/feature_flag/local_evaluation/*
}
@surveys {
path /surveys
path /surveys/
path /api/surveys
path /api/surveys/
}
@remote-config {
path /array/*
}
@webhooks {
path /public/webhooks
path /public/webhooks/
path /public/webhooks/*
path /public/m/
path /public/m/*
}
@livestream {
path /livestream
path /livestream/
path /livestream/*
}
handle @livestream {
uri strip_prefix /livestream
reverse_proxy livestream:8080 {
flush_interval -1
}
}
handle @capture-ai {
reverse_proxy capture-ai:3000
}
handle @capture {
reverse_proxy capture:3000
}
handle @replay-capture {
reverse_proxy replay-capture:3000
}
handle @capture-logs {
reverse_proxy capture-logs:4318
}
handle @flags {
reverse_proxy feature-flags:3001
}
handle @surveys {
reverse_proxy hypercache-server:3002
}
handle @remote-config {
reverse_proxy hypercache-server:3002
}
handle @webhooks {
reverse_proxy plugins:6738
}
@objectstorage {
path /posthog
path /posthog/
path /posthog/*
}
handle @objectstorage {
reverse_proxy objectstorage:19000
}
handle {
reverse_proxy web:8000
}
}
# Django is no longer the TLS terminator. Tell it to read the forwarded scheme so
# SECURE_SSL_REDIRECT and absolute-URL generation resolve to https.
web:
environment:
IS_BEHIND_PROXY: 'true'
# Only xCloud's nginx can reach the origin (loopback-bound), so the forwarded
# headers are trustworthy by construction. Narrow this by setting
# POSTHOG_TRUSTED_PROXIES in .env if you want explicit CIDRs instead.
TRUST_ALL_PROXIES: ${POSTHOG_TRUST_ALL_PROXIES:-true}
TRUSTED_PROXIES: ${POSTHOG_TRUSTED_PROXIES:-}
# --- Auxiliary services: reachable from the host, never from the public interface ---
# Each of these publishes on 0.0.0.0 in docker-compose.hobby.yml. Rebound to
# loopback so they are reachable only via SSH tunnel or from the server itself.
# Note the app does not need any of these published: the web/worker containers
# talk to them over the compose network, and MinIO is additionally reachable
# through Caddy at /posthog/*.
objectstorage:
ports: !override
- '127.0.0.1:19000:19000' # S3 API
- '127.0.0.1:19001:19001' # MinIO console
temporal:
ports: !override
- '127.0.0.1:7233:7233' # gRPC frontend
temporal-ui:
ports: !override
- '127.0.0.1:8081:8080'
# seaweedfs already binds 127.0.0.1 for 8333/9333 in docker-compose.hobby.yml,
# so it needs no override here.