Deploy Teleproxy [Updated Sep '26]

Teleproxy — Self-Hosted MTProto Proxy for Telegram, Fake-TLS DPI Resistant

Deploy Teleproxy [Updated Sep '26]

Just deployed

/opt/teleproxy/data

Deploy and Host Teleproxy (MTProto Proxy) on Railway

Teleproxy is an open-source MTProto proxy for Telegram — a small, high-performance relay that disguises your proxy traffic as ordinary HTTPS to a domain of your choosing, so network-level censorship that blocks Telegram directly has a much harder time blocking this. This template deploys it as a single container, verified live against the app's own startup script rather than guessed from documentation.

About Hosting Teleproxy

Teleproxy's fake-TLS camouflage means connections to your proxy look, at a glance, like a normal HTTPS handshake to whatever domain you set as EE_DOMAIN. Combined with DPI resistance built into the proxy engine itself, this makes Teleproxy a meaningfully harder target to block than a plain, unobfuscated proxy. Self-hosting it on Railway means you control the secret, the camouflage domain, and the underlying server — nothing routes through a third party.

How MTProto Fake-TLS Actually Works

MTProto is Telegram's own transport protocol — the format its official clients use to talk to Telegram's servers. An MTProto proxy is a relay that forwards this specific traffic on your behalf, which is a narrower job than a general-purpose SOCKS or HTTP proxy, but that narrowness is exactly what makes the obfuscation effective: since the proxy only ever needs to speak one protocol, it can specialize in disguising that one protocol convincingly.

There are effectively three generations of MTProto obfuscation, distinguished by the format of the connection secret:

  • Plain MTProto (no obfuscation): traffic is forwarded as-is, and any ISP running deep packet inspection can fingerprint the packet structure almost immediately. In networks that actively filter Telegram, plain MTProto gets blocked within seconds.
  • Obfuscated MTProto (dd-prefixed secrets): randomizes enough of the traffic to defeat casual inspection. This was generally sufficient protection through the early 2020s.
  • Fake-TLS (ee-prefixed secrets): the connection imitates a genuine TLS handshake to a real domain — the one you set as EE_DOMAIN. To a firewall doing DPI, the traffic reads as someone visiting an ordinary HTTPS site, not as Telegram traffic at all.

This template uses fake-TLS by default — the ee prefix and the domain-hex encoding get constructed automatically in the connection link Teleproxy generates, built directly from your EE_DOMAIN and SECRET values. You don't need to hand-construct anything.

Worth being precise about what this hides: the proxy operator never sees message content — Telegram's own end-to-end and client-server encryption stays intact regardless of proxy. Fake-TLS hides the fact that you're using Telegram, from network observers between you and the proxy. It doesn't hide your connection from the proxy operator itself, which is exactly why self-hosting matters: no third party sees your connection metadata.

Why Deploy Teleproxy on Railway

Running an MTProto proxy normally means renting a small VPS specifically for this one purpose, SSHing in, and manually running a Docker command. Railway collapses that into a one-click deploy with persistent storage for the proxy's config cache and a real public TCP endpoint, generated automatically.

The reference version of this template on Railway's marketplace currently sits at 68% health, and it's worth understanding why before deploying it as-is: its configuration ships with no networking set up at all. It deploys successfully every time — the container boots clean — but nothing is ever exposed publicly, so no Telegram client can actually reach it. It's not broken so much as inert. This template fixes that directly.

This Template's One Real Finding

Getting to a working fix took more than "just add a TCP proxy," since the wrong port was surprisingly easy to assume. The app's own logs print Started as [IP:8888:worker_id:timestamp] for every worker — including the main one — which looks like confirmation that 8888 is the real listener. It isn't; that's a worker identifier, not a bind address. The real answer came from reading the container's own start.sh directly: PORT=${PORT:-443} is the actual MTProto port; STATS_PORT=${STATS_PORT:-8888} is a separate stats/QR server, bound to 127.0.0.1 only, and never externally reachable.

Worth naming a real dead end hit along the way: an earlier attempt targeted port 8888 with a TCP proxy staged before first boot, and that reliably crashed with bind(): Address in use — reproduced identically on a brand-new project, ruling out leftover state. That looked like a platform-level bug. It wasn't. Repeating the same test on the correct port, 443, deployed clean with zero crashes, verified twice. The crash was entirely due to the wrong port, not a Railway issue — meaning a TCP proxy on 443 is safe to pre-configure directly in this template.

Understanding the Configuration Variables

EE_DOMAIN is the most important variable for the camouflage. It should be a real, reachable HTTPS domain not served through a CDN like Cloudflare (fake-TLS is incompatible with shared-IP CDN proxying) — the default, www.microsoft.com, works well. At startup Teleproxy fetches that domain's real TLS response to shape its fake handshake; if the fetch fails (seen during this template's own testing, logged as Failed to parse upstream TLS response), it falls back to default response settings and keeps running — non-fatal.

SECRET is your connection credential, auto-generated as a 32-character hex string — treat it like any shared credential. Teleproxy also supports numbered SECRET_1 through SECRET_16 variables for issuing distinct, independently revocable credentials per person or device.

WORKERS controls how many worker processes handle connections concurrently — 4 is a reasonable default, raise it for higher volume.

DIRECT_MODE (default false) routes through Telegram's official "ME" relay; true connects straight to Telegram's data centers instead, but is incompatible with PROXY_TAG.

PROXY_TAG is optional and ties into Telegram's proxy-sponsorship mechanism for promoting a channel. Leave it blank unless you want that.

Common Use Cases

  • Bypassing network-level Telegram blocks: fake-TLS camouflage makes proxy traffic harder to distinguish from normal HTTPS
  • Running a private proxy for personal or family use: your own secret, your own server, no third-party proxy operator
  • Issuing separate, revocable credentials: numbered SECRET_N variables let you hand out distinct connection links per person or device
  • Sharing proxy access via PROXY_TAG: optionally promote a channel through your proxy's connection link

Dependencies for Teleproxy Hosting

Just one service — no database, no cache. The volume at /opt/teleproxy/data caches Telegram's proxy config so it isn't re-fetched from core.telegram.org on every restart.

Implementation Details

The template runs the official ghcr.io/teleproxy/teleproxy:latest image, verified against its actual entrypoint (/opt/teleproxy/start.sh) rather than assumed from docs. A TCP proxy on port 443 is included in the networking config — confirmed safe to pre-stage before first boot. Deploy logs print the ready-to-share tg://proxy?... link automatically.

How Teleproxy Compares to General-Purpose Circumvention Tools

Against Shadowsocks, a general-purpose SOCKS5 proxy: Shadowsocks carries any traffic, not just Telegram, but its distinct pattern has grown more fingerprintable to advanced DPI over time. Teleproxy is narrower by design — Telegram only — and its fake-TLS mode directly targets that weakness.

Against V2Ray/Xray, a larger, more flexible framework: its configuration surface is substantially bigger, which pays off for general internet circumvention. For reliable Telegram access specifically, Teleproxy's handful of variables gets there with far less setup.

Getting Started

Deploy the template. Railway assigns your proxy a public domain:port pair via the TCP proxy on port 443. Check the deploy logs for the printed tg://proxy?... connection link, or build one from your assigned endpoint and SECRET. Share that link (or the equivalent QR code) with whoever needs proxy access.

Frequently Asked Questions

Why does this template need a TCP proxy instead of a normal HTTP domain?

MTProto isn't HTTP — Telegram clients connect over raw TCP, so this needs a TCP proxy (a public domain:port pair) rather than an HTTP-routed domain.

Is port 8888 usable for anything external?

No. It's the stats/QR-code server, and it's bound to 127.0.0.1 inside the container by design — confirmed directly from the app's own startup script. No TCP proxy configuration can make it externally reachable.

Can the proxy operator read my Telegram messages?

No. Telegram's own encryption is unaffected by which proxy you use — the proxy only sees encrypted data. It can see metadata: your IP and connection timing, which is why self-hosting matters if that metadata concerns you.

Why did the reference template end up with poor health?

Its configuration has no networking set up at all — it deploys successfully but is completely unreachable by any Telegram client. This template's own composer config includes the correct TCP proxy from the start.

What happens if EE_DOMAIN can't be reached during startup?

Teleproxy tries to fetch that domain's real TLS response to make the fake handshake more convincing. If the fetch fails, it logs a warning and falls back to default response settings — the proxy still starts and works normally.

Can I issue different connection credentials to different people?

Yes — use the numbered SECRET_1 through SECRET_16 variables instead of (or alongside) SECRET. Each gets its own connection link, and each can be revoked independently by clearing that one variable, without affecting anyone else's access.


Template Content

More templates in this category

View Template
Rocky Linux
Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀

codestorm
47
View Template
Foundry Virtual Tabletop
A Self-Hosted & Modern Roleplaying Platform

Lucas
71
View Template
Letta Code Remote
Run a Letta Code agent 24/7. No inbound ports, just deploy.

Letta
50