A provider-neutral framework for connecting personal messengers to XMPP. Telegram and MAX are the first planned backend adapters.
The project currently contains the foundation layer: provider-neutral domain objects, commands, events, focused ports, a backend registry, configuration, and lifecycle supervision.
python3 -m unittest discover -s tests
python3 -m xmpp_transport.runtime.app --helpCreate a configuration for the selected backend with newly generated secrets:
python3 -m xmpp_transport.runtime.create_config \
--backend max --output max.ini
python3 -m xmpp_transport.runtime.create_config \
--backend telegram --output telegram.ini \
--telegram-api-id 123456 \
--telegram-api-hash replace-with-telegram-api-hashBoth Telegram API arguments are optional. When omitted, the command leaves
api_id and api_hash empty for manual configuration later.
Each file contains only the selected backend plus shared database and security
settings. Omit --backend to generate both backends in one file as before.
For manual setup, use max.example.ini or telegram.example.ini as the
template for the corresponding private config file.
When deploying separate files against the same database, keep the same
credential_key in both files and preserve it across configuration updates.
Roster IQ requests use AES-GCM with the component password already configured
on both the transport and the server. No separate roster IQ secret is needed.
The command creates transports.ini with mode 0600. It refuses to overwrite
an existing file unless --force is passed. Use --database-dsn,
--server-domain, --server-ip, or --output to override defaults.
Login QR codes are generated as SVG files without Pillow, stored under each
backend's qr_storage_dir, and served by the transport at /qr/. Set
qr_base_url to the externally reachable HTTP base URL. Expired files are
removed according to qr_max_age_seconds and qr_cleanup_interval_seconds.
Authentication diagnostics are written at DEBUG level to
logs/xabber_transport_<backend>.log (or the backend's log_file setting).
The file is private (0600) and rotates at 10 MiB with three backups.
Password commands and MAX API replies are logged as stages and result flags;
passwords, response bodies, tokens, and QR links are not logged. Restart the
transport after updating the code, then inspect the MAX log while repeating
/login and /password.
Backend adapters are discovered from the xabber_transport.backends Python
entry-point group. Validate a backend directly from the source checkout without
opening connections:
python3 -m xmpp_transport.runtime.app \
--config transports.ini \
--backend telegram \
--check-configThe daemon lifecycle follows xmpp-transport-max. Each backend has its own PID
file and runs as an isolated process:
python3 -m xmpp_transport.runtime.app --config transports.ini --backend max --daemon
python3 -m xmpp_transport.runtime.app --config transports.ini --backend max --status
python3 -m xmpp_transport.runtime.app --config transports.ini --backend max --stopWithout --pid-file, PID files are stored as
run/xabber_transport_<backend>.pid. Override the location when integrating
with a service manager.
The systemd template can run MAX and Telegram simultaneously. Review User,
Group, WorkingDirectory, ExecStart, and ReadWritePaths before installing
it. Keep production secrets outside the source checkout:
sudo install -d -m 0750 -o root -g xabber-transport /etc/xabber-transport
sudo install -m 0640 -o root -g xabber-transport transports.ini /etc/xabber-transport/transports.ini
sudo cp deploy/systemd/xabber-transport@.service.example /etc/systemd/system/xabber-transport@.service
sudo systemctl daemon-reload
sudo systemctl enable --now xabber-transport@max xabber-transport@telegram
sudo systemctl status xabber-transport@max xabber-transport@telegramThe built-in fake backend echoes an outbound direct message back through the
normal backend event, deduplication, and XMPP delivery path. Create a
[backend:fake] configuration, then create an active fake binding with an
encrypted non-empty credential payload.
Generate a Fernet key once and store it in the configured secret manager:
python3 -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())'Then validate the local wiring without opening PostgreSQL, HTTP, or XMPP:
python3 -m xmpp_transport.runtime.app \
--config transports.ini \
--backend fake \
--check-configRuntime integrations and their external dependencies will be introduced in later phases rather than leaking them into the domain package.