// DevOps
Telemt: installing MTProxy for Telegram in Docker on port 443 with Fake TLS
Published on 2026-05-29
Link to check how the installed TeleMT works
Telemt is an MTProxy server for Telegram written in Rust. Unlike the classic official image, it supports Fake TLS: traffic from outside looks like regular HTTPS to a real site, without a local SSL certificate. If someone connects to the port without the correct secret — DPI, a scanner, just a browser — the connection is transparently forwarded to the real github.com (or any other domain you specify). The inspecting party receives a live TLS handshake and understands nothing.
Below is a step-by-step installation in Docker Compose on port 443.
About SSL certificates — the main point
A local certificate is not needed. You don’t need Certbot, Let’s Encrypt, or ACME. You simply specify a real HTTPS domain in the config — Telemt uses it as a mask. This is a fundamental difference from Nginx or any classic proxy.
Step 1. Prepare the server
You need:
- A Linux server with a public IP;
- Docker Engine + Docker Compose plugin;
- Free port 443.
First, check whether the port is occupied:
ss -ltnp 'sport = :443'
If Nginx or Caddy is already running there — either free the port, or run Telemt on another port and perform L4 forwarding.
Create the working directory:
install -d -m 0750 /opt/telemt
cd /opt/telemt
Step 2. Generate the secret
The secret is 16 bytes, i.e. 32 hex characters:
openssl rand -hex 16
Or without OpenSSL:
xxd -l 16 -p /dev/urandom
Example:
7a2f8b5c9d0e1f2a3b4c5d6e7f8a9b0c
Save this value — it goes into the [access.users] section. The config uses exactly this short hex. The full client link with the ee prefix and the domain code will appear in the logs after startup — you don’t need to assemble it manually.
Step 3. config.toml
nano /opt/telemt/config.toml
Minimal working config for Fake TLS:
[general]
use_middle_proxy = true
log_level = "normal"
[general.modes]
classic = false
secure = false
tls = true
[general.links]
show = "*"
# If you want a domain instead of IP in links:
# public_host = "proxy.example.com"
# public_port = 443
[server]
port = 443
max_connections = 10000
# Prometheus metrics — localhost only
metrics_port = 9090
metrics_whitelist = ["127.0.0.1/32", "::1/128"]
[server.api]
enabled = true
listen = "127.0.0.1:9091"
whitelist = ["127.0.0.1/32", "::1/128"]
minimal_runtime_enabled = false
minimal_runtime_cache_ttl_ms = 1000
[[server.listeners]]
ip = "0.0.0.0"
[censorship]
# Mask domain. Do not change after links are issued — links will break.
tls_domain = "github.com"
mask = true
tls_emulation = true
tls_front_dir = "tlsfront"
[access.users]
tg_user1 = "7a2f8b5c9d0e1f2a3b4c5d6e7f8a9b0c"
Replace github.com with any working HTTPS site, tg_user1 with a convenient name, and the hex string with your secret.
Important: tls_domain, mask, tls_emulation — all of these live in the [censorship] section, not in [general]. Put them in the wrong place — the config will not work.
Step 4. docker-compose.yml
nano /opt/telemt/docker-compose.yml
services:
telemt:
image: ghcr.io/telemt/telemt:latest
container_name: telemt
restart: unless-stopped
ports:
- "443:443"
- "127.0.0.1:9090:9090"
- "127.0.0.1:9091:9091"
working_dir: /etc/telemt
volumes:
- ./config.toml:/etc/telemt/config.toml:ro
tmpfs:
- /etc/telemt:rw,mode=1777,size=4m
environment:
- RUST_LOG=info
healthcheck:
test: [ "CMD", "/app/telemt", "healthcheck", "/etc/telemt/config.toml", "--mode", "liveness" ]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
read_only: true
security_opt:
- no-new-privileges:true
ulimits:
nofile:
soft: 65536
hard: 262144
logging:
driver: json-file
options:
max-size: "50m"
max-file: "5"
In production it’s better to pin the image version:
image: ghcr.io/telemt/telemt:3.4.12
NET_BIND_SERVICE is needed because the process inside the container doesn’t run as root but must listen on port 443 — a privileged port. Docker port binding by itself does not solve that.
Step 5. Start
cd /opt/telemt
docker compose up -d
docker compose ps
docker compose logs -f telemt
Links will appear in the logs:
tg://proxy?server=SERVER_IP&port=443&secret=ee...
This is the working link — ee + your 32-character secret + the domain hex code.
Step 6. Get links via the Control API
You can skip the logs and call the API:
curl -s http://127.0.0.1:9091/v1/users | jq -r '
.data[]
| "[\(.username)]",
(.links.classic[]? | "classic: \(.)"),
(.links.secure[]? | "secure: \(.)"),
(.links.tls[]? | "tls: \(.)"),
""
'
If the command returns nothing — check server.api.listen, server.api.whitelist, and the Docker binding 127.0.0.1:9091:9091. Do not expose the API externally.
Step 7. Verify masking
Check that without the MTProxy secret the server behaves like regular HTTPS:
SERVER_IP="203.0.113.10"
TLS_DOMAIN="github.com"
curl -vkI --resolve "${TLS_DOMAIN}:443:${SERVER_IP}" "https://${TLS_DOMAIN}/"
TCP goes to your server, SNI indicates the tls_domain — the response should be a normal TLS from the real site.
Step 8. Multiple users
One secret per user:
openssl rand -hex 16
openssl rand -hex 16
openssl rand -hex 16
[access.users]
team1 = "00000000000000000000000000000001"
team2 = "00000000000000000000000000000002"
team3 = "00000000000000000000000000000003"
After editing the config, check via the API that the new users appeared. In theory reload works without restart, but in practice in a Docker environment I always run docker compose restart and check the logs.
Step 9. Limit unique IPs per link
If you don’t want one link to be used by a crowd:
[access.user_max_unique_ips]
team1 = 1
Limit by unique IPs. Devices behind the same NAT/router will appear as one IP.
Step 10. Prometheus metrics
curl http://127.0.0.1:9090/metrics
Do not expose metrics to the outside — 0.0.0.0/0 in metrics_whitelist opens them to everyone.
Troubleshooting
Port 443 is occupied
ss -ltnp 'sport = :443'
Find who occupied it and stop them or move Telemt to another port.
Old links stopped working
If you changed tls_domain — links broke, the domain is embedded in the ee secret. Reissue links via the API or logs.
Error Unknown TLS SNI
Clients with old links after changing the domain. You can mask it:
[censorship]
unknown_sni_action = "mask"
Or reject the handshake:
[censorship]
unknown_sni_action = "reject_handshake"
Telegram calls don’t work
MTProxy does not support calls — this is a limitation of Telegram itself, not Telemt. For calls you need SOCKS5 or a VPN.
Parameter reference
| Parameter | Purpose |
|---|---|
use_middle_proxy = true | Middle-End mode; when false — direct routing to DC. |
[general.modes].tls = true | Enables Fake TLS / ee mode. |
[censorship].tls_domain | Mask domain, included in client links. |
[censorship].mask = true | Fallback for unidentified connections. |
[censorship].mask_host | Separate upstream for masking. By default — tls_domain. |
[censorship].tls_emulation = true | TLS emulation using cached data from real sites. |
[server].metrics_port | Prometheus metrics. |
[server.api] | Control API: users, links, runtime info. |
[access.users] | Users and their hex secrets. |
[access.user_max_unique_ips] | Limit of unique IPs per user. |
Summary
Telemt is useful when the standard MTProxy is already blocked. Fake TLS makes the traffic indistinguishable from regular HTTPS — without dealing with certificates. Main points: do not change tls_domain after issuing links, keep the API and metrics bound to localhost only, and remember — MTProxy does not replace a VPN for calls and other Telegram features.
// Reviews
Related reviews
The collaboration left an extremely positive impression, primarily because of the professionalism and the approach to resolving issues as they arose.
The experience of working together left an extremely positive impression, above all because of the professionalism and the approach to solving the issues that arose.
Jitsi Meet: a personal Zoom — setup in Docker and on a VPS
2025-11-11 · ★ 5/5
I needed to get n8n, Redis, and the database working. I had hired another contractor before and everything kept breaking. I hired Mikhail, and the next day everything was working quickly, like clockwork!
There was a task to get n8n, redis and the database working. I had previously ordered from another contractor, it kept breaking all the time. Ordered from Mikhail, the next day everything started working fast, like …
n8n installation on your VPS server. Configuration of n8n, Docker, AI, Telegram
2025-09-24 · ★ 5/5
Thank you for the fast and excellent work. Everything was done promptly and just as needed!
Thank you for the quick and good work. Everything was done promptly and as needed!
n8n installation on your VPS server. Configuration of n8n, Docker, AI, Telegram
2025-09-06 · ★ 5/5
Quick solution — I highly recommend Mikhail as a contractor! I tried to build a similar configuration myself and even followed AI advice, which ended up costing a lot of time and money (due to server downtime). So my advice: hire professionals — it's cheaper =) Thanks to Mikhail for his professionalism.
Quick fix for the problem, I recommend Mikhail as a contractor to everyone! I tried to assemble a similar configuration myself and following advice from neural networks, which resulted in a lot of wasted effort and …
n8n installation on your VPS server. Configuration of n8n, Docker, AI, Telegram.
2025-08-25 · ★ 5/5
Mikhail completed the setup of another VPS. He quickly and professionally bypassed certain hosting providers' restrictions.
Mikhail completed the setup of another VPS. Quickly, professionally bypassing certain limitations of hosting providers.
n8n installation on your VPS server. n8n, Docker, AI, Telegram setup
2025-08-12 · ★ 5/5
Great job, thank you! Mikhail is a true professional — I recommend him!
Excellent work, thank you! Mikhail is a professional in his field, I recommend him!
N8n installation on your VPS server. Setup of n8n, Docker, AI, Telegram
2025-07-03 · ★ 5/5
// Contact
Need help?
Get in touch with me and I'll help solve the problem
// Related