Skip to content

Environment variables

This page lists every setting Telegram Archive reads. Each row gives the default, which process reads it, how the value is checked, and what a bad value does. The feature pages explain what the settings are for. This page is the only one that states every default.

How settings are read

All configuration comes from environment variables. There is no configuration file.

At startup the program also loads a .env file. It starts in the directory of the installed telegram_archive package and walks up through its parents. It never looks in the working directory. In a source checkout this finds the checkout's .env. In a pip install it only finds a .env in a parent of site-packages, such as a project folder that holds the virtualenv. Otherwise, export the variables in the shell. A variable that is already set in the environment always wins over the same name in .env.

Under the stock docker-compose.yml:

  • The backup container receives the whole .env through env_file. Its environment: block wins when both set the same name.
  • The viewer container has no env_file. It receives only the variables listed in its own environment: block. Run with Docker has that list. To give the viewer anything else, add the variable to its block.

The viewer builds the same settings object as the backup. A shared check that fails stops the viewer too. A viewer that receives a bad DELETION_MODE or a bad MASS_OPERATION_* value refuses to start, even though it never uses them.

Parsing rules

  • Booleans accept 1, true, yes, on and 0, false, no, off, in any case, with surrounding spaces ignored. Empty or unset means the default. Anything else stops startup with Invalid boolean value for <NAME>.
  • Three booleans are stricter. ALLOW_ANONYMOUS_VIEWER, TRUST_PROXY_HEADERS and DB_ECHO treat only the word true, in any case, as true. 1 or yes silently mean false.
  • For integers and decimals, empty or unset means the default. A value that is not a number stops startup with an error that names the variable. nan and inf are rejected, except by BACKOFF_MIN_SECONDS and BACKOFF_MAX_SECONDS, which accept them.
  • Chat id lists are comma-separated integers. Use the marked form that Telegram uses for groups and channels, such as -1001234567890. A non-integer entry stops startup with Python's generic invalid literal for int() error, which does not say which variable is wrong. When a backup starts, it looks at filter ids written without the -100 prefix. If the marked chat is already archived, it uses the marked id instead.
  • A FloodWait is Telegram telling the client to pause before its next request.
  • Empty id lists count as unset. A chat id list set to an empty string behaves as if it were not set. CHAT_TYPES is the exception: an explicitly empty value means no types. To clear a filter for one account in a multi-account setup, set its per-account override to none.

What happens on a bad value

Outcome Settings
Startup stops, and the error names the variable Most booleans, integers and decimals
SKIP_TOPIC_IDS, the proxy settings, the TG_ACCOUNT_<N> credentials and TG_ACCOUNT_<N>_CHAT_TYPES
DELETION_MODE and MASS_OPERATION_*, in the viewer too and even with the listener off
TRANSCRIPTION_MAX_SECONDS, TRANSCRIPTION_MAX_UPLOAD_MB and TRANSCRIPTION_BACKFILL_PER_RUN, while transcription is on
Startup stops, and the error shows the bad value but not the variable CHAT_TYPES, DOWNLOAD_MEDIA_TYPES, DOWNLOAD_DOCUMENT_MIME_TYPES.
Startup stops with a generic error A non-integer entry in any chat or folder id list, including the TG_ACCOUNT_<N>_* id overrides and TRANSCRIPTION_PRIORITY_CHAT_IDS.
The viewer crashes as it starts AUTH_SESSION_DAYS, MAX_WS_CONNECTIONS, MAX_WS_SUBSCRIPTIONS_PER_CONNECTION.
A warning is logged and the default is used MAX_FLOOD_RETRIES, MAX_FLOOD_WAIT_SECONDS, BACKOFF_MIN_SECONDS, BACKOFF_MAX_SECONDS, FLOOD_WAIT_LOG_THRESHOLD, MEDIA_REFRESH_MAX_ATTEMPTS, MEDIA_REFRESH_TIMEOUT_SECONDS. VIEWER_TIMEZONE becomes UTC. STATS_CALCULATION_HOUR becomes 3.
The value silently falls back LOG_LEVEL becomes INFO. PUSH_NOTIFICATIONS becomes basic, and it is not trimmed, so a stray space counts as a bad value. PARALLEL_DOWNLOAD_PART_SIZE_KB snaps to a valid size. DATABASE_TIMEOUT becomes 60 seconds.
A warning is logged and the feature turns off or falls back to a default Every EVENT_WEBHOOK_* setting except EVENT_WEBHOOK_ENABLED and EVENT_WEBHOOK_BODY_TEMPLATE. TRANSCRIPTION_URL, TRANSCRIPTION_PRESET, TRANSCRIPTION_PROVIDER, TRANSCRIPTION_TYPES, TRANSCRIPTION_WEBHOOK_SECRET and TRANSCRIPTION_CALLBACK_URL. VIEWER_CHAT_BACKGROUND.

Applying a change

Settings are read once, when a process starts. Under compose, edit .env and run:

docker compose up -d

Compose recreates every container whose configuration changed. docker compose restart does not read .env again. For a pip install, stop and start the process.

Telegram credentials

Feature page: Log in to Telegram.

Variable Default Read by Notes
TELEGRAM_API_ID unset backup Integer API id from my.telegram.org. Required in single-account mode. Ignored once any TG_ACCOUNT_<N> credential variable is set. A non-numeric value stops startup in single-account and indexed mode.
TELEGRAM_API_HASH unset backup API hash from my.telegram.org. Required in single-account mode. Ignored in indexed mode.
TELEGRAM_PHONE unset backup Phone number with country code. Required in single-account mode. Ignored in indexed mode.
SESSION_NAME telegram_backup backup Session file name inside SESSION_DIR for the single account. Also the fallback name for account 1 in indexed mode.
SESSION_DIR session beside BACKUP_PATH, so /data/session backup Directory for session files. Made absolute and created at startup. --data-dir PATH sets it to PATH/session.
TELEGRAM_DEVICE_MODEL Telegram Archive backup Device name this install shows in Telegram under Settings, Devices. One name for every account of the install. A blank value uses the default. Give each install its own name to tell them apart.

Multiple accounts

Feature page: Multiple accounts.

Any non-empty TG_ACCOUNT_<N>_API_ID, _API_HASH, _PHONE_NUMBER, _LABEL or _SESSION_NAME switches to indexed mode. N starts at 1, has no leading zeros and must be contiguous. A TG_ACCOUNT_ variable with an unknown suffix stops startup. Errors name the variable. A credential or phone number is never echoed; an invalid TG_ACCOUNT_<N>_CHAT_TYPES entry is.

Variable Default Read by Notes
TG_ACCOUNT_<N>_API_ID unset backup Integer API id of account N. Required for each declared account. A non-integer stops startup.
TG_ACCOUNT_<N>_API_HASH unset backup API hash of account N. Required for each declared account.
TG_ACCOUNT_<N>_PHONE_NUMBER unset backup Phone number of account N. Required. Two accounts with the same number stop startup.
TG_ACCOUNT_<N>_LABEL default for account 1, account<N> for the others backup Name shown on the account chips in the viewer.
TG_ACCOUNT_<N>_SESSION_NAME account 1: SESSION_NAME, then telegram_backup
account 2 and up: telegram_backup_account<N>
backup Session file name of account N. Two accounts resolving to the same name stop startup.
TG_ACCOUNT_<N>_<FILTER> unset, inherits the global filter backup Overrides one filter for account N. Empty inherits the global value. none, in any case, means explicitly empty. TG_ACCOUNT_<N>_INCLUDE_CHAT_IDS and _EXCLUDE_CHAT_IDS replace the global include and exclude lists for that account. An override never switches to indexed mode by itself, and one for an account that does not exist stops startup. With several accounts, an unprefixed *_INCLUDE_FOLDER_IDS that two or more accounts would inherit stops startup, because folder ids are numbered per account.

<FILTER> can be any of these:

  • CHAT_IDS
  • CHAT_TYPES
  • INCLUDE_CHAT_IDS and EXCLUDE_CHAT_IDS
  • the PRIVATE_, GROUPS_ and CHANNELS_ include and exclude lists
  • PRIORITY_CHAT_IDS
  • SKIP_MEDIA_CHAT_IDS
  • INCLUDE_FOLDER_IDS
  • PRIVATE_INCLUDE_FOLDER_IDS, GROUPS_INCLUDE_FOLDER_IDS and CHANNELS_INCLUDE_FOLDER_IDS

Proxy

Feature page: Log in to Telegram.

Setting any of TELEGRAM_PROXY_TYPE, _ADDR, _PORT, _USERNAME or _PASSWORD turns the proxy on for every Telegram connection. TYPE, ADDR and PORT are then required.

Variable Default Read by Notes
TELEGRAM_PROXY_TYPE unset backup Must be socks5, in any case.
TELEGRAM_PROXY_ADDR unset backup SOCKS5 host name or IP address.
TELEGRAM_PROXY_PORT unset backup Integer from 1 to 65535.
TELEGRAM_PROXY_USERNAME unset backup Must be set together with TELEGRAM_PROXY_PASSWORD.
TELEGRAM_PROXY_PASSWORD unset backup Must be set together with TELEGRAM_PROXY_USERNAME.
TELEGRAM_PROXY_RDNS false backup Resolve host names through the proxy. Boolean. It only modifies a proxy that is already on and never turns one on.

Schedule and paths

Feature page: Schedule and backup tuning.

Variable Default Read by Notes
SCHEDULE 0 */6 * * * backup Five cron fields: minute, hour, day, month, day of week. Any other field count stops the scheduler. Evaluated in the process's local time zone, which is UTC in the images unless you set TZ. VIEWER_TIMEZONE does not apply. The schedule command also runs one backup as soon as it starts.
BACKUP_PATH /data/backups
compose: fixed at /data/backups
both Archive root. Media goes to BACKUP_PATH/media and the default SQLite file is BACKUP_PATH/telegram_backup.db. The stock compose sets it in both services' environment: block, so a value in .env is ignored there. --data-dir PATH sets it to PATH/backups.

Chat filters

Feature page: Choosing chats.

Variable Default Read by Notes
CHAT_IDS empty backup Whitelist mode. When non-empty, the backup saves only these chats and ignores every other filter, including folder filters. PRIORITY_CHAT_IDS and SKIP_MEDIA_CHAT_IDS still apply.
WHITELIST_RESOLVE_DIALOG_LIMIT 1000 backup If the backup cannot find a CHAT_IDS entry, it scans up to this many chats in your chat list once, for at most 300 seconds, then tries the entry again. 0 turns the scan off.
CHAT_TYPES private,groups,channels backup Types backed up in type-based mode: private, groups, channels, bots. Bots are not in the default. An explicitly empty value means no types, so only include lists admit chats. The stock compose turns an empty value into the default. An unknown type stops startup.
GLOBAL_INCLUDE_CHAT_IDS empty backup When set, only these chats of any type, plus the members of GLOBAL_INCLUDE_FOLDER_IDS, are backed up. CHAT_TYPES and the per-type include lists are then ignored.
GLOBAL_EXCLUDE_CHAT_IDS empty backup Never back up these chats. Checked before every other rule.
INCLUDE_CHAT_IDS empty backup Deprecated. Old name of GLOBAL_INCLUDE_CHAT_IDS, read when the new name is unset or empty.
EXCLUDE_CHAT_IDS empty backup Deprecated. Old name of GLOBAL_EXCLUDE_CHAT_IDS, read when the new name is unset or empty.
PRIVATE_INCLUDE_CHAT_IDS empty backup Allow-list for private chats and bots. When set, only these private chats are backed up, even if private is missing from CHAT_TYPES.
PRIVATE_EXCLUDE_CHAT_IDS empty backup Exclude list for private chats and bots.
GROUPS_INCLUDE_CHAT_IDS empty backup Allow-list for groups and supergroups.
GROUPS_EXCLUDE_CHAT_IDS empty backup Exclude list for groups and supergroups.
CHANNELS_INCLUDE_CHAT_IDS empty backup Allow-list for channels.
CHANNELS_EXCLUDE_CHAT_IDS empty backup Exclude list for channels.
EXCLUDE_DELETE_EXISTING false backup Delete what the archive already holds for chats in any exclude list: rows, the chat's media folder and its avatars. Files in media/_shared stay. Cannot be undone. Has no effect in whitelist mode.
GLOBAL_INCLUDE_FOLDER_IDS empty backup Telegram folder ids. The chats listed in those folders are included the same way as GLOBAL_INCLUDE_CHAT_IDS. Membership is refreshed every run. Ignored in whitelist mode.
INCLUDE_FOLDER_IDS empty backup Deprecated. Old name of GLOBAL_INCLUDE_FOLDER_IDS, read when the new name is unset or empty.
PRIVATE_INCLUDE_FOLDER_IDS empty backup Folder-based allow-list for private chats and bots.
GROUPS_INCLUDE_FOLDER_IDS empty backup Folder-based allow-list for groups.
CHANNELS_INCLUDE_FOLDER_IDS empty backup Folder-based allow-list for channels.
PRIORITY_CHAT_IDS empty backup These chats are backed up first.
SKIP_TOPIC_IDS empty backup Forum topics to skip, as comma-separated chat_id:topic_id pairs. Topic 1 is the General topic. A malformed entry stops startup and names the entry.
FOLLOW_CHAT_MIGRATIONS false backup When a tracked basic group becomes a supergroup, back up the new supergroup too. When this is false, the backup only logs a warning.

Media

Feature page: Media downloads.

Variable Default Read by Notes
DOWNLOAD_MEDIA true backup Download media files at all. When false, messages are stored with no media rows.
MAX_MEDIA_SIZE_MB 100 backup Skip files larger than this. 0 or a negative value means no limit. Skipped files keep a row and are fetched on a later run if you raise the limit.
DOWNLOAD_MEDIA_TYPES empty, every type backup Comma-separated allow-list: photo, video, video_note, animation, voice, audio, sticker, document, webpage. An unknown type stops startup. Applies to the scheduled backup and the listener.
DOWNLOAD_DOCUMENT_MIME_TYPES empty, every document backup Narrows document to full type/subtype MIME types. A document passes on an exact MIME match or on a file extension that belongs to one of the listed types. Wildcards and bare extensions stop startup.
DOWNLOAD_CHAT_DESCRIPTION false backup Fetch each chat's description or bio and member count every run, at one extra request per chat.
DOWNLOAD_TIMEOUT_SECONDS 3600 backup Time limit for one download attempt. 0 turns the limit off. Time spent waiting out a FloodWait counts toward this limit.
MEDIA_FLOOD_SLEEP_THRESHOLD 60 backup The backup and the listener wait out a FloodWait of up to this many seconds during a media transfer. 0 fails at once.
MEDIA_MAX_FILENAME_BYTES 143 backup Byte budget for a stored media file name. The file id prefix and the extension are always kept. The import command uses it too.
MEDIA_MAX_DOWNLOAD_ATTEMPTS 5 both The retry pass gives up on a file after this many failed attempts. The viewer reads it only to split pending from given-up files in Archive Status. The stock compose does not pass it to the viewer.
MEDIA_REFRESH_MAX_ATTEMPTS 3 backup Total attempts per file within one run, the first included. Covers expired file references, location errors and timeouts.
MEDIA_REFRESH_TIMEOUT_SECONDS 120 backup Time limit for re-fetching one message to refresh its file reference.
PARALLEL_DOWNLOAD_ENABLED false backup Download large files over several connections. The scheduled backup only, never the listener.
PARALLEL_DOWNLOAD_MIN_SIZE_MB 20 backup Smallest file that takes the parallel path. Floored at 1.
PARALLEL_DOWNLOAD_CONNECTIONS 4 backup Connections per file. Clamped to 2 through 8.
PARALLEL_DOWNLOAD_PART_SIZE_KB 512 backup Chunk size: 4, 8, 16, 32, 64, 128, 256 or 512. A non-integer becomes 512. Other integers snap down to the largest valid size below them, and anything under 4 becomes 4. Never stops startup.
DEDUPLICATE_MEDIA true backup Store each file once under media/_shared and link to it from every chat folder that holds it.
SKIP_MEDIA_CHAT_IDS empty backup Chats whose media is not downloaded. Their messages are still archived. Removing a chat from the list later does not fetch media for messages already archived.
SKIP_MEDIA_DELETE_EXISTING false backup Also delete the media already archived for SKIP_MEDIA_CHAT_IDS chats. Files in media/_shared stay.
DOWNLOAD_YOUTUBE_VIDEOS false backup Download the video file of a YouTube link preview. The link, its card and the card thumbnail are archived either way.
YOUTUBE_VIDEOS_DELETE_EXISTING false backup Delete YouTube preview videos already downloaded. Ignored, with a warning, while DOWNLOAD_YOUTUBE_VIDEOS=true.
VERIFY_MEDIA false backup Check every downloaded file each run and download missing, empty or damaged files again.
THUMBNAIL_CACHE_DIR BACKUP_PATH/media/.thumbs if writable, else /tmp/telegram-archive-thumbs viewer Where the viewer caches generated thumbnails. Created if missing. The backup always writes its thumbnails to media/.thumbs, so with this set the viewer ignores those and makes its own. The stock compose does not pass it to the viewer.

Backup tuning

Feature page: Schedule and backup tuning.

Variable Default Read by Notes
BATCH_SIZE 100 backup Messages written per database batch. Not clamped.
CHECKPOINT_INTERVAL 1 backup Save the chat's progress every N batches. Floored at 1.
SYNC_DELETIONS_EDITS false backup Re-read every archived message each run to catch edits and deletions. Slow on large archives. Deletions follow DELETION_MODE. The mass-operation limit does not apply to it, and it never fires the event webhook.
FILL_GAPS false backup Run gap-fill after the startup backup and after each scheduled backup. The one-shot backup command never runs it.
GAP_THRESHOLD 50 backup A gap is a jump between stored message ids larger than this. fill-gaps --threshold overrides it.
DIALOG_FLOOD_SLEEP_THRESHOLD 60 backup While listing dialogs, the backup waits out a FloodWait of up to this many seconds. 0 fails at once.
MAX_FLOOD_RETRIES 5 backup Retries after a FloodWait or a transient error before a call gives up.
MAX_FLOOD_WAIT_SECONDS 3600 backup A FloodWait longer than this is not waited out. The call fails and the work is retried next run.
BACKOFF_MIN_SECONDS 2.0 backup First delay of the exponential backoff.
BACKOFF_MAX_SECONDS 300.0 backup Longest backoff delay.
REACTION_RESWEEP_DAYS 0 backup Each scheduled backup re-checks reactions on messages from the last N days. 0 turns it off. Floored at 0. Works with the listener off.
REACTION_RESWEEP_MAX_PER_CHAT 500 backup Most messages re-checked per chat per run. Floored at 1.
REACTION_RESWEEP_BATCH_DELAY_SECONDS 2.0 backup Minimum gap between re-sweep requests, across chats. 0 removes the gap. Floored at 0.

Real-time listener

Feature page: Real-time listener.

Variable Default Read by Notes
ENABLE_LISTENER false backup Start one real-time listener per account inside the schedule command. The LISTEN_* settings do nothing without it.
LISTEN_NEW_MESSAGES true backup Save new messages as they arrive. Viewer notifications depend on it.
LISTEN_NEW_MESSAGES_MEDIA false backup Also download the media of new messages at once. Otherwise media waits for the next scheduled backup.
LISTEN_EDITS true backup Apply text edits as they happen. The previous text is kept as a version.
LISTEN_DELETIONS false backup Apply deletions as DELETION_MODE says. When false, the listener only counts them.
DELETION_MODE soft backup soft marks messages deleted and keeps them. hard removes them with their versions, media rows, transcripts and reactions. Any other value stops startup, in the viewer too. Also applies to SYNC_DELETIONS_EDITS.
LISTEN_CHAT_ACTIONS true backup Save service messages such as joins and leaves, and refresh chat titles and photos.
LISTEN_REACTIONS false backup Capture per-emoji reaction counts as they change.
REACTION_DEBOUNCE_SECONDS 1.5 backup How often buffered reaction changes are written. Floored at 0.1.
MASS_OPERATION_THRESHOLD 10 backup The most edits and deletions the listener applies to one chat in one window. The listener drops any beyond that, and the chat stays blocked for one window length. Below 1 stops startup, even with the listener off.
MASS_OPERATION_WINDOW_SECONDS 30 backup Length of that sliding window, and how long a chat stays blocked after it trips. Below 1 stops startup.
MASS_OPERATION_BUFFER_DELAY 2.0 backup Deprecated and unused. It is still parsed, so a non-number stops startup.

Event webhook

Feature page: Event webhook.

The sub-settings other than the body template are checked only when EVENT_WEBHOOK_ENABLED is true. A bad one logs one warning that names the variable, never the value, and turns the webhook off.

Variable Default Read by Notes
EVENT_WEBHOOK_ENABLED false backup Send an HTTP request when the listener applies an edit or a deletion. Needs ENABLE_LISTENER=true. A bad boolean stops startup.
EVENT_WEBHOOK_URL empty backup An http or https URL with a host name. Required when enabled. Never logged.
EVENT_WEBHOOK_METHOD POST backup POST or PUT, in any case.
EVENT_WEBHOOK_HEADERS empty, and Content-Type: application/json; charset=utf-8 is added backup A JSON object with string values. The Content-Type picks how placeholders are escaped.
EVENT_WEBHOOK_EVENTS message_edited,message_deleted backup Which events fire, from those two names.
EVENT_WEBHOOK_CHAT_IDS empty, all chats backup Marked chat ids to fire for. No -100 correction is applied.
EVENT_WEBHOOK_BODY_TEMPLATE empty, the built-in JSON body backup Custom body with {placeholder} substitution. The feature page lists the placeholders and filters. Not checked at startup. An unknown placeholder renders as an empty string and an unknown filter uses the automatic escaping, silently.

Voice transcription

Feature page: Voice transcription.

The backup checks the transcription settings only while transcription is on. What happens on a bad value lists which ones stop startup and which only log a warning.

Added in 8.17.0

TRANSCRIPTION_PROVIDER, TRANSCRIPTION_MODEL and TRANSCRIPTION_HOTWORDS were added in 8.17.0. Older images ignore them.

Variable Default Read by Notes
TRANSCRIPTION_ENABLED true both Turns transcription on or off. Off means no transcription runs, no button in the viewer and no callback route. The stock compose passes it to the viewer.
TRANSCRIPTION_URL empty both Base URL of the transcription server, without a /v1 suffix. Empty means no server. A URL that is not http or https with a host name warns and turns transcription off. The viewer only checks whether it is set and never connects to it. The stock compose passes it to the viewer.
TRANSCRIPTION_API_KEY empty backup Key sent in the provider's authentication header. Never logged.
TRANSCRIPTION_PROVIDER auto backup auto, akou, openai, deepgram, assemblyai or elevenlabs. An unknown name warns and becomes auto.
TRANSCRIPTION_PRESET auto backup lite, fast, best, fusion or auto. Only sent to an akou transcription server. An unknown name warns and becomes auto.
TRANSCRIPTION_MODEL empty, the provider's default backup Model name for every server except akou, which gets TRANSCRIPTION_PRESET instead. The defaults are whisper-1 on the OpenAI endpoint, nova-3 on Deepgram and scribe_v2 on ElevenLabs. AssemblyAI picks its own.
TRANSCRIPTION_HOTWORDS empty backup Comma-separated words sent as the prompt on the OpenAI endpoint only.
TRANSCRIPTION_TYPES voice backup Media transcribed without a button press: voice, video_note, audio, video, document. Documents count only with an audio/ or video/ MIME type. Unknown names are dropped with a warning, and if none remain the value is voice.
TRANSCRIPTION_MAX_SECONDS 1800 backup Longer media is skipped with a stored reason. There is no value for unlimited: 0 skips every file with a known length.
TRANSCRIPTION_MAX_UPLOAD_MB 500
25 when unset and the provider is openai
backup Largest upload, measured on what is sent. 0 means no limit. A negative value warns and means no limit.
TRANSCRIPTION_LANGUAGE empty, the server detects it backup Language hint, passed as written.
TRANSCRIPTION_DIARIZE false backup Ask for speaker labels. Boolean. The OpenAI endpoint ignores it.
TRANSCRIPTION_CALLBACK_URL empty, poll only backup The viewer's public URL plus /api/transcriptions/callback, sent to akou with each job. An invalid URL is dropped with a warning. Its host must be allowed by the akou key, or akou refuses every job.
TRANSCRIPTION_WEBHOOK_SECRET empty viewer The whsec_ secret the viewer uses to check akou's callbacks. The callback route exists only when this is valid and transcription is on in the viewer. A value without the whsec_ prefix is ignored with a warning. The stock compose has it commented out for the viewer.
TRANSCRIPTION_BACKFILL_PER_RUN 50 backup Most files sent per backup run per account, button presses included. Floored at 1. When akou runs transcriptions as queued jobs, jobs still open count against it.
TRANSCRIPTION_PRIORITY_CHAT_IDS empty backup Chat ids whose media is sent first, in list order, in every account. Repeats are dropped.

Database

Feature page: SQLite and PostgreSQL.

The backup and the viewer each pick a database in the order given on SQLite and PostgreSQL. Both must end up at the same database.

The stock compose passes DATABASE_URL, DB_TYPE, DB_PATH and the POSTGRES_* settings to the viewer. It does not pass DATABASE_PATH, DATABASE_DIR, DATABASE_TIMEOUT or DB_ECHO.

Variable Default Read by Notes
DATABASE_URL unset both Full URL, highest priority. Accepts sqlite://, sqlite+aiosqlite://, postgresql://, postgresql+asyncpg:// and postgres://. An absolute SQLite path needs four slashes. The backup image refuses to start with any other scheme.
DB_TYPE sqlite both sqlite, postgresql or postgres, in any case. The backup image refuses to start with any other non-empty value. The viewer and a pip install treat any other value as sqlite without a warning.
DATABASE_PATH unset both Full SQLite file path. Beats DATABASE_DIR and DB_PATH. Under the stock compose, setting it in .env moves only the backup's database.
DATABASE_DIR unset both Directory holding telegram_backup.db. Beats DB_PATH.
DB_PATH BACKUP_PATH/telegram_backup.db
compose: /data/backups/telegram_backup.db
both SQLite file path, used when DATABASE_URL, DATABASE_PATH and DATABASE_DIR are unset and DB_TYPE is not PostgreSQL.
POSTGRES_HOST localhost
compose: postgres
both PostgreSQL host.
POSTGRES_PORT 5432 both PostgreSQL port.
POSTGRES_USER telegram both PostgreSQL user. It must be allowed to create the pg_trgm extension.
POSTGRES_PASSWORD empty both PostgreSQL password. The optional compose postgres service refuses to start without it.
POSTGRES_DB telegram_backup both PostgreSQL database name.
DATABASE_TIMEOUT 60.0 both SQLite only: how many seconds to wait for a locked database. A bad, zero or negative value silently becomes 60. No effect on PostgreSQL.
DB_ECHO false both Log every SQL statement. Only the word true turns it on.

Live updates

Feature page: Live updates and notifications.

With PostgreSQL, the backup reaches the viewer through the database and these settings do nothing. With SQLite, the backup sends each change to the viewer over unencrypted HTTP. When VIEWER_HOST points at another machine, keep the two on a trusted network or a secure tunnel.

Variable Default Read by Notes
INTERNAL_PUSH_SECRET unset. With SQLite, the processes create and share a .push-secret file beside the database. both Secret the viewer requires on pushes from non-loopback addresses. Needed only when the two processes do not share the database directory. The stock compose passes it to the viewer.
VIEWER_HOST localhost
compose: telegram-viewer
backup Host the backup sends SQLite pushes to.
VIEWER_PORT 8080
compose: 8000
backup Port the backup sends SQLite pushes to. It must match the port the viewer listens on: 8000 in the images and in the pip instructions, so a setup outside the stock compose must set it, because the code default is 8080.

Viewer access

Feature pages: Logins, viewer accounts and share links and Exposing the viewer safely.

The stock compose passes every variable in this table to the viewer except MAX_WS_CONNECTIONS and MAX_WS_SUBSCRIPTIONS_PER_CONNECTION.

Variable Default Read by Notes
VIEWER_USERNAME empty viewer Master login name. Password login is on only when this and VIEWER_PASSWORD are both set.
VIEWER_PASSWORD empty viewer Master login password. Spaces at either end are removed.
ALLOW_ANONYMOUS_VIEWER false viewer With no password and no proxy login configured, let anyone in as a read-only viewer. Only the word true turns it on. Without any of the three, every data request answers HTTP 503.
AUTH_SESSION_DAYS 30 viewer Session lifetime in days, counted from login. A non-integer crashes the viewer.
AUTH_PROXY_HEADER empty viewer Request header that carries the user name from a trusted reverse proxy. Setting it turns proxy login on. The proxy must strip that header from client requests.
AUTH_PROXY_ADMIN_USERS empty viewer Comma-separated proxy user names, matched exactly, that get the master role.
AUTH_PROXY_DEFAULT_ACCESS none viewer all gives new proxy users every chat. Any other value gives them none until an admin grants access.
TRUST_PROXY_HEADERS false viewer Take the client address for the login rate limit and the audit log from X-Forwarded-For, then X-Real-IP. Only the word true turns it on.
SECURE_COOKIES empty, detected viewer true or false forces the cookie's Secure flag. Any other value sets it when the request arrived over https or carries X-Forwarded-Proto: https, whatever TRUST_PROXY_HEADERS says.
CORS_ORIGINS * viewer Comma-separated allowed origins. With *, credentials are not allowed. Also the list of origins allowed to open a cross-origin WebSocket, where * matches nothing.
MAX_WS_CONNECTIONS 200 viewer Most WebSocket connections the viewer holds. Extra ones are closed. A non-integer crashes the viewer.
MAX_WS_SUBSCRIPTIONS_PER_CONNECTION 16 viewer Most chats one WebSocket may follow. A non-integer crashes the viewer.
DISPLAY_CHAT_IDS empty viewer Show only these chats, to every login including the master login. Ids without the -100 prefix are corrected when the marked chat is archived.

Viewer display

Feature pages: Using the viewer and Themes and wallpaper.

The stock compose passes VIEWER_TIMEZONE, VIEWER_DEFAULT_THEME, VIEWER_CHAT_BACKGROUND and SHOW_STATS to the viewer. It does not pass the other three.

Variable Default Read by Notes
VIEWER_TIMEZONE Europe/Madrid viewer Time zone name for displayed times, the date picker and the daily statistics job. An unknown name warns and becomes UTC.
VIEWER_DEFAULT_THEME empty, Slate viewer Theme for browsers with no saved choice: slate, night, amoled, forest, aubergine, day, paper. A ?theme= link and the browser's saved choice win over it. A value that is not 3 to 16 letters is dropped, and an unknown theme falls back to Slate.
VIEWER_CHAT_BACKGROUND empty, no wallpaper viewer Bare file name of an image in the viewer's static directory, used as the chat wallpaper. Anything that is not a plain file name is ignored with a warning. The image is served without a login.
SHOW_STATS true viewer false hides the statistics menu in the header. The statistics API still answers.
STATS_CALCULATION_HOUR 3 viewer Hour, 0 to 23 in VIEWER_TIMEZONE, of the viewer's daily statistics run. A bad value warns and becomes 3. Under the stock compose, setting it in .env has no effect, because the viewer does not receive it. Add it to the viewer's environment: block.
MEDIA_OPEN_CMD empty viewer Shell command behind the master-login-only Open button. Placeholders %PATH%, %DIR% and %FILENAME% are quoted and filled in. Opens images, video, audio and PDF only. Runs on the machine serving the viewer, so it suits native installs.
MEDIA_OPEN_PATH_CMD empty viewer Shell command behind the master-login-only Show in folder button. Same placeholders, any file type.

Notifications

Feature page: Live updates and notifications.

The stock compose passes every variable in this table to the viewer except ENABLE_NOTIFICATIONS.

Variable Default Read by Notes
PUSH_NOTIFICATIONS basic viewer off, basic or full. Only full sends Web Push, which works with the browser closed. Any other value becomes basic without a warning.
ENABLE_NOTIFICATIONS false viewer Legacy. Notifications count as on when this is true or PUSH_NOTIFICATIONS is basic or full.
VAPID_PRIVATE_KEY empty, generated and stored in the database viewer Web Push signing key. Used only when both VAPID keys are set.
VAPID_PUBLIC_KEY empty, generated and stored in the database viewer Web Push public key given to browsers.
VAPID_CONTACT mailto:admin@example.com viewer Contact address sent with every Web Push request.

Logging

Feature page: Monitoring and troubleshooting.

Variable Default Read by Notes
LOG_LEVEL INFO backup DEBUG, INFO, WARNING, ERROR or CRITICAL, in any case. WARN counts as WARNING. An unknown name silently becomes INFO. Applied by the backup, the scheduler and the CLI. The viewer always logs at INFO, even though the stock compose passes it.
LOG_CHAT_TITLES false backup Name the chat on the two per-chat progress lines. Private chats are named by kind only.
FLOOD_WAIT_LOG_THRESHOLD 10 backup While fetching message history, a first FloodWait shorter than this many seconds is not logged. 0 logs every one. Other calls log every FloodWait as a warning.

Health checks and images

Feature page: Monitoring and troubleshooting.

Variable Default Read by Notes
HEARTBEAT_FILE /tmp/telegram-archive.heartbeat backup File the schedule command rewrites every 30 seconds and the backup health check reads. Other commands never write it.
HEARTBEAT_MAX_AGE_SECONDS 180 backup The backup container reports unhealthy once the heartbeat is older than this. A value that is not an integer makes every health check fail, so the container stays unhealthy.
HEALTHCHECK_URL http://127.0.0.1:8000/api/health viewer URL the viewer health check requests. The check passes only when the JSON response has status set to ok.
ALEMBIC_CONFIG /app/telegram_archive/alembic.ini in the backup image backup Set by the backup image so a bare alembic command works inside the container.

Maintenance scripts only

Feature page: Import and maintenance tasks. These scripts ship in the backup image under /app/scripts, not in the PyPI package.

Variable Default Read by Notes
TELEGRAM_PHONE_CODE_HASH unset script scripts/auth_noninteractive.py verify uses it first. Only when it is unset or empty does the script read the file written by its send step. The script handles the single legacy account only.
SESSION_PATH unset script Full session file path for scripts/restore_chat.py. Without it the script uses SESSION_DIR, default /data/session, plus SESSION_NAME.
SQLITE_PATH unset script Source database for scripts/migrate-sqlite-to-postgres.py, checked before DATABASE_PATH, DATABASE_DIR, DB_PATH and the usual locations.
MEDIA_PATH /data/backups/media script Default media path for scripts/migrate_media_paths.py. The script builds its database URL on its own: it ignores DB_PATH, DATABASE_PATH and DATABASE_DIR, treats only DB_TYPE=postgresql as PostgreSQL and defaults POSTGRES_PASSWORD to telegram. Pass --db-url or set DATABASE_URL when your database is elsewhere.

Variables that do nothing

  • LISTEN_ALBUMS is no longer read. Albums are grouped automatically.
  • AVATAR_REFRESH_HOURS is no longer read. Avatars are checked on every run.
  • MASS_OPERATION_BUFFER_DELAY is unused but still parsed.
  • No forensic, hashing, timestamping or blockchain settings exist. Names such as FORENSIC_MODE or HASH_ALGORITHM are ignored.