Operar el servidor
Administración y ajustes
Panel de administración, entrega de códigos de registro (SMS y correo electrónico), valores de configuración del servidor, copias de seguridad y seguridad: una referencia para operadores.
El servidor incluye un panel de administración que se abre en el navegador. Desde él se consulta el estado del servidor, se decide cómo se entregan los códigos de registro e inicio de sesión y se gestionan los usuarios y los bots. Este documento es una referencia que reúne en un solo lugar el panel de administración y los valores de configuración del servidor. Si primero tienes que instalarlo, consulta Instalar el servidor.
Por ahora, la interfaz del panel de administración solo está en coreano. En este documento, las pestañas, los botones y los ajustes aparecen traducidos y, junto a ellos, el texto en coreano tal como se ve en pantalla; por ejemplo: Ajustes (설정).
Abrir el panel de administración
El panel de administración está en /admin/ del puerto HTTP de administración (8080 en la configuración de producción) y solo se abre desde el propio servidor (127.0.0.1). El operador entra mediante un túnel SSH.
# En tu ordenador (déjalo abierto)
ssh -N -L 8080:127.0.0.1:8080 <usuario>@<servidor>
# Navegador: http://localhost:8080/admin/
# Token (en el servidor)
sudo cat /srv/pabal/pabal_server/data/admin-token
Introduce el token y pulsa Abrir (열기). El navegador recuerda el token, y se borra con Borrar token (토큰 지우기), arriba a la derecha. Si quieres fijar tú el token, define TELEGRAM_ADMIN_TOKEN (al menos 16 caracteres); en ese caso no se escribe el archivo.
Qué muestra cada pestaña
| Pestaña | Contenido | Actualización |
|---|---|---|
| Resumen (대시보드) | Personas, sesiones y conexiones activas en este momento; número de personas, bots, grupos, mensajes, fotos y archivos; tiempo en marcha, puertos y base de datos; JVM; comprobaciones de estado. Si los números de prueba están activados, aparece una franja de aviso | 5 segundos |
| Códigos de registro (가입 코드) | Códigos pendientes (número, método de entrega, estado del envío, código, tiempo restante, intentos fallidos) e historial reciente. Copiar y cancelar códigos | 3 segundos |
| Usuarios (사용자) | Todas las cuentas: número de teléfono, correo de inicio de sesión (editable), si están conectadas, número de dispositivos con sesión iniciada y número de mensajes. Cerrar sesión en todos los dispositivos (모든 기기 로그아웃), Bloquear número (번호 차단), Eliminar cuenta (계정 삭제, con una nota de cómo se verificó a la persona; de la cuenta eliminada solo quedan su id y la nota) | 10 segundos |
| Bots (봇) | Los bots creados con BotFather: quién los creó, menú de comandos, modo de conexión (MTProto · sondeo HTTP · dirección del webhook y motivo del fallo), número de actualizaciones pendientes | 10 segundos |
| Voz (음성) | Bots de voz: estado de las pasarelas, del relé y de la política, interruptor de emergencia, apertura al público, autorización de transcripciones, llamadas en curso y colgar, autorización y suspensión de bots, testers, límites (abajo) | 5 segundos |
| Denuncias (신고) | Lo que llega por «Denunciar» en la aplicación: una copia del contenido en el momento de la denuncia (se puede leer aunque quien lo envió lo borre después). Eliminar (en los dos lados de la conversación; en un grupo, para todos los miembros), Suspender la cuenta (cierra la sesión en todos los dispositivos y ya no puede iniciar sesión ni registrarse), lista de cuentas suspendidas. El número de una cuenta eliminada mientras estaba suspendida no puede volver a registrarse durante 1 año desde la eliminación (por defecto); al suspender, o después con Bloquear el registro (재가입 막기) en la lista, se puede alargar hasta una fecha de fin posterior (cuenta la más tardía entre el año y la fecha; nunca se acorta) o dejarlo indefinido (API de administración: POST /admin/api/reports/<id>/suspend {"userId": …, "blockSignupUntil": "2028-01-01"} o "blockSignupForever": true; para cambiarlo después, POST /admin/api/suspensions/<id>/block-signup, y con el cuerpo vacío vuelve al valor por defecto). También se pueden ver las denuncias ya tramitadas. Una denuncia tramitada se borra, copia incluida, 3 años después del día en que se tramitó (la tarjeta muestra la fecha); si empieza una disputa, una investigación o un pleito, Conservar (보존) la mantiene hasta que se libera (API de administración: POST /admin/api/reports/<id>/hold, y /release para liberarla) | 10 s |
| Soporte (고객센터) | Las conversaciones que llegan a @PabalSupport. Elige una conversación y responde: la respuesta llega a esa conversación con el nombre del bot de soporte | 10 s |
| Ajustes (설정) | Reglas de registro e inicio de sesión, cuentas de revisión de las tiendas de aplicaciones, SMS, correo electrónico (SMTP), bloqueo de números de teléfono, datos del operador que se publican en el sitio web | Se guardan manualmente |
| Nombres de usuario reservados (예약 아이디) | Nombres de usuario bloqueados para que nadie pueda quedárselos: búsqueda, añadir, descargar la lista (.txt) y los nombres que el servidor bloquea por defecto. Reservar un nombre que ya usa alguien no se lo quita | Una vez, al abrir |
| Almacenamiento (저장소) | Directorio de datos y dirección de la base de datos (con la contraseña oculta), número y tamaño de las fotos y los archivos, número de flujos (streams) almacenados por tipo | 10 segundos |
Las acciones peligrosas (cerrar sesiones, bloquear, cancelar códigos) solo se ejecutan si se pulsan dos veces.
Códigos de registro e inicio de sesión
Cuando alguien introduce su número de teléfono en la aplicación, el servidor genera un código y lo envía por el método elegido en la pestaña Ajustes (설정).
| Método de entrega | Adónde va el código | Pantallas de la aplicación |
|---|---|---|
| Panel de administración (관리 화면) | A la pestaña Códigos de registro (가입 코드). El operador lo copia y lo comunica personalmente | Número → «Te hemos enviado el código» → código (y nombre, si es un número nuevo) |
| SMS | Mensaje de texto a través de Twilio, Solapi o un webhook | Igual que con el panel de administración |
| Correo electrónico (이메일) | Correo a través de SMTP | Número → introducir el correo → «Te hemos enviado el código por correo» → código |
- Con el método de correo electrónico, en un registro nuevo se puede usar cualquier dirección, y esa dirección pasa a ser el correo de inicio de sesión de la cuenta. Las cuentas existentes solo lo reciben en su correo de inicio de sesión registrado: así se impide que alguien entre poniendo su propia dirección con el número de otra persona. A las cuentas existentes sin correo de inicio de sesión se les envía en su lugar por SMS (si está configurado) o por el panel de administración. En la pestaña Usuarios (사용자) puedes asignarles un correo de inicio de sesión.
- El envío se hace en segundo plano, así que la aplicación pasa enseguida a la pantalla del código. El resultado del envío (éxito o fallo, y el motivo) aparece en la pestaña Códigos de registro.
- El registro (introducir el nombre) solo es posible después de acertar el código. Los códigos incorrectos se admiten solo hasta el número de intentos permitido; a partir de ahí se rechaza incluso el código correcto.
- Cambiar el número de una cuenta (Ajustes → número de teléfono en la aplicación) está cerrado por defecto, y la aplicación muestra un error. Con Permitir cambiar de número activado, el código va al número nuevo solo por SMS, sea cual sea el método de entrega (la pestaña Códigos de registro no lo muestra, ni siquiera con los códigos visibles: quien lo reciba allí puede no ser el titular del número), con un texto propio, el texto de cambio de número de los ajustes de SMS (번호 바꾸기 문구; por defecto
[파발] 번호 바꾸기 확인 코드: {code}). El intervalo de reenvío y el máximo diario se aplican al número nuevo y a la cuenta; los números bloqueados o de cuentas suspendidas, y los que ya tiene otra cuenta, se rechazan al pedir el código y otra vez al cambiar. Un código vale solo para esa cuenta y ese número, y se usa una vez; el código de inicio de sesión de otra persona que espera ese número queda como estaba. Después del cambio, el número antiguo ya no inicia sesión en la cuenta.
Ajustes — registro e inicio de sesión
| Opción | Significado | Por defecto |
|---|---|---|
| Permitir registros nuevos (새 가입 허용) | Si se desactiva, solo inician sesión las cuentas que ya existen. Los números nuevos se rechazan como «número no válido» | Activado |
| Método de entrega del código (코드 전달 방식) | Panel de administración (관리 화면) / SMS / correo electrónico (이메일) | Panel de administración |
| Mostrar el código en el panel de administración (관리 화면에 코드 표시) | Muestra el código en la pestaña Códigos de registro también con los métodos de SMS y correo (por si falla el envío) | Activado |
| Números de prueba (+99966…) (테스트 번호) | Según el servidor (서버 설정대로) / Activar (켜기) / Desactivar (끄기). En producción, desactivar | Según el servidor |
| Dígitos del código · validez (코드 자릿수 · 코드 유효 시간) | 5–6 dígitos · 1–60 minutos | 5 dígitos · 5 minutos |
| Intervalo entre peticiones · máximo diario (재요청 간격 · 번호당 하루 최대 요청) | Segundos hasta que el mismo número puede volver a recibir un código (0–3600) · número máximo de veces en 24 horas (1–1000) | 60 segundos · 10 veces |
| Intentos fallidos permitidos (틀린 입력 허용 횟수) | Si se superan, ese código se bloquea (1–20) | 5 veces |
| Permitir cambiar de número (번호 바꾸기 허용) | Una cuenta con la sesión iniciada puede pasar a otro número con «Cambiar número» de la aplicación. Solo se puede activar con el SMS configurado | Desactivado |
Ajustes — SMS
| Proveedor | Qué introducir | Notas |
|---|---|---|
| Webhook (웹훅) | Dirección de destino (https://…), cabecera Authorization (opcional) | El servidor envía POST {"phone":"+8210…","code":"12345","text":"…"}. Una respuesta 2xx es un éxito. Para conectar con tu propio servidor de SMS o con otro servicio |
| Twilio | Account SID, Auth Token, número remitente (발신 번호) o Messaging Service SID | Todo el mundo, números extranjeros incluidos |
| Solapi (antes CoolSMS) | API Key, API Secret, número remitente | SMS dentro de Corea. El número remitente debe estar registrado previamente en Solapi. Los números +82 se envían con el formato 010… |
En el texto del mensaje (문구) puedes incluir {code} (el código) y {minutes} (el tiempo de validez). Valor por defecto: [파발] 인증 코드: {code} («[Pabal] Código de verificación: {code}»). Después de guardar, compruébalo con Envío de prueba (테스트 발송).
Ajustes — correo electrónico (SMTP)
| Servicio | Servidor · puerto · seguridad | Usuario · contraseña |
|---|---|---|
| Gmail | smtp.gmail.com · 587 · STARTTLS | Dirección de Gmail · contraseña de aplicación (Cuenta de Google → Seguridad → Verificación en dos pasos → Contraseñas de aplicaciones) |
| Naver | smtp.naver.com · 587 · STARTTLS | ID · contraseña (activa el uso de POP3/SMTP en la configuración del correo) |
| Relay de correo interno de la empresa | Dirección del relay · 25 · ninguna | Vacíos |
La dirección remitente (보내는 주소) debe ser una desde la que la cuenta SMTP pueda enviar. En el asunto (제목) y en el cuerpo (본문) también se usan {code} y {minutes}.
Gestión de usuarios
- Cerrar sesión en todos los dispositivos (모든 기기 로그아웃): corta todos los inicios de sesión (claves de autorización) de esa cuenta. Se usa con usuarios que han perdido un dispositivo.
- Bloquear número (번호 차단): ese número no puede recibir códigos, y la cuenta de ese número cierra sesión al instante en todos los dispositivos. Equivale a la lista de bloqueo de números de teléfono (전화번호 차단) de la pestaña Ajustes (설정).
- Correo de inicio de sesión (로그인 이메일): lo necesitan las cuentas existentes para iniciar sesión por correo con el método de correo electrónico.
- Eliminar cuenta (계정 삭제): para un usuario que ha pedido que se elimine su cuenta, una vez comprobada su identidad. Elimina exactamente lo mismo que la eliminación de cuenta de la app y no se puede deshacer. Solo se ejecuta tras volver a escribir el ID o el número de teléfono de la cuenta y dejar una nota de cómo llegó la solicitud y cómo se comprobó la identidad. La nota se conserva junto con el ID y la fecha (se le quitan los números de teléfono, las direcciones de correo y el nombre y el nombre de usuario de la cuenta). Para una solicitud por correo que no viene del correo de inicio de sesión de la cuenta, la misma ventana envía un código por SMS al número de la cuenta; escribe el código que la persona devuelve por correo. Los bots y las cuentas propias del servidor no se pueden eliminar aquí.
- @BotFather es un bot interno del servidor, así que no se le puede cerrar la sesión.
Gestión de bots
En la pestaña Bots (봇) se ve el modo de conexión de cada bot: si está conectado por MTProto, si ha llamado a getUpdates por HTTP en el último minuto, cuál es la dirección de su webhook y si está fallando ahora (con el motivo). Si las actualizaciones pendientes no dejan de aumentar, el programa del bot se ha detenido o el webhook está fallando. Eliminar un bot o emitir un token nuevo lo hace quien creó el bot, desde @BotFather.
Pestaña Voz
Desde aquí se gestionan los bots de voz (bots cuyas llamadas, hechas desde la aplicación, atiende un modelo de voz de IA; ver Bots de voz). La pestaña se ve aunque la voz no esté activada en el servidor, y la zona de estado indica qué falta. Para activarla, consulta Instalar el servidor — Bots de voz. Se actualiza cada 5 segundos.
| Zona | Qué se ve y qué se puede hacer |
|---|---|
| Cifras de arriba | Llamadas en curso · tiempo usado hoy (límite diario del servidor, tiempo reservado por las llamadas en curso) · pasarelas conectadas · bots con la voz activada (bots autorizados) · testers (abierto al público o no) |
| Estado | Enlace con la pasarela (su dirección, o «Desactivado: sin secreto de enlace» (꺼짐 (링크 비밀 없음))), relé de llamadas (TURN; sin él, «Todas las llamadas a bots dan ocupado» (모든 봇 통화가 통화 중)), si la política de privacidad tiene la sección bot-calls (sin ella, «Ningún bot atiende llamadas» (어떤 봇도 받지 않음)), consentimientos pendientes y el número de llamadas terminadas con tono de ocupado, por motivo (por ejemplo, 워치가 못 거는 모드, «modo al que el reloj no puede llamar»: una llamada desde el Apple Watch a un bot que usa herramientas, MCP, clave propia, modo stream o la transcripción del propietario, WATCH_NOT_YET) |
| Interruptor de emergencia | Detener todas las llamadas de voz (모든 음성 통화 멈추기): en cuanto se pulsa, terminan todas las llamadas a bots en curso en este servidor, no se aceptan llamadas nuevas y ningún bot muestra el botón de llamada. Después se guarda y se mantiene aunque se reinicie el servidor (si falla el guardado, se muestra un aviso). Se quita con Reabrir las llamadas de voz (음성 통화 다시 열기) |
| Apertura al público | Antes de la apertura, solo los testers de abajo pueden llamar a los bots de voz. Para abrirlo a todo el mundo, escribe exactamente 공개합니다 («Lo abro al público») en el campo y pulsa Abrir a todos (모두에게 공개) (se rechaza si la clave de destinatario del servidor, TELEGRAM_VOICE_RECIPIENTS, es …@unset, es decir, sin región de tratamiento: primero hay que publicar una compilación de la aplicación que indique la región). Con Volver a solo testers (시험자만으로 되돌리기) se deshace. Terminar la revisión legal y tener la respuesta por escrito del proveedor (Google) antes de abrir al público es una decisión del operador: el código no lo impide |
| Pasarelas | Para cada pasarela conectada: id, llamadas atendidas/capacidad, adónde envía el audio (google.vertex.gemini-live@us-central1, etc.), funciones (tools·byok·transcripts·stream …), motor, boot |
| Transcripción · clave propia | Autorizar la transcripción: escribe 대화 기록을 허용합니다 («Autorizo las transcripciones») en el campo y pulsa Autorizar la transcripción (대화 기록 허용). No la autorices antes de una revisión legal. Si se desactiva, deja de funcionar al instante y también se descartan los textos que las llamadas en curso y los bots aún no han recogido. «Guardar conversación», que elige quien llama, no depende de esta autorización y no tiene interruptor en el panel de administración: lo activa la sección bot-calls-keep-text de la política de privacidad (Instalar el servidor: Guardar conversación). Clave propia: si se aceptan claves y, si no, por qué; el id de la clave maestra; y cuántos bots tienen clave (la clave en sí no aparece en ningún sitio) |
| Llamadas en curso | ID de la llamada, bot, quien llama (nombre e id), estado, transcurrido/máximo, pasarela, número de consultas de herramienta abiertas. Colgar (끊기) (se ejecuta al pulsar por segunda vez) |
| Bots de voz | Bots que pueden usar la voz: Solo los bots autorizados (허용한 봇만) (por defecto) o Todos los bots creados con @BotFather (@BotFather 로 만든 모든 봇). Autorizar (허용) con el id o el @nombre de usuario del bot. Tabla: bot, quién lo creó, estado (activado o no, si puede atender llamadas y por qué, suspendido, dirección a la que va el audio en modo stream, herramientas y número de respuestas, errores y tiempos agotados), voz e idioma, límites, llamadas de hoy. Acciones: Autorizar (허용)·Retirar la autorización (허용 취소), Revisar y volver a autorizar (확인하고 다시 허용), Suspender (멈추기) (motivo obligatorio, 200 caracteres, visible para el propietario del bot; las llamadas en curso terminan)·Reabrir (다시 열기), Ver ajustes (설정 보기) |
| Ajustes de un bot | Texto completo de las instrucciones y del saludo (para revisar), definiciones de las herramientas y tiempo de respuesta por herramienta (p50·p95), adónde van las consultas de herramienta, versión de las reglas aceptada, control de suplantación aplicado o exento, cambios recientes y, por mes, llamadas, minutos, llamadas perdidas y rechazadas |
| Testers | Con el id o el @nombre de usuario de una persona (con o sin @, sin distinguir mayúsculas): Añadir como tester (시험자로 넣기)·Quitar (빼기) (no vale para bots ni para las cuentas propias del servidor). Las personas añadidas con el ajuste de servidor TELEGRAM_VOICE_TESTERS aparecen como «Servidor» (서버) y no se pueden quitar aquí |
| Límites | La tabla de abajo + Nombres que añadir al control de suplantación (사칭 검사에 더할 이름) (uno por línea). Al guardar, avisa de los bots que ya no podrán atender llamadas |
| Llamadas de bots | El interruptor general: escribe exactamente 봇이 거는 전화를 켭니다 en la casilla y actívalo, solo tras la revisión legal (se rechaza mientras callme.legal_review de la pantalla de permiso no sea done; la excepción para servidores de desarrollo y de pruebas es TELEGRAM_VOICE_CALLME_UNREVIEWED). Al apagarlo, las peticiones nuevas reciben 503 al instante. Los países (82 por defecto, 999 solo en servidores de pruebas), los límites (un servidor de producción nunca los guarda más laxos que los mínimos), la tabla de bots que sus propietarios activaron (estado de la revisión, congelamiento por token, parada automática, peticiones de hoy) y el detalle de un bot (nombre, @nombre de usuario, foto, instrucciones, saludo, herramientas, voz, idioma, modo, propósitos, nombre del propietario y su outboundReviewHash) con Autorizar·Retirar, Levantar una parada automática y los rechazos por etapa de la evaluación |
Autorizar es revisar. En el modo «Solo los bots autorizados», autorizar un bot significa autorizar sus instrucciones, su saludo y sus herramientas actuales (en modo stream, su dirección de stream). Si el propietario del bot cambia cualquiera de ellos, la tabla de bots muestra «Las instrucciones o el saludo cambiaron: revisa y vuelve a autorizar para que atienda llamadas» (지시문·인사말이 바뀜 — 확인하고 다시 허용해야 전화를 받습니다), y ese bot no atiende llamadas hasta que pulses Revisar y volver a autorizar (확인하고 다시 허용). Con los bots cuyo idioma no es el coreano ni el inglés ocurre lo mismo también en el modo «Todos los bots creados con @BotFather», porque el control automático de las reglas que se hace al guardar solo lee coreano e inglés. En la tabla, esos bots muestran «Bot que no está en coreano ni en inglés (el control automático de las reglas no lo lee): lee las instrucciones y el saludo; revisa y vuelve a autorizar para que atienda llamadas» (한국어·영어가 아닌 봇 (자동 규칙 검사가 읽지 못함): 지시문·인사말을 읽어 주세요 — 확인하고 다시 허용해야 전화를 받습니다), así que haz que alguien que lea ese idioma revise las instrucciones y el saludo antes de autorizarlo.
| Límite | Por defecto | Rango |
|---|---|---|
| Duración máxima de una llamada (segundos) | 600 | De 60 a 3600, hasta el ajuste de servidor TELEGRAM_VOICE_MAX_SECONDS |
| Llamadas simultáneas de un bot | 2 | De 1 a 100, hasta el ajuste de servidor TELEGRAM_VOICE_BOT_CONCURRENCY |
| Llamadas por hora de una persona | 20 | De 1 a 200 |
| Minutos de llamada al día de una persona | 60 | De 1 a 600 |
| Minutos de llamada al día de un bot | 60 | De 1 a 6000 |
| Minutos de llamada al día de un propietario de bots | 120 | De 1 a 6000 |
| Minutos de llamada al día de todo el servidor | 300 | De 1 a 100000 |
| Llamada más corta que se atiende (segundos) | 60 | De 30 a 300: si queda menos tiempo, no se atiende |
| Restricción de cuentas nuevas (días) | 7 | De 0 a 90 (0 = desactivada), salvo los testers y las personas a las que el bot envió un mensaje hace más de un día |
- El día sigue la zona horaria del servidor (
TELEGRAM_VOICE_TIME_ZONE,Asia/Seoulpor defecto). Al aceptar una llamada se fija su duración máxima dentro del tiempo que queda del día y se reserva en todos los límites; al terminar, solo se cobran los segundos reales según el reloj del servidor. Las llamadas atendidas con la clave propia del propietario de un bot solo consumen los límites de quien llama. - El propietario de un bot solo puede fijar la duración de una llamada (300 segundos por defecto) y las llamadas simultáneas de su bot dentro de estos límites.
- Todas las acciones (interruptor de emergencia, apertura, autorización, suspensión, colgar, límites…) quedan en el registro de actividad de la pestaña Códigos de registro (가입 코드) con el prefijo
음성: …(«Voz: …»). - Las cifras de calidad de las llamadas de voz (tiempo hasta el primer sonido, tiempo hasta detenerse en una interrupción, tiempo de respuesta de las herramientas, etc.) no están en esta pestaña, solo en
/metricsdel puerto de administración (nombres que empiezan porvoice.en JSON y porvoice_en formato Prometheus,/metrics?format=prometheus). Solo contienen totales: ni personas, ni bots, ni palabras.
Lo mismo se puede hacer con la API de administración (siempre con Authorization: Bearer <token>): GET /admin/api/voice, GET /admin/api/voice/bots/<id> y, con POST, voice/kill {"on": true}, voice/launch {"launched": true, "confirm": "…"}, voice/transcripts {"allowed": true, "confirm": "…"}, voice/testers·voice/testers/remove {"userId": …}, voice/gate {"botGate": "ALLOWLIST"}, voice/bots/allow·voice/bots/disallow {"botId": …}, voice/bots/<id>/suspend {"reason": "…"}·…/lift·…/name-exempt, voice/calls/<id>/end; los límites, con /admin/api/settings/voice. Llamadas de bots: voice/outbound {"on": true, "confirm": "…"}, voice/outbound/settings {"countries": […], "limits": {…}}, GET /admin/api/voice/outbound/bots/<id>, voice/outbound/bots/allow {"botId": …, "expect": "<outboundReviewHash>"}·voice/outbound/bots/disallow, voice/outbound/bots/<id>/lift.
Variables de entorno
El servidor lee el archivo de configuración (server-config.json) y después lo sobrescribe con las variables de entorno. El archivo compose de producción ya fija los valores de abajo, así que normalmente basta con modificar .env.
| Variable | Significado | Valor en el compose de producción |
|---|---|---|
TELEGRAM_PORT | Puerto MTProto | MTPROTO_PORT (8443) |
TELEGRAM_HOST | Dirección en la que escucha MTProto | 0.0.0.0 |
TELEGRAM_PUBLIC_HOST | Dirección del servidor que se comunica a la aplicación (help.getConfig) | PUBLIC_IP |
TELEGRAM_WEB_PORT | Puerto del sitio web, la documentación, la Bot API y el panel de administración | 8080 |
TELEGRAM_WEB_HOST | Dirección en la que escucha ese puerto. Por defecto, 127.0.0.1 | 0.0.0.0 (dentro del contenedor; en el host solo se publica en 127.0.0.1) |
TELEGRAM_PUBLIC_URL | Dirección del sitio web. Enlaces (me_url_prefix), enlaces de invitación, ejemplos de la documentación e imágenes de vista previa | https://DOMAIN/ |
TELEGRAM_DATA_DIR | Ubicación de las fotos, los archivos, admin-token y operations.json | /app/data |
TELEGRAM_RSA_KEY | Ruta de la clave privada RSA del servidor (si no existe, se crea la primera vez; la clave pública es .pub) | /app/keys/private.pem |
TELEGRAM_DC_ID | Número de DC de este servidor. Tiene que ser el DC que las aplicaciones usan como casa (2 en todas las aplicaciones de Telegram); si no, las descargas de fotos y archivos no empiezan nunca | DC_ID (2) |
TELEGRAM_DB_TYPE | memory · h2 · postgresql | postgresql |
TELEGRAM_DB_URL, TELEGRAM_DB_USERNAME, TELEGRAM_DB_PASSWORD | Conexión JDBC | jdbc:postgresql://pabal-postgres:5432/pabal, pabal, POSTGRES_PASSWORD |
TELEGRAM_DB_MAX_POOL_SIZE | Número de conexiones a la base de datos | 20 |
TELEGRAM_ADMIN_TOKEN | Token del panel de administración (si se deja vacío, se crea en data/admin-token) | ADMIN_TOKEN |
TELEGRAM_MAX_FILE_SIZE | El archivo más grande que se puede enviar (2GB·512MB·número de bytes). Los fragmentos se escriben en disco a medida que llegan, así que el límite lo pone el disco, no la memoria | MAX_FILE_SIZE (2GB) |
TELEGRAM_TEST_NUMBERS | Números de prueba +99966…. Solo para desarrollo | false |
TELEGRAM_WEBHOOK_ALLOW_LOCAL | Permite que los webhooks de los bots usen http:// y direcciones internas. Solo para desarrollo | (sin definir = false) |
TELEGRAM_FCM_CREDENTIALS | Ruta del archivo de clave de la cuenta de servicio de Firebase para las notificaciones push de Android. Si se deja vacío, no hay notificaciones push (Instalar el servidor — Paso 10) | FCM_CREDENTIALS (vacío) |
TELEGRAM_FCM_PROJECT_ID | Solo si hay que enviar a un proyecto de Firebase distinto del project_id del archivo de clave | FCM_PROJECT_ID (vacío) |
TELEGRAM_PUSH_PREVIEWS | Con false, las notificaciones push muestran solo el remitente, sin el contenido del mensaje | PUSH_PREVIEWS (true) |
TELEGRAM_TURN_HOST, TELEGRAM_TURN_PORT, TELEGRAM_TURN_SECRET | Relé de llamadas (TURN): donde se encuentran dos aplicaciones en redes distintas. Sin secreto, solo hay conexión directa (Instalar el servidor: Relé de llamadas) | TURN_HOST (vacío: DOMAIN), TURN_PORT (3478), TURN_SECRET (vacío) |
TELEGRAM_APNS_KEY, TELEGRAM_APNS_KEY_ID, TELEGRAM_APNS_TEAM_ID, TELEGRAM_APNS_TOPIC, TELEGRAM_APNS_MIN_BUILD, TELEGRAM_APNS_VOIP_MIN_BUILD | Push de iPhone (APNs): la ruta del archivo de clave, el ID de la clave (vacío: se toma del nombre del archivo), el equipo que firmó la aplicación, el bundle ID, la compilación más baja a la que se envía y la primera que recibe la pantalla de llamada de CallKit. Sin clave, el push de iPhone está desactivado (Instalar el servidor: paso 11) | APNS_* (sin clave, vacío — del nombre del archivo, 4Z8R468M2D, me.pabal.ios, 4, vacío) |
TELEGRAM_STATIC_MAPS_KEY, TELEGRAM_STATIC_MAPS_PER_DAY, TELEGRAM_STATIC_MAPS_PER_USER_HOUR | Imágenes de mapa de los mensajes de ubicación: la clave de Google Maps Static API, las imágenes nuevas que se obtienen al día y las que una persona puede provocar por hora. Sin clave, las imágenes de mapa están desactivadas (Instalar el servidor: Imágenes de mapa) | STATIC_MAPS_* (sin clave, 300, 120) |
JAVA_OPTS | Opciones de la JVM (memoria) | El valor de .env |
Variables de entorno: bots de voz
En producción, el archivo adicional deploy/docker-compose.voice.yml fija a partir de los valores de .env el enlace, el relé, la zona horaria, los límites, los testers y las compilaciones mínimas; las demás se añaden función por función, después de su propia revisión (Instalar el servidor — Bots de voz). Los ajustes VOICE_* de la pasarela (pabal-voice) están en voice/README.md del repositorio.
| Variable | Por defecto | Significado |
|---|---|---|
TELEGRAM_VOICE_LINK_SECRET_FILE | — | Secreto de enlace de 32 bytes (64 caracteres hexadecimales), el mismo que el de la pasarela. Si falta o es incorrecto, la voz queda desactivada |
TELEGRAM_VOICE_LINK_HOST, TELEGRAM_VOICE_LINK_PORT | 127.0.0.1, 8095 | Dónde escucha el enlace. Si no es loopback hace falta TELEGRAM_VOICE_LINK_ANY_ADDRESS=true, y una dirección pública siempre se rechaza |
TELEGRAM_VOICE_LINK_ANY_ADDRESS | — | Declaración de que «esta red solo la usan el servidor y la pasarela» |
TELEGRAM_VOICE_TURN_HOST, TELEGRAM_VOICE_TURN_PORT | — | Dirección del relé que se da a la pasarela (la dirección LAN del servidor). Se ignora si es loopback |
TELEGRAM_VOICE_MAX_SECONDS | 600 | La llamada más larga que permite este servidor (de 60 a 3600) |
TELEGRAM_VOICE_BOT_CONCURRENCY | 2 | Tope de llamadas simultáneas de un bot (el operador y el propietario del bot solo pueden bajarlo) |
TELEGRAM_VOICE_TIME_ZONE | Asia/Seoul | Referencia de los límites diarios y mensuales |
TELEGRAM_VOICE_TESTERS | — | Lista de IDs de usuario de testers (se suma a la lista del panel de administración). * solo en servidores de pruebas |
TELEGRAM_VOICE_RECIPIENTS | google.vertex.gemini-live@us-central1 | El destinatario que anuncia la pantalla de confirmación de la aplicación. Tiene que coincidir con el de la pasarela para que la llamada pase |
TELEGRAM_VOICE_MIN_BUILD_DESKTOP, _ANDROID, _IOS, _WATCHOS | 1, 62151, 5, 1 | Primera compilación de la aplicación que de verdad incluye la pantalla de confirmación (en escritorio, el número que sigue a la etiqueta pabal-bc). Si cambia el destinatario, publica una compilación nueva y sube este valor. En escritorio, súbelo a 2 cuando apruebes por primera vez una pantalla de confirmación en un idioma distinto del coreano y el inglés |
TELEGRAM_VOICE_MIN_SHEET_VERSION | 1 | Versión más baja de la pantalla de confirmación que se acepta |
TELEGRAM_VOICE_TOOL_RESULT_BYTES | 16384 | Tamaño máximo de la respuesta de una herramienta (de 1024 a 16384) |
TELEGRAM_VOICE_KEYS_MASTER_FILE, TELEGRAM_VOICE_KEYS_PREVIOUS_MASTER_FILE | — | Clave maestra que cifra las claves propias y los secretos de stream, y la clave anterior durante un cambio. En una carpeta 700, fuera de las copias de seguridad |
TELEGRAM_VOICE_OWN_KEYS_APPS_READY | — | true solo cuando las aplicaciones ya muestren la pantalla de confirmación (versión 2) de los bots con clave propia. Hasta entonces no se aceptan claves propias |
TELEGRAM_VOICE_OWN_KEY_MIN_SHEET_VERSION, TELEGRAM_VOICE_TRANSCRIPT_MIN_SHEET_VERSION | 2, 1 | Versión de la pantalla de confirmación necesaria para las llamadas con clave propia y para el aviso de transcripción (un servidor de producción no baja la de clave propia de 2) |
TELEGRAM_VOICE_STREAM_MIN_BUILD_DESKTOP, _ANDROID, _IOS | 0 (ninguna) | Primera compilación de la aplicación con la pantalla de confirmación del modo stream. Con 0, nadie puede llamar a un bot en modo stream |
TELEGRAM_VOICE_STREAM_MIN_SHEET_VERSION | 2 | Versión de la pantalla de confirmación del modo stream |
TELEGRAM_VOICE_STREAM_DENY_ADDRESSES | — | Direcciones de este despliegue a las que no deben llegar las direcciones de stream (el host público y el del sitio se añaden solos) |
TELEGRAM_WATCH_API_PORT, _HOST, _ANY_ADDRESS, TELEGRAM_WATCH_AUDIO_URL, TELEGRAM_WATCH_ALLOW_PLAIN, TELEGRAM_WATCH_SESSION_DAYS, TELEGRAM_WATCH_AUTH_PER_MINUTE | —, 127.0.0.1, —, —, —, 7, 30 | Direcciones de la API del Apple Watch y del punto de entrada de audio (Instalar el servidor: punto de entrada del Apple Watch). ALLOW_PLAIN es solo para desarrollo |
TELEGRAM_VOICE_EVIDENCE_KEY_DIR | — | La carpeta de la clave con la que se hacen los registros de permisos de las llamadas de bots (pruebas HMAC). 700, fuera de las carpetas de las copias de seguridad. Se crea y se cambia con scripts/voice-evidence-key.py. Sin ella nadie puede activar un permiso. Con Docker Compose, la variable puesta solo en .env no llega al servidor: al activar las llamadas de bots, añádela al pabal-server de deploy/docker-compose.voice.yml, en environment (la ruta dentro del contenedor) y volumes (la carpeta del host) |
TELEGRAM_VOICE_OUTBOUND_MIN_BUILD_DESKTOP, _ANDROID, _IOS, _WATCHOS | 0 (ninguna) | La primera versión de la aplicación con la pantalla de permiso. Las versiones anteriores no pueden activar un permiso y las llamadas de bots no las hacen sonar. 0: ninguna en esa plataforma |
TELEGRAM_VOICE_CALLME_DEVICE_AGE_SECONDS | 86400 | Cuánto tiempo tras iniciar sesión puede un dispositivo activar un permiso (segundos). Solo los servidores de pruebas pueden cambiarlo (un servidor de producción avisa y lo ignora) |
TELEGRAM_VOICE_KEEP_TEXT_UNREVIEWED | — | Muestra en el reloj el texto aún sin revisión legal de la casilla de «Guardar conversación». Solo para servidores de pruebas internos |
TELEGRAM_MCP_*, TELEGRAM_MCP_APPS_READY | — | Componentes MCP (los añade deploy/docker-compose.mcp.yml). TELEGRAM_MCP_EGRESS_OWN_ADDRESSES (las direcciones públicas de Pabal) se usa aunque no haya MCP, para que las peticiones de webhooks y herramientas no puedan ir al propio Pabal |
TELEGRAM_VOICE_BOTS, TELEGRAM_VOICE_NOTICE_CHECK=off, TELEGRAM_VOICE_STREAM_ALLOW_PRIVATE | — | Solo para servidores de pruebas (solo con TELEGRAM_TEST_NUMBERS=true): autorizar los bots de la lista (id o @nombre, * para todos) · saltarse la comprobación de las secciones legales · permitir direcciones privadas como dirección de stream |
TELEGRAM_VOICE_CALLME_UNREVIEWED, TELEGRAM_VOICE_DEV_ECHO_OUTBOUND, TELEGRAM_VOICE_TEST_DIAL, TELEGRAM_VOICE_TEST_DIAL_USERS | — | Solo para servidores de pruebas y de desarrollo: el interruptor de las llamadas de bots se puede encender antes de la revisión legal (servidores de desarrollo y de pruebas) · una pasarela de eco hace las llamadas de los bots (servidores de desarrollo, TELEGRAM_TEST_MODE) · la llamada de prueba de la API de administración y las cuentas que puede hacer sonar (hasta 20 además de los números de prueba +99966, servidores de pruebas). Un servidor de producción avisa y los ignora |
Archivos de datos
| Archivo | Contenido | Permisos |
|---|---|---|
keys/private.pem | Clave privada RSA del servidor. No debe salir nunca del servidor | 600 |
keys/private.pem.pub | Clave pública. Se usa al compilar la aplicación y en /docs/server-key.pem | — |
keys/firebase-service-account.json | (Opcional) Clave secreta de Firebase para las notificaciones push de Android. Si se filtra, bórrala en la consola de Firebase y descarga una nueva | 600 |
data/admin-token | Token del panel de administración | 600 |
data/operations.json | Los valores de la pestaña Ajustes (설정): reglas de registro, secretos de SMS y SMTP, números bloqueados, y los ajustes de la pestaña Voz (interruptor de emergencia, apertura, testers, bots autorizados, límites) | 600 |
keys/voice-link.secret | (Bots de voz) El secreto de enlace, el mismo que el de la pasarela | 400 |
/etc/pabal/voice/voice-master.key | (Bots de voz) Clave maestra que cifra las claves propias de los propietarios de bots y los secretos de stream. Fuera de la carpeta de datos y nunca en las copias de seguridad | 600 (carpeta 700) |
data/media/ | Originales de las fotos y los archivos | — |
Tabla events de PostgreSQL | Cuentas, conversaciones, mensajes, inicios de sesión, bots y ajustes de webhooks: el registro de todos los cambios | — |
Notas de seguridad
- No abras el puerto de administración directamente a internet. En la configuración de producción, Caddy bloquea con un 404 las rutas de administración como
/admin,/healtho/metrics. - Todas las peticiones de datos de administración requieren
Authorization: Bearer <token>, y las páginas de otros sitios no pueden leerlos. - Los secretos de SMS y SMTP solo están en
operations.json; la pantalla y la API solo indican «guardado» (저장됨). Si guardas con un campo de secreto vacío, se mantiene el valor anterior. - Los tokens y los secretos no se escriben en los logs, y los números de teléfono aparecen enmascarados. Las direcciones de la Bot API (que incluyen el token) tampoco se registran.
- Los tokens de dispositivo de las notificaciones push solo quedan en los logs como huella, y ni el contenido del archivo de clave de Firebase ni el de las notificaciones se escribe en los logs.
- Las claves de autorización están en la base de datos, así que quien tenga acceso a la base de datos puede descifrar el tráfico de los usuarios. Protege la base de datos y las copias de seguridad tanto como la clave RSA.
Limitaciones
- Los códigos pendientes y el historial reciente están en memoria, así que se pierden al reiniciar el servidor (basta con volver a pedirlos desde la aplicación).
- El envío real a través de cada proveedor de SMS hay que comprobarlo con la cuenta de cada proveedor. El servidor construye las peticiones según la documentación de cada proveedor.
- Lo que todavía no existe: eliminar bots a la fuerza, leer mensajes, ver logs, gráficos, estadísticas de notificaciones push (las notificaciones push se comprueban en los logs del servidor).