Documentation menu

Quickstart

Quickstart

From an empty host to a delivered forward: the three install routes, the guided wizard, your first task and the checks that prove it serves.

Verified against the checkout built for v2.2.4 · updated 20 Oct 2026

On this page

This is the shortest honest path from an empty host to a message that actually lands in a destination chat. Every route below ends in the same place — one guided wizard, the same four services, the same CLI afterwards — so the install choice does not lock you in.

Before you start

Have the bot token and your numeric Telegram id ready; the wizard asks for nothing else you cannot press enter through.

v2.2.4 — what the quickstart assumes
RequirementDetails
Container pathDocker Engine with the Compose v2 plugin — docker compose version has to answer. atf platform prints the exact install command for this specific distribution.
Native pathPython 3.11+ and either Bash (Linux, macOS, WSL) or PowerShell (Windows). scripts/setup.sh walks python3, python3.13, python3.12, python3.11 and refuses to continue when none of them is 3.11+.
TelegramA bot token from @BotFather, and your own numeric Telegram user id for ADMIN_USER_ID.
Hardware1 vCPU and 512 MB RAM is enough to start four services; media staging is the only thing that wants more disk.
NetworkOutbound access to Telegram. Ports 8088 (dashboard) and 8080 (REST API) must be free; core and logger gRPC stay inside the compose network on 50051 and 50052.

Pick an install route

Docker ComposeRecommended

cp .env.example .env → docker compose up -d

Four containers from one file: atf-core, atf-logger, atf-api, atf-web. Nothing else is installed on the host.

Best when: A host you control with docker already present.

Native scriptBare metal

./scripts/setup.sh

Creates .venv, installs dependencies, puts atf on PATH and hands over to the wizard. Same program on Windows: python scripts\bootstrap.py.

Best when: A VPS or home server where you want the CLI and native services.

Zero prerequisiteOne file

curl -fsSL .../install.sh | bash

Installs git and Python when missing, clones the repository and ends in the same wizard. The portable build (atf release portable → dist/atf.pyz) needs no checkout at all.

Best when: A machine you do not want to prepare by hand.

The container route is the one most operators should take. It is also the shortest: two commands after a clone.

bash
git clone https://github.com/Opselon/AutoTelegramForward.git
cd AutoTelegramForward

# route 1 — containers only
cp .env.example .env          # fill ATF_API_ID, ATF_API_HASH, ATF_BOT_TOKEN, ADMIN_USER_ID
docker compose up -d
docker compose ps             # atf-core, atf-logger, atf-api, atf-web

# route 2 — native script (same wizard, no docker)
./scripts/setup.sh            # venv + deps + atf on PATH + guided setup
./scripts/setup.sh --check    # read-only readiness report, changes nothing

# route 3 — zero prerequisite, or the single-file build
curl -fsSL https://raw.githubusercontent.com/Opselon/AutoTelegramForward/master/install.sh | bash
atf release portable          # -> dist/atf.pyz, standard library only
python3 atf.pyz setup         # the same wizard, no checkout needed

The guided wizard

atf setup is one command for a machine that has never run ATF. It asks, validates, builds, then verifies — in that order, and it refuses a wrong answer instead of storing it.

  1. Detect the host

    Reads the OS, distribution and architecture, then probes docker, the daemon and docker compose version. On a machine without docker it offers source mode instead of failing.

    atf setup

    Every path — installer, setup.sh, or python3 atf.pyz setup — lands in this one wizard.

  2. Ask only what it cannot work out

    Run mode, Telegram credentials, admin id, dashboard URL, TLS and the boot-service questions. Each answer is validated as you type it; a malformed value is refused rather than stored.

    atf setup --check        # read-only readiness report
    atf setup --print-answers # emit the answers template

    Secrets are typed blind and echoed back masked in a review panel before anything is written.

  3. Write .env

    The answers become .env with mode 0600. The keys the stack cannot run without are ATF_API_ID, ATF_API_HASH, ATF_BOT_TOKEN, ADMIN_USER_ID and ATF_MASTER_KEY.

    A placeholder left in a required key is treated as missing, not as a value.

  4. Build and start

    Runs the static validator first, then builds and starts the four services in order: logger → core → api → web.

    atf up        # build + start the whole stack (validator-gated)
    atf setup --no-build --no-start   # prepare .env only

    Use --force only when you have read the validator failure and accepted it.

  5. Prove each service is serving

    Inspects every service and reports container, status, state, reachability, endpoint and version. A container that started but cannot answer is reported as not serving.

    atf system services        # colourised table + fix hints; exit 1 if something is down
    atf system services --json # {services:[...], healthy:N, total:4, failing:[...]}

    "docker compose returned 0" is not evidence; this probe is.

What it asks, and how each answer is checked

Answers accepted by the wizard
QuestionValidator — a wrong answer is refused, never written
Run modedocker, source or portable — anything else is refused.
Bot token (@BotFather)Must match <digits>:<35+ chars>. Typed blind, stored in .env as 0600.
api_idNumeric and ≥ 1. Defaults to the public Telegram Desktop value when you press enter.
api_hashExactly 32 hex characters, from my.telegram.org.
Admin user idNumeric and ≥ 1 — your own Telegram id, not a username.
Dashboard URLMust start with http:// or https://.
TLS domainOptional; if you set one, a valid domain and a contact email become required.
Boot service / start now / mint tokenExplicit yes/no answers. The boot service is a systemd unit that starts the stack at boot.

For automation, drive the same wizard without a terminal:

bash
atf setup --check                       # read-only readiness report (safe before anything exists)
atf setup --yes                         # take every default, never prompt (CI / cron)
atf setup --answers answers.json        # non-interactive answers
atf setup --print-answers               # emit the answers template
atf setup --no-build --no-start         # prepare .env only
atf setup --source-wizard               # bare-metal path for a machine without docker

First run

Two things must be true before a single message can move: the bot credentials are in .env, and the stack is up. Nothing about the token is echoed back — the CLI redacts it from every line it prints.

.env
ATF_API_ID=17349
ATF_API_HASH=344583e45741c457fe1862106095a5eb
ATF_BOT_TOKEN=123456:ABC-DEF...        # from @BotFather — never a real token in a ticket or a chat
ADMIN_USER_ID=123456789                # your numeric Telegram id
ATF_MASTER_KEY=<long random string>
ATF_WEB_URL=http://localhost:8088

ATF_MASTER_KEY is what encrypts session strings, bot tokens and AI keys at rest, so generate it and keep it. Then bring the stack up and look at the board:

bash
atf up            # build + start all four services (docker path)
atf status        # per-service state, ports, reachability, task counts, dashboard URL
atf validate --strict   # static checks: env, compose, catalog parity, secrets, database, ports
atf doctor --fix  # deeper diagnosis; repairs what it can

The dashboard is the Rust gateway plus React SPA on port 8088. The REST API answers on 8080. Open the dashboard at http://localhost:8088 and sign in with the credential the wizard minted (or with a single-use login link the bot issues — the link carries a short-lived code, never a session token).

Link your Telegram account

Forwarding happens as some Telegram account, so one has to be authorised before the first task can deliver. Open the bot in Telegram, send /start and use Login: enter the phone number in international format, then the OTP Telegram sends you, then your 2FA password if the account has one. The resulting session is encrypted with ATF_MASTER_KEY and stored in data/atf.db; the bot deletes the message that carried the credentials. The same login is available from the dashboard and the REST API. The full walkthrough, including what to do when the OTP never arrives, is in account linking.

Your first task

A task is one source list plus one target list. The bot can create it (/settings → Create task), and the CLI can create it with the same fields:

bash
atf rules create --name "News mirror" --source @MarketNews --target @MyBroadcast
atf rules list                                          # confirm it exists and is on
atf rules show <id>                                     # the full task as the server sees it

# prove the pipeline before you trust it with live traffic
atf rules simulate <id> --text "Breaking: market surge t.me/spam @admin"
atf logs tail --follow -n 20                            # then watch the first real delivery
atf logs stats                                          # delivered / dropped / retried counts

What success looks like

An install is finished when all of these hold — not when a build command returns zero.

  • atf status — the live board: services, ports, reachability, task counts and the dashboard URL.
  • atf system services — all four services OK, running, reachable, with their endpoints.
  • The dashboard answers on http://localhost:8088 (the value of ATF_WEB_URL in .env).
  • atf rules list shows your task, with state on.
  • A real post from the source lands in the target and atf logs tail --follow shows [PIPELINE:DISPATCH] followed by [PIPELINE:DELIVERED] for it.

Common first-run failures

These four cover almost every first install. Each fix is a command you can run right now.

First-run failure catalogue
SymptomCauseFix
docker is not usable hereNo docker, or the daemon is down.Run atf platform for this host’s exact install command, start the daemon, or take the no-docker path with atf setup --source-wizard.
port 8088 is already in useAnother process owns the dashboard port.atf validate --runtime names the owner through its ports check; free it or change the published port in the compose file.
The bot says it is unconfigured although .env is filledThe container was started before the .env change, so it never received the value.atf system restart. The container-env check detects exactly this condition.
The first task forwards nothing; logs say the upstream is disconnectedThe Telegram account session was never authorised.atf sessions list to see it, then link the account from the bot (see below) and retry the task.

The rest of the catalogue — stale containers, missing network aliases, a wizard waiting on a piped stdin, TLS and certificate renewal — lives in the Operations & troubleshooting runbook, and atf doctor names the failing check and its own fix line for each one.