diff --git a/.env.example b/.env.example index 97bd072d..784f7823 100644 --- a/.env.example +++ b/.env.example @@ -1,20 +1,236 @@ # Optional local config file for telesrv. # Copy to .env for local development. Do not commit real tokens or passwords. -# Complete reference / 完整参数手册: +# Complete reference: # docs/configuration.en.md # docs/configuration.zh-CN.md +# +# This file has two parts: +# 1. Everyday settings (below) -- IPs, ports, passwords, login methods, +# SMTP, links, calls/streaming. These are the ones the server-panel.py +# TUI shows and lets you edit, grouped the same way as here. +# 2. "Advanced / internal tuning" (further down) -- queue sizes, cache +# limits, retention windows and similar performance knobs. Sensible +# defaults are already set; most self-hosters never need to touch this +# part, so it's left out of the panel to keep that screen readable. +## Server & Network -- Where the server listens and what address it tells clients to connect to. + +# Address and port the server listens on for MTProto client connections. TELESRV_LISTEN=0.0.0.0:2398 +# Public IP or hostname clients should use to reach this server. Set this to +# your server's real public IP (or domain) once you're past local testing. TELESRV_ADVERTISE_IP=127.0.0.1 +# Which "data center" number this server presents itself as. There's only +# ever one physical server, so this normally stays 2 -- no need to change it. TELESRV_DC=2 + +## Phone Login Codes -- How a login code gets to a phone number when someone signs in. + +# development: every phone number accepts the same fixed code below (fine +# for local testing, or when only email/Telegram sign-in is used). webhook: +# sends a real random code to TELESRV_OTP_WEBHOOK_URL for actual delivery. +TELESRV_PHONE_CODE_DELIVERY_PROVIDER=development +# The fixed code accepted for every phone number when the provider above is +# "development". Change this if you keep phone login open in that mode. TELESRV_DEV_AUTH_CODE=12345 +# How many digits a real (webhook-delivered) login code has. +TELESRV_PHONE_CODE_LENGTH=5 +# How long a login code stays valid after being sent. TELESRV_AUTH_CODE_TTL=5m +# How many wrong guesses are allowed before a code is rejected outright. TELESRV_AUTH_CODE_MAX_ATTEMPTS=5 -# Unauthenticated login-code issuance uses the same limits for existing and -# unknown phones. Phone numbers are SHA-256 digested before becoming Redis keys. -TELESRV_AUTH_CODE_PHONE_RATE_LIMIT=5 -TELESRV_AUTH_CODE_AUTH_KEY_RATE_LIMIT=20 -TELESRV_AUTH_CODE_RATE_WINDOW=10m +# Where webhook-delivered codes are POSTed, and the shared secret used to +# sign that request (see docs/otp-delivery.md for the exact payload). +TELESRV_OTP_WEBHOOK_URL= +TELESRV_OTP_WEBHOOK_SECRET= +TELESRV_OTP_WEBHOOK_TIMEOUT=5s + +## Email Login & Signup -- Signing in (or registering) with an email address instead of a phone number. + +# Lets an existing phone-number account also add an email address for login +# codes. REQUIRE_SETUP forces every account without one to set it up. +TELESRV_LOGIN_EMAIL_ENABLE=false +TELESRV_LOGIN_EMAIL_REQUIRE_SETUP=false +# How many digits an email login code has. +TELESRV_LOGIN_EMAIL_CODE_LENGTH=6 +# How an email login code is actually delivered: smtp (send it yourself, +# see the SMTP section below) or webhook (reuses the phone webhook above). +TELESRV_EMAIL_CODE_DELIVERY_PROVIDER=smtp +# Lets people register and log in with just an email address, no phone +# number at all. Uses the same SMTP/webhook delivery as email login above. +TELESRV_EMAIL_SIGNUP_ENABLE=false +# Comma-separated phone-number prefixes randomly assigned as the visible +# "phone number" for email-signup accounts, e.g. "888,380,373". Purely +# cosmetic -- doesn't need a client update to change. +TELESRV_EMAIL_SIGNUP_PHONE_PREFIXES=888 + +## SMTP (Outgoing Email) -- The mail server used to send login/signup codes by email. + +TELESRV_SMTP_HOST= +TELESRV_SMTP_PORT=587 +TELESRV_SMTP_USERNAME= +TELESRV_SMTP_PASSWORD= +# Sender address and display name shown on outgoing emails. +TELESRV_SMTP_FROM= +TELESRV_SMTP_FROM_NAME=OwpenGram +# Encryption mode: starttls, tls, or none (use "none" for a local test +# server like Mailpit that doesn't support encryption at all). +TELESRV_SMTP_TLS=starttls +TELESRV_SMTP_TIMEOUT=10s + +## Public Links & Branding -- What clients show/open for links, and your product's name. + +# Public web address for links this server generates (invite links, sticker +# packs, etc). Use your real domain once you have one, e.g. https://example.com. +TELESRV_PUBLIC_BASE_URL=https://telesrv.net +# Custom URL scheme (like "owpg://") that public pages use to open your +# patched client. Must match what your client builds were compiled with. +TELESRV_PUBLIC_APP_SCHEME=telesrv +# Optional: use "scheme://yourdomain.com/..." links instead of plain +# "scheme://...". Leave empty unless you specifically need this. +TELESRV_PUBLIC_APP_LINK_BASE= +# Address of your web client (if you have one) and the product name shown +# on public landing pages. +TELESRV_PUBLIC_WEB_BASE_URL=https://web.telesrv.net +TELESRV_PUBLIC_APP_NAME=telesrv +# Where the "Download" button on public pages links to. +TELESRV_PUBLIC_DOWNLOAD_URL=https://owpengram.org +# Warning text shown on a profile/channel the admin panel flagged as +# scam/fake. Leave empty to use the built-in English text. +TELESRV_SCAM_WARNING= +TELESRV_FAKE_WARNING= + +## Admin Panel -- Login and access for the web-based admin dashboard. + +# Secret token shared between the main server and the admin panel process -- +# both must use the exact same value, or the admin panel can't save changes. +TELESRV_ADMIN_API_TOKEN= +# Password to log into the admin panel (or use a token below instead; set +# at least one of the two). +TELESRV_ADMIN_UI_PASSWORD= +TELESRV_ADMIN_UI_TOKEN= +# Encrypts the admin panel's login session cookie. Use a random string of +# at least 32 characters; changing it logs everyone out. +TELESRV_ADMIN_SESSION_KEY= +# Address the main server exposes its admin API on. Leave empty to disable +# the admin panel entirely; set to a loopback address (127.0.0.1:...) to +# enable it without exposing it outside this machine. +TELESRV_ADMIN_API_ADDR= +# Address the admin panel's own web UI listens on. +TELESRV_ADMIN_UI_ADDR=127.0.0.1:2600 + +## Bot API Gateway -- Optional HTTP gateway for bot libraries (e.g. python-telegram-bot). + +# Leave empty to disable. Set to an address like 127.0.0.1:2500 to enable. +TELESRV_BOT_API_ADDR= + +## Database -- Where the server stores its data. + +TELESRV_POSTGRES_DSN=postgres://owpengram:owpengram@127.0.0.1:5432/owpengram?sslmode=disable +TELESRV_REDIS_ADDR=127.0.0.1:6399 +TELESRV_REDIS_PASSWORD= +TELESRV_REDIS_DB=0 + +## Public Web Listener -- Serves public profile pages, avatars, and sticker/emoji pack previews. + +# Host:port this listens on (not a URL). In production, keep this on +# loopback and let nginx (or similar) proxy public traffic to it. +TELESRV_PUBLIC_LINK_WEB_ADDR=127.0.0.1:2401 + +## Telegram Login (OpenID Connect) -- Self-hosted "Log in with Telegram" for third-party sites. + +# Keep disabled until you've generated the required key files with: +# go run ./cmd/telegramloginkeygen -mode init +TELESRV_TELEGRAM_LOGIN_ENABLE=false +# The public HTTPS origin this login provider identifies itself as. +TELESRV_TELEGRAM_LOGIN_ISSUER=https://telesrv.net +# Allow plain HTTP instead of HTTPS (only for local testing). +TELESRV_TELEGRAM_LOGIN_ALLOW_HTTP=false + +## Passkey Login (WebAuthn) -- Signing in with a device passkey/fingerprint instead of a code. + +# Must match the real public domain you serve this from, or passkey login +# will fail (browsers check this against their own address bar). +TELESRV_PASSKEY_RP_ID=telesrv.net + +## Calls -- Voice/video calls (1-to-1 and group), and the relay servers they need to work across networks. + +# Turns off the TURN relay for 1-to-1 calls (falls back to direct +# connections only, which fail across most home/mobile networks). +TELESRV_TURN_ENABLE=true +# Port the built-in TURN/STUN relay listens on. Must be open in your firewall. +TELESRV_TURN_UDP_PORT=12400 +# Public IP the relay tells clients to connect to. Leave empty to reuse +# TELESRV_ADVERTISE_IP above. +TELESRV_TURN_ADVERTISE_IP= +# Secret used to sign relay credentials. Leave empty for a random one +# generated at startup (fine for a single server instance). +TELESRV_TURN_SECRET= +# Port range the relay hands out for active call media. Must be open in +# your firewall. +TELESRV_TURN_RELAY_MIN_PORT=12500 +TELESRV_TURN_RELAY_MAX_PORT=12999 +# Turns off the group-call media server (SFU) -- group calls become +# signaling-only, with no actual audio/video. +TELESRV_SFU_ENABLE=true +# Single UDP port the group-call media server listens on. Must be open in +# your firewall. +TELESRV_SFU_UDP_PORT=12399 +# Public IP the group-call media server tells clients to connect to. Leave +# empty to reuse TELESRV_ADVERTISE_IP above. Warning: setting this to +# 127.0.0.1 silently breaks calls from real devices. +TELESRV_SFU_ADVERTISE_IP= +# Maximum number of people allowed in one group call. +TELESRV_GROUPCALL_MAX_PARTICIPANTS=32 + +## Live Streaming -- Broadcasting live video into a channel (RTMP ingest, e.g. from OBS). + +TELESRV_LIVESTREAM_ENABLE=true +# TCP address the RTMP ingest listens on for incoming streams. +TELESRV_LIVESTREAM_RTMP_ADDR=:2400 +# Path to the ffmpeg executable used to process incoming streams. Leave as +# "ffmpeg" if it's already on your system PATH. +TELESRV_LIVESTREAM_FFMPEG_PATH=ffmpeg + +## Maps -- Optional map previews (e.g. for shared locations) in patched clients. + +# Mapbox access token. Leave empty to disable map previews. +TELESRV_MAPBOX_TOKEN= + +## AI Features -- Optional AI-assisted message composing, business auto-replies, and translation. + +# Master switch for the "improve my message" AI button in patched clients. +TELESRV_AI_ENABLED=true +# Auto-reply generator for Business accounts: "echo" just echoes the +# message back (safe default to verify the feature works end-to-end). +TELESRV_BUSINESS_AI_PROVIDER=echo +# Master switch for in-app message/chat translation. +TELESRV_TRANSLATION_ENABLED=true + + +# ============================================================================== +# Advanced / internal tuning +# +# Everything below this line is NOT shown in the server-panel.py TUI. These +# are performance/capacity knobs (queue sizes, cache limits, retention +# windows, economy tuning, etc.) with defaults that work fine for a single +# self-hosted server. Edit them here directly if you actually need to. +# ============================================================================== + +# RSA key: server identity used in the MTProto key exchange. Auto-generated +# on first run if the file doesn't exist yet. +TELESRV_RSA_KEY=data/server_rsa.pem +# Enforces exact DC-ID matching during key exchange. Leave off (default): +# this server is always a single physical backend, but client forks +# intentionally send DC IDs 1..5 for it, which is expected, not an attack. +TELESRV_STRICT_DC_CHECK=false +# Enables MTProto-over-WebSocket on the same port (for web-based clients), +# and which browser page origins are allowed to open that connection. +TELESRV_WEBSOCKET_ENABLE=true +TELESRV_WEBSOCKET_ALLOWED_ORIGINS=http://localhost:1234,http://127.0.0.1:1234 +# pprof debug/profiling endpoint (CPU/heap/goroutine snapshots). Keep this +# on loopback; use an SSH tunnel to reach it remotely. Empty disables it. +TELESRV_DEBUG_ADDR=127.0.0.1:6060 # MTProto admission and shared inbound RPC budgets. Negative connection/handshake limits disable # that gate; non-positive RPC values fall back to the built-in safe defaults. @@ -27,7 +243,8 @@ TELESRV_MTPROTO_RPC_TIMEOUT=30s TELESRV_MTPROTO_RPC_GLOBAL_WORKERS=256 TELESRV_MTPROTO_RPC_GLOBAL_MAX_TASKS=8192 TELESRV_MTPROTO_RPC_GLOBAL_MAX_BYTES=536870912 -# In-process 331s rpc_result ownership budgets: global >= auth >= session. +# In-memory cache of recent RPC results, used to safely retry a request the +# client resends. Keep the limits ordered global >= auth >= session. TELESRV_MTPROTO_RPC_RESULT_CACHE_MAX_ENTRIES=262144 TELESRV_MTPROTO_RPC_RESULT_CACHE_MAX_BYTES=67108864 TELESRV_MTPROTO_RPC_RESULT_CACHE_AUTH_MAX_ENTRIES=32768 @@ -44,140 +261,96 @@ TELESRV_MTPROTO_OUTBOUND_TRACKED_GLOBAL_MAX_BYTES=536870912 # Concurrent encrypted wire/codec/obfuscation scratch (shared bounded pool, not per connection). TELESRV_MTPROTO_OUTBOUND_WRITE_GLOBAL_MAX_BYTES=536870912 -# OTP delivery routing. "development" preserves the fixed phone code. "webhook" -# generates a random SMS code and sends it with the versioned protocol documented -# in docs/otp-delivery.md. For an existing account, both modes first create the -# durable 777000 message; Webhook is an additional delivery channel for that code. -TELESRV_PHONE_CODE_DELIVERY_PROVIDER=development -TELESRV_PHONE_CODE_LENGTH=5 -TELESRV_OTP_WEBHOOK_URL= -TELESRV_OTP_WEBHOOK_SECRET= -TELESRV_OTP_WEBHOOK_TIMEOUT=5s +# Unauthenticated login-code issuance rate limits, by phone number digest and by connection. +TELESRV_AUTH_CODE_PHONE_RATE_LIMIT=5 +TELESRV_AUTH_CODE_AUTH_KEY_RATE_LIMIT=20 +TELESRV_AUTH_CODE_RATE_WINDOW=10m -# Optional login-email verification. EMAIL_CODE_DELIVERY_PROVIDER may be smtp -# or webhook. Existing-account login codes are also mirrored into 777000 before -# provider delivery; setup/change codes are provider-only. REQUIRE_SETUP forces -# accounts without a login email to set one during the phone login flow. -TELESRV_LOGIN_EMAIL_ENABLE=false -TELESRV_LOGIN_EMAIL_REQUIRE_SETUP=false -TELESRV_LOGIN_EMAIL_CODE_LENGTH=6 -TELESRV_EMAIL_CODE_DELIVERY_PROVIDER=smtp -TELESRV_SMTP_HOST= -TELESRV_SMTP_PORT=587 -TELESRV_SMTP_USERNAME= -TELESRV_SMTP_PASSWORD= -TELESRV_SMTP_FROM= -TELESRV_SMTP_FROM_NAME=OwpenGram -TELESRV_SMTP_TLS=starttls -TELESRV_SMTP_TIMEOUT=10s +# Postgres connection pool sizing. +TELESRV_POSTGRES_MAX_CONNS=50 +TELESRV_POSTGRES_MIN_CONNS=16 -# Email-as-identity signup mode. When enabled, patched clients let the user -# register/log in with an email address instead of a phone number: the client -# encodes the email into a synthetic "888"-prefixed number and drives the -# existing sendCode/signUp/signIn/changePhone flow unchanged; the server -# decodes 888-numbers back to the email and delivers the code over SMTP -# (same TELESRV_SMTP_* settings as login email above) instead of SMS. -# account.changePhone is blocked from moving such an account to a number that -# doesn't decode back to a valid email, since this server has no real SMS -# delivery at all. -TELESRV_EMAIL_SIGNUP_ENABLE=false +# Cache linking each temporary encryption key to the permanent account key it +# belongs to (part of Perfect Forward Secrecy). Entries are removed as soon +# as a key is revoked or replaced, so this is just a performance cache. +TELESRV_TEMP_KEY_CACHE_MAX_ENTRIES=262144 +TELESRV_TEMP_KEY_CACHE_TTL=30m -# Comma-separated list of phone-number prefixes randomly assigned as the -# account's actual, visible short display number (unrelated to the internal -# "888" wire encoding above, which is fixed and never shown to anyone). -# Defaults to "888" alone. Change this to make freshly registered accounts -# look like they have a locally-flavored number, e.g. "888,380,373" — no -# client update needed, since clients never construct this number themselves, -# they only ever display whatever the server assigns. -TELESRV_EMAIL_SIGNUP_PHONE_PREFIXES=888 +# In-memory read caches for channel rows/members/dialogs/boosts, kept fresh +# by database change notifications. Lower values use less RAM. +TELESRV_CHANNEL_ROW_CACHE_MAX=50000 +TELESRV_CHANNEL_MEMBER_CACHE_MAX=100000 +TELESRV_CHANNEL_DIALOG_CACHE_MAX=100000 +TELESRV_CHANNEL_BOOST_CACHE_MAX=100000 +TELESRV_CHANNEL_BOOST_CACHE_TTL=10s -# Client-visible telesrv links. This is an HTTP(S) URL, not a listen address. -# Production uses https://telesrv.net. For local link/deeplink smoke tests use -# http://127.0.0.1:2401. Invalid schemes, credentials, query strings, fragments, -# or a missing host fail startup instead of silently falling back. -TELESRV_PUBLIC_BASE_URL=https://telesrv.net - -# Public landing pages auto-open this custom scheme. It must match the scheme -# registered by every patched client build; tg/http/https are rejected. -TELESRV_PUBLIC_APP_SCHEME=telesrv - -# Optional host-based app-link root for multi-server clients. When set, public -# links use e.g. owpg://example.com/oauth and owpg://example.com/username while -# the scheme above remains accepted for existing/in-flight links. The value -# must be exactly ://, without port/path/query/fragment. -TELESRV_PUBLIC_APP_LINK_BASE= - -# Web client target and display brand used by public landing pages. -TELESRV_PUBLIC_WEB_BASE_URL=https://web.telesrv.net -TELESRV_PUBLIC_APP_NAME=telesrv - -# Product site/download page linked from the "Download" button in the public -# landing pages' header. -TELESRV_PUBLIC_DOWNLOAD_URL=https://owpengram.org - -# Profile warning text injected into getFullUser/getFullChannel About for peers -# flagged SCAM/FAKE from the admin panel. Empty keeps built-in English defaults. -# Clients cannot localize server text, so set your audience language here. The -# stored bio/description is never overwritten; the warning is re-applied from the -# flag on every read and survives the owner editing their description. -TELESRV_SCAM_WARNING= -TELESRV_FAKE_WARNING= - -# Admin API / Admin UI 配置 -# -# TELESRV_ADMIN_API_TOKEN 是主服务 (cmd/telesrv) 暴露 Admin REST API 的鉴权 token, -# 也是 Admin UI (cmd/telesrv-admin) 调用 Admin API 时使用的凭证。 -# 重要:主服务与 Admin UI 必须使用完全相同的 TELESRV_ADMIN_API_TOKEN,否则管理后台无法执行写操作。 -TELESRV_ADMIN_API_TOKEN= - -# TELESRV_ADMIN_UI_PASSWORD 是登录管理后台的密码; -# 也可改用 TELESRV_ADMIN_UI_TOKEN,二者至少填一个。 -TELESRV_ADMIN_UI_PASSWORD= -TELESRV_ADMIN_UI_TOKEN= - -# TELESRV_ADMIN_SESSION_KEY 用于加密 Admin UI 的登录 session cookie。 -# 生产环境请使用至少 32 字节的强随机字符串,修改后会导致已登录会话失效。 -TELESRV_ADMIN_SESSION_KEY= - -# 主服务 Admin API 默认关闭;Admin UI 写操作需要同时配置强 token 并显式开启该 loopback 监听地址。 -TELESRV_ADMIN_API_ADDR= - -# Admin UI 监听地址,默认值通常无需修改;RTMP ingest 保留 2400。 -TELESRV_ADMIN_UI_ADDR=127.0.0.1:2600 - -TELESRV_POSTGRES_DSN=postgres://owpengram:owpengram@127.0.0.1:5432/owpengram?sslmode=disable -TELESRV_REDIS_ADDR=127.0.0.1:6399 -TELESRV_REDIS_PASSWORD= -TELESRV_REDIS_DB=0 +# Background delivery workers that push new-message/update notifications to clients. +TELESRV_OUTBOX_WORKERS=4 +TELESRV_OUTBOX_BATCH=100 +TELESRV_OUTBOX_INTERVAL=200ms +TELESRV_OUTBOX_LEASE_TIMEOUT=30s +# Terminal failed outbox heads are kept briefly for diagnosis, then only the online +# delivery task is removed. The durable update remains available to getDifference. +TELESRV_OUTBOX_POISON_RETENTION=1m +TELESRV_OUTBOX_POISON_CLEANUP_INTERVAL=15s +TELESRV_OUTBOUND_PUSH_TIMEOUT=200ms +# How many messages an account may send per rate-limit window; <=0 disables this limit. +TELESRV_SEND_RATE_LIMIT=30 +TELESRV_SEND_RATE_WINDOW=1m +# Rate limit for "catch up on missed updates" requests; <=0 disables it. +TELESRV_CATCHUP_RATE_LIMIT=0 +TELESRV_CATCHUP_RATE_WINDOW=1m +# Cap on how many members get individually notified when a large channel changes; <=0 uses the built-in default. +TELESRV_CHANNEL_NUDGE_MAX_TARGETS=0 # Bounded retention/GC. User/channel update rows are only pruned behind protocol-safe floors. TELESRV_UPDATE_EVENT_RETENTION=168h TELESRV_BOT_API_UPDATE_RETENTION=24h TELESRV_ORPHAN_AUTH_KEY_RETENTION=24h -# Terminal failed outbox heads are kept briefly for diagnosis, then only the online -# delivery task is removed. The durable update remains available to getDifference. -TELESRV_OUTBOX_POISON_RETENTION=1m -TELESRV_OUTBOX_POISON_CLEANUP_INTERVAL=15s TELESRV_RETENTION_INTERVAL=1h TELESRV_RETENTION_BATCH=10000 +# Cleanup of abandoned (never-finished) file upload fragments. +TELESRV_UPLOAD_PART_TTL=24h +TELESRV_UPLOAD_PART_GC_INTERVAL=30m +TELESRV_UPLOAD_PART_GC_BATCH=10000 +TELESRV_UPLOAD_INFLIGHT_MAX_BYTES=4194304000 +TELESRV_UPLOAD_INFLIGHT_MAX_PARTS=8000 +TELESRV_UPLOAD_INFLIGHT_MAX_FILES=64 -# PFS temp->perm binding cache; write-side revoke/rebind invalidates entries precisely. -TELESRV_TEMP_KEY_CACHE_MAX_ENTRIES=262144 -TELESRV_TEMP_KEY_CACHE_TTL=30m +# Server-side fetching of external media links and link-preview cards (SSRF-safe fetch + size/rate limits). +TELESRV_EXTERNAL_MEDIA_ENABLE=true +TELESRV_EXTERNAL_MEDIA_MAX_BYTES=10485760 +TELESRV_EXTERNAL_MEDIA_RATE_PER_MIN=60 +TELESRV_WEBPAGE_PREVIEW_ENABLE=true +TELESRV_WEBPAGE_PREVIEW_MAX_BYTES=5242880 +TELESRV_WEBPAGE_PREVIEW_RATE_PER_MIN=300 -# Optional. Enables Mapbox-backed map previews and TDesktop map picker config. -TELESRV_MAPBOX_TOKEN= +# Map tile disk cache location (paired with TELESRV_MAPBOX_TOKEN above). TELESRV_MAPTILE_CACHE_DIR=data/maptiles +# Data directories the server seeds/serves media and content from. TELESRV_LANGPACK_SEED_DIR=data/langpack TELESRV_OFFICIAL_GIFTS_DIR=data/official-gifts -# Built-in original demo Star Gifts (geometric Lottie we author ourselves — not -# Telegram's copyrighted assets) are available to import from the admin console's -# "Default gifts" tab; nothing is imported automatically and no config is needed. -# An operator-supplied official Star Gift snapshot (see cmd/giftfetch) can also be -# dropped into TELESRV_OFFICIAL_GIFTS_DIR for manual import — empty by default. -# Star Gift expiry/auction worker. TON values are handled by the local ledger; -# no wallet, Fragment or chain node endpoint is configured or contacted. +TELESRV_BLOB_DIR=data/blobs +TELESRV_STICKER_SEED_DIR=data/sticker-seed +# Caps how many built-in sticker sets get imported on startup; <=0 means no limit. +TELESRV_STICKER_SEED_MAX_SETS=300 +# Sticker set auto-installed for every newly registered account; <=0 disables this. +TELESRV_DEFAULT_STICKER_SET_ID=0 + +# New-account perks: free Telegram Premium months and starting Stars balance. +TELESRV_PREMIUM_GRANT_MONTHS=3 +TELESRV_STARS_STARTING_GRANT=1000 +TELESRV_PREMIUM_SWEEP_INTERVAL=1m +TELESRV_PREMIUM_SWEEP_BATCH=500 + +# Origins allowed for WebAuthn/passkey requests; empty means any origin is accepted +# (the server usually can't predict a mobile app's origin ahead of time). +TELESRV_PASSKEY_ALLOWED_ORIGINS= + +# Star Gifts: unique collectible gifts, transfer/resale, crafting/upgrades, auctions. TON +# values are a purely local ledger inside the server -- no real wallet, Fragment, or +# blockchain is ever contacted. TELESRV_STARGIFT_SWEEP_INTERVAL=15s TELESRV_STARGIFT_SWEEP_BATCH=1000 # Internal nanoton granted once per user on first local-ledger access. @@ -192,24 +365,31 @@ TELESRV_STARGIFT_TRANSFER_DELAY=0s TELESRV_STARGIFT_RESELL_DELAY=0s TELESRV_STARGIFT_CRAFT_DELAY=0s TELESRV_STARGIFT_CRAFT_CHANCE_PERMILLE=250 -TELESRV_BLOB_DIR=data/blobs -TELESRV_STICKER_SEED_DIR=data/sticker-seed -# Optional public-link Web listener for /, profile avatars, -# sticker/custom emoji sets, and shared folders. This is a host:port bind -# address without a URL scheme. It is not replaced by TELESRV_PUBLIC_BASE_URL. -# Production should keep it on loopback and reverse-proxy the documented routes -# through nginx; public canonical URLs use TELESRV_PUBLIC_BASE_URL. -TELESRV_PUBLIC_LINK_WEB_ADDR=127.0.0.1:2401 +# 1-to-1 call timing/limits. +TELESRV_CALL_RING_TIMEOUT=90s +TELESRV_CALL_TOMBSTONE_TTL=60s +TELESRV_CALL_MAX_ACTIVE_PER_USER=4 +TELESRV_CALL_SIGNALING_MAX_BYTES=65536 +TELESRV_CALL_SIGNALING_RATE=50 +TELESRV_CALL_EXPIRY_INTERVAL=1s +TELESRV_CALL_TURN_CREDENTIAL_TTL=6h +# Forces calls through the TURN relay even when a direct connection would work (debugging only). +TELESRV_CALL_FORCE_RELAY=false -# Self-hosted Telegram Login / OpenID Connect. The provider is mounted on the -# public-link listener above. Keep disabled until all three local key files -# have been generated with `go run ./cmd/telegramloginkeygen -mode init`. -TELESRV_TELEGRAM_LOGIN_ENABLE=false -TELESRV_TELEGRAM_LOGIN_ISSUER=https://telesrv.net -# Set true to permit an HTTP issuer and HTTP registered origins/redirect URIs -# on any hostname or IP address. HTTPS remains the default when false. -TELESRV_TELEGRAM_LOGIN_ALLOW_HTTP=false +# Group call housekeeping (participant liveness checks, stale-entry cleanup). +TELESRV_GROUPCALL_CHECK_TTL=45s +TELESRV_GROUPCALL_SWEEP_INTERVAL=10s + +# Extra live-streaming options: where the "connect OBS here" URL points (auto-derived if +# empty), the working directory for stream segments, and how many seconds of each stream +# are kept in memory. +TELESRV_LIVESTREAM_RTMP_URL= +TELESRV_LIVESTREAM_WORK_DIR= +TELESRV_LIVESTREAM_SEGMENT_KEEP=32 + +# Telegram Login (OpenID Connect) advanced settings: local key files (generate with +# `go run ./cmd/telegramloginkeygen -mode init`), token lifetimes, and cleanup. TELESRV_TELEGRAM_LOGIN_SIGNING_KEYS_FILE=data/telegram-login/signing-keys.json TELESRV_TELEGRAM_LOGIN_CODE_KEYS_FILE=data/telegram-login/code-keys.json TELESRV_TELEGRAM_LOGIN_SECRET_PEPPER_FILE=data/telegram-login/client-secret-pepper @@ -222,27 +402,27 @@ TELESRV_TELEGRAM_LOGIN_RETENTION=168h TELESRV_TELEGRAM_LOGIN_SWEEP_INTERVAL=5m TELESRV_TELEGRAM_LOGIN_SWEEP_BATCH=500 -# AI compose for TDesktop/Android input box rewrite/polish. -# The local provider is deterministic and does not call external services. -TELESRV_AI_ENABLED=true +# AI compose provider chain (tried in order; "local" is deterministic and never leaves +# the server) and its limits. TELESRV_AI_PROVIDERS=local TELESRV_AI_TIMEOUT=15s TELESRV_AI_RATE_LIMIT=20 TELESRV_AI_RATE_WINDOW=1m +# When false (default), logs only length/provider/status for AI calls -- never the +# user's actual input or generated text. TELESRV_AI_LOG_CONTENT=false # Chat/message translation reuses the remote providers declared above. The # deterministic "local" AI provider is excluded because it cannot translate. # Leave TRANSLATION_PROVIDERS empty to use all configured remote AI providers, # or provide a comma-separated subset such as "openai,gemini". -TELESRV_TRANSLATION_ENABLED=true TELESRV_TRANSLATION_PROVIDERS= TELESRV_TRANSLATION_TIMEOUT=15s # Counts translated text items, not RPC envelopes (one RPC may contain 20). TELESRV_TRANSLATION_RATE_LIMIT=60 TELESRV_TRANSLATION_RATE_WINDOW=1m -# External providers are optional. Keep API keys in TELESRV_* variables here; +# External AI providers are optional. Keep API keys in TELESRV_* variables here; # the loader rejects non-TELESRV keys from .env files by design. # TELESRV_AI_OPENAI_KIND=openai_responses # TELESRV_AI_OPENAI_API_KEY= @@ -268,10 +448,3 @@ TELESRV_TRANSLATION_RATE_WINDOW=1m # TELESRV_AI_KIMI_MODEL=kimi-k2.6 # TELESRV_AI_KIMI_THINKING=disabled # TELESRV_AI_KIMI_TEMPERATURE=0.6 - -# Business automation reply provider: -# echo (default/empty), template/quick_reply/quick-reply, or -# ai/compose_ai/ai_compose/aicompose/kimi to reuse TELESRV_AI_PROVIDERS. -# Custom provider names such as "ollama" are selected through TELESRV_AI_PROVIDERS; -# use TELESRV_BUSINESS_AI_PROVIDER=ai for those. -TELESRV_BUSINESS_AI_PROVIDER=echo diff --git a/server-panel.py b/server-panel.py index 961fc234..c36be4df 100644 --- a/server-panel.py +++ b/server-panel.py @@ -324,6 +324,8 @@ def read_env_value(key: str) -> str | None: _ACTIVE_FIELD_RE = re.compile(r"^(TELESRV_[A-Z0-9_]+)=(.*)$") _COMMENTED_FIELD_RE = re.compile(r"^#\s*(TELESRV_[A-Z0-9_]+)=(.*)$") _SENSITIVE_KEY_RE = re.compile(r"(PASSWORD|SECRET|_TOKEN|API_KEY)") +_GROUP_HEADER_RE = re.compile(r"^##\s*(.+?)\s*--\s*(.+)$") +_SECTION_BREAK_RE = re.compile(r"^#\s*={10,}\s*$") @dataclass @@ -341,40 +343,46 @@ class EnvField: @dataclass class EnvGroup: title: str + description: str = "" fields: list[EnvField] = field(default_factory=list) def parse_env_template() -> list[EnvGroup]: - """Parses .env.example into groups of fields for the editor. Grouping - follows the file's own blank-line-separated blocks; a group's title is - the first sentence of whichever field in it has a comment (falling back - to its first key when none of them do, e.g. the bare Postgres/Redis DSN - pair that has no comment of its own).""" + """Parses .env.example into panel-visible groups. + + Only fields inside an explicit "## Title -- description." header belong + to a group and show up in the editor. A "# ====...====" banner line (the + "Advanced / internal tuning" divider) ends panel-group collection for + the rest of the file -- those fields are still perfectly valid config + the server reads normally, they're just left out of the TUI on purpose + to keep it to what a self-hoster actually needs to touch.""" if not ENV_EXAMPLE_FILE.exists(): return [] groups: list[EnvGroup] = [] - current_fields: list[EnvField] = [] + current: EnvGroup | None = None pending: list[str] = [] in_comment_run = False seen_keys: set[str] = set() - def flush_group() -> None: - nonlocal current_fields - if current_fields: - described = next((f.description for f in current_fields if f.description), "") - if described: - title = described.split(". ", 1)[0].strip().rstrip(".") - else: - title = current_fields[0].key - groups.append(EnvGroup(title=title[:70], fields=current_fields)) - current_fields = [] - for raw_line in ENV_EXAMPLE_FILE.read_text(encoding="utf-8", errors="replace").splitlines(): stripped = raw_line.strip() if not stripped: - flush_group() + pending = [] + in_comment_run = False + continue + + header = _GROUP_HEADER_RE.match(stripped) + if header: + current = EnvGroup(title=header.group(1).strip(), description=header.group(2).strip()) + groups.append(current) + pending = [] + in_comment_run = False + continue + + if _SECTION_BREAK_RE.match(stripped): + current = None pending = [] in_comment_run = False continue @@ -388,10 +396,11 @@ def parse_env_template() -> list[EnvGroup]: # occurrence wins and later repeats fold into descriptive text. if active.group(1) not in seen_keys: seen_keys.add(active.group(1)) - current_fields.append(EnvField( - key=active.group(1), default_value=active.group(2), - description=" ".join(pending), enabled_by_default=True, - )) + if current is not None: + current.fields.append(EnvField( + key=active.group(1), default_value=active.group(2), + description=" ".join(pending), enabled_by_default=True, + )) in_comment_run = False continue @@ -399,10 +408,11 @@ def parse_env_template() -> list[EnvGroup]: commented = _COMMENTED_FIELD_RE.match(stripped) if commented and commented.group(1) not in seen_keys: seen_keys.add(commented.group(1)) - current_fields.append(EnvField( - key=commented.group(1), default_value=commented.group(2), - description=" ".join(pending), enabled_by_default=False, - )) + if current is not None: + current.fields.append(EnvField( + key=commented.group(1), default_value=commented.group(2), + description=" ".join(pending), enabled_by_default=False, + )) in_comment_run = False continue text = stripped.lstrip("#").strip() @@ -417,8 +427,7 @@ def parse_env_template() -> list[EnvGroup]: # whatever comment run was in progress without touching fields. in_comment_run = False - flush_group() - return groups + return [g for g in groups if g.fields] def current_env_values(groups: list[EnvGroup]) -> dict[str, str]: @@ -717,6 +726,8 @@ class EnvEditorScreen(Screen): with VerticalScroll(id="env-scroll"): for i, group in enumerate(self._groups): with Collapsible(title=f"{group.title} ({len(group.fields)})", id=f"env-group-{i}"): + if group.description: + yield Static(group.description, classes="env-group-desc") for f in group.fields: with Vertical(classes="env-field"): badge = "" if f.enabled_by_default else " [dim i](optional, currently disabled)[/]" @@ -1098,6 +1109,11 @@ class ServerPanelApp(App): height: 1fr; padding: 1 2; } + .env-group-desc { + color: $text-muted; + text-style: italic; + margin: 1 0 0 2; + } .env-field { height: auto; margin: 1 0 0 2;