n1kita я после обеда в другом окне сидел, твой пост открыл краем глаза и почти закрыл. думал, ну у меня же секрет прокинут, чего логи смотреть. полез всё равно, потому что «почти» у меня обычно значит «забыл».
сначала access.log за вчера. post на /
webhook пачками.
user-agent пустой, иногда
curl/7, ip которые к телеге никак не вяжутся. не брут какой-то, просто сканеры тыкают урлы, интернет. потом
unit: EnvironmentFile прописан, а в
.env строка WH_SECRET закомментирована, рядом моим почерком «потом допишу». когда с ноута гонял, без секрета стартовало удобнее. .get это не аккуратность, это я оставил дырку, чтобы процесс не падал.
n1kita писал:
за ночь в access.log nginx чужие post на /webhook
у меня не ночь, просто вчерашний лог, и картина та же.
systemd зелёный, процесс живой, телега иногда доходит. в
python-telegram-
bot если secret_token=None, заголовок X-Telegram-
Bot-
Api-Secret-
Token он не проверяет. это не защита по умолчанию, это выключено. я почему-то решил, что None это нормально.
переписал. на токене и секрете теперь обычные скобки, не .get. нет переменной — бот не поднимается, в
journalctl сразу KeyError, а не «вроде 24/7». listen и port пусть остаются с дефолтом, там не секрет.
import os
from telegram import Update
from telegram.ext import Application, CommandHandler, ContextTypes
TOKEN = os.environ["BOT_TOKEN"]
WH_URL = os.environ["WH_URL"]
WH_SECRET = os.environ["WH_SECRET"]
LISTEN = os.environ.get("WH_LISTEN", "127.0.0.1")
PORT = int(os.environ.get("WH_PORT", "8080"))
async def ping(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text("жив")
def main() -> None:
app = Application.builder().token(TOKEN).build()
app.add_handler(CommandHandler("ping", ping))
app.run_webhook(
listen=LISTEN,
port=PORT,
url_path="webhook",
webhook_url=WH_URL,
secret_token=WH_SECRET,
)
if __name__ == "__main__":
main()
.env лежит рядом с ботом, в
git не идёт. на
unit EnvironmentFile=/home/
bot/app/
.env, права 600, пользователь отдельный, не
root. токен в репу я уже один раз затаскивал, второй раз не хочу.
nginx секрету учить не стал. если тот же WH_SECRET засунуть в if внутри
location, потом поменяешь в одном месте и неделю ловишь 403 от собственной телеги. один раз в
env, проверяет питон.
nginx только проксирует на
127.0.0.1:8080, этот порт снаружи закрыт.
location ровно /
webhook, как url_path. без фантазий про /
bot/secret-
path — умный путь всё равно не секрет.
location /webhook {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 30s;
}
юнит простой. Restart=always, чтобы когда я снова забуду переменную, починил
env и не ходил руками. After=
nginx, потому что без прокси телега бьёт в пустоту — это я уже ловил. NoNewPrivileges нагуглил, если лишнее — ну стоит.
[Unit]
Description=tg webhook bot
After=network-online.target nginx.service
Wants=network-online.target
[Service]
Type=simple
User=bot
Group=bot
WorkingDirectory=/home/bot/app
EnvironmentFile=/home/bot/app/.env
ExecStart=/home/bot/app/.venv/bin/python /home/bot/app/bot.py
Restart=always
RestartSec=5
NoNewPrivileges=yes
[Install]
WantedBy=multi-user.target
сел,
daemon-reload, restart, сразу
journalctl -u
bot -n 50. Application started, traceback нет, руки отпустило)) setWebhook ещё раз, secret_token в запросе. с телеги /
ping — «жив». с самой машины
curl на свой же
https без заголовка — 403, с кривым секретом тоже. в access.log левые post как ходили, так и ходят, сеть такая, но в
journalctl бота их уже нет. вот это я хотел, а не зелёную лампочку.
getWebhookInfo смотрел из
env, токен в историю шелла не копировал. pending_update_count ноль, last_error_message пусто, url как в WH_URL. если last_error висит сутками — это не «бот живой 24/7», это телега стучится и получает фигню. на этом уже обжёгся.
url_path в питоне менял, в
nginx забывал, или наоборот. сейчас в обоих просто
webhook и всё.
утром от безысходности думал на поллинг переехать, чтобы хоть что-то жило без
nginx. не стал. вебхук на этом же хосте нормально работает, если не оставлять .get «на потом» 🤦
сейчас бот не падает, я почти горд, пока не ткнут в следующее))
а у кого вебхук без секрета уже месяц крутится — когда access.log в последний раз открывали? я вот был уверен, что у меня чисто.