A store is one channel of one backend: a private Telegram channel or a Discord channel. Give each a short name; file systems below refer to stores by that name, and the name never reaches the stored metadata, so it can be changed later.
Used in this file only; file systems refer to it
Channel ID is required
Each file system is a top-level directory over WebDAV and SFTP. It has one primary store and any number of mirror stores; primary and mirror can be swapped later with a config change. Files that existed before a mirror was added are copied by the backfill task (Manager API: POST /api/redundancy/backfill/<file system>).
Top-level directory over WebDAV and SFTP
The directory tree is kept as a JSON document pinned in the primary store and copied to every mirror. Never delete the pinned file or pin anything else. On a Discord primary the tree has to fit one attachment; use GitHub metadata for anything but small trees.
Every file lands in the primary and is copied to each mirror. A mirror in another backend, or with smaller messages, receives a re-uploaded copy. Swapping primary and a mirror later is a config change.
Every bot must be admin in every Telegram store, mirrors included. A primary channel with "Restrict saving content" enabled cannot be forwarded from; the auto copy mode then re-uploads.
Discord channels can be stores too, as primaries or as mirrors. Create an application at discord.com/developers, add a bot, enable the Message Content intent and invite it with View Channel, Send Messages, Manage Messages, Read Message History, Attach Files and Pin Messages.
WebDAV server will be at http://0.0.0.0:1900/webdav
TGDCFS server will be at http://0.0.0.0:1900 (Used in the Telegram Mini App).
Serves the same file tree over SFTP, next to WebDAV, using the same users and the same readonly flags. SSH cannot share the HTTP port, so it needs a port of its own.
At-rest encryption with AES-256-GCM. When enabled, every file is encrypted client-side before being uploaded; the Telegram channel only ever sees ciphertext plus a public per-file salt.
A cache on the data volume. Uploads are staged into it while they stream to the primary store, so the mirrors read the file from disk instead of downloading it from the primary again; kept after replication, it also serves repeated reads. It holds what the stores hold: ciphertext when encryption is on, never plaintext. Keep the directory on the mounted data volume so it survives a container restart, and give it room for the budget plus one upload in flight.
A folder listing shows the size and dates of every file, and those live in each file's descriptor message, not in the directory tree. Without these settings a folder of 10,000 files costs about 20,000 store reads per listing.
How file bytes are moved to and from Telegram. Every setting has a default that matches the behaviour you get without this block, so leave it off unless you want to tune something.
backends:
telegram:
api_id: ''
api_hash: ''
lib: telethon
account:
session_file: account.session
used_to_upload: false
used_to_download: false
bot:
session_file: bot.session
tokens: []
stores: {}
filesystems: {}
tgdcfs:
users:
user:
password: password
jwt:
secret: ''
algorithm: HS256
life: 604800
server:
host: 0.0.0.0
port: 1900
encryption:
enabled: false
encrypt_names: false
master_salt_file: master.salt
chunk_size: 65536
Put the downloaded config.yaml into the directory below; the sessions, the salt and the cache are written next to it.
Path Style:
docker run -it --pull=always --name tgdcfs -p 1900:1900 -v "/home/user/.tgdcfs:/home/tgdcfs/.tgdcfs" xyvran/tgdcfs:latest