New supergroups are created with "chat history for new members" hidden (the client sets this right after creation, matching official Telegram). The official server then forces it back to visible when the group is made public; owpengram's UpdateUsername left the flag alone, leaving public groups in a state where non-members (and post-join members) see no history at all. UpdateUsername now clears pre_history_hidden whenever a non-empty username is assigned, in the same transaction, with a matching admin-log event. Removing the username leaves the flag untouched, so the creator can hide history again once the group is private. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|---|---|---|
| .claude | ||
| cmd | ||
| data | ||
| deploy | ||
| docs | ||
| internal | ||
| media/readme | ||
| scripts | ||
| tui-panel | ||
| .containerignore | ||
| .env.example | ||
| .gitignore | ||
| Containerfile | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| owpengram-server.bat | ||
| owpengram-server.sh | ||
| README.md | ||
| sqlc.yaml | ||
🚀 OwpenGram Server
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.
✨ Why OwpenGram?
- 🔒 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.
🎯 What works today
- 💬 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.
⚡ Quick Start
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-server
2. Start the infrastructure (PostgreSQL + Redis)
docker compose -f deploy/docker-compose.yml up -d
3. Build and run the server
Windows (PowerShell):
go build -o bin/gramsrv.exe ./cmd/telesrv
.\bin\gramsrv.exe
Linux / macOS:
go build -o bin/gramsrv ./cmd/telesrv
./bin/gramsrv
On 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.
🖥️ Server Panel (optional)
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 # Windows
Both 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 — launches
owpengram-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.
⚙️ Configuration
.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.
✉️ Login codes, email login, and email sign-up
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 |
🪣 Media storage: local disk or S3/MinIO
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.
🔌 Ports to open
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.
🌐 Public link landing pages
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=YourApp
In production, keep TELESRV_PUBLIC_LINK_WEB_ADDR on loopback and reverse-proxy
the public routes to it with HTTPS.
📱 Connect a client
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.pub
2. 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
🧪 Development: multi-device smoke test
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.
📂 Repository layout
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
🤝 Contributing
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.
💬 Community
- 📢 Channel: @owpengram
- 💬 Chat: Join the discussion
OwpenGram Server builds on the open-source gramsrv project.
📄 License
⭐ If OwpenGram is useful to you, a star on GitHub helps the project grow.