Your own private messaging server — self-hosted, protocol-compatible, fully yours.
The protocol stack is built on the published
github.com/iamxvbaba/td module
(v1.1.0), using a canonical Layer 228 schema with sparse tlprofile
exact Layer 225-228 compatibility profiles.
If you are looking for a Telegram server, MTProto server, Telegram backend, Telegram clone server, or self-hosted Telegram-like chat server, this repository is the server-side implementation to study, run, and improve.
OwpenGram Server is an open-source, Telegram-compatible MTProto backend written in Go. Run it on your own network for a private, closed setup, or on a VPS to be reachable anywhere in the world. Your data, your keys, your rules — no cloud, no lock-in, no censorship.
🔗 Implements MTProto API layer 228.
OwpenGram Server is independent and unofficial. It is not affiliated with, endorsed by,
or sponsored by Telegram or the official Telegram team.
- 🔒 Private & self-hosted — messages live on infrastructure you control.
- 🧩 Telegram-compatible — works with the OwpenGram Android and Desktop clients.
- 🌍 Reachable anywhere — host it globally, or keep it on your own network.
- 🛡️ Censorship-resistant — no central authority can shut you down.
- ⚙️ Single binary — one Go program prepares keys, runs migrations, serves MTProto, and dispatches updates and background workers.
- 🆓 Free & open source — Apache-2.0, audit and extend it freely.
- 💬 Private chats, groups, supergroups & channels
- 📞 Voice & group calls, live streams, SFU/TURN building blocks
- 🖼️ Media & files — photos, videos, documents, stickers, reactions
- 🪣 Media storage on local disk or an S3/MinIO-compatible object store
- 🤖 Bots and mini apps, with a minimal Bot API gateway
- 🏷️ Fragment-style NFT/collectible usernames and bot verification marks
- 📢 Admin-panel broadcasts — announce to every user, or a picked list
- 🔑 Self-hosted "Log in with Telegram" (OpenID Connect) and passkey sign-in
- 🌐 Message translation and AI-assisted compose
- 📇 Contacts, dialogs sync, chat folders, public link landing pages
- 🖥️ Admin API and web UI for operations, plus a TUI server panel to run it all
📋 Full feature checklist (click to expand)
| Status | Feature | What works today |
|---|---|---|
| ✅ | MTProto server edge | TCP transport, RSA key exchange, auth keys, encrypted sessions, salts, ack/resend, bad messages, RPC dispatch, canonical Layer 228, and sparse exact Layer 225-228 compatibility profiles. |
| ✅ | Login and accounts | Development login code, configurable external code delivery (SMS webhook or SMTP), login email as a second factor, email-as-identity sign-up (no phone number needed), sign-in, sign-up, log-out, authorizations, account settings, SRP/password state, WebAuthn passkey sign-in, and a self-hosted Telegram Login (OpenID Connect) provider for third-party sites. |
| ✅ | Users and contacts | User profiles, usernames, profile photos, contact import/search, blocked/privacy state, presence, and last-seen style status. |
| ✅ | Dialogs and sync | Dialog list, pinned dialogs, manual unread, folders/filters, drafts, read boundaries, durable updates, online fan-out, and offline difference recovery. |
| ✅ | Chatlists and public links | Chat folder sharing, exported chatlist invite links, join/import flows, revoked invite handling, public username landing pages, and shared public link landing pages. |
| ✅ | Private chats | Send, history, read receipts, edit, delete, forward, reply, rich entities, grouped/media messages, reactions, scheduled/TTL-oriented paths. |
| ✅ | Rich messages | Telegram Desktop rich text messages, rich content conversion, send/edit/scheduled flows, dialog/history projections, and memory/PostgreSQL persistence. |
| ✅ | AI compose and ChatBot | Input-box rewrite/polish, default and custom tones, addstyle previews, local and external provider chains, streamed @ChatBot draft replies, and Business AI reply hooks. |
| ✅ | Message translation | Telegram messages.translateText, provider-backed batch translation, peer language settings, per-account rate limits, and privacy-conscious logging defaults. |
| ✅ | Supergroups and channels | Create, join, leave, invite links, participants, admins, forum topics, linked discussion guests, history, send/edit/delete/read, reactions, public search, and previews. |
| ✅ | Media and files | Upload, download, local-disk or S3/MinIO-compatible object storage (switchable per deployment, existing files stay reachable after a switch), low-space upload guard, automatic stale-media cleanup, photos, documents, thumbnails, canonical GIFv conversion, external media fetch, web page previews, map tile cache hooks, profile/channel photos. |
| ✅ | Stickers, reactions, and GIFs | Sticker/reaction catalog, seed support, recent/top/default reactions, moderation-oriented reaction paths, and an admin-curated @gif inline catalog (categorized, auto-save-to-Saved-GIFs on send, category-icon filtering in the client's GIF picker) served alongside the client's Saved GIFs. |
| ✅ | Collectible usernames and verification | Fragment-style NFT/collectible usernames (mint, transfer, activate/deactivate), the official platform-checkmark flow (@verifybot), and a third-party bot-verification mark mechanism (@marksbot, icon + description before a name) — the latter is experimental and hidden by default. |
| ✅ | Bots and mini apps | Bot service foundations, callbacks, inline helpers, webview/mini-app paths, a minimal Bot API gateway for libraries such as python-telegram-bot, persistent getUpdates delivery, and demo tools. |
| ✅ | Calls and live streams | Private call signaling foundations, group call state, RTMP live streaming, scheduled video chats, channel join_as, SFU/TURN building blocks, liveness, and expiry workers. |
| ✅ | Admin and operations | Admin API/UI backend, per-account freeze (admin-set read-only restriction, advertised to the client via appConfig), broadcast messaging (announce from the official account to every user or a picked list), shared-device detection across accounts, RBAC-scoped admin API tokens, PostgreSQL migrations, Redis volatile state, retention workers, pprof/debug hooks, load-test helpers, and a bundled TUI server panel (setup wizard, start/stop/restart, one-click update via git pull + rebuild, live logs, .env editor) as an alternative to manual builds. |
| ✅ | Desktop, Android, iOS, and Web focus | Telegram Desktop is the primary target, with Android, iOS, and Web compatibility paths actively covered by the same server. |
Some items are compatibility-first or experimental, but they are real open server code, not hidden product-only features.
Requirements:
- Go 1.25+
- Docker (or Docker Desktop), for PostgreSQL and Redis
- OpenSSL, to export the server's RSA public key for the client's "Add Server" dialog
1. Clone the repository
git clone https://github.com/owpengram/owpengram-server.git
cd owpengram-server2. Start the infrastructure (PostgreSQL + Redis)
docker compose -f deploy/docker-compose.yml up -d3. Build and run the server
Windows (PowerShell):
go build -o bin/gramsrv.exe ./cmd/telesrv
.\bin\gramsrv.exeLinux / macOS:
go build -o bin/gramsrv ./cmd/telesrv
./bin/gramsrvOn first start, the server creates data/server_rsa.pem, applies database
migrations, seeds bundled language packs, prepares optional media resources,
starts MTProto on 0.0.0.0:2398, and brings up the update/media/background
workers in the same process.
Default local login code:
12345— change it before any real use!
💡 Prefer a menu over the command line? Steps 2 and 3 above (Docker infrastructure, build, run) can be done through the bundled TUI server panel instead — see "🖥️ Server Panel" right below.
A cross-platform interactive TUI wraps the steps above — Docker naming
migration, docker compose up, go build, and launching both
owpengram-server and owpengram-admin-panel — behind a menu, so you don't
re-run commands from scratch every time.
./owpengram-server.sh # Linux/macOS.\owpengram-server.bat # WindowsBoth launchers check prerequisites first (Go, Python 3, and the panel's own
dependencies via tui-panel/requirements-panel.txt), then start the panel.
What it does:
- 🧙 First-run setup wizard — walks through the required
.envvalues before the first start. ▶️ Start / Stop / Restart — launchesowpengram-serverandowpengram-admin-panelas detached background processes; closing the panel does not stop them, only "Stop" does. Reopening the panel later picks the same processes back up and reports live status.- ⬆️ Update —
git pull --ff-only, rebuilds both binaries, restarts them, and re-execs the panel itself so it also picks up any change to its own code — one menu action instead of a manual pull/build/restart sequence. - 📜 Live log viewer — tail either binary's log, or both in a split view.
- ⚙️
.enveditor — edit configuration from inside the panel, grouped by feature, without hand-editing the file.
.env.example is the complete configuration reference — every
variable is documented there with an explanatory comment, grouped by feature.
Copy it to .env and edit, or set the variables directly as environment
variables. Most commonly used variables:
| Variable | Default | Meaning |
|---|---|---|
TELESRV_LISTEN |
0.0.0.0:2398 |
MTProto listen address |
TELESRV_ADVERTISE_IP |
127.0.0.1 |
client-reachable fallback IP for media and calls |
TELESRV_DC |
2 |
self-hosted DC id |
TELESRV_DEV_AUTH_CODE |
12345 |
fixed login code for local development |
TELESRV_AUTH_CODE_MAX_ATTEMPTS |
5 |
wrong-code attempts before the code hash is deleted |
TELESRV_POSTGRES_DSN |
local Compose DSN | PostgreSQL connection string |
TELESRV_REDIS_ADDR |
127.0.0.1:6399 |
Redis address |
TELESRV_BLOB_DIR |
data/blobs |
local media blob directory |
TELESRV_PUBLIC_LINK_WEB_ADDR |
empty | optional public link landing listener, for example 127.0.0.1:2401 |
TELESRV_BOT_API_ADDR |
empty | optional HTTP Bot API gateway listen address, for example 127.0.0.1:8081 |
TELESRV_AI_ENABLED |
true |
enable AI compose entry points |
TELESRV_TRANSLATION_ENABLED |
true |
enable Telegram message translation RPCs |
Optional OpenAI-compatible, Kimi/Moonshot, Gemini, and Anthropic AI provider
variables, login email/SMTP settings, and Business AI settings are documented
in .env.example.
By default the server just uses a fixed development code
(TELESRV_DEV_AUTH_CODE, 12345) for everything and writes it as a durable
777000 message on the account. Three optional, independent features build on
top of that:
1. External code delivery providers — send the real login/phone-change code out via SMS webhook or SMTP instead of only the fixed dev code. An existing account's durable 777000 message is always written first; the provider is an additional delivery channel, never a replacement.
| Variable | Default | Meaning |
|---|---|---|
TELESRV_PHONE_CODE_DELIVERY_PROVIDER |
development |
development keeps the fixed code; webhook generates a random code and posts it to your own SMS webhook (protocol in TELESRV_OTP_WEBHOOK_URL/_SECRET/_TIMEOUT) |
TELESRV_EMAIL_CODE_DELIVERY_PROVIDER |
smtp |
smtp sends via TELESRV_SMTP_*; webhook reuses the same SMS webhook above |
2. Login email — an extra verification factor on top of the phone number (not a replacement for it), similar to Telegram's own login-email feature.
| Variable | Default | Meaning |
|---|---|---|
TELESRV_LOGIN_EMAIL_ENABLE |
false |
turn the feature on |
TELESRV_LOGIN_EMAIL_REQUIRE_SETUP |
false |
force accounts without a login email to set one during the phone login flow |
TELESRV_LOGIN_EMAIL_CODE_LENGTH |
6 |
length of the emailed code |
TELESRV_SMTP_HOST / _PORT / _USERNAME / _PASSWORD / _FROM / _FROM_NAME / _TLS / _TIMEOUT |
— | outbound SMTP settings, required when the email provider is smtp |
3. Email-as-identity sign-up — lets patched clients register and log in
with just an email address, no phone number at all. The client encodes the
email into a synthetic 888-prefixed number and drives the ordinary
sendCode/signUp/signIn/changePhone flow unchanged; the server decodes
that number back to the email and delivers the code over the same channel as
login email above (TELESRV_EMAIL_CODE_DELIVERY_PROVIDER). The account's
real, visible phone number is a random-looking short number from
TELESRV_EMAIL_SIGNUP_PHONE_PREFIXES — cosmetic only, never used to route the
code — so admins can make freshly signed-up accounts look locally flavored
(e.g. 888,380,373) without any client update.
| Variable | Default | Meaning |
|---|---|---|
TELESRV_EMAIL_SIGNUP_ENABLE |
false |
turn the feature on (requires the email delivery channel above to be configured) |
TELESRV_EMAIL_SIGNUP_PHONE_PREFIXES |
888 |
comma-separated prefixes for the account's cosmetic display number |
Uploaded media (photos, documents, stickers) can live on this machine's disk,
or in an S3-compatible object store. deploy/docker-compose.yml bundles a
self-hosted MinIO container, pre-wired to the defaults below, so s3 (the
default) works out of the box with no extra setup — point the same variables
at AWS S3 instead if you'd rather not self-host it.
| Variable | Default | Meaning |
|---|---|---|
TELESRV_BLOB_BACKEND |
s3 |
s3 for MinIO/AWS S3, localfs to write to TELESRV_BLOB_DIR on disk instead |
TELESRV_S3_ENDPOINT |
127.0.0.1:9000 |
S3 API endpoint (MinIO's default) |
TELESRV_S3_REGION |
us-east-1 |
S3 region |
TELESRV_S3_BUCKET |
owpengram-media |
bucket name |
TELESRV_S3_ACCESS_KEY_ID / TELESRV_S3_SECRET_ACCESS_KEY |
owpengram / owpengram123 |
credentials — also what seeds MinIO's root user in docker-compose.yml; change both before any real use |
TELESRV_S3_USE_SSL |
false |
true for AWS S3 or a MinIO behind TLS; local MinIO runs plain HTTP |
TELESRV_S3_PATH_STYLE |
true |
required for MinIO (bucket in the URL path); leave false for AWS S3 |
Switching backends only affects new uploads — existing files stay wherever
they were written and remain reachable as long as that backend's settings
stay filled in. MinIO's own web console is reachable at
http://localhost:9001 (docker compose -f deploy/docker-compose.yml up -d
also starts it) using the same access key/secret as above.
Related toggles (defaults in .env.example's Advanced section): a low-space
guard that rejects new uploads once storage nears full, and automatic
cleanup of media no longer referenced by any message.
When deploying on a public server, open the following according to the features you enable.
Minimal (chat only)
| Port | Protocol | Purpose | Required |
|---|---|---|---|
| 2398 | TCP | MTProto main port; also handles WebSocket when TELESRV_WEBSOCKET_ENABLE=true |
Yes |
With admin backend
| Port | Protocol | Purpose | Notes |
|---|---|---|---|
| 2399 | TCP | Admin REST API | Restrict to trusted IPs or put behind VPN |
| 2600 | TCP | Admin Web UI | Use Nginx/reverse proxy + HTTPS in production |
Optional features
| Port | Protocol | Purpose | When needed |
|---|---|---|---|
| 2400 | TCP | RTMP live stream ingest | Live streaming |
| 12399 | UDP | SFU/WebRTC conferencing | Voice/video group calls |
| 12400 | UDP | TURN/STUN server | P2P/call relay |
| 12500-12999 | UDP | TURN relay port range | TURN relay |
| configurable | TCP | Bot API | When TELESRV_BOT_API_ADDR is set |
| 2401 example | TCP | Public username/sticker/chatlist landing pages | When TELESRV_PUBLIC_LINK_WEB_ADDR=127.0.0.1:2401 is set |
Internal/debug (do not expose publicly)
| Port | Default bind | Purpose |
|---|---|---|
| 6060 | 127.0.0.1:6060 |
pprof debugging endpoint |
| 5432 | 127.0.0.1:5432 |
PostgreSQL |
| 6399 | 127.0.0.1:6399 |
Redis |
| 9000 | 127.0.0.1:9000 |
MinIO S3 API (only when TELESRV_BLOB_BACKEND=s3 and self-hosting MinIO) |
| 9001 | 127.0.0.1:9001 |
MinIO web console |
Make sure TELESRV_LISTEN=0.0.0.0:2398 is set, and TELESRV_ADVERTISE_IP
points to your public IP so clients can connect.
The server can serve public landing pages for /<username>, profile avatars,
/addstickers/<shortName>, /addemoji/<shortName>, and /addlist/<slug>.
TELESRV_PUBLIC_LINK_WEB_ADDR=127.0.0.1:2401
TELESRV_PUBLIC_BASE_URL=https://your-domain.example
TELESRV_PUBLIC_APP_SCHEME=yourapp
TELESRV_PUBLIC_WEB_BASE_URL=https://web.your-domain.example
TELESRV_PUBLIC_APP_NAME=YourAppIn production, keep TELESRV_PUBLIC_LINK_WEB_ADDR on loopback and reverse-proxy
the public routes to it with HTTPS.
Use the OwpenGram clients, which have a built-in Add Server option on the server-selection screen at login — no source patching or custom build needed:
A stock Telegram client will not connect, since it only trusts Telegram's own DC list and RSA keys.
- Telegram Desktop commit:
9caf32dffc90ddd9bb08ad5777b865f729fa167b - Canonical TL layer: 228
- Exact compatibility profiles: Layer 225-228
- Local DC:
127.0.0.1:2398, DC id2
1. Export your server's public key
After the server generates data/server_rsa.pem, export the matching public
key as PEM:
openssl rsa -in data/server_rsa.pem -RSAPublicKey_out -out data/server_rsa.pub2. Add the server in the client
On the login screen, open server selection → Add Server, and fill in:
- Host — your server's address (e.g.
192.168.1.50orchat.example.com) - Port —
2398by default - Main data center — the DC id from
TELESRV_DC(2by default) - RSA Public Key — paste the full contents of
data/server_rsa.pub(the-----BEGIN RSA PUBLIC KEY-----...PEM block) into the key field
Use separate client working directories so sessions do not share local tdata:
$tdesktop = "C:\path\to\tdesktop\out\Debug\Telegram.exe"
Start-Process $tdesktop -ArgumentList @("-workdir", "$PWD\.tdata-alice")
Start-Process $tdesktop -ArgumentList @("-workdir", "$PWD\.tdata-bob")Log in with different phone numbers — the local login code is 12345 unless
you changed TELESRV_DEV_AUTH_CODE. Recommended checks:
- Send private messages, stickers, media, replies, forwards, edits, deletes, and read receipts between two users.
- Keep one device online and restart another device to verify offline
updates.getDifferencerecovery. - Open the same account from multiple sessions and confirm current-session echoes are not duplicated while other online sessions receive updates.
- Check server logs for no new
NOT_IMPLEMENTED,Unhandled RPC,bad_msg, panic, or internal errors.
cmd/telesrv/ server entrypoint
cmd/telesrv-admin/ admin backend and web UI
tui-panel/ interactive TUI server panel (setup, start/stop, update, logs, .env editor)
deploy/ docker-compose (incl. MinIO), migrations, deploy helpers
data/ bundled language packs and optional seed data
internal/mtprotoedge/ MTProto transport, auth key, session, ack/resend
internal/rpc/ TL router and client compatibility handlers
internal/app/ domain services
internal/domain/ protocol-independent domain models
internal/store/ memory/postgres/redis storage backends
internal/seed/ bundled seed catalog loaders
internal/sfu/ real-time SFU experiments
internal/turnsrv/ TURN/STUN building blocks
This server gets better fastest with real usage and focused fixes:
- Telegram Desktop and Android compatibility reports with reproducible steps.
- RPC traces for startup, sync, chat, media, calls, bots, or edge cases.
- Focused fixes for implemented paths instead of broad rewrites.
- Tests for online/offline updates, multi-device sessions, read state, media, and channel behavior.
- Performance work on hot paths such as fan-out, pagination, storage queries, media upload/download, and connection handling.
If a change affects visible client behavior, please include the client
version/commit, the RPC path you tested, and whether server logs stayed free
of new NOT_IMPLEMENTED, Unhandled RPC, bad_msg, panic, or internal errors.
- 📢 Channel: @owpengram
- 💬 Chat: Join the discussion
OwpenGram Server builds on the open-source gramsrv project.
⭐ If OwpenGram is useful to you, a star on GitHub helps the project grow.
