Add docker-compose example with HAProxy SNI router#462
Merged
9seconds merged 3 commits into9seconds:masterfrom Apr 14, 2026
Merged
Add docker-compose example with HAProxy SNI router#4629seconds merged 3 commits into9seconds:masterfrom
9seconds merged 3 commits into9seconds:masterfrom
Conversation
Turnkey deployment: HAProxy on :443 peeks at the TLS SNI and routes Telegram clients to mtg while forwarding everything else (including DPI probes) to a real Caddy web server with automatic HTTPS. This is the setup recommended in BEST_PRACTICES.md, packaged so that operators can clone and run it with minimal configuration. Refs: 9seconds#458
Add an ACL that routes /.well-known/acme-challenge/ requests on :80 to Caddy instead of redirecting to HTTPS, so Let's Encrypt certificate issuance works out of the box. Also simplify Caddyfile to use Caddy's http_port/https_port directives.
Contributor
|
I believe that in this scheme, you should use the PROXY protocol to pass the real client IP to MTG and the web server. MTG supports the PROXY protocol for both inbound and outbound connections, so please consider the configuration changes required to use the PROXY protocol. |
Owner
|
Nice one! But agree with @ivulit about PROXY protocol |
Without this, mtg and Caddy see HAProxy's container IP for every connection, which breaks meaningful logging, abuse handling, and any IP-based blocklist logic. HAProxy sends a PROXY protocol v2 header on its TCP backends; mtg enables proxy-protocol-listener, and Caddy wraps :8443 with a proxy_protocol listener before tls. The :80 path (ACME HTTP-01 passthrough) is unchanged — client IP there is not useful and HAProxy's http mode already adds X-Forwarded-For if anyone wants it. Requested in 9seconds#462 review.
Contributor
Author
|
Pushed 170346b wiring up PROXY protocol v2 end-to-end:
Verified on a test VPS: HAProxy emits a well-formed v2 header and Caddy's wrapper unwraps it — |
Owner
|
Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A turnkey
docker composesetup incontrib/sni-router/that deploysmtg behind an HAProxy SNI router alongside a real Caddy web server with
automatic HTTPS.
Motivation
The setup recommended in
BEST_PRACTICES.md— own domain, real webserver, SNI-based routing — requires piecing together several services.
This bundle packages it so operators can clone and run with minimal
configuration.
How it works:
:443peeks at the TLS ClientHello SNI.:80redirects to HTTPS.Active probes see a genuine website with a valid Let's Encrypt
certificate. Passive DPI sees consistent SNI/IP because the domain's DNS
points to this server.
Files
docker-compose.ymlhaproxy.cfgmtg-config.tomlCaddyfilewww/index.htmlREADME.mdTest plan
docker compose configvalidates the compose filecurl https://DOMAIN/returns the Caddy-served pageopenssl s_client -connect IP:443 -servername random.examplegets Caddy's certRefs: #458