Fix Telegram allowlist .env pitfall; default one-liner to Hermes

Document and force TELEGRAM_ALLOWED_USERS into ~/.hermes/.env (gateway
source of truth). Client creates bot via BotFather. install.sh defaults
conductor to hermes for a true single-command demo start.
This commit is contained in:
domfelipe 2026-08-04 18:45:03 -03:00
parent 1ec8930426
commit 297a7d3fe0
5 changed files with 122 additions and 42 deletions

View file

@ -1,7 +1,7 @@
---
name: hermes-client-onboarding
description: Use when setting up Hermes for a client, install Hermes + Telegram + DeepSeek, run a demo setup, or launch client onboarding. Conducts guided conversational onboarding on a clean Linux VM (deepseek-v4-flash, Telegram gateway, systemd, SOUL.md).
version: 1.1.0
version: 1.2.0
author: DomHubs
license: MIT
platforms: [linux, macos]
@ -122,24 +122,44 @@ Optional: Offer fallback model `deepseek-v4-pro` if the user wants a stronger mo
**Done when:** provider=deepseek, model=deepseek-v4-flash, key set without printing it.
### Phase 3 — Telegram Bot
### Phase 3 — Telegram Bot (client creates their agent)
1. Guide the user (or do it yourself if they give you the token) to create a bot with @BotFather if they do not have one yet.
The client owns the bot — guide **them** to create it (interactive, no BotFather quota on DomHubs). Narrative: “você está criando o seu agente de IA”.
1. Ask them to open Telegram (company account preferred) and talk to @BotFather:
- `/newbot` → choose display name + username ending in `bot`
- Copy the **HTTP API token**
2. Collect:
- `TELEGRAM_BOT_TOKEN`
- At least one numeric User ID (from @userinfobot or @get_id_bot). Multiple IDs can be comma-separated.
3. Apply:
- At least one **numeric** User ID (from @userinfobot or @get_id_bot). Multiple IDs comma-separated.
3. Apply **and force the values into `~/.hermes/.env`** (source of truth for the gateway):
```bash
hermes config set TELEGRAM_BOT_TOKEN "TOKEN"
hermes config set TELEGRAM_ALLOWED_USERS "ID1,ID2"
```
4. Optional advanced settings (only if requested):
- Home channel for proactive messages
- Group chat IDs
**Critical pitfall (do not skip):** the messaging gateway reads allowlist / token from **`~/.hermes/.env`**, not from a free-form key dumped only into `config.yaml`. An **old** `TELEGRAM_ALLOWED_USERS=` line in `.env` silently wins → bot ignores the client and logs:
**Done when:** token set, at least one allowed user ID set, values repeated back (IDs only, never full token).
```text
Blocked unauthorized user
```
After every `config set` for Telegram secrets:
```bash
# Verify .env actually has the NEW ids (do not print full token)
grep -E '^TELEGRAM_ALLOWED_USERS=' ~/.hermes/.env
# If stale or missing, write explicitly:
# printf 'TELEGRAM_ALLOWED_USERS=%s\n' 'ID1,ID2' >> ~/.hermes/.env # or edit in place
# Prefer: hermes config set again, then re-grep
```
If `.env` still shows the wrong ID after `config set`, rewrite the line yourself (sed/python) so only the new IDs remain, `chmod 600 ~/.hermes/.env`, then restart gateway (Phase 5).
4. Optional advanced settings (only if requested): home channel, group chat IDs.
**Done when:** token set, allowed user IDs confirmed in **`.env`**, values repeated back (IDs only, never full token).
### Phase 4 — Agent Personality (SOUL.md)
@ -218,7 +238,7 @@ hermes update
## Error Handling Guidelines
- If `hermes config set` fails, check file permissions on `~/.hermes/.env` and `~/.hermes/config.yaml`.
- If Telegram does not respond: verify token with a direct `getMe` call, confirm Allowed Users, restart gateway, check logs for connection errors.
- If Telegram does not respond: verify token with `getMe`, confirm **`TELEGRAM_ALLOWED_USERS` inside `~/.hermes/.env`** (not only yaml), restart gateway. Log signature of wrong allowlist: `Blocked unauthorized user`.
- If DeepSeek returns auth errors: re-validate `DEEPSEEK_API_KEY` and model name (`deepseek-v4-flash`). See `references/troubleshooting.md`.
- Prefer fixing issues yourself when possible, then explain what was wrong in plain language.
- Never leave the system in a half-configured state. Either finish a phase or clearly roll back.
@ -257,12 +277,14 @@ hermes config set model.default deepseek-v4-flash
hermes config set model.base_url "https://api.deepseek.com/v1"
hermes config set TELEGRAM_BOT_TOKEN "..."
hermes config set TELEGRAM_ALLOWED_USERS "123456789"
grep -E '^TELEGRAM_ALLOWED_USERS=' ~/.hermes/.env # must match IDs above
# Gateway
hermes gateway install
hermes gateway start
hermes gateway restart
hermes gateway status
hermes gateway logs
# Linux: journalctl --user -u hermes-gateway -n 50
# macOS: tail -f ~/.hermes/logs/gateway.log
# Validation
hermes doctor

View file

@ -49,26 +49,47 @@ hermes config set model.base_url "https://api.deepseek.com/v1"
## Telegram bot does not reply
### Log signature: `Blocked unauthorized user`
The gateway **ignores** the sender because `TELEGRAM_ALLOWED_USERS` in **`~/.hermes/.env`** does not include their numeric ID.
**Root cause seen in production:** `hermes config set TELEGRAM_ALLOWED_USERS "..."` may leave a **stale** line in `.env` (or write somewhere the gateway does not use). Gateway loads allowlist from **`.env`**, not from a yaml-only mirror.
**Fix:**
```bash
# See what gateway will actually load (do not paste tokens into chat)
grep -E '^TELEGRAM_(BOT_TOKEN|ALLOWED_USERS)=' ~/.hermes/.env
# Set again, then re-grep until ALLOWED_USERS is exactly the new IDs
hermes config set TELEGRAM_ALLOWED_USERS "ID1,ID2"
grep -E '^TELEGRAM_ALLOWED_USERS=' ~/.hermes/.env
# If still stale, rewrite the line (example):
# sed -i.bak '/^TELEGRAM_ALLOWED_USERS=/d' ~/.hermes/.env
# echo 'TELEGRAM_ALLOWED_USERS=ID1,ID2' >> ~/.hermes/.env
chmod 600 ~/.hermes/.env
hermes gateway restart
# Linux (user service): journalctl --user -u hermes-gateway -n 50 --no-pager
# macOS: tail -n 50 ~/.hermes/logs/gateway.log
```
### Other checks
1. Token validity:
```bash
# TOKEN from env; do not log it
source ~/.hermes/.env 2>/dev/null || true
curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getMe" | head -c 200
```
2. Allowed users: numeric IDs only (from @userinfobot). Restart after change:
```bash
hermes config set TELEGRAM_ALLOWED_USERS "ID1,ID2"
hermes gateway restart
hermes gateway status
hermes gateway logs
```
2. Allowed users must be **numeric** IDs only (@userinfobot / @get_id_bot), comma-separated.
3. Common mistakes:
- User ID is username string instead of numeric ID
- Gateway not running
- Username string instead of numeric ID
- Stale ALLOWED_USERS in `.env` after a previous client on the same machine
- Gateway not running / not restarted after env change
- Bot blocked by user / wrong bot
## Gateway service won't start

View file

@ -1,5 +1,6 @@
#!/usr/bin/env bash
# Apply DeepSeek native + model + Telegram core config for Hermes client onboarding.
# Forces Telegram secrets into ~/.hermes/.env (gateway source of truth).
# Does not print secrets. Requires: hermes on PATH.
set -euo pipefail
@ -26,7 +27,7 @@ TG_USERS="${TELEGRAM_ALLOWED_USERS:-}"
while [[ $# -gt 0 ]]; do
case "$1" in
--deepseek-key|--openrouter-key) DS_KEY="${2:-}"; shift 2 ;; # --openrouter-key kept as alias
--deepseek-key|--openrouter-key) DS_KEY="${2:-}"; shift 2 ;;
--telegram-token) TG_TOKEN="${2:-}"; shift 2 ;;
--allowed-users) TG_USERS="${2:-}"; shift 2 ;;
--model) MODEL="${2:-}"; shift 2 ;;
@ -57,6 +58,26 @@ if [[ "$PROVIDER" == "openrouter" ]]; then
BASE_URL="https://openrouter.ai/api/v1"
fi
HERMES_HOME="${HERMES_HOME:-$HOME/.hermes}"
ENV_FILE="${HERMES_HOME}/.env"
mkdir -p "$HERMES_HOME"
touch "$ENV_FILE"
chmod 600 "$ENV_FILE"
# Upsert KEY=VALUE in .env (gateway reads this file)
env_upsert() {
local key="$1" val="$2" tmp
tmp="$(mktemp)"
if [[ -f "$ENV_FILE" ]]; then
grep -v -E "^${key}=" "$ENV_FILE" >"$tmp" || true
else
: >"$tmp"
fi
printf '%s=%s\n' "$key" "$val" >>"$tmp"
mv "$tmp" "$ENV_FILE"
chmod 600 "$ENV_FILE"
}
hermes config set DEEPSEEK_API_KEY "$DS_KEY"
hermes config set model.provider "$PROVIDER"
hermes config set model.default "$MODEL"
@ -64,8 +85,20 @@ hermes config set model.base_url "$BASE_URL"
hermes config set TELEGRAM_BOT_TOKEN "$TG_TOKEN"
hermes config set TELEGRAM_ALLOWED_USERS "$TG_USERS"
# Force .env — prevents stale ALLOWED_USERS silently blocking the client
env_upsert "DEEPSEEK_API_KEY" "$DS_KEY"
env_upsert "TELEGRAM_BOT_TOKEN" "$TG_TOKEN"
env_upsert "TELEGRAM_ALLOWED_USERS" "$TG_USERS"
# Verify allowlist line matches what we just wrote
got="$(grep -E '^TELEGRAM_ALLOWED_USERS=' "$ENV_FILE" | tail -1 | cut -d= -f2- || true)"
if [[ "$got" != "$TG_USERS" ]]; then
echo "error: TELEGRAM_ALLOWED_USERS in $ENV_FILE is '$got', expected '$TG_USERS'" >&2
exit 1
fi
echo "ok: provider=$(hermes config get model.provider 2>/dev/null || echo "$PROVIDER")"
echo "ok: model=$(hermes config get model.default 2>/dev/null || echo "$MODEL")"
echo "ok: base_url=$(hermes config get model.base_url 2>/dev/null || echo "$BASE_URL")"
echo "ok: allowed_users=$TG_USERS"
echo "ok: secrets written (not displayed)"
echo "ok: secrets written to hermes config + $ENV_FILE (not displayed)"