From ec751e5414c44fb96f85843dfee1f51d0622fff7 Mon Sep 17 00:00:00 2001 From: markosbenitez Date: Thu, 28 May 2026 19:48:29 -0300 Subject: [PATCH] docs: DEPLOY.md adaptado al estado real del servidor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- DEPLOY.md | 978 +++++++++++++----------------------------------------- 1 file changed, 230 insertions(+), 748 deletions(-) diff --git a/DEPLOY.md b/DEPLOY.md index 60b6588..67bfdfb 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -2,41 +2,58 @@ > **Destinatario:** equipo técnico de InQuality > **Entorno objetivo:** VPS Ubuntu 22.04 en Hostinger — producción -> **Tiempo estimado:** 60–90 minutos (primera vez) +> **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 (antes de tocar el servidor)** +**PARTE A — Preparación** 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) +2. [Conectarse al VPS](#2-conectarse-al-vps) +3. [Agregar `pedrito` al grupo docker](#3-agregar-pedrito-al-grupo-docker) -**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 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** -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) +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** -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) +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) --- @@ -49,293 +66,59 @@ Antes de conectarte al VPS, juntá estos datos. Sin alguno de ellos el deploy no | 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` | +| 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 | -| 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 | +| 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, 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. +> ⚠️ **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. Configurar DNS en Bluehost +## 2. Conectarse al VPS -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. +```bash +ssh root@93.127.136.210 +``` -**Necesitás:** La IP pública del VPS (Panel de Hostinger → tu VPS → ver IP). +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. --- -### Opción A: Hacerlo vos mismo en Bluehost cPanel +## 3. Agregar `pedrito` al grupo docker -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) | `` | - -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:** `` *(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á `` con la IP real del VPS antes de enviar el mensaje. - ---- - -## 3. Conectarse al VPS - -Desde tu computadora local, abrí una terminal: +El usuario `pedrito` existe pero no está en el grupo `docker`. Sin esto no puede correr contenedores. ```bash -ssh root@ -``` - -Si tenés clave SSH configurada en Hostinger (recomendado): -```bash -ssh -i ~/.ssh/id_rsa root@ -``` - -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@`. 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 +# Como root: usermod -aG docker pedrito -# Verificar +# Verificar que se agregó: 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. +> **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. --- -## 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`: +## 4. Clonar el repositorio ```bash # Cambiar al usuario pedrito su - pedrito -# Verificar que estamos en el home correcto +# Verificar que estamos en su home pwd # Debe mostrar: /home/pedrito @@ -349,46 +132,35 @@ cd hechakuaa_bot ls -la ``` -Deberías ver archivos como: `main.py`, `config.py`, `telegram_bot.py`, `Dockerfile`, -`docker-compose.yml`, `migrations/`, etc. +Deberías ver: `main.py`, `config.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: +Salir 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: +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 ... data +# Verificar: +ls -la /home/pedrito/hechakuaa_bot/ +# data debe mostrar: drwxr-xr-x 2 1000 1000 ``` -> **¿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. +## 5. Configurar el archivo .env ```bash # Como pedrito: @@ -398,21 +170,21 @@ cd /home/pedrito/hechakuaa_bot # Crear .env a partir del template cp .env.example .env -# Editar (nano es el editor más simple) +# Editar 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: +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 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 +# ── 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) @@ -422,38 +194,33 @@ TELEGRAM_EXTRA_IDS= # ← COMPLETAR si hay más abogados (ej: 1112223 # ── 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 +# ── 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 # 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) +HEALTH_ALERT_HOURS=2 +HEALTH_AUTH_TOKEN= # ← COMPLETAR: python3 -c "import secrets; print(secrets.token_hex(32))" # ── 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) +POLL_INTERVAL_MINUTES=60 +POLL_HORA_INICIO=7 +POLL_HORA_FIN=18 ``` -Guardar y salir de nano: `Ctrl+O` → `Enter` → `Ctrl+X`. +Guardar y salir: `Ctrl+O` → `Enter` → `Ctrl+X`. -### Generar FERNET_KEY si Marcos no te la dio +### 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())" +python3 -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) +### Instalar uv (si no está disponible) ```bash curl -LsSf https://astral.sh/uv/install.sh | sh @@ -466,27 +233,24 @@ uv --version ```bash chmod 600 /home/pedrito/hechakuaa_bot/.env -# Verificar +# 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`. +## 6. Cifrar las credenciales del PJ ```bash -# Como pedrito, dentro del directorio del proyecto: +# Como pedrito, en el directorio del proyecto: cd /home/pedrito/hechakuaa_bot uv run python scripts/cifrar_credenciales.py ``` -El script te va a pedir: +El script pide: 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) +2. **Contraseña** — no se muestra mientras escribís Salida esperada: ``` @@ -494,104 +258,74 @@ Salida esperada: PJ_USUARIO_ENC y PJ_PASSWORD_ENC actualizadas. ``` -Verificar que se guardaron: +Verificar: ```bash grep "PJ_USUARIO_ENC" /home/pedrito/hechakuaa_bot/.env -# Debe mostrar un valor cifrado largo, NUNCA la cédula en texto plano +# Debe mostrar un token cifrado largo, NUNCA la cédula en texto plano ``` --- -## 10. Obtener certificado SSL con Certbot +## 7. 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. +HTTPS es obligatorio para el modo webhook de Telegram. -> **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 +> **Prerequisito:** el DNS ya está propagado (verificado: `pedrito.inqualityhq.com` → 93.127.136.210). ```bash # Como root: -exit # si estabas como pedrito, volver a root +exit # salir de pedrito si estabas ahí +# Instalar Certbot con plugin de Nginx apt install -y certbot python3-certbot-nginx -``` -### 10.2 Obtener el certificado - -```bash +# Obtener el certificado 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 +1. Tu dirección de email (para avisos de vencimiento) 2. Aceptar los términos de servicio → `Y` -3. Si querés compartir el email con EFF → `N` (opcional) +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 -... ``` -> **¿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: +### Verificar renovación automática ```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 +## 8. 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 +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 (reemplazá el nombre de dominio si usás uno diferente): +Pegar **exactamente** este contenido: ```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; } @@ -599,23 +333,17 @@ 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; @@ -629,14 +357,10 @@ server { 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; @@ -648,8 +372,6 @@ server { proxy_read_timeout 30s; } - # ── Denegar cualquier otra ruta ─────────────────────────────────────────── - # Respuesta genérica — no revelar que hay un bot ni su propósito location / { return 404; } @@ -658,56 +380,36 @@ server { Guardar: `Ctrl+O` → `Enter` → `Ctrl+X`. -### 11.2 Activar el sitio - ```bash -# Crear el enlace simbólico que activa el sitio +# Activar 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 +# Verificar sintaxis nginx -t -``` +# Debe decir: syntax is ok / test is successful -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 +# Recargar Nginx 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 -``` +> **Si `nginx -t` falla:** revisá que las comillas y los `;` estén correctos en el archivo. --- -## 12. Configurar el firewall +## 9. Configurar el firewall + +```bash +# Como root — verificar estado actual +ufw status +``` + +Si dice `Status: inactive` o no tiene las reglas necesarias: ```bash -# Como root ufw allow OpenSSH -ufw allow 'Nginx Full' # abre puertos 80 (HTTP) y 443 (HTTPS) +ufw allow 'Nginx Full' # puertos 80 y 443 ufw --force enable -# Verificar estado ufw status ``` @@ -719,134 +421,80 @@ 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. +> **Importante:** El puerto 8080 del bot **no** se abre al exterior. Solo Nginx accede a él +> internamente desde el mismo servidor. --- -## 13. Iniciar el bot con Docker +## 10. 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: +### Verificar que docker-compose.yml usa binding correcto ```bash -# Como pedrito: su - pedrito cd /home/pedrito/hechakuaa_bot - -# Editar docker-compose.yml -nano docker-compose.yml +grep "8080" 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 +Debe mostrar `127.0.0.1:8080:8080`. Si muestra solo `8080:8080`: ```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 +nano docker-compose.yml +# Cambiar "8080:8080" por "127.0.0.1:8080:8080" ``` -### 13.3 Primera prueba: correr en primer plano +### Construir la imagen -Antes de dejarlo en background, verificamos que arranca bien: +```bash +docker compose build +# Tarda 1-3 minutos la primera vez +``` + +### Primera prueba: correr en primer plano ```bash docker compose up ``` -Deberías ver logs como: +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": "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 aparece `login_exitoso`, el bot se conectó al PJ correctamente. Detenerlo con `Ctrl+C`. -> **Si no aparece `login_exitoso`:** ver la sección [Troubleshooting](#19-troubleshooting). +> **Si no aparece `login_exitoso`:** ver [Troubleshooting](#16-troubleshooting). -### 13.4 Correr en background (modo producción) +### Correr en background (modo producción) ```bash -# Arrancar en modo detached (background) docker compose up -d -# Verificar que el contenedor está corriendo +# Verificar que está corriendo: docker compose ps +# STATUS debe decir "running" ``` -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 +## 11. 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: +### Generar el WEBHOOK_SECRET ```bash -# Generar un token aleatorio seguro: python3 -c "import secrets; print(secrets.token_hex(32))" -# Salida: una cadena de 64 caracteres hexadecimales +# Salida: 64 caracteres hexadecimales — copiarlos ``` -Copiar la salida. La vamos a usar en el siguiente paso. - -### 14.2 Actualizar .env con los datos del webhook +### Actualizar .env ```bash -su - pedrito nano /home/pedrito/hechakuaa_bot/.env ``` @@ -856,285 +504,181 @@ WEBHOOK_URL=https://pedrito.inqualityhq.com WEBHOOK_SECRET= ``` -Guardar y salir. - -### 14.3 Reiniciar el bot para aplicar el cambio +### Reiniciar el bot ```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: {"event": "webhook_registrado", "url": "https://pedrito.inqualityhq.com/webhook", ...} ``` -Buscar en los logs: -``` -{"event": "webhook_registrado", "url": "https://pedrito.inqualityhq.com/webhook", ...} -``` - -### 14.4 Verificar que el webhook quedó registrado en Telegram +### 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/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. +El campo `url` debe mostrar `https://pedrito.inqualityhq.com/webhook`. --- -## 15. Verificación final - -Correr esta lista de verificaciones antes de dar el deploy por terminado: +## 12. Verificación final ```bash -# 1. El contenedor Docker está corriendo +# 1. El contenedor está corriendo docker compose ps -# STATUS debe ser "running" +# STATUS: running -# 2. Los logs no tienen errores +# 2. Logs sin errores docker compose logs --tail=30 -# Buscar "login_exitoso" y "pedrito_hechakuaa_corriendo" -# NO debe aparecer: ERROR, exception, Traceback +# Buscar "login_exitoso" — NO debe aparecer: ERROR, exception, Traceback -# 3. El health check responde +# 3. Health check responde curl -s https://pedrito.inqualityhq.com/health | python3 -m json.tool -# Debe retornar JSON con "status": "ok" +# {"status": "ok", ...} -# 4. El webhook está registrado (si activaste el modo webhook) +# 4. Webhook registrado curl -s "https://api.telegram.org/bot/getWebhookInfo" | python3 -m json.tool -# url debe ser: https://pedrito.inqualityhq.com/webhook +# url: https://pedrito.inqualityhq.com/webhook -# 5. El .env tiene los permisos correctos +# 5. Permisos del .env ls -la /home/pedrito/hechakuaa_bot/.env -# Debe mostrar: -rw------- 1 pedrito pedrito +# -rw------- 1 pedrito pedrito -# 6. El directorio data existe y tiene contenido +# 6. Directorio data existe ls -la /home/pedrito/hechakuaa_bot/data/ -# Debe aparecer pasante.db y snapshot_*.json +# pasante.db y snapshot_*.json -# 7. Nginx redirige HTTP a HTTPS +# 7. HTTP redirige a HTTPS curl -I http://pedrito.inqualityhq.com/health -# Debe retornar: HTTP/1.1 301 Moved Permanently +# HTTP/1.1 301 Moved Permanently ``` -Si todos los checks pasan, avisarle a Marcos para que pruebe mandándole `/start` al bot en Telegram. +Si todos pasan, avisarle a Marcos para que pruebe con `/start` en Telegram. --- -## 16. Monitoreo y logs - -### Logs del bot en tiempo real +## 13. Monitoreo y logs ```bash -# Como pedrito: su - pedrito cd /home/pedrito/hechakuaa_bot -# Ver logs en tiempo real (Ctrl+C para salir) +# Logs en tiempo real docker compose logs -f -# Ver solo los últimos 50 registros +# Ú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): +# 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 +### Eventos clave 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 | +| `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 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 -``` +| `health_alerta_enviada` | El poller está detenido — alerta al admin | +| `webhook_registrado` | Webhook activo con Telegram | --- -## 17. Health check HTTP +## 14. Health check HTTP -El bot expone un endpoint HTTP en `https://pedrito.inqualityhq.com/health` que retorna el estado actual. +El bot expone `https://pedrito.inqualityhq.com/health`. -### Ejemplo de respuesta normal (status 200) +```bash +# Sin auth — respuesta mínima pública: +curl -s https://pedrito.inqualityhq.com/health | python3 -m json.tool +# {"status": "ok", "timestamp": "..."} -```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 -} +# Con auth — respuesta completa (reemplazá TOKEN): +curl -s -H "Authorization: Bearer " \ + https://pedrito.inqualityhq.com/health/history | python3 -m json.tool ``` -### Ejemplo de respuesta degradada (status 503) +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. -Si el poller no actualizó en más de `HEALTH_ALERT_HOURS` horas, retorna: -```json -{ - "status": "degraded", - ... -} -``` +### Monitor externo (opcional) -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` +- URL: `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): +## 15. Cómo actualizar el bot ```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. +> `.env` y `data/` no se tocan con `git pull` — están en `.gitignore`. -> **Si hubo cambios en `.env.example`:** revisar manualmente si hay nuevos campos que agregar al `.env` existente. +> **Si hubo cambios en `.env.example`:** > ```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+) +### Migración de credenciales vault v3 (solo al actualizar desde versiones < 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`: +Si había abogados registrados antes de v0.4.0, migrar sus credenciales **antes** del restart: ```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: +# Verificar output, luego: 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 +## 16. 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. +**`FERNET_KEY inválida`** — la clave en `.env` tiene espacios o comillas. Verificar el valor. -**`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. +**`telegram.error.InvalidToken`** — el `TELEGRAM_BOT_TOKEN` tiene un error. Recopiarlo de @BotFather. -**`ModuleNotFoundError: No module named 'X'`** -La imagen necesita ser reconstruida: +**`ModuleNotFoundError`** — reconstruir la imagen: ```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 +docker compose build --no-cache && 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/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` +1. `docker compose ps` — ¿está corriendo? +2. `curl -s "https://api.telegram.org/bot/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? --- @@ -1143,58 +687,27 @@ docker compose up -d ```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 +### El certificado SSL venció ```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/setWebhook?url=https://pedrito.inqualityhq.com/webhook&secret_token=" -``` - ---- - ### 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 +# El contenedor tiene restart: unless-stopped — debería volver solo. +# Si no: su - pedrito cd /home/pedrito/hechakuaa_bot docker compose up -d @@ -1202,23 +715,11 @@ 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/ +### Error de permisos en data/ ```bash # Como root: chown -R 1000:1000 /home/pedrito/hechakuaa_bot/data -# Reiniciar: su - pedrito cd /home/pedrito/hechakuaa_bot docker compose restart @@ -1226,55 +727,38 @@ docker compose restart --- -## 20. Referencia rápida de comandos +## 17. Referencia rápida de comandos -### Gestión del bot (como usuario `pedrito`) +### Gestión del bot (como `pedrito`) ```bash cd /home/pedrito/hechakuaa_bot -# Estado -docker compose ps +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 -# 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) +# Actualización rápida: 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 +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 -# Renovar certificado manualmente -certbot renew - -# Ver fecha de vencimiento del certificado actual -certbot certificates +certbot renew # renovar manualmente +certbot certificates # ver fecha de vencimiento ``` ### Rutas de archivos importantes @@ -1283,15 +767,13 @@ certbot certificates |---------|---------------| | 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` | +| 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 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` | +| Config Nginx | `/etc/nginx/sites-available/pedrito` | +| Logs Nginx | `/var/log/nginx/` | +| Certificado SSL | `/etc/letsencrypt/live/pedrito.inqualityhq.com/` | --- -*Repositorio: https://github.com/InqGit/hechakuaa_bot* -*Ante dudas técnicas no cubiertas acá, contactar a Marcos Benítez.* +*Ante dudas técnicas, contactar a Marcos Benítez.*