Versión para VPS donde Docker, Nginx y usuario pedrito ya existen. Elimina: instalación de Docker, Nginx, creación de usuario, configuración DNS. Agrega: tabla de estado inicial, nota sobre docker-compose v1 vs v2. De 20 secciones (60-90 min) a 17 secciones (30-45 min). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
780 lines
21 KiB
Markdown
780 lines
21 KiB
Markdown
# Guía de despliegue — Pedrito Hechakuaa en VPS Ubuntu
|
||
|
||
> **Destinatario:** equipo técnico de InQuality
|
||
> **Entorno objetivo:** VPS Ubuntu 22.04 en Hostinger — producción
|
||
> **Tiempo estimado:** 30–45 minutos
|
||
> **Acceso requerido:** SSH root al VPS + datos de configuración provistos por Marcos
|
||
> **Subdominio objetivo:** `pedrito.inqualityhq.com`
|
||
|
||
### Estado del servidor al momento de esta guía
|
||
|
||
| Componente | Estado |
|
||
|---|---|
|
||
| DNS `pedrito.inqualityhq.com` | ✅ ya apunta al VPS (93.127.136.210) |
|
||
| Docker v29.2.1 + compose v2 plugin | ✅ instalados |
|
||
| Nginx v1.24.0 | ✅ instalado |
|
||
| Usuario `pedrito` (UID 1003) | ✅ existe |
|
||
| `pedrito` en grupo docker | ❌ paso 3 |
|
||
| Repositorio clonado | ❌ paso 4 |
|
||
| `.env` configurado | ❌ paso 5 |
|
||
| Credenciales PJ cifradas | ❌ paso 6 |
|
||
| Certificado SSL | ❌ paso 7 |
|
||
| Nginx configurado para el bot | ❌ paso 8 |
|
||
| Firewall | ❓ paso 9 |
|
||
| Bot corriendo | ❌ paso 10 |
|
||
|
||
> **Nota sobre docker-compose:** el servidor tiene `docker-compose` v1.29.2 (standalone) instalado.
|
||
> Esta guía usa `docker compose` (con espacio, plugin v2) que también está disponible. No mezclar los dos.
|
||
|
||
---
|
||
|
||
## Índice
|
||
|
||
**PARTE A — Preparación**
|
||
1. [Datos que necesitás antes de empezar](#1-datos-que-necesitás-antes-de-empezar)
|
||
2. [Conectarse al VPS](#2-conectarse-al-vps)
|
||
3. [Agregar `pedrito` al grupo docker](#3-agregar-pedrito-al-grupo-docker)
|
||
|
||
**PARTE B — Código y configuración**
|
||
4. [Clonar el repositorio](#4-clonar-el-repositorio)
|
||
5. [Configurar el archivo .env](#5-configurar-el-archivo-env)
|
||
6. [Cifrar las credenciales del PJ](#6-cifrar-las-credenciales-del-pj)
|
||
|
||
**PARTE C — HTTPS y producción**
|
||
7. [Obtener certificado SSL con Certbot](#7-obtener-certificado-ssl-con-certbot)
|
||
8. [Configurar Nginx como reverse proxy](#8-configurar-nginx-como-reverse-proxy)
|
||
9. [Configurar el firewall](#9-configurar-el-firewall)
|
||
10. [Iniciar el bot con Docker](#10-iniciar-el-bot-con-docker)
|
||
11. [Activar el modo webhook](#11-activar-el-modo-webhook)
|
||
|
||
**PARTE D — Operación**
|
||
12. [Verificación final](#12-verificación-final)
|
||
13. [Monitoreo y logs](#13-monitoreo-y-logs)
|
||
14. [Health check HTTP](#14-health-check-http)
|
||
15. [Cómo actualizar el bot](#15-cómo-actualizar-el-bot)
|
||
16. [Troubleshooting](#16-troubleshooting)
|
||
17. [Referencia rápida de comandos](#17-referencia-rápida-de-comandos)
|
||
|
||
---
|
||
|
||
## 1. Datos que necesitás antes de empezar
|
||
|
||
Antes de conectarte al VPS, juntá estos datos. Sin alguno de ellos el deploy no puede completarse.
|
||
|
||
| # | Dato | Quién lo tiene | Dónde va |
|
||
|---|------|---------------|----------|
|
||
| 1 | `FERNET_KEY` (clave de cifrado) | Marcos la genera | `.env` |
|
||
| 2 | `TELEGRAM_BOT_TOKEN` | Marcos (de @BotFather) | `.env` |
|
||
| 3 | `TELEGRAM_CHAT_ID` | Marcos (de @userinfobot) | `.env` |
|
||
| 4 | `TELEGRAM_EXTRA_IDS` | Marcos (chat IDs de otros abogados) | `.env` |
|
||
| 5 | `INVITE_CODE` | Marcos lo decide | `.env` |
|
||
| 6 | Cédula del PJ | Marcos | Script de cifrado (paso 6) |
|
||
| 7 | Contraseña del PJ | Marcos | Script de cifrado (paso 6) |
|
||
|
||
> **Tip:** Pedile a Marcos que te envíe los datos 1-5 por un canal seguro (Signal, Bitwarden Send, etc.).
|
||
> Nunca por email ni WhatsApp.
|
||
|
||
> ⚠️ **Seguridad crítica:** Nunca guardés la contraseña del PJ (dato 7) en ningún archivo.
|
||
> El script del paso 6 la pide en pantalla y guarda solo el resultado cifrado.
|
||
|
||
---
|
||
|
||
## 2. Conectarse al VPS
|
||
|
||
```bash
|
||
ssh root@93.127.136.210
|
||
```
|
||
|
||
Si tenés clave SSH configurada en Hostinger:
|
||
```bash
|
||
ssh -i ~/.ssh/id_rsa root@93.127.136.210
|
||
```
|
||
|
||
> Si es la primera conexión, escribí `yes` cuando pregunte por el fingerprint.
|
||
|
||
---
|
||
|
||
## 3. Agregar `pedrito` al grupo docker
|
||
|
||
El usuario `pedrito` existe pero no está en el grupo `docker`. Sin esto no puede correr contenedores.
|
||
|
||
```bash
|
||
# Como root:
|
||
usermod -aG docker pedrito
|
||
|
||
# Verificar que se agregó:
|
||
groups pedrito
|
||
# Debe incluir "docker" en la lista
|
||
```
|
||
|
||
> **Importante:** Este cambio toma efecto en la **próxima sesión SSH** de `pedrito`.
|
||
> Si ya tenés una sesión abierta como `pedrito`, cerrala y volvé a abrir.
|
||
|
||
---
|
||
|
||
## 4. Clonar el repositorio
|
||
|
||
```bash
|
||
# Cambiar al usuario pedrito
|
||
su - pedrito
|
||
|
||
# Verificar que estamos en su home
|
||
pwd
|
||
# Debe mostrar: /home/pedrito
|
||
|
||
# Clonar el repositorio
|
||
git clone https://github.com/InqGit/hechakuaa_bot.git
|
||
|
||
# Entrar al directorio
|
||
cd hechakuaa_bot
|
||
|
||
# Verificar que los archivos están presentes
|
||
ls -la
|
||
```
|
||
|
||
Deberías ver: `main.py`, `config.py`, `Dockerfile`, `docker-compose.yml`, `migrations/`, etc.
|
||
|
||
### Crear el directorio de datos
|
||
|
||
```bash
|
||
mkdir -p /home/pedrito/hechakuaa_bot/data
|
||
```
|
||
|
||
Salir a root para el siguiente paso:
|
||
```bash
|
||
exit
|
||
```
|
||
|
||
### Ajustar permisos del directorio data para Docker
|
||
|
||
El contenedor corre con UID 1000. El directorio `data/` necesita ser escribible por ese UID:
|
||
|
||
```bash
|
||
# Como root:
|
||
chown -R 1000:1000 /home/pedrito/hechakuaa_bot/data
|
||
|
||
# Verificar:
|
||
ls -la /home/pedrito/hechakuaa_bot/
|
||
# data debe mostrar: drwxr-xr-x 2 1000 1000
|
||
```
|
||
|
||
---
|
||
|
||
## 5. Configurar el archivo .env
|
||
|
||
```bash
|
||
# Como pedrito:
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
|
||
# Crear .env a partir del template
|
||
cp .env.example .env
|
||
|
||
# Editar
|
||
nano .env
|
||
```
|
||
|
||
### Guía de campos del .env
|
||
|
||
Completá los campos marcados con `← COMPLETAR`:
|
||
|
||
```bash
|
||
# ── CIFRADO ──────────────────────────────────────────────────────────────────
|
||
FERNET_KEY= # ← COMPLETAR (Marcos te la da o la generás abajo)
|
||
|
||
# ── CREDENCIALES PJ (se completan en el paso 6) ───────────────────────────────
|
||
PJ_USUARIO_ENC= # ← se completa automáticamente con el script
|
||
PJ_PASSWORD_ENC= # ← se completa automáticamente con el script
|
||
|
||
# ── TELEGRAM ─────────────────────────────────────────────────────────────────
|
||
TELEGRAM_BOT_TOKEN= # ← COMPLETAR (de @BotFather)
|
||
TELEGRAM_CHAT_ID= # ← COMPLETAR (chat ID de Marcos)
|
||
TELEGRAM_EXTRA_IDS= # ← COMPLETAR si hay más abogados (ej: 111222333,444555666)
|
||
|
||
# ── INVITACIÓN ────────────────────────────────────────────────────────────────
|
||
INVITE_CODE= # ← COMPLETAR (código maestro ilimitado)
|
||
|
||
# ── WEBHOOK (completar después del paso 11) ───────────────────────────────────
|
||
WEBHOOK_URL= # ← dejar vacío por ahora
|
||
WEBHOOK_SECRET= # ← dejar vacío por ahora
|
||
|
||
# ── HEALTH CHECK ─────────────────────────────────────────────────────────────
|
||
HEALTH_PORT=8080 # dejar así
|
||
HEALTH_ALERT_HOURS=2
|
||
HEALTH_AUTH_TOKEN= # ← COMPLETAR: python3 -c "import secrets; print(secrets.token_hex(32))"
|
||
|
||
# ── POLLING ──────────────────────────────────────────────────────────────────
|
||
POLL_INTERVAL_MINUTES=60
|
||
POLL_HORA_INICIO=7
|
||
POLL_HORA_FIN=18
|
||
```
|
||
|
||
Guardar y salir: `Ctrl+O` → `Enter` → `Ctrl+X`.
|
||
|
||
### Generar FERNET_KEY (si Marcos no te la dio)
|
||
|
||
```bash
|
||
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
||
```
|
||
|
||
> ⚠️ **Guardá la FERNET_KEY en un gestor de contraseñas (Bitwarden, 1Password, etc.).**
|
||
> Si se pierde, las credenciales cifradas de todos los abogados quedan irrecuperables.
|
||
|
||
### Instalar uv (si no está disponible)
|
||
|
||
```bash
|
||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||
source $HOME/.local/bin/env
|
||
uv --version
|
||
```
|
||
|
||
### Restringir permisos del .env
|
||
|
||
```bash
|
||
chmod 600 /home/pedrito/hechakuaa_bot/.env
|
||
|
||
# Verificar:
|
||
ls -la /home/pedrito/hechakuaa_bot/.env
|
||
# Debe mostrar: -rw------- 1 pedrito pedrito
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Cifrar las credenciales del PJ
|
||
|
||
```bash
|
||
# Como pedrito, en el directorio del proyecto:
|
||
cd /home/pedrito/hechakuaa_bot
|
||
uv run python scripts/cifrar_credenciales.py
|
||
```
|
||
|
||
El script pide:
|
||
1. **Cédula de identidad** — el número con el que Marcos entra a `apps.csj.gov.py`
|
||
2. **Contraseña** — no se muestra mientras escribís
|
||
|
||
Salida esperada:
|
||
```
|
||
✅ Credenciales cifradas y guardadas en .env
|
||
PJ_USUARIO_ENC y PJ_PASSWORD_ENC actualizadas.
|
||
```
|
||
|
||
Verificar:
|
||
```bash
|
||
grep "PJ_USUARIO_ENC" /home/pedrito/hechakuaa_bot/.env
|
||
# Debe mostrar un token cifrado largo, NUNCA la cédula en texto plano
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Obtener certificado SSL con Certbot
|
||
|
||
HTTPS es obligatorio para el modo webhook de Telegram.
|
||
|
||
> **Prerequisito:** el DNS ya está propagado (verificado: `pedrito.inqualityhq.com` → 93.127.136.210).
|
||
|
||
```bash
|
||
# Como root:
|
||
exit # salir de pedrito si estabas ahí
|
||
|
||
# Instalar Certbot con plugin de Nginx
|
||
apt install -y certbot python3-certbot-nginx
|
||
|
||
# Obtener el certificado
|
||
certbot --nginx -d pedrito.inqualityhq.com
|
||
```
|
||
|
||
Certbot te va a preguntar:
|
||
1. Tu dirección de email (para avisos de vencimiento)
|
||
2. Aceptar los términos de servicio → `Y`
|
||
3. Compartir email con EFF → `N`
|
||
|
||
Salida esperada al terminar:
|
||
```
|
||
Successfully received certificate.
|
||
Certificate is saved at: /etc/letsencrypt/live/pedrito.inqualityhq.com/fullchain.pem
|
||
Key is saved at: /etc/letsencrypt/live/pedrito.inqualityhq.com/privkey.pem
|
||
```
|
||
|
||
### Verificar renovación automática
|
||
|
||
```bash
|
||
systemctl status certbot.timer
|
||
# Debe estar "active (waiting)"
|
||
|
||
certbot renew --dry-run
|
||
# Debe decir: "Simulating renewal of an existing certificate..."
|
||
```
|
||
|
||
---
|
||
|
||
## 8. Configurar Nginx como reverse proxy
|
||
|
||
Nginx recibe las conexiones HTTPS y las redirige al bot en el puerto 8080.
|
||
|
||
```bash
|
||
# Como root:
|
||
nano /etc/nginx/sites-available/pedrito
|
||
```
|
||
|
||
Pegar **exactamente** este contenido:
|
||
|
||
```nginx
|
||
# /etc/nginx/sites-available/pedrito
|
||
limit_req_zone $binary_remote_addr zone=pedrito_webhook:10m rate=30r/s;
|
||
limit_req_zone $binary_remote_addr zone=pedrito_health:10m rate=10r/m;
|
||
|
||
server {
|
||
listen 80;
|
||
server_name pedrito.inqualityhq.com;
|
||
return 301 https://$server_name$request_uri;
|
||
}
|
||
|
||
server {
|
||
listen 443 ssl;
|
||
server_name pedrito.inqualityhq.com;
|
||
|
||
ssl_certificate /etc/letsencrypt/live/pedrito.inqualityhq.com/fullchain.pem;
|
||
ssl_certificate_key /etc/letsencrypt/live/pedrito.inqualityhq.com/privkey.pem;
|
||
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||
|
||
server_tokens off;
|
||
add_header X-Content-Type-Options nosniff;
|
||
add_header X-Frame-Options DENY;
|
||
|
||
client_max_body_size 20M;
|
||
|
||
location /health {
|
||
limit_req zone=pedrito_health burst=5 nodelay;
|
||
proxy_pass http://127.0.0.1:8080/health;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_read_timeout 10s;
|
||
}
|
||
|
||
location /health/history {
|
||
limit_req zone=pedrito_health burst=3 nodelay;
|
||
proxy_pass http://127.0.0.1:8080/health/history;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header Authorization $http_authorization;
|
||
proxy_read_timeout 10s;
|
||
}
|
||
|
||
location /webhook {
|
||
limit_req zone=pedrito_webhook burst=50 nodelay;
|
||
proxy_pass http://127.0.0.1:8080/webhook;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
proxy_set_header X-Telegram-Bot-Api-Secret-Token $http_x_telegram_bot_api_secret_token;
|
||
proxy_read_timeout 30s;
|
||
}
|
||
|
||
location / {
|
||
return 404;
|
||
}
|
||
}
|
||
```
|
||
|
||
Guardar: `Ctrl+O` → `Enter` → `Ctrl+X`.
|
||
|
||
```bash
|
||
# Activar el sitio
|
||
ln -s /etc/nginx/sites-available/pedrito /etc/nginx/sites-enabled/pedrito
|
||
|
||
# Verificar sintaxis
|
||
nginx -t
|
||
# Debe decir: syntax is ok / test is successful
|
||
|
||
# Recargar Nginx
|
||
systemctl reload nginx
|
||
```
|
||
|
||
> **Si `nginx -t` falla:** revisá que las comillas y los `;` estén correctos en el archivo.
|
||
|
||
---
|
||
|
||
## 9. Configurar el firewall
|
||
|
||
```bash
|
||
# Como root — verificar estado actual
|
||
ufw status
|
||
```
|
||
|
||
Si dice `Status: inactive` o no tiene las reglas necesarias:
|
||
|
||
```bash
|
||
ufw allow OpenSSH
|
||
ufw allow 'Nginx Full' # puertos 80 y 443
|
||
ufw --force enable
|
||
|
||
ufw status
|
||
```
|
||
|
||
Salida esperada:
|
||
```
|
||
Status: active
|
||
|
||
To Action From
|
||
-- ------ ----
|
||
OpenSSH ALLOW Anywhere
|
||
Nginx Full ALLOW Anywhere
|
||
```
|
||
|
||
> **Importante:** El puerto 8080 del bot **no** se abre al exterior. Solo Nginx accede a él
|
||
> internamente desde el mismo servidor.
|
||
|
||
---
|
||
|
||
## 10. Iniciar el bot con Docker
|
||
|
||
### Verificar que docker-compose.yml usa binding correcto
|
||
|
||
```bash
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
grep "8080" docker-compose.yml
|
||
```
|
||
|
||
Debe mostrar `127.0.0.1:8080:8080`. Si muestra solo `8080:8080`:
|
||
|
||
```bash
|
||
nano docker-compose.yml
|
||
# Cambiar "8080:8080" por "127.0.0.1:8080:8080"
|
||
```
|
||
|
||
### Construir la imagen
|
||
|
||
```bash
|
||
docker compose build
|
||
# Tarda 1-3 minutos la primera vez
|
||
```
|
||
|
||
### Primera prueba: correr en primer plano
|
||
|
||
```bash
|
||
docker compose up
|
||
```
|
||
|
||
Deberías ver:
|
||
```
|
||
pedrito-1 | {"event": "migration_aplicada", "version": "001_initial_schema", ...}
|
||
pedrito-1 | {"event": "database_iniciada", ...}
|
||
pedrito-1 | {"event": "health_server_iniciado", "port": 8080, ...}
|
||
pedrito-1 | {"event": "bot_telegram_iniciado", ...}
|
||
pedrito-1 | {"event": "login_exitoso", ...}
|
||
```
|
||
|
||
Si aparece `login_exitoso`, el bot se conectó al PJ correctamente. Detenerlo con `Ctrl+C`.
|
||
|
||
> **Si no aparece `login_exitoso`:** ver [Troubleshooting](#16-troubleshooting).
|
||
|
||
### Correr en background (modo producción)
|
||
|
||
```bash
|
||
docker compose up -d
|
||
|
||
# Verificar que está corriendo:
|
||
docker compose ps
|
||
# STATUS debe decir "running"
|
||
```
|
||
|
||
---
|
||
|
||
## 11. Activar el modo webhook
|
||
|
||
### Generar el WEBHOOK_SECRET
|
||
|
||
```bash
|
||
python3 -c "import secrets; print(secrets.token_hex(32))"
|
||
# Salida: 64 caracteres hexadecimales — copiarlos
|
||
```
|
||
|
||
### Actualizar .env
|
||
|
||
```bash
|
||
nano /home/pedrito/hechakuaa_bot/.env
|
||
```
|
||
|
||
Completar estas dos líneas:
|
||
```bash
|
||
WEBHOOK_URL=https://pedrito.inqualityhq.com
|
||
WEBHOOK_SECRET=<el token que generaste arriba>
|
||
```
|
||
|
||
### Reiniciar el bot
|
||
|
||
```bash
|
||
cd /home/pedrito/hechakuaa_bot
|
||
docker compose restart
|
||
|
||
docker compose logs --tail=20
|
||
# Buscar: {"event": "webhook_registrado", "url": "https://pedrito.inqualityhq.com/webhook", ...}
|
||
```
|
||
|
||
### Verificar que el webhook quedó registrado en Telegram
|
||
|
||
```bash
|
||
curl -s "https://api.telegram.org/bot<TU_BOT_TOKEN>/getWebhookInfo" | python3 -m json.tool
|
||
```
|
||
|
||
El campo `url` debe mostrar `https://pedrito.inqualityhq.com/webhook`.
|
||
|
||
---
|
||
|
||
## 12. Verificación final
|
||
|
||
```bash
|
||
# 1. El contenedor está corriendo
|
||
docker compose ps
|
||
# STATUS: running
|
||
|
||
# 2. Logs sin errores
|
||
docker compose logs --tail=30
|
||
# Buscar "login_exitoso" — NO debe aparecer: ERROR, exception, Traceback
|
||
|
||
# 3. Health check responde
|
||
curl -s https://pedrito.inqualityhq.com/health | python3 -m json.tool
|
||
# {"status": "ok", ...}
|
||
|
||
# 4. Webhook registrado
|
||
curl -s "https://api.telegram.org/bot<TU_BOT_TOKEN>/getWebhookInfo" | python3 -m json.tool
|
||
# url: https://pedrito.inqualityhq.com/webhook
|
||
|
||
# 5. Permisos del .env
|
||
ls -la /home/pedrito/hechakuaa_bot/.env
|
||
# -rw------- 1 pedrito pedrito
|
||
|
||
# 6. Directorio data existe
|
||
ls -la /home/pedrito/hechakuaa_bot/data/
|
||
# pasante.db y snapshot_*.json
|
||
|
||
# 7. HTTP redirige a HTTPS
|
||
curl -I http://pedrito.inqualityhq.com/health
|
||
# HTTP/1.1 301 Moved Permanently
|
||
```
|
||
|
||
Si todos pasan, avisarle a Marcos para que pruebe con `/start` en Telegram.
|
||
|
||
---
|
||
|
||
## 13. Monitoreo y logs
|
||
|
||
```bash
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
|
||
# Logs en tiempo real
|
||
docker compose logs -f
|
||
|
||
# Últimos 50 registros
|
||
docker compose logs --tail=50
|
||
```
|
||
|
||
### Logs de Nginx
|
||
|
||
```bash
|
||
# Como root:
|
||
tail -f /var/log/nginx/access.log
|
||
tail -f /var/log/nginx/error.log
|
||
```
|
||
|
||
### Eventos clave en los logs del bot
|
||
|
||
| Evento | Qué significa |
|
||
|--------|---------------|
|
||
| `login_exitoso` | Conectó al PJ correctamente |
|
||
| `polling_tenant_ok` | Revisión completada sin errores |
|
||
| `polling_tenant_error` | Error al revisar notificaciones |
|
||
| `bot_notificacion_enviada` | Notificación enviada a Telegram |
|
||
| `onboarding_completado` | Un abogado completó el registro |
|
||
| `health_alerta_enviada` | El poller está detenido — alerta al admin |
|
||
| `webhook_registrado` | Webhook activo con Telegram |
|
||
|
||
---
|
||
|
||
## 14. Health check HTTP
|
||
|
||
El bot expone `https://pedrito.inqualityhq.com/health`.
|
||
|
||
```bash
|
||
# Sin auth — respuesta mínima pública:
|
||
curl -s https://pedrito.inqualityhq.com/health | python3 -m json.tool
|
||
# {"status": "ok", "timestamp": "..."}
|
||
|
||
# Con auth — respuesta completa (reemplazá TOKEN):
|
||
curl -s -H "Authorization: Bearer <HEALTH_AUTH_TOKEN>" \
|
||
https://pedrito.inqualityhq.com/health/history | python3 -m json.tool
|
||
```
|
||
|
||
Si el poller no actualizó en más de `HEALTH_ALERT_HOURS` horas, retorna `"status": "degraded"`
|
||
y el bot manda una alerta automática al Telegram de Marcos.
|
||
|
||
### Monitor externo (opcional)
|
||
|
||
- URL: `https://pedrito.inqualityhq.com/health`
|
||
- Método: `GET` — código esperado: `200` — intervalo: 5 minutos
|
||
|
||
---
|
||
|
||
## 15. Cómo actualizar el bot
|
||
|
||
```bash
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
|
||
git pull
|
||
docker compose build
|
||
docker compose up -d
|
||
|
||
docker compose ps
|
||
docker compose logs --tail=20
|
||
```
|
||
|
||
> `.env` y `data/` no se tocan con `git pull` — están en `.gitignore`.
|
||
|
||
> **Si hubo cambios en `.env.example`:**
|
||
> ```bash
|
||
> diff .env.example .env
|
||
> ```
|
||
|
||
### Migración de credenciales vault v3 (solo al actualizar desde versiones < v0.4.0)
|
||
|
||
Si había abogados registrados antes de v0.4.0, migrar sus credenciales **antes** del restart:
|
||
|
||
```bash
|
||
docker compose run --rm pedrito uv run python scripts/migrar_vault_v3.py --dry-run
|
||
# Verificar output, luego:
|
||
docker compose run --rm pedrito uv run python scripts/migrar_vault_v3.py
|
||
```
|
||
|
||
---
|
||
|
||
## 16. Troubleshooting
|
||
|
||
### El contenedor no arranca
|
||
|
||
```bash
|
||
docker compose logs --tail=50
|
||
docker compose ps
|
||
```
|
||
|
||
**`FERNET_KEY inválida`** — la clave en `.env` tiene espacios o comillas. Verificar el valor.
|
||
|
||
**`telegram.error.InvalidToken`** — el `TELEGRAM_BOT_TOKEN` tiene un error. Recopiarlo de @BotFather.
|
||
|
||
**`ModuleNotFoundError`** — reconstruir la imagen:
|
||
```bash
|
||
docker compose build --no-cache && docker compose up -d
|
||
```
|
||
|
||
---
|
||
|
||
### El bot arranca pero no responde en Telegram
|
||
|
||
1. `docker compose ps` — ¿está corriendo?
|
||
2. `curl -s "https://api.telegram.org/bot<TOKEN>/getWebhookInfo"` — ¿el webhook está registrado?
|
||
3. `systemctl status nginx` — ¿Nginx está activo?
|
||
4. `curl -s https://pedrito.inqualityhq.com/health` — ¿el health responde?
|
||
5. `tail -20 /var/log/nginx/error.log` — ¿hay errores en Nginx?
|
||
|
||
---
|
||
|
||
### Error de credenciales del PJ
|
||
|
||
```bash
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
uv run python scripts/cifrar_credenciales.py
|
||
docker compose restart
|
||
docker compose logs --tail=10
|
||
```
|
||
|
||
---
|
||
|
||
### El certificado SSL venció
|
||
|
||
```bash
|
||
certbot renew
|
||
systemctl reload nginx
|
||
```
|
||
|
||
---
|
||
|
||
### El VPS se reinició y el bot no volvió
|
||
|
||
```bash
|
||
# El contenedor tiene restart: unless-stopped — debería volver solo.
|
||
# Si no:
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
docker compose up -d
|
||
```
|
||
|
||
---
|
||
|
||
### Error de permisos en data/
|
||
|
||
```bash
|
||
# Como root:
|
||
chown -R 1000:1000 /home/pedrito/hechakuaa_bot/data
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
docker compose restart
|
||
```
|
||
|
||
---
|
||
|
||
## 17. Referencia rápida de comandos
|
||
|
||
### Gestión del bot (como `pedrito`)
|
||
|
||
```bash
|
||
cd /home/pedrito/hechakuaa_bot
|
||
|
||
docker compose ps # estado
|
||
docker compose up -d # iniciar
|
||
docker compose down # detener
|
||
docker compose restart # reiniciar
|
||
docker compose logs -f # logs en tiempo real
|
||
docker compose logs --tail=50 # últimos 50 registros
|
||
|
||
# Actualización rápida:
|
||
git pull && docker compose build && docker compose up -d
|
||
```
|
||
|
||
### Nginx (como `root`)
|
||
|
||
```bash
|
||
nginx -t # verificar configuración
|
||
systemctl reload nginx # recargar sin cortar conexiones
|
||
systemctl restart nginx # reiniciar completamente
|
||
tail -f /var/log/nginx/error.log
|
||
```
|
||
|
||
### SSL
|
||
|
||
```bash
|
||
certbot renew # renovar manualmente
|
||
certbot certificates # ver fecha de vencimiento
|
||
```
|
||
|
||
### Rutas de archivos importantes
|
||
|
||
| Archivo | Ruta absoluta |
|
||
|---------|---------------|
|
||
| Código del bot | `/home/pedrito/hechakuaa_bot/` |
|
||
| Configuración | `/home/pedrito/hechakuaa_bot/.env` |
|
||
| Base de datos | `/home/pedrito/hechakuaa_bot/data/pasante.db` |
|
||
| Snapshots | `/home/pedrito/hechakuaa_bot/data/snapshot_*.json` |
|
||
| Docker Compose | `/home/pedrito/hechakuaa_bot/docker-compose.yml` |
|
||
| Config Nginx | `/etc/nginx/sites-available/pedrito` |
|
||
| Logs Nginx | `/var/log/nginx/` |
|
||
| Certificado SSL | `/etc/letsencrypt/live/pedrito.inqualityhq.com/` |
|
||
|
||
---
|
||
|
||
*Ante dudas técnicas, contactar a Marcos Benítez.*
|