# Guía de despliegue — Pedrito Hechakuaa en VPS Ubuntu > **Destinatario:** equipo técnico de InQuality > **Entorno objetivo:** VPS Ubuntu en Hostinger — pre-producción estable > **Tiempo estimado:** 30–45 minutos > **Acceso requerido:** SSH root a la VPS + datos de configuración provistos por Marcos --- ## Índice 1. [Antes de empezar — datos que necesitás de Marcos](#1-antes-de-empezar) 2. [Conectarse a la VPS](#2-conectarse-a-la-vps) 3. [Crear usuario dedicado](#3-crear-usuario-dedicado) 4. [Instalar dependencias del sistema](#4-instalar-dependencias-del-sistema) 5. [Clonar el repositorio](#5-clonar-el-repositorio) 6. [Instalar dependencias del proyecto](#6-instalar-dependencias-del-proyecto) 7. [Configurar el archivo .env](#7-configurar-el-archivo-env) 8. [Cifrar las credenciales del PJ](#8-cifrar-las-credenciales-del-pj) 9. [Verificar que el bot arranca](#9-verificar-que-el-bot-arranca) 10. [Crear el servicio systemd](#10-crear-el-servicio-systemd) 11. [Configurar el firewall](#11-configurar-el-firewall) 12. [Verificación final](#12-verificación-final) 13. [Monitoreo y logs](#13-monitoreo-y-logs) 14. [Cómo actualizar el bot](#14-cómo-actualizar-el-bot) 15. [Troubleshooting](#15-troubleshooting) --- ## 1. Antes de empezar Antes de tocar la VPS, pedile a Marcos que te provea estos datos. Sin ellos no podés completar el deploy. | Dato | Dónde conseguirlo | Dónde va | |------|------------------|----------| | `FERNET_KEY` | Marcos la genera o te la pasa | `.env` | | `TELEGRAM_BOT_TOKEN` | Token del bot de Telegram (de @BotFather) | `.env` | | `TELEGRAM_CHAT_ID` | Chat ID de Telegram de Marcos (de @userinfobot) | `.env` | | Cédula de identidad del PJ | Marcos | Script de cifrado (paso 8) | | Contraseña del sistema del PJ | Marcos | Script de cifrado (paso 8) | | IP de la VPS | Panel de Hostinger | SSH | > ⚠️ **Seguridad:** No guardes la contraseña del PJ en ningún archivo, chat ni nota. > El script de cifrado (paso 8) la pide interactivamente y la descarta de memoria al terminar. > Solo persiste cifrada en `.env`. --- ## 2. Conectarse a la VPS ```bash ssh root@ ``` Si usás clave SSH (recomendado): ```bash ssh -i ~/.ssh/id_rsa root@ ``` Verificar que el sistema está actualizado: ```bash apt update && apt upgrade -y ``` --- ## 3. Crear usuario dedicado El bot no debe correr como root. Creamos un usuario propio llamado `pedrito`. ```bash # Crear usuario sin contraseña de login (solo acceso SSH) adduser pedrito --disabled-password --gecos "" # Verificar que se creó correctamente id pedrito # Salida esperada: uid=1001(pedrito) gid=1001(pedrito) groups=1001(pedrito) ``` ### Configurar acceso SSH para el usuario pedrito ```bash # Crear directorio SSH para el usuario mkdir -p /home/pedrito/.ssh # Copiar las claves autorizadas de root (si ya tenés acceso por clave SSH como root) cp /root/.ssh/authorized_keys /home/pedrito/.ssh/ # Dar los permisos correctos (obligatorio para que SSH funcione) chown -R pedrito:pedrito /home/pedrito/.ssh chmod 700 /home/pedrito/.ssh chmod 600 /home/pedrito/.ssh/authorized_keys ``` > Podés verificar el acceso abriendo una segunda terminal: > ```bash > ssh pedrito@ > ``` > Si entra sin pedir contraseña, todo está bien. --- ## 4. Instalar dependencias del sistema ```bash # Aún como root apt install -y git curl ``` Verificar Python 3.12+: ```bash python3 --version ``` Si la versión es menor a 3.12: ```bash apt install -y software-properties-common add-apt-repository ppa:deadsnakes/ppa -y apt update apt install -y python3.12 python3.12-venv ``` --- ## 5. Clonar el repositorio A partir de acá trabajamos como el usuario `pedrito`: ```bash # Cambiar al usuario pedrito su - pedrito # Verificar que estamos en el home correcto pwd # /home/pedrito # Clonar el repo git clone https://github.com/InqGit/hechakuaa_bot.git cd hechakuaa_bot # Verificar que los archivos están ls -la # Deberías ver: main.py, config.py, telegram_bot.py, poller.py, etc. ``` --- ## 6. Instalar dependencias del proyecto El proyecto usa `uv` como gestor de dependencias (más rápido que pip). ```bash # Instalar uv (como usuario pedrito) curl -LsSf https://astral.sh/uv/install.sh | sh # Cargar uv en el shell actual (sin necesidad de cerrar sesión) source $HOME/.local/bin/env # Verificar instalación uv --version # Salida esperada: uv 0.x.x # Instalar todas las dependencias del proyecto en un entorno virtual uv sync # Verificar que el entorno virtual se creó ls .venv/bin/python # Salida esperada: .venv/bin/python ``` --- ## 7. Configurar el archivo .env > ⚠️ **Importante:** El `.env` se crea directamente en la VPS. Nunca se copia desde tu > máquina ni se sube al repositorio. Tiene permisos 600 (solo lo puede leer `pedrito`). ```bash # Estamos en /home/pedrito/hechakuaa_bot/ # Copiar el template cp .env.example .env # Editar el archivo nano .env ``` Completar los siguientes campos (los demás se pueden dejar con sus valores por defecto): ``` FERNET_KEY= TELEGRAM_BOT_TOKEN= TELEGRAM_CHAT_ID= ``` Guardar y salir de nano: `Ctrl+O`, `Enter`, `Ctrl+X`. Restringir permisos (obligatorio): ```bash chmod 600 .env # Verificar ls -la .env # Salida esperada: -rw------- 1 pedrito pedrito ... .env ``` > Si la FERNET_KEY todavía no existe, generala así y anotala en un gestor de contraseñas: > ```bash > uv run python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" > ``` > Copiá la salida (una cadena larga de letras y números) y pegala en `.env` como valor de `FERNET_KEY`. --- ## 8. Cifrar las credenciales del PJ El bot nunca guarda la cédula ni la contraseña del PJ en texto plano. Este script las cifra con la `FERNET_KEY` y guarda el resultado cifrado en `.env`. ```bash uv run python scripts/cifrar_credenciales.py ``` El script te va a pedir: 1. **Cédula de identidad** — el usuario con el que Marcos entra a `apps.csj.gov.py` 2. **Contraseña** — se escribe pero no se muestra en pantalla Salida esperada al terminar: ``` ✅ Credenciales cifradas y guardadas en .env PJ_USUARIO_ENC y PJ_PASSWORD_ENC actualizadas. ``` Verificar que se guardaron en `.env`: ```bash grep "PJ_USUARIO_ENC" .env # Debe mostrar una línea con un valor cifrado largo (no la cédula en texto plano) ``` --- ## 9. Verificar que el bot arranca Antes de configurar el servicio, probamos que todo funciona: ```bash uv run python main.py ``` Salida esperada (en formato JSON, primeras líneas): ```json {"event": "pedrito_hechakuaa_iniciando", "level": "info", ...} {"event": "database_iniciada", "level": "info", ...} {"event": "bot_telegram_iniciado", "level": "info", ...} {"event": "pedrito_hechakuaa_corriendo", "level": "info", ...} {"event": "poller_iniciado", "level": "info", ...} {"event": "login_exitoso", "level": "info", ...} ``` Si aparece `"login_exitoso"` el bot se conectó al PJ correctamente. **Detener el bot:** `Ctrl+C` ### Errores comunes en este paso | Mensaje de error | Causa | Solución | |-----------------|-------|----------| | `FERNET_KEY inválida` | La clave en `.env` es incorrecta o tiene espacios | Verificar que no tiene espacios ni comillas en `.env` | | `Credenciales incorrectas (401)` | Cédula o contraseña del PJ incorrecta | Repetir paso 8 con los datos correctos | | `telegram.error.InvalidToken` | TELEGRAM_BOT_TOKEN mal copiado | Verificar el token en `.env` | | `ModuleNotFoundError` | `uv sync` no se ejecutó o falló | Correr `uv sync` de nuevo | --- ## 10. Crear el servicio systemd El servicio systemd mantiene el bot corriendo en background, lo reinicia si cae, y lo levanta automáticamente al reiniciar la VPS. Volver a root para crear el archivo de servicio: ```bash exit # salir del usuario pedrito, volver a root ``` Crear el archivo de servicio: ```bash nano /etc/systemd/system/pedrito.service ``` Pegar exactamente este contenido: ```ini [Unit] Description=Pedrito Hechakuaa — Monitor judicial PY After=network-online.target Wants=network-online.target [Service] Type=simple User=pedrito WorkingDirectory=/home/pedrito/hechakuaa_bot # Usar el Python del entorno virtual directamente (no depende del PATH) ExecStart=/home/pedrito/hechakuaa_bot/.venv/bin/python main.py # Reiniciar automáticamente si el proceso cae Restart=on-failure RestartSec=15 # Seguridad: el proceso no puede escalar privilegios NoNewPrivileges=true PrivateTmp=true # Logs a journald StandardOutput=journal StandardError=journal SyslogIdentifier=pedrito [Install] WantedBy=multi-user.target ``` Guardar: `Ctrl+O`, `Enter`, `Ctrl+X`. Activar e iniciar el servicio: ```bash # Recargar la configuración de systemd para que detecte el nuevo servicio systemctl daemon-reload # Habilitar para que arranque en cada reboot systemctl enable pedrito # Iniciar el servicio ahora systemctl start pedrito # Verificar que está corriendo systemctl status pedrito ``` Salida esperada de `systemctl status pedrito`: ``` ● pedrito.service - Pedrito Hechakuaa — Monitor judicial PY Loaded: loaded (/etc/systemd/system/pedrito.service; enabled; ...) Active: active (running) since ... ``` El campo clave es `Active: active (running)`. Si dice `failed` o `inactive`, ver la sección de [Troubleshooting](#15-troubleshooting). --- ## 11. Configurar el firewall El bot de Telegram usa polling saliente — no necesita puertos abiertos para funcionar. Solo habilitamos SSH para no quedarnos sin acceso. ```bash # Como root ufw allow OpenSSH ufw --force enable ufw status ``` Salida esperada: ``` Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere ``` > Si en la VPS ya tenés otros servicios corriendo (nginx, etc.), agregá sus puertos > antes de hacer `ufw enable` para no cortarlos: > ```bash > ufw allow 80/tcp # HTTP > ufw allow 443/tcp # HTTPS > ``` --- ## 12. Verificación final Revisar que todo quedó en orden: ```bash # 1. El servicio está corriendo systemctl status pedrito # Esperado: active (running) # 2. El bot se loguea al PJ y al bot de Telegram journalctl -u pedrito -n 30 # Buscar: "login_exitoso" y "bot_telegram_iniciado" # 3. El proceso existe ps aux | grep "python main.py" | grep -v grep # Debe mostrar el proceso del usuario pedrito # 4. El .env tiene los permisos correctos su - pedrito -c "ls -la /home/pedrito/hechakuaa_bot/.env" # Debe mostrar: -rw------- 1 pedrito pedrito # 5. El servicio se recupera de reinicios # Opcional: reiniciar la VPS y verificar que el bot vuelve solo reboot # Esperar 1-2 minutos, reconectarse y correr: systemctl status pedrito ``` Si todos los puntos pasan, el deploy está completo. Avisarle a Marcos para que pruebe mandándole `/start` al bot en Telegram. --- ## 13. Monitoreo y logs ### Ver logs en tiempo real ```bash journalctl -u pedrito -f ``` Detener con `Ctrl+C`. ### Ver los últimos N registros ```bash journalctl -u pedrito -n 50 ``` ### Ver logs de la última hora ```bash journalctl -u pedrito --since "1 hour ago" ``` ### Ver logs de un día específico ```bash journalctl -u pedrito --since "2026-05-25 00:00:00" --until "2026-05-25 23:59:59" ``` ### Buscar errores ```bash journalctl -u pedrito -p err ``` ### Eventos útiles que buscar en los logs | Evento en el log | Qué significa | |-----------------|---------------| | `login_exitoso` | Se conectó al PJ correctamente | | `polling_tenant_ok` | Revisión de notificaciones completada | | `polling_tenant_error` | Error en la revisión (ver `tipo` en el detalle) | | `pj_error_conexion` | El PJ no respondió (puede ser transitorio) | | `bot_notificacion_enviada` | Se envió una notificación a Telegram | | `onboarding_completado` | Un usuario completó el registro | --- ## 14. Cómo actualizar el bot Cuando hay cambios en el código (nuevo commit en el repo): ```bash # Como pedrito (o desde root: su - pedrito) cd /home/pedrito/hechakuaa_bot # Traer los cambios git pull # Reinstalar dependencias si hubo cambios en pyproject.toml uv sync # Reiniciar el servicio para aplicar los cambios # (hacerlo como root o con sudo) exit # si estabas como pedrito systemctl restart pedrito # Verificar que levantó bien systemctl status pedrito journalctl -u pedrito -n 20 ``` > **Nota:** El archivo `.env` y el directorio `data/` **no se tocan con `git pull`** — > están en `.gitignore`. Las credenciales y el historial de notificaciones persisten > entre actualizaciones. --- ## 15. Troubleshooting ### El servicio no arranca (`failed`) ```bash # Ver el error específico journalctl -u pedrito -n 50 systemctl status pedrito ``` **`ModuleNotFoundError: No module named 'X'`** ```bash su - pedrito cd hechakuaa_bot uv sync exit systemctl restart pedrito ``` **`.venv/bin/python: No such file or directory`** ```bash su - pedrito cd hechakuaa_bot uv sync # esto crea el .venv exit systemctl restart pedrito ``` **`DB no inicializada`** El `data/` no existe todavía. El bot lo crea solo al arrancar. Si persiste: ```bash su - pedrito mkdir -p /home/pedrito/hechakuaa_bot/data exit systemctl restart pedrito ``` --- ### El bot arranca pero no responde en Telegram 1. Verificar que `TELEGRAM_BOT_TOKEN` en `.env` es correcto 2. Verificar que `TELEGRAM_CHAT_ID` es el chat_id correcto de Marcos 3. Revisar logs: `journalctl -u pedrito -n 30` 4. Desde otro cliente probar que el bot existe: buscar `@pedrito_hechakuaabot` en Telegram --- ### Error de credenciales del PJ (`Credenciales incorrectas`) ```bash su - pedrito cd hechakuaa_bot # Repetir el cifrado de credenciales uv run python scripts/cifrar_credenciales.py exit systemctl restart pedrito ``` --- ### La VPS se reinició y el bot no volvió ```bash systemctl status pedrito # Si dice "disabled": systemctl enable pedrito systemctl start pedrito ``` --- ### Ver si hay dos instancias corriendo (causa conflictos) ```bash ps aux | grep "python main.py" | grep -v grep ``` Si hay más de una línea, matar todas y reiniciar el servicio: ```bash pkill -f "python main.py" systemctl start pedrito ``` --- ## Referencia rápida de comandos ```bash # Estado del servicio systemctl status pedrito # Iniciar / detener / reiniciar systemctl start pedrito systemctl stop pedrito systemctl restart pedrito # Logs en tiempo real journalctl -u pedrito -f # Actualizar el bot su - pedrito -c "cd hechakuaa_bot && git pull && uv sync" systemctl restart pedrito ``` --- *Repositorio: https://github.com/InqGit/hechakuaa_bot* *Ante dudas, contactar a Marcos Benítez.*