Un bot privado de Telegram facilita acceder a un agente en un VPS, pero conectar la pasarela no demuestra que responda a la persona prevista. Partimos de un directorio nuevo de Hermes Agent, permitimos un ID numérico, comprobamos una respuesta real y dejamos una parada verificada. Seguimos las instrucciones Docker v0.22.2 y instrucciones Telegram de NousResearch, comprobadas el 19 de octubre de 2026. BIG CHANGE no ejecutó un VPS, descargó la imagen, creó un bot ni llamó a un modelo para esta guía.
El gran cambio
- Qué cambia: Una imagen Docker fijada por digest y verificada por versión, con un montaje dedicado
/opt/data, permite identificar el software y estado de esta pasarela. - Por qué importa: Una lista de ID numéricos permitidos y una respuesta privada real muestran si la cuenta prevista puede usarla.
- Qué vigilar: El emparejamiento o los permisos globales amplían el acceso; una petición inocua no limita las herramientas del agente. Revisa permisos, registros, reinicio y parada.
Necesitas autoridad para administrar un VPS Linux por SSH, Docker Engine funcionando y acceso de recuperación al servidor, una cuenta Telegram capaz de crear un bot en BotFather y una cuenta elegible del proveedor de modelos Hermes. Contrasta arquitectura y recursos con la imagen oficial amd64 o arm64 y consulta acceso y facturación antes del asistente. Se presupone Docker operativo; instalación y cortafuegos dependen de SO y proveedor. El host necesita salida a Telegram y al proveedor. Reserva un directorio privado para el estado y limita sus lectores: /opt/data guardará credenciales, sesiones y registros. El manual Docker lo considera la fuente persistente de referencia.
1. Fija la imagen antes de configurar
Conecta por SSH y conserva el mismo shell para los comandos. La etiqueta stable puede cambiar. Descarga la imagen, registra el digest del repositorio y confirma que la propia imagen indica la versión 0.22.2. Detente si cambia, falta el digest, hay estado previo o existe un contenedor llamado hermes. Actualiza las instrucciones para la versión real o consigue una imagen documentada correspondiente antes de seguir. El digest fija la imagen, pero por sí solo no prueba su versión.
set -eu
docker info >/dev/null
docker container inspect hermes >/dev/null 2>&1 && { echo 'Container hermes already exists; stop here.'; exit 1; }
HERMES_DATA="$HOME/.hermes"
if [ -e "$HERMES_DATA" ]; then echo 'Hermes data path already exists; stop here.'; exit 1; fi
mkdir -m 700 "$HERMES_DATA"
docker pull nousresearch/hermes-agent:stable
docker image inspect nousresearch/hermes-agent:stable --format '{{json .RepoDigests}}'
IMAGE_REF="$(docker image inspect nousresearch/hermes-agent:stable --format '{{index .RepoDigests 0}}')"
if ! printf '%s\n' "$IMAGE_REF" | grep -Eq '^nousresearch/hermes-agent@sha256:[0-9a-f]{64}$'; then
echo 'No valid repository digest; stop here.'; exit 1
fi
printf 'Pinned image: %s\n' "$IMAGE_REF"
VERSION_OUTPUT="$(docker run --rm "$IMAGE_REF" --version)"
printf 'Image version: %s\n' "$VERSION_OUTPUT"
if ! printf '%s\n' "$VERSION_OUTPUT" | grep -Eq '(^|[^0-9])v?0[.]22[.]2([^0-9]|$)'; then
echo 'Image version is not 0.22.2; stop here.'; exit 1
fiset -eu detiene esta secuencia si Docker no está disponible, falla la descarga o inspección, o falla el comando de versión. Las comprobaciones explícitas paran también ante digest vacío u otra versión. No sigas a la configuración tras esos resultados. Guarda el valor nousresearch/hermes-agent@sha256:… registrado. Configuración y pasarela usan IMAGE_REF, así que un cambio posterior de etiqueta no cambia silenciosamente el contenedor. Son comprobaciones del lector en su VPS; el artículo no contiene un digest verificado. Usa un directorio nuevo y dedicado en el sistema de archivos nativo. Nunca ejecutes dos pasarelas contra los mismos datos.
2. Configura el proveedor y un remitente privado
Ejecuta el asistente de configuración Docker con el directorio montado. Elige una ruta de modelo permitida, autentícate y revisa el proveedor/modelo resultante. Acceso y cargos dependen de la cuenta; guardar ajustes no prueba una petición exitosa.
docker run -it --rm -v "$HERMES_DATA:/opt/data" "$IMAGE_REF" setupEn Telegram solicita a @BotFather un bot con /newbot y mantén su token privado. Obtén el ID numérico Telegram del remitente, por ejemplo mediante el método enlazado en el manual Telegram; un nombre de usuario no es un ID. El asistente o hermes gateway setup escribe token y lista permitida. A mano, coloca TELEGRAM_BOT_TOKEN=<private token> y TELEGRAM_ALLOWED_USERS=<your numeric ID> en $HERMES_DATA/.env, que aparece como /opt/data/.env dentro del contenedor. No incluyas el token en comandos, historial, notas compartidas ni este artículo.
En $HERMES_DATA/config.yaml (/opt/data/config.yaml dentro del contenedor), define el comportamiento global para mensajes privados no autorizados:
unauthorized_dm_behavior: ignoreTras salir el contenedor de configuración, la imagen puede haber cambiado $HERMES_DATA a su UID de ejecución 10000. El arranque limita .env al modo 600 y restringe un config.yaml existente a 640; uno creado por primera vez en ese arranque puede necesitar igual ajuste. Un usuario SSH normal podría no abrirlos. Si faltan claves, un administrador autorizado del host puede inspeccionar y editar esos dos archivos con sudo y restaurar propietario y modos privados. Un editor ejecutado como UID 10000 puede no atravesar un $HOME del usuario de acceso; por eso se usa administración del host. En un host con sudo y vi, úsalo después de verificar metadatos de propietario/modo sin secretos. No sigas con otro UID o archivo ausente; resuelve primero el acceso específico.
sudo stat -c '%u:%g %a %n' "$HERMES_DATA" "$HERMES_DATA/.env" "$HERMES_DATA/config.yaml"
# Expected: directory owner 10000 and mode 700; .env owner 10000 and mode 600.
# config.yaml should have owner 10000; its first-boot mode can vary.
sudo vi "$HERMES_DATA/.env"
sudo vi "$HERMES_DATA/config.yaml"
sudo chown 10000:10000 "$HERMES_DATA/.env" "$HERMES_DATA/config.yaml"
sudo chmod 700 "$HERMES_DATA"
sudo chmod 600 "$HERMES_DATA/.env"
sudo chmod 640 "$HERMES_DATA/config.yaml"
sudo stat -c '%u:%g %a %n' "$HERMES_DATA" "$HERMES_DATA/.env" "$HERMES_DATA/config.yaml"La salida final de stat debe mostrar UID/GID 10000 en ambos archivos, modo del directorio 700, .env con modo 600 y config.yaml con modo 640. Muestra metadatos, no credenciales. El chown afecta solo a esos dos archivos, incluida una sustitución creada por el editor. Si no existe sudo o vi, sigue el procedimiento autorizado del host con igual lectura de propietario y modos. No hagas los datos legibles para todos ni reasignes el usuario del contenedor.
Conserva los ajustes del proveedor al editar. Ninguna anulación Telegram de unauthorized_dm_behavior debe establecer pair, ni un parámetro global GATEWAY_ALLOWED_USERS o GATEWAY_ALLOW_ALL_USERS conceder acceso más amplio. En config.yaml, comprueba también que ni gateway.allow_all_users ni el parámetro de nivel superior allow_all_users sean true y que no haya otro remitente global o Telegram. No uses * en las listas, añadas listas de grupos ni apruebes códigos de emparejamiento. Un directorio nuevo evita permisos heredados; si contiene datos, detente e inspecciona sin sobrescribir. Mantén la privacidad de grupos de BotFather, no añadas el bot a grupos ni lo hagas administrador. El manual de acceso a la pasarela separa listas permitidas y autorizaciones persistentes de emparejamiento. El manual de seguridad describe ignore como descarte silencioso de mensajes privados no autorizados.
La lista limita quién inicia conversaciones, no lo que hace el agente autorizado. Las sesiones Telegram de Hermes incluyen terminal por defecto. Revisa permisos, montajes, proveedor y política del host antes de admitir al remitente. Una petición de prueba inocua es solo una petición.
3. Inicia la pasarela y comprueba la primera respuesta
Inicia un contenedor con nombre desde el digest registrado. El comando publicado incluye un -p 8642:8642 opcional para la API; omítelo, pues un mensaje privado no requiere API o panel públicos. La imagen supervisa la pasarela; la política Docker unless-stopped controla el reinicio al arrancar Docker. El montaje conserva configuración y sesiones tras reiniciar.
docker run -d --name hermes --restart unless-stopped \
-v "$HERMES_DATA:/opt/data" "$IMAGE_REF" gateway run
if ! {
docker inspect hermes --format '{{.Image}} {{.State.Status}}' &&
[ "$(docker inspect hermes --format '{{.State.Status}}')" = running ] &&
docker logs --tail 50 hermes &&
docker exec -u hermes hermes hermes pairing list
}; then
echo 'State, logs or pairing check failed; stopping before any message.'
docker stop hermes || true
docker inspect hermes --format '{{.State.Status}}' || true
exit 1
fiConfirma que el contenedor está running, examina conexión Telegram y errores del proveedor en los registros y consulta emparejamientos antes de enviar. Si falla una lectura inicial, el bloque detiene la pasarela y muestra estado; un resultado desconocido no autoriza seguir. Confirma exited antes de investigar, sin enviar ni reiniciar si hay incertidumbre. No debe existir otro remitente aprobado; si aparece, detén y comprueba la parada. docker exec no funciona contra un contenedor parado, y el punto de entrada normal puede restaurar una pasarela anterior. En instalación nueva con UID predeterminado, la comprobación sin conexión ejecuta solo la CLI Hermes fijada, como UID 10000 y sin red, evitando el arranque. Es adaptación de comandos y punto de entrada documentados, no un comando probado por BIG CHANGE. Úsala solo tras confirmar UID activo y propietario de datos 10000. Si hay dudas de propietario, UID, salida CLI o permisos, mantén parada hasta resolverlas antes de reiniciar.
if [ "$(docker exec -u hermes hermes id -u)" != 10000 ] || [ "$(stat -c %u "$HERMES_DATA")" != 10000 ]; then
echo 'Runtime UID or data owner differs; stop for a host-specific repair.'; docker stop hermes; exit 1
fi
docker stop hermes
if [ "$(docker inspect hermes --format '{{.State.Status}}')" != exited ]; then
echo 'Container is not exited; do not mount state in another container.'; exit 1
fi
docker run --rm --network none --user 10000:10000 \
--entrypoint /opt/hermes/.venv/bin/hermes \
-v "$HERMES_DATA:/opt/data" "$IMAGE_REF" pairing list
# For a listed unwanted Telegram user, read the exact numeric ID first:
printf 'Unwanted numeric Telegram user ID: '; IFS= read -r UNWANTED_ID
if ! printf '%s\n' "$UNWANTED_ID" | grep -Eq '^[0-9]+$'; then echo 'Invalid ID; leave gateway stopped.'; exit 1; fi
docker run --rm --network none --user 10000:10000 \
--entrypoint /opt/hermes/.venv/bin/hermes \
-v "$HERMES_DATA:/opt/data" "$IMAGE_REF" pairing revoke telegram "$UNWANTED_ID"
docker run --rm --network none --user 10000:10000 \
--entrypoint /opt/hermes/.venv/bin/hermes \
-v "$HERMES_DATA:/opt/data" "$IMAGE_REF" pairing listConfirma que el ID no deseado ya no aparece. Inspecciona en privado $HERMES_DATA/.env y config.yaml para otras listas globales o de plataforma, * o ajustes de acceso total. Retira permisos por la configuración documentada. Mantén parada hasta revisar todas las vías. Quitar una entrada no revoca emparejamientos independientes o permisos globales. Después de comprobarlo, docker start hermes reanuda deliberadamente el contenedor original; revisa registros y lista antes de escribirle.
Desde la cuenta permitida abre un chat privado con el bot y envía algo inocuo, como «Responde con un saludo breve». Comprueba respuesta real y su registro o sesión. Mensaje enviado, escritura en curso, estado o configuración terminada no son una respuesta. El comando Telegram /whoami muestra el ámbito activo, no demuestra autorización del host. Guarda solo pruebas no sensibles.
Sin respuesta, lee primero estado y docker logs --tail 50 hermes. Comprueba token, valor numérico exacto de TELEGRAM_ALLOWED_USERS, autenticación y elegibilidad del modelo y salida de red. Ante resultado incierto lee chat y registros antes de repetir. El arranque en frío puede descartar actualizaciones pendientes y la supresión de duplicados es limitada en memoria. No se garantiza entrega exactamente una vez.
4. Comprueba reinicio, parada y recuperación
Terminado el primer turno, reinicia el mismo contenedor, revisa registros nuevos y el estado guardado en /opt/data, envía una petición privada inocua nueva y verifica su respuesta. Detén y lee el estado Docker. exited confirma parada; el silencio del chat no basta. docker start hermes reanuda intencionadamente más tarde.
docker restart hermes
docker logs --tail 50 hermes
docker inspect hermes --format '{{.State.Status}}'
# After the restarted gateway is ready, send a new private test message.
docker stop hermes
docker inspect hermes --format '{{.State.Status}}'
# Expected after stop: exited
# When intentionally resuming later: docker start hermesSi falla el reinicio, revisa Docker, después $HERMES_DATA/logs/gateways/default/current y $HERMES_DATA/logs/container-boot.log, montaje, propietario e imagen/versión fijadas. Las notas v0.22.2 describen una corrección de actividad al arrancar, sin establecer qué pasó en tu host. No borres el estado para reparar. Si se filtra el token, detén, revócalo en BotFather, cámbialo en privado en el archivo montado .env y revisa acceso antes de reiniciar. Revoca emparejamientos no deseados y revisa listas efectivas.
Alojamiento y modelo pueden cobrar por separado. Consulta plan, límites y cargos reales; no se prometen tiempo, cuota gratuita o disponibilidad. Telegram y el proveedor procesan los mensajes; el host guarda secretos y estado. Solo se comprueba primera respuesta de un host y bot. Otras guías BIG CHANGE cubren copia y recuperación de Hermes y un trabajo periódico de Hermes.
Fuentes y lecturas adicionales
La configuración Docker, configuración Telegram, guía de acceso, guía de seguridad y versión v0.22.2 son fuentes primarias de NousResearch. El inicio rápido explica el proveedor. Documentan el procedimiento, no una ejecución de VPS o bot de BIG CHANGE.



