Agrega nota en sección 18 de DEPLOY.md sobre correr migrar_vault_v3.py al actualizar desde versiones anteriores a v0.4.0 con tenants existentes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1298 lines
38 KiB
Markdown
1298 lines
38 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:** 60–90 minutos (primera vez)
|
||
> **Acceso requerido:** SSH root al VPS + datos de configuración provistos por Marcos
|
||
> **Subdominio objetivo:** `pedrito.inqualityhq.com`
|
||
|
||
---
|
||
|
||
## Índice
|
||
|
||
**PARTE A — Preparación (antes de tocar el servidor)**
|
||
1. [Datos que necesitás antes de empezar](#1-datos-que-necesitás-antes-de-empezar)
|
||
2. [Configurar DNS en Bluehost](#2-configurar-dns-en-bluehost)
|
||
|
||
**PARTE B — Servidor: base**
|
||
3. [Conectarse al VPS](#3-conectarse-al-vps)
|
||
4. [Actualizar el sistema y crear usuario](#4-actualizar-el-sistema-y-crear-usuario)
|
||
5. [Instalar Docker](#5-instalar-docker)
|
||
6. [Instalar Nginx](#6-instalar-nginx)
|
||
7. [Clonar el repositorio](#7-clonar-el-repositorio)
|
||
8. [Configurar el archivo .env](#8-configurar-el-archivo-env)
|
||
9. [Cifrar las credenciales del PJ](#9-cifrar-las-credenciales-del-pj)
|
||
|
||
**PARTE C — HTTPS y producción**
|
||
10. [Obtener certificado SSL con Certbot](#10-obtener-certificado-ssl-con-certbot)
|
||
11. [Configurar Nginx como reverse proxy](#11-configurar-nginx-como-reverse-proxy)
|
||
12. [Configurar el firewall](#12-configurar-el-firewall)
|
||
13. [Iniciar el bot con Docker](#13-iniciar-el-bot-con-docker)
|
||
14. [Activar el modo webhook](#14-activar-el-modo-webhook)
|
||
|
||
**PARTE D — Operación**
|
||
15. [Verificación final](#15-verificación-final)
|
||
16. [Monitoreo y logs](#16-monitoreo-y-logs)
|
||
17. [Health check HTTP](#17-health-check-http)
|
||
18. [Cómo actualizar el bot](#18-cómo-actualizar-el-bot)
|
||
19. [Troubleshooting](#19-troubleshooting)
|
||
20. [Referencia rápida de comandos](#20-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, separados por coma) | `.env` |
|
||
| 5 | `INVITE_CODE` | Marcos lo decide | `.env` |
|
||
| 6 | Cédula del PJ | Marcos | Script de cifrado |
|
||
| 7 | Contraseña del PJ | Marcos | Script de cifrado |
|
||
| 8 | IP pública del VPS | Panel de Hostinger | DNS + SSH |
|
||
| 9 | Credenciales SSH del VPS | Panel de Hostinger | Terminal |
|
||
|
||
> **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, chat,
|
||
> nota, ni Post-it. El script del paso 9 la pide en pantalla, la descarta de memoria y guarda
|
||
> solo el resultado cifrado. Una vez que el script termina exitosamente, podés olvidarla.
|
||
|
||
---
|
||
|
||
## 2. Configurar DNS en Bluehost
|
||
|
||
El bot va a ser accesible en `pedrito.inqualityhq.com`. Para eso necesitamos apuntar ese
|
||
subdominio a la IP del VPS con un registro DNS tipo A.
|
||
|
||
**Necesitás:** La IP pública del VPS (Panel de Hostinger → tu VPS → ver IP).
|
||
|
||
---
|
||
|
||
### Opción A: Hacerlo vos mismo en Bluehost cPanel
|
||
|
||
1. Entrá a [bluehost.com](https://www.bluehost.com) con las credenciales de InQuality
|
||
2. En el panel, buscá **"cPanel"** y hacé click
|
||
3. Dentro de cPanel, en la sección **"Domains"**, hacé click en **"Zone Editor"**
|
||
(también puede aparecer como **"DNS Zone Editor"** o **"Advanced DNS Editor"**)
|
||
4. Buscá `inqualityhq.com` en la lista y hacé click en **"Manage"**
|
||
5. Hacé click en **"Add Record"**
|
||
6. Completá el formulario así:
|
||
|
||
| Campo | Valor |
|
||
|-------|-------|
|
||
| **Name** (o Host) | `pedrito` |
|
||
| **Type** | `A` |
|
||
| **TTL** | `300` (o el mínimo disponible) |
|
||
| **Value** (o Points To) | `<IP_DE_TU_VPS>` |
|
||
|
||
7. Hacé click en **"Save"** o **"Add Record"**
|
||
|
||
8. Para verificar que se propagó (puede tardar de 5 minutos a 2 horas):
|
||
```bash
|
||
# Desde tu computadora local
|
||
nslookup pedrito.inqualityhq.com
|
||
# Debe mostrar la IP del VPS en la respuesta
|
||
|
||
# O también:
|
||
dig pedrito.inqualityhq.com A +short
|
||
# Debe retornar solo la IP del VPS
|
||
```
|
||
|
||
> **Tip:** Si `nslookup` aún no muestra la IP, esperá 10-15 minutos y volvé a intentar.
|
||
> La propagación en Bluehost suele ser rápida, pero a veces tarda más.
|
||
|
||
---
|
||
|
||
### Opción B: Mensaje exacto para pedirle a un asistente de Bluehost (en inglés)
|
||
|
||
Si necesitás que un asistente del equipo (que tenga acceso al cPanel de Bluehost) lo haga por vos,
|
||
podés enviarle exactamente este mensaje:
|
||
|
||
---
|
||
|
||
> Hi,
|
||
>
|
||
> I need to add a DNS A record to the `inqualityhq.com` domain managed through Bluehost cPanel.
|
||
> Could you please add the following record?
|
||
>
|
||
> - **Domain:** inqualityhq.com
|
||
> - **Record type:** A
|
||
> - **Host/Name:** pedrito *(this will create pedrito.inqualityhq.com)*
|
||
> - **Value/Points to:** `<IP_DEL_VPS>` *(replace with the actual VPS IP)*
|
||
> - **TTL:** 300 seconds (minimum available)
|
||
>
|
||
> Once added, please confirm so I can verify propagation.
|
||
> If you need me to confirm with the account holder, let me know.
|
||
>
|
||
> Thank you!
|
||
|
||
---
|
||
|
||
Reemplazá `<IP_DEL_VPS>` con la IP real del VPS antes de enviar el mensaje.
|
||
|
||
---
|
||
|
||
## 3. Conectarse al VPS
|
||
|
||
Desde tu computadora local, abrí una terminal:
|
||
|
||
```bash
|
||
ssh root@<IP_DE_LA_VPS>
|
||
```
|
||
|
||
Si tenés clave SSH configurada en Hostinger (recomendado):
|
||
```bash
|
||
ssh -i ~/.ssh/id_rsa root@<IP_DE_LA_VPS>
|
||
```
|
||
|
||
Si te pide contraseña, es la del panel de Hostinger.
|
||
|
||
> **Tip para Windows:** Usá [Windows Terminal](https://apps.microsoft.com/detail/9n0dx20hk701) o
|
||
> [PuTTY](https://www.putty.org/). En Windows Terminal el comando SSH es el mismo.
|
||
|
||
> **Tip:** Si es la primera conexión, va a preguntar:
|
||
> ```
|
||
> Are you sure you want to continue connecting (yes/no/[fingerprint])?
|
||
> ```
|
||
> Escribí `yes` y Enter.
|
||
|
||
---
|
||
|
||
## 4. Actualizar el sistema y crear usuario
|
||
|
||
Todos estos comandos se ejecutan como **root**.
|
||
|
||
### 4.1 Actualizar paquetes
|
||
|
||
```bash
|
||
apt update && apt upgrade -y
|
||
```
|
||
|
||
Esto puede tardar 2-5 minutos. Esperá que termine.
|
||
|
||
### 4.2 Verificar la versión de Ubuntu
|
||
|
||
```bash
|
||
lsb_release -a
|
||
```
|
||
Salida esperada: `Ubuntu 22.04.x LTS`. Si es otra versión, avisale a Marcos antes de continuar.
|
||
|
||
### 4.3 Crear el usuario `pedrito`
|
||
|
||
El bot no debe correr como root. Le creamos un usuario propio:
|
||
|
||
```bash
|
||
# Crear el usuario (sin contraseña de login interactivo)
|
||
adduser pedrito --disabled-password --gecos ""
|
||
|
||
# Verificar que se creó
|
||
id pedrito
|
||
```
|
||
|
||
Salida esperada:
|
||
```
|
||
uid=1001(pedrito) gid=1001(pedrito) groups=1001(pedrito)
|
||
```
|
||
|
||
> **¿Por qué UID 1001 y no 1000?** En Ubuntu el usuario 1000 suele ser el primer usuario
|
||
> creado durante la instalación. En un VPS de Hostinger puede o no existir.
|
||
> Lo importante es que `pedrito` tenga su propio UID.
|
||
|
||
### 4.4 Permitir que `pedrito` use Docker (sin sudo)
|
||
|
||
```bash
|
||
# Esto lo hacemos después de instalar Docker (paso 5), pero lo dejamos acá como referencia
|
||
# usermod -aG docker pedrito ← lo corremos en el paso 5.3
|
||
```
|
||
|
||
### 4.5 Configurar acceso SSH para `pedrito` (opcional pero recomendado)
|
||
|
||
```bash
|
||
mkdir -p /home/pedrito/.ssh
|
||
cp /root/.ssh/authorized_keys /home/pedrito/.ssh/
|
||
chown -R pedrito:pedrito /home/pedrito/.ssh
|
||
chmod 700 /home/pedrito/.ssh
|
||
chmod 600 /home/pedrito/.ssh/authorized_keys
|
||
```
|
||
|
||
Para verificar: en una segunda terminal, intentá `ssh pedrito@<IP>`. Si entra sin contraseña, perfecto.
|
||
|
||
---
|
||
|
||
## 5. Instalar Docker
|
||
|
||
Docker es el motor de contenedores que va a correr el bot de forma aislada y reproducible.
|
||
|
||
### 5.1 Instalar dependencias previas
|
||
|
||
```bash
|
||
apt install -y \
|
||
ca-certificates \
|
||
curl \
|
||
gnupg \
|
||
lsb-release
|
||
```
|
||
|
||
### 5.2 Agregar el repositorio oficial de Docker
|
||
|
||
```bash
|
||
# Crear directorio para las claves GPG
|
||
install -m 0755 -d /etc/apt/keyrings
|
||
|
||
# Descargar e instalar la clave GPG de Docker
|
||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
|
||
gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||
|
||
chmod a+r /etc/apt/keyrings/docker.gpg
|
||
|
||
# Agregar el repositorio
|
||
echo \
|
||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
|
||
https://download.docker.com/linux/ubuntu \
|
||
$(lsb_release -cs) stable" | \
|
||
tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||
|
||
# Actualizar lista de paquetes
|
||
apt update
|
||
```
|
||
|
||
### 5.3 Instalar Docker Engine y docker-compose
|
||
|
||
```bash
|
||
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||
|
||
# Verificar que Docker se instaló correctamente
|
||
docker --version
|
||
# Salida esperada: Docker version 24.x.x o mayor
|
||
|
||
docker compose version
|
||
# Salida esperada: Docker Compose version v2.x.x
|
||
```
|
||
|
||
### 5.4 Agregar a `pedrito` al grupo docker
|
||
|
||
```bash
|
||
# Esto permite que pedrito corra docker sin sudo
|
||
usermod -aG docker pedrito
|
||
|
||
# Verificar
|
||
groups pedrito
|
||
# Debe incluir "docker" en la lista
|
||
```
|
||
|
||
### 5.5 Verificar que Docker funciona
|
||
|
||
```bash
|
||
docker run --rm hello-world
|
||
```
|
||
|
||
Si imprime `Hello from Docker!`, Docker está funcionando.
|
||
|
||
> **¿Qué es un contenedor?** Pensalo como una "caja" cerrada que incluye el código del bot
|
||
> y todas sus dependencias. Si algo falla dentro de la caja, no afecta al resto del servidor.
|
||
> `docker compose up` abre la caja, `docker compose down` la cierra.
|
||
|
||
---
|
||
|
||
## 6. Instalar Nginx
|
||
|
||
Nginx actúa como intermediario entre internet y el bot. Recibe las conexiones HTTPS (puerto 443)
|
||
y las reenvía internamente al bot (puerto 8080). Esto permite tener SSL sin que el bot lo maneje.
|
||
|
||
```bash
|
||
# Instalar Nginx
|
||
apt install -y nginx
|
||
|
||
# Verificar que arrancó
|
||
systemctl status nginx
|
||
```
|
||
|
||
Salida esperada:
|
||
```
|
||
● nginx.service - A high performance web server and reverse proxy server
|
||
Active: active (running) since ...
|
||
```
|
||
|
||
Si dice `inactive`, arrancalo manualmente:
|
||
```bash
|
||
systemctl start nginx
|
||
systemctl enable nginx # para que arranque en cada reboot
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 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
|
||
# 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 archivos como: `main.py`, `config.py`, `telegram_bot.py`, `Dockerfile`,
|
||
`docker-compose.yml`, `migrations/`, etc.
|
||
|
||
### Crear el directorio de datos
|
||
|
||
```bash
|
||
# Este directorio persiste entre reinicios del bot (DB, snapshots)
|
||
mkdir -p /home/pedrito/hechakuaa_bot/data
|
||
```
|
||
|
||
Salir de vuelta a root para el siguiente paso:
|
||
```bash
|
||
exit
|
||
# Ahora estás como root de nuevo
|
||
```
|
||
|
||
### Ajustar permisos del directorio data para Docker
|
||
|
||
El contenedor Docker corre con usuario UID 1000. El directorio `data/` necesita
|
||
ser escribible por ese UID:
|
||
|
||
```bash
|
||
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 ... data
|
||
```
|
||
|
||
> **¿Por qué 1000 y no pedrito?** Dentro del contenedor Docker existe un usuario con UID 1000.
|
||
> El servidor no sabe que ese usuario se llama "pedrito" — solo entiende el número UID.
|
||
> En el sistema anfitrión, UID 1000 puede corresponder a un usuario diferente, pero Docker
|
||
> solo necesita que el directorio sea escribible por ese número.
|
||
|
||
---
|
||
|
||
## 8. Configurar el archivo .env
|
||
|
||
El archivo `.env` contiene toda la configuración sensible del bot. Se crea directamente en el VPS
|
||
y **nunca** se sube al repositorio ni se copia entre máquinas.
|
||
|
||
```bash
|
||
# Como pedrito:
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
|
||
# Crear .env a partir del template
|
||
cp .env.example .env
|
||
|
||
# Editar (nano es el editor más simple)
|
||
nano .env
|
||
```
|
||
|
||
### Guía de campos del .env
|
||
|
||
Completá los campos marcados con `← COMPLETAR`. Los demás se pueden dejar con sus valores por defecto:
|
||
|
||
```bash
|
||
# ── CIFRADO ──────────────────────────────────────────────────────────────────
|
||
FERNET_KEY= # ← COMPLETAR (Marcos te la da o la generás abajo)
|
||
|
||
# ── CREDENCIALES PJ (se completan en el paso 9) ───────────────────────────────
|
||
PJ_USUARIO_ENC= # ← se completa automáticamente con el script de cifrado
|
||
PJ_PASSWORD_ENC= # ← se completa automáticamente con el script de cifrado
|
||
|
||
# ── 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 14) ───────────────────────────────────
|
||
WEBHOOK_URL= # ← dejar vacío por ahora, completar en el paso 14
|
||
WEBHOOK_SECRET= # ← dejar vacío por ahora, completar en el paso 14
|
||
|
||
# ── HEALTH CHECK ─────────────────────────────────────────────────────────────
|
||
HEALTH_PORT=8080 # dejar así
|
||
HEALTH_ALERT_HOURS=2 # alerta al admin si el poller no actualizó en 2 horas
|
||
# Token para /health (detallado) y /health/history — generar con:
|
||
# python3 -c "import secrets; print(secrets.token_hex(32))"
|
||
HEALTH_AUTH_TOKEN= # ← COMPLETAR (recomendado)
|
||
|
||
# ── POLLING ──────────────────────────────────────────────────────────────────
|
||
POLL_INTERVAL_MINUTES=60 # revisar el PJ cada 60 minutos
|
||
POLL_HORA_INICIO=7 # desde las 7am (hora Paraguay)
|
||
POLL_HORA_FIN=18 # hasta las 6pm (hora Paraguay)
|
||
```
|
||
|
||
Guardar y salir de nano: `Ctrl+O` → `Enter` → `Ctrl+X`.
|
||
|
||
### Generar FERNET_KEY si Marcos no te la dio
|
||
|
||
```bash
|
||
# Generar una clave nueva (solo si no tenés una preexistente)
|
||
uv run python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
||
```
|
||
|
||
Salida esperada: una cadena de ~44 caracteres como `gAAAAABx3...`. Copiarla y pegarla en `.env`.
|
||
|
||
> ⚠️ **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 como pedrito)
|
||
|
||
```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
|
||
```
|
||
|
||
---
|
||
|
||
## 9. 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
|
||
# Como pedrito, dentro del directorio del proyecto:
|
||
cd /home/pedrito/hechakuaa_bot
|
||
uv run python scripts/cifrar_credenciales.py
|
||
```
|
||
|
||
El script te va a pedir:
|
||
1. **Cédula de identidad** — el número con el que Marcos entra a `apps.csj.gov.py`
|
||
2. **Contraseña** — la contraseña de ese sistema (no se muestra mientras escribís)
|
||
|
||
Salida esperada:
|
||
```
|
||
✅ Credenciales cifradas y guardadas en .env
|
||
PJ_USUARIO_ENC y PJ_PASSWORD_ENC actualizadas.
|
||
```
|
||
|
||
Verificar que se guardaron:
|
||
```bash
|
||
grep "PJ_USUARIO_ENC" /home/pedrito/hechakuaa_bot/.env
|
||
# Debe mostrar un valor cifrado largo, NUNCA la cédula en texto plano
|
||
```
|
||
|
||
---
|
||
|
||
## 10. Obtener certificado SSL con Certbot
|
||
|
||
HTTPS es obligatorio para el modo webhook de Telegram y para cualquier servicio expuesto
|
||
en producción. Certbot obtiene el certificado gratis de Let's Encrypt.
|
||
|
||
> **Prerequisito:** El DNS del paso 2 ya debe estar propagado. Verificalo:
|
||
> ```bash
|
||
> nslookup pedrito.inqualityhq.com
|
||
> # Debe retornar la IP de este VPS
|
||
> ```
|
||
> Si no retorna la IP correcta, esperá y volvé después.
|
||
|
||
### 10.1 Instalar Certbot
|
||
|
||
```bash
|
||
# Como root:
|
||
exit # si estabas como pedrito, volver a root
|
||
|
||
apt install -y certbot python3-certbot-nginx
|
||
```
|
||
|
||
### 10.2 Obtener el certificado
|
||
|
||
```bash
|
||
certbot --nginx -d pedrito.inqualityhq.com
|
||
```
|
||
|
||
Certbot te va a preguntar:
|
||
1. Tu dirección de email (para avisos de vencimiento) — ponés la de Marcos o la del equipo
|
||
2. Aceptar los términos de servicio → `Y`
|
||
3. Si querés compartir el email con EFF → `N` (opcional)
|
||
|
||
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
|
||
...
|
||
```
|
||
|
||
> **¿Por qué usamos --nginx?** Le decimos a Certbot que tenemos Nginx instalado y que puede
|
||
> configurar automáticamente el sitio para HTTPS. Pero vamos a sobreescribir esa configuración
|
||
> en el siguiente paso para personalizarla.
|
||
|
||
### 10.3 Verificar la renovación automática
|
||
|
||
Los certificados de Let's Encrypt duran 90 días y se renuevan automáticamente:
|
||
|
||
```bash
|
||
# Verificar que el timer de renovación automática existe
|
||
systemctl status certbot.timer
|
||
# Debe estar "active (waiting)"
|
||
|
||
# Simular una renovación para verificar que funciona
|
||
certbot renew --dry-run
|
||
# Debe decir: "Simulating renewal of an existing certificate..."
|
||
```
|
||
|
||
---
|
||
|
||
## 11. Configurar Nginx como reverse proxy
|
||
|
||
Nginx recibe las requests de internet y las redirige al bot corriendo en el contenedor Docker
|
||
(puerto 8080). También maneja el SSL automáticamente.
|
||
|
||
### 11.1 Crear el archivo de configuración
|
||
|
||
```bash
|
||
# Como root:
|
||
nano /etc/nginx/sites-available/pedrito
|
||
```
|
||
|
||
Pegar **exactamente** este contenido (reemplazá el nombre de dominio si usás uno diferente):
|
||
|
||
```nginx
|
||
# /etc/nginx/sites-available/pedrito
|
||
# Reverse proxy para Pedrito Hechakuaa
|
||
|
||
# ── Rate limiting ─────────────────────────────────────────────────────────────
|
||
# Limita requests por IP para mitigar escaneo automatizado y ataques de fuerza bruta.
|
||
# La zona se define fuera del bloque server (en el contexto http).
|
||
# Si tenés otros sites en este Nginx, mover estas líneas a /etc/nginx/nginx.conf
|
||
# dentro del bloque http { }.
|
||
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;
|
||
# Redirigir todo el tráfico HTTP a HTTPS
|
||
return 301 https://$server_name$request_uri;
|
||
}
|
||
|
||
server {
|
||
listen 443 ssl;
|
||
server_name pedrito.inqualityhq.com;
|
||
|
||
# Certificados SSL de Let's Encrypt
|
||
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;
|
||
|
||
# Seguridad: no exponer versión de Nginx ni headers informativos
|
||
server_tokens off;
|
||
add_header X-Content-Type-Options nosniff;
|
||
add_header X-Frame-Options DENY;
|
||
|
||
# Tamaño máximo de payload (Telegram puede enviar archivos)
|
||
client_max_body_size 20M;
|
||
|
||
# ── Health check ──────────────────────────────────────────────────────────
|
||
# /health es público (respuesta mínima sin datos sensibles)
|
||
# /health/history requiere Bearer token — el bot lo rechaza sin él
|
||
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;
|
||
# Pasar Authorization header para que el bot pueda validar el Bearer token
|
||
proxy_set_header Authorization $http_authorization;
|
||
proxy_read_timeout 10s;
|
||
}
|
||
|
||
# ── Webhook de Telegram ───────────────────────────────────────────────────
|
||
# Solo Telegram envía aquí — los IPs de Telegram son bien conocidos (149.154.x, 91.108.x)
|
||
# El bot valida el X-Telegram-Bot-Api-Secret-Token internamente
|
||
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;
|
||
}
|
||
|
||
# ── Denegar cualquier otra ruta ───────────────────────────────────────────
|
||
# Respuesta genérica — no revelar que hay un bot ni su propósito
|
||
location / {
|
||
return 404;
|
||
}
|
||
}
|
||
```
|
||
|
||
Guardar: `Ctrl+O` → `Enter` → `Ctrl+X`.
|
||
|
||
### 11.2 Activar el sitio
|
||
|
||
```bash
|
||
# Crear el enlace simbólico que activa el sitio
|
||
ln -s /etc/nginx/sites-available/pedrito /etc/nginx/sites-enabled/pedrito
|
||
|
||
# Verificar que no hay errores de sintaxis en la configuración
|
||
nginx -t
|
||
```
|
||
|
||
Salida esperada:
|
||
```
|
||
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
|
||
nginx: configuration file /etc/nginx/nginx.conf test is successful
|
||
```
|
||
|
||
Si hay errores, revisá que el archivo se pegó correctamente (especialmente las comillas y los `;`).
|
||
|
||
### 11.3 Recargar Nginx
|
||
|
||
```bash
|
||
systemctl reload nginx
|
||
systemctl status nginx
|
||
# Debe estar active (running)
|
||
```
|
||
|
||
### 11.4 Verificar que Nginx responde
|
||
|
||
```bash
|
||
# Desde el propio servidor:
|
||
curl -sk https://pedrito.inqualityhq.com/health
|
||
# Debe retornar un error de conexión rechazada (porque el bot no está corriendo aún)
|
||
# o un JSON si ya está corriendo
|
||
|
||
# Verificar que HTTP redirige a HTTPS:
|
||
curl -I http://pedrito.inqualityhq.com/health
|
||
# Debe retornar: HTTP/1.1 301 Moved Permanently
|
||
```
|
||
|
||
---
|
||
|
||
## 12. Configurar el firewall
|
||
|
||
```bash
|
||
# Como root
|
||
ufw allow OpenSSH
|
||
ufw allow 'Nginx Full' # abre puertos 80 (HTTP) y 443 (HTTPS)
|
||
ufw --force enable
|
||
|
||
# Verificar estado
|
||
ufw status
|
||
```
|
||
|
||
Salida esperada:
|
||
```
|
||
Status: active
|
||
|
||
To Action From
|
||
-- ------ ----
|
||
OpenSSH ALLOW Anywhere
|
||
Nginx Full ALLOW Anywhere
|
||
OpenSSH (v6) ALLOW Anywhere (v6)
|
||
Nginx Full (v6) ALLOW Anywhere (v6)
|
||
```
|
||
|
||
> **Importante:** El puerto 8080 del bot **no** se abre al exterior. Solo Nginx (que corre en el
|
||
> mismo servidor) se comunica con el bot internamente. El bot no es accesible directamente desde
|
||
> internet, solo a través de Nginx.
|
||
|
||
---
|
||
|
||
## 13. Iniciar el bot con Docker
|
||
|
||
### 13.1 Actualizar docker-compose.yml para producción
|
||
|
||
Por seguridad, el bot solo debe escuchar en localhost (no en todas las interfaces de red).
|
||
Modificá el puerto en docker-compose.yml:
|
||
|
||
```bash
|
||
# Como pedrito:
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
|
||
# Editar docker-compose.yml
|
||
nano docker-compose.yml
|
||
```
|
||
|
||
Buscá la línea:
|
||
```yaml
|
||
- "8080:8080"
|
||
```
|
||
|
||
Cambiala por:
|
||
```yaml
|
||
- "127.0.0.1:8080:8080"
|
||
```
|
||
|
||
Guardar y salir. Esto hace que el bot solo sea accesible desde el mismo servidor (por Nginx),
|
||
no desde internet.
|
||
|
||
### 13.2 Construir la imagen Docker
|
||
|
||
```bash
|
||
# Construir la imagen (tarda 1-3 minutos la primera vez)
|
||
docker compose build
|
||
|
||
# Salida esperada al final:
|
||
# => exporting to image
|
||
# => => naming to docker.io/library/hechakuaa_bot-pedrito
|
||
```
|
||
|
||
### 13.3 Primera prueba: correr en primer plano
|
||
|
||
Antes de dejarlo en background, verificamos que arranca bien:
|
||
|
||
```bash
|
||
docker compose up
|
||
```
|
||
|
||
Deberías ver logs como:
|
||
```
|
||
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": "pedrito_hechakuaa_corriendo", ...}
|
||
pedrito-1 | {"event": "poller_iniciado", ...}
|
||
pedrito-1 | {"event": "login_exitoso", ...}
|
||
```
|
||
|
||
Si aparece `login_exitoso`, el bot se conectó al PJ. Detenerlo con `Ctrl+C`.
|
||
|
||
> **Si no aparece `login_exitoso`:** ver la sección [Troubleshooting](#19-troubleshooting).
|
||
|
||
### 13.4 Correr en background (modo producción)
|
||
|
||
```bash
|
||
# Arrancar en modo detached (background)
|
||
docker compose up -d
|
||
|
||
# Verificar que el contenedor está corriendo
|
||
docker compose ps
|
||
```
|
||
|
||
Salida esperada:
|
||
```
|
||
NAME IMAGE COMMAND SERVICE STATUS PORTS
|
||
hechakuaa_bot-... hechakuaa_bot-pedrito "uv run python main.…" pedrito running 127.0.0.1:8080->8080/tcp
|
||
```
|
||
|
||
El `STATUS` debe decir `running`.
|
||
|
||
### 13.5 Configurar Docker para que arranque en cada reboot
|
||
|
||
```bash
|
||
# Como root:
|
||
exit # salir de pedrito
|
||
|
||
# El servicio de Docker ya inicia automáticamente
|
||
# Solo verificar que el contenedor tiene restart policy correcta
|
||
systemctl enable docker
|
||
```
|
||
|
||
El `docker-compose.yml` ya tiene `restart: unless-stopped`, lo que hace que el contenedor
|
||
se reinicie automáticamente si el VPS se reinicia.
|
||
|
||
---
|
||
|
||
## 14. Activar el modo webhook
|
||
|
||
En modo webhook, Telegram envía los mensajes al bot directamente (HTTPS push), en lugar de
|
||
que el bot los pida constantemente (polling). Es más eficiente y tiene menor latencia.
|
||
|
||
### 14.1 Generar el WEBHOOK_SECRET
|
||
|
||
Este token es como una contraseña que Telegram incluye en cada request para probar que es legítimo:
|
||
|
||
```bash
|
||
# Generar un token aleatorio seguro:
|
||
python3 -c "import secrets; print(secrets.token_hex(32))"
|
||
# Salida: una cadena de 64 caracteres hexadecimales
|
||
```
|
||
|
||
Copiar la salida. La vamos a usar en el siguiente paso.
|
||
|
||
### 14.2 Actualizar .env con los datos del webhook
|
||
|
||
```bash
|
||
su - pedrito
|
||
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>
|
||
```
|
||
|
||
Guardar y salir.
|
||
|
||
### 14.3 Reiniciar el bot para aplicar el cambio
|
||
|
||
```bash
|
||
cd /home/pedrito/hechakuaa_bot
|
||
docker compose restart
|
||
|
||
# Ver los logs para confirmar que el webhook se registró:
|
||
docker compose logs --tail=20
|
||
```
|
||
|
||
Buscar en los logs:
|
||
```
|
||
{"event": "webhook_registrado", "url": "https://pedrito.inqualityhq.com/webhook", ...}
|
||
```
|
||
|
||
### 14.4 Verificar que el webhook quedó registrado en Telegram
|
||
|
||
```bash
|
||
# Reemplazá TU_BOT_TOKEN con el valor real del .env
|
||
curl -s "https://api.telegram.org/bot<TU_BOT_TOKEN>/getWebhookInfo" | python3 -m json.tool
|
||
```
|
||
|
||
Salida esperada:
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"result": {
|
||
"url": "https://pedrito.inqualityhq.com/webhook",
|
||
"has_custom_certificate": false,
|
||
"pending_update_count": 0,
|
||
...
|
||
}
|
||
}
|
||
```
|
||
|
||
El campo `url` debe mostrar la URL correcta. Si está vacío o muestra otra URL, revisá los logs del bot.
|
||
|
||
---
|
||
|
||
## 15. Verificación final
|
||
|
||
Correr esta lista de verificaciones antes de dar el deploy por terminado:
|
||
|
||
```bash
|
||
# 1. El contenedor Docker está corriendo
|
||
docker compose ps
|
||
# STATUS debe ser "running"
|
||
|
||
# 2. Los logs no tienen errores
|
||
docker compose logs --tail=30
|
||
# Buscar "login_exitoso" y "pedrito_hechakuaa_corriendo"
|
||
# NO debe aparecer: ERROR, exception, Traceback
|
||
|
||
# 3. El health check responde
|
||
curl -s https://pedrito.inqualityhq.com/health | python3 -m json.tool
|
||
# Debe retornar JSON con "status": "ok"
|
||
|
||
# 4. El webhook está registrado (si activaste el modo webhook)
|
||
curl -s "https://api.telegram.org/bot<TU_BOT_TOKEN>/getWebhookInfo" | python3 -m json.tool
|
||
# url debe ser: https://pedrito.inqualityhq.com/webhook
|
||
|
||
# 5. El .env tiene los permisos correctos
|
||
ls -la /home/pedrito/hechakuaa_bot/.env
|
||
# Debe mostrar: -rw------- 1 pedrito pedrito
|
||
|
||
# 6. El directorio data existe y tiene contenido
|
||
ls -la /home/pedrito/hechakuaa_bot/data/
|
||
# Debe aparecer pasante.db y snapshot_*.json
|
||
|
||
# 7. Nginx redirige HTTP a HTTPS
|
||
curl -I http://pedrito.inqualityhq.com/health
|
||
# Debe retornar: HTTP/1.1 301 Moved Permanently
|
||
```
|
||
|
||
Si todos los checks pasan, avisarle a Marcos para que pruebe mandándole `/start` al bot en Telegram.
|
||
|
||
---
|
||
|
||
## 16. Monitoreo y logs
|
||
|
||
### Logs del bot en tiempo real
|
||
|
||
```bash
|
||
# Como pedrito:
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
|
||
# Ver logs en tiempo real (Ctrl+C para salir)
|
||
docker compose logs -f
|
||
|
||
# Ver solo los últimos 50 registros
|
||
docker compose logs --tail=50
|
||
|
||
# Ver logs con timestamps más legibles
|
||
docker compose logs --tail=50 --timestamps
|
||
```
|
||
|
||
### Logs de Nginx
|
||
|
||
```bash
|
||
# Accesos (como root):
|
||
tail -f /var/log/nginx/access.log
|
||
|
||
# Errores:
|
||
tail -f /var/log/nginx/error.log
|
||
|
||
# Solo errores del bot (filtra por el path):
|
||
grep "/webhook\|/health" /var/log/nginx/access.log | tail -20
|
||
```
|
||
|
||
### Eventos útiles que buscar en los logs del bot
|
||
|
||
| Evento | Qué significa |
|
||
|--------|---------------|
|
||
| `login_exitoso` | Se conectó al PJ correctamente |
|
||
| `migration_aplicada` | Se aplicó una migración de DB (solo al arrancar) |
|
||
| `health_server_iniciado` | El server HTTP de health está escuchando |
|
||
| `webhook_registrado` | El webhook se registró con Telegram correctamente |
|
||
| `polling_tenant_ok` | Revisión de notificaciones completada sin errores |
|
||
| `polling_tenant_error` | Error al revisar notificaciones de un abogado |
|
||
| `pj_error_conexion` | El PJ no respondió (puede ser transitorio) |
|
||
| `bot_notificacion_enviada` | Se envió una notificación a Telegram |
|
||
| `onboarding_completado` | Un abogado completó el registro |
|
||
| `health_alerta_enviada` | El bot detectó que el poller está detenido y avisó al admin |
|
||
|
||
### Ver historial de eventos vía HTTP
|
||
|
||
```bash
|
||
# Últimos 50 eventos del audit log:
|
||
curl -s https://pedrito.inqualityhq.com/health/history | python3 -m json.tool
|
||
|
||
# Últimos 100 eventos:
|
||
curl -s "https://pedrito.inqualityhq.com/health/history?limit=100" | python3 -m json.tool
|
||
```
|
||
|
||
---
|
||
|
||
## 17. Health check HTTP
|
||
|
||
El bot expone un endpoint HTTP en `https://pedrito.inqualityhq.com/health` que retorna el estado actual.
|
||
|
||
### Ejemplo de respuesta normal (status 200)
|
||
|
||
```json
|
||
{
|
||
"status": "ok",
|
||
"timestamp": "2026-05-25T10:00:00+00:00",
|
||
"tenants_activos": 3,
|
||
"last_poll": "2026-05-25T09:58:42+00:00",
|
||
"last_poll_tenants": 3,
|
||
"seconds_since_last_poll": 78,
|
||
"poll_interval_minutes": 60,
|
||
"webhook_mode": true
|
||
}
|
||
```
|
||
|
||
### Ejemplo de respuesta degradada (status 503)
|
||
|
||
Si el poller no actualizó en más de `HEALTH_ALERT_HOURS` horas, retorna:
|
||
```json
|
||
{
|
||
"status": "degraded",
|
||
...
|
||
}
|
||
```
|
||
|
||
En ese caso, el bot también manda un mensaje de alerta automáticamente al Telegram de Marcos.
|
||
|
||
### Integrar con un monitor externo (opcional)
|
||
|
||
Si tienen un servicio de uptime monitoring (UptimeRobot, BetterUptime, etc.):
|
||
- URL a monitorear: `https://pedrito.inqualityhq.com/health`
|
||
- Método: `GET`
|
||
- Código esperado: `200`
|
||
- Intervalo: `5 minutos`
|
||
|
||
---
|
||
|
||
## 18. Cómo actualizar el bot
|
||
|
||
Cuando hay cambios en el código (nuevo commit en el repositorio):
|
||
|
||
```bash
|
||
# Como pedrito:
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
|
||
# 1. Traer los cambios del repositorio
|
||
git pull
|
||
|
||
# 2. Reconstruir la imagen con el nuevo código
|
||
docker compose build
|
||
|
||
# 3. Reiniciar el contenedor con la nueva imagen
|
||
docker compose up -d
|
||
|
||
# 4. Verificar que levantó bien
|
||
docker compose ps
|
||
docker compose logs --tail=20
|
||
```
|
||
|
||
> **Importante:** 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.
|
||
|
||
> **Si hubo cambios en `.env.example`:** revisar manualmente si hay nuevos campos que agregar al `.env` existente.
|
||
> ```bash
|
||
> # Ver diferencias entre el template nuevo y el .env actual:
|
||
> diff .env.example .env
|
||
> ```
|
||
|
||
### Actualización especial: migración de credenciales a vault v3 (v0.4.0+)
|
||
|
||
Si el servidor tenía abogados registrados **antes de la versión v0.4.0**, sus credenciales en la DB
|
||
están en formato v1 (cifrado simple). Hay que migrarlas a v3 (PBKDF2 + envelope encryption) **una sola vez**.
|
||
|
||
Hacerlo después del `git pull` y **antes** del `docker compose up -d`:
|
||
|
||
```bash
|
||
# Dentro del contenedor (o con uv si no usás Docker):
|
||
docker compose run --rm pedrito uv run python scripts/migrar_vault_v3.py --dry-run
|
||
# Verificar que lista los tenants esperados, luego migrar de verdad:
|
||
docker compose run --rm pedrito uv run python scripts/migrar_vault_v3.py
|
||
```
|
||
|
||
El script:
|
||
- Verifica que puede descifrar todos los tenants antes de tocar la DB
|
||
- Hace backup automático de la DB (`data/pasante.db.bak`)
|
||
- Si algo falla, no escribe nada — la DB original queda intacta
|
||
|
||
Si todos los tenants registrados son nuevos (post v0.4.0), este paso no es necesario.
|
||
|
||
---
|
||
|
||
## 19. Troubleshooting
|
||
|
||
### El contenedor no arranca
|
||
|
||
```bash
|
||
# Ver el error específico:
|
||
docker compose logs --tail=50
|
||
|
||
# O ver el estado del contenedor:
|
||
docker compose ps
|
||
```
|
||
|
||
**`FERNET_KEY inválida`**
|
||
La clave en `.env` es incorrecta o tiene espacios/comillas. Verificar que el valor
|
||
en `.env` no tiene comillas ni espacios al inicio/final.
|
||
|
||
**`telegram.error.InvalidToken`**
|
||
El `TELEGRAM_BOT_TOKEN` en `.env` tiene un error. Verificar copiando el token
|
||
directamente desde la conversación con @BotFather en Telegram.
|
||
|
||
**`ModuleNotFoundError: No module named 'X'`**
|
||
La imagen necesita ser reconstruida:
|
||
```bash
|
||
docker compose build --no-cache
|
||
docker compose up -d
|
||
```
|
||
|
||
**`Error response from daemon: Cannot connect to the Docker daemon`**
|
||
Docker no está corriendo:
|
||
```bash
|
||
systemctl start docker
|
||
docker compose up -d
|
||
```
|
||
|
||
---
|
||
|
||
### El bot arranca pero no responde en Telegram
|
||
|
||
1. Verificar que el contenedor está corriendo: `docker compose ps`
|
||
2. Verificar que el webhook está registrado: `curl -s "https://api.telegram.org/bot<TOKEN>/getWebhookInfo"`
|
||
3. Verificar que Nginx está ok: `systemctl status nginx`
|
||
4. Verificar que el health check responde: `curl -s https://pedrito.inqualityhq.com/health`
|
||
5. Revisar logs de Nginx: `tail -20 /var/log/nginx/error.log`
|
||
|
||
---
|
||
|
||
### Error de credenciales del PJ
|
||
|
||
```bash
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
|
||
# Repetir el cifrado de credenciales
|
||
uv run python scripts/cifrar_credenciales.py
|
||
|
||
# Reiniciar el bot
|
||
docker compose restart
|
||
docker compose logs --tail=10
|
||
```
|
||
|
||
---
|
||
|
||
### El certificado SSL venció o hay error de SSL
|
||
|
||
```bash
|
||
# Renovar manualmente (normalmente es automático):
|
||
certbot renew
|
||
|
||
# Recargar Nginx para que use el nuevo certificado:
|
||
systemctl reload nginx
|
||
```
|
||
|
||
---
|
||
|
||
### El webhook no recibe mensajes (pero el bot arranca)
|
||
|
||
```bash
|
||
# 1. Verificar que Nginx está reenviando correctamente:
|
||
tail -20 /var/log/nginx/access.log
|
||
# Debe aparecer peticiones POST a /webhook cuando alguien manda un mensaje
|
||
|
||
# 2. Verificar el health check del bot directamente (sin pasar por Nginx):
|
||
# Desde el propio servidor:
|
||
curl -s http://127.0.0.1:8080/health
|
||
|
||
# 3. Volver a registrar el webhook manualmente:
|
||
curl "https://api.telegram.org/bot<TOKEN>/setWebhook?url=https://pedrito.inqualityhq.com/webhook&secret_token=<WEBHOOK_SECRET>"
|
||
```
|
||
|
||
---
|
||
|
||
### El VPS se reinició y el bot no volvió
|
||
|
||
El contenedor tiene `restart: unless-stopped`, así que debería volver solo. Si no:
|
||
```bash
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
docker compose up -d
|
||
```
|
||
|
||
Si Docker en sí no arrancó:
|
||
```bash
|
||
systemctl start docker
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
docker compose up -d
|
||
```
|
||
|
||
---
|
||
|
||
### Ver dos instancias corriendo (causa conflictos de Telegram)
|
||
|
||
```bash
|
||
docker compose ps
|
||
# Si hay más de un contenedor corriendo:
|
||
docker compose down
|
||
docker compose up -d
|
||
```
|
||
|
||
---
|
||
|
||
### Error de permisos en el directorio data/
|
||
|
||
```bash
|
||
# Como root:
|
||
chown -R 1000:1000 /home/pedrito/hechakuaa_bot/data
|
||
# Reiniciar:
|
||
su - pedrito
|
||
cd /home/pedrito/hechakuaa_bot
|
||
docker compose restart
|
||
```
|
||
|
||
---
|
||
|
||
## 20. Referencia rápida de comandos
|
||
|
||
### Gestión del bot (como usuario `pedrito`)
|
||
|
||
```bash
|
||
cd /home/pedrito/hechakuaa_bot
|
||
|
||
# Estado
|
||
docker compose ps
|
||
|
||
# Iniciar / detener / reiniciar
|
||
docker compose up -d
|
||
docker compose down
|
||
docker compose restart
|
||
|
||
# Logs en tiempo real
|
||
docker compose logs -f
|
||
|
||
# Logs últimos 50 registros
|
||
docker compose logs --tail=50
|
||
|
||
# Actualizar (git pull + rebuild + restart)
|
||
git pull && docker compose build && docker compose up -d
|
||
```
|
||
|
||
### Nginx (como `root`)
|
||
|
||
```bash
|
||
# Verificar configuración
|
||
nginx -t
|
||
|
||
# Recargar sin cortar conexiones
|
||
systemctl reload nginx
|
||
|
||
# Reiniciar completamente
|
||
systemctl restart nginx
|
||
|
||
# Ver logs de error
|
||
tail -f /var/log/nginx/error.log
|
||
```
|
||
|
||
### SSL
|
||
|
||
```bash
|
||
# Renovar certificado manualmente
|
||
certbot renew
|
||
|
||
# Ver fecha de vencimiento del certificado actual
|
||
certbot certificates
|
||
```
|
||
|
||
### 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 SQLite | `/home/pedrito/hechakuaa_bot/data/pasante.db` |
|
||
| Snapshots de notificaciones | `/home/pedrito/hechakuaa_bot/data/snapshot_*.json` |
|
||
| Docker Compose | `/home/pedrito/hechakuaa_bot/docker-compose.yml` |
|
||
| Config Nginx del bot | `/etc/nginx/sites-available/pedrito` |
|
||
| Logs de Nginx | `/var/log/nginx/` |
|
||
| Certificado SSL (cert) | `/etc/letsencrypt/live/pedrito.inqualityhq.com/fullchain.pem` |
|
||
| Certificado SSL (clave) | `/etc/letsencrypt/live/pedrito.inqualityhq.com/privkey.pem` |
|
||
|
||
---
|
||
|
||
*Repositorio: https://github.com/InqGit/hechakuaa_bot*
|
||
*Ante dudas técnicas no cubiertas acá, contactar a Marcos Benítez.*
|