Saltar al contenido
openplate

La aplicación

Variables de entorno

Cada variable que leen la app, el servidor central y el servicio de inferencia, con su valor predeterminado, y los ajustes que impiden el arranque

Esta página es una traducción automática de la documentación en inglés.

Cada ajuste de los tres contenedores de openplate es una variable de entorno. Esta página los lista todos, para la aplicación, el servidor central (openplate-core) y el servicio de inferencia. La mayoría son opcionales. Cuando dejas uno sin definir, se aplica el valor predeterminado de su fila.

Algunos ajustes detienen el arranque a propósito. Un valor que el servicio no pueda usar, o dejar incompleto un par de variables, hace que el contenedor se cierre. El mensaje de salida indica el nombre de la variable. El contenedor no se inicia haciendo suposiciones. Ajustes que detienen el arranque lista cada una de estas reglas.

Cómo definir una variable

  • Docker Compose. Añade la línea en el archivo .env junto al archivo compose, por ejemplo LOG_LEVEL=debug. Luego vuelve a ejecutar docker compose -f <your file> up -d. Cada archivo compose incluido pasa al contenedor las variables que lee su servicio. docker compose restart no vuelve a leer .env.
  • Quadlet. Añade la línea en el archivo <unit>.env junto a la unidad, por ejemplo app.env, core.env o inference.env. Usa los nombres propios del contenedor indicados en esta página. Luego reinicia la unidad, por ejemplo systemctl --user restart core.service. podman.md explica estos archivos.
  • Sin contenedor. La aplicación y el servidor central leen cada uno un archivo .env en la carpeta donde se ejecutan. También puedes definir la variable en la shell o en la unidad de systemd. Sin Docker muestra la configuración de la aplicación.

La columna Predeterminado indica qué hace el servicio si la variable no está definida. Un archivo compose puede pasar un valor propio, por ejemplo MODEL_PROFILE: lite. El archivo compose muestra ese valor junto al nombre.

Nombres que los archivos compose completan por ti

Los tres archivos de topología, compose.core.yml, compose.inference.yml y compose.full.yml, completan algunas variables del contenedor a partir de nombres compartidos en .env. Define allí el nombre compartido. La variable del contenedor por sí sola no tiene efecto en estos archivos.

En .envCompleta
PUBLIC_APP_URLel APP_URL de la aplicación, y el CLIENT_BASE_URL del servidor central
PUBLIC_SYNC_URLel CORE_URL de la aplicación, y el SERVER_PUBLIC_URL del servidor central
PUBLIC_INFERENCE_URLDEFAULT_INFERENCE_BASE_URL de la app
INFERENCE_API_KEYDEFAULT_INFERENCE_API_KEY de la app, y API_KEYS del servicio de inferencia
POSTGRES_USER, POSTGRES_PASSWORD, SYNC_DB_NAMEla base de datos, y el DATABASE_URL del servidor central

docker/compose.yml, la aplicación por sí sola, toma APP_URL bajo su propio nombre. El archivo de inicio rápido propio del servidor central es apps/core/docker/compose.yml. Toma SERVER_PUBLIC_URL y CLIENT_BASE_URL bajo sus propios nombres. Construye DATABASE_URL a partir de POSTGRES_USER, POSTGRES_PASSWORD y POSTGRES_DB.

La app

El contenedor de la app, ghcr.io/lowcarbcheck/openplate. Se inicia sin nada configurado. configuration.md explica a fondo sus funciones principales.

Servidor y direcciones

VariablePor defectoQué haceMás información
NODE_ENVproduction en la imagen; de lo contrario, developmentproduction sirve la app compilada, hace que APP_URL sea obligatoria y establece 1 como el valor predeterminado de TRUST_PROXY. La imagen lo define.
APP_URLhttp://localhost:3000, obligatorios en producciónLa dirección pública que la gente abre, por ejemplo https://openplate.example.com. La página principal la incluye en sus enlaces para compartir. El servidor no se inicia en producción sin ella.Caddy
PORT3000El puerto en el que escucha el servidor.
HOSTsin definir, todas las interfacesLa dirección en la que escucha el servidor. Déjala sin definir en un contenedor. Sin un contenedor, 127.0.0.1 mantiene el servidor en esta máquina, para un proxy en el mismo equipo.Sin Docker
TRUST_PROXY1 en producción, si no, desactivadoCuántos proxies inversos hay delante de la aplicación: un número, true, false, o un preajuste de Express o rango de direcciones como loopback o 10.0.0.0/8. La comprobación que detiene los envíos de formularios entre sitios necesita el valor correcto detrás de un proxy. Usa 0 si no hay proxy.La aplicación por sí sola
CSP_CONNECT_EXTRAsin definirOrígenes adicionales para la directiva connect-src de Content-Security-Policy, separados por espacios. Tu propio endpoint de IA en otro host necesita esto.Endpoints de IA personalizados

Idioma y contenido

VariablePor defectoQué haceMás información
DEFAULT_UI_LANGUAGEenEl idioma que ve quien visita el sitio antes de elegir uno: en, de, fr, it, es o tr. La elección que haga la persona siempre tiene preferencia. Cualquier otro valor detiene el arranque.
NUTRIENT_REFERENCE_BASISdgeLos valores de referencia que cita la pantalla Nutrientes: dge (DGE de Alemania), efsa (UE) o us (NASEM). Cualquier otro valor detiene el arranque.
CONTENT_DIRsin definir, sin páginas legalesUna carpeta de archivos Markdown para las páginas legales, montada como solo lectura. Un valor que no apunte a una carpeta detiene el arranque.Páginas de contenido

Sincronización y tipo de instancia

VariablePor defectoQué haceMás información
CORE_URLsin definir, sincronización desactivadaLa dirección de tu servidor central, tal como accede a ella un navegador. Su origen va a la Content-Security-Policy. En una instancia administrada, el servidor de la aplicación también accede a ella, para comprobar la cuenta de cada consulta de alimentos. Un valor con formato incorrecto detiene el arranque.Sincronización
SYNC_SERVER_URLsin definirEn desuso. El nombre antiguo de CORE_URL. Sigue funcionando durante una versión más, y el arranque registra una advertencia cuando es el único configurado. Si ambos se definen con direcciones distintas, el nombre antiguo prevalece para esta versión y el arranque registra una advertencia que nombra a los dos. Elimina la línea antigua antes de la versión que retire el nombre antiguo.Sincronización
INSTANCE_MODEopenopen o managed. En una instancia administrada, un administrador invita a usuarios, y el servidor central proporciona la IA. managed necesita CORE_URL. Cualquier otro valor detiene el arranque.Instancias gestionadas

IA provista por la instancia

VariablePor defectoQué haceMás información
DEFAULT_INFERENCE_BASE_URLsin definirUn endpoint compatible con OpenAI que esta instancia ofrece a cada visitante, tal como accede a él un navegador. Un valor con formato incorrecto detiene el arranque.IA provista por la instancia
DEFAULT_INFERENCE_API_KEYsin definirLa clave para ese endpoint. Es pública: la recibe el navegador de cada visitante.IA provista por la instancia
DEFAULT_INFERENCE_MODELopenplate-plate-1El nombre del modelo que se envía a ese endpoint.IA provista por la instancia

Base de datos de alimentos

VariablePor defectoQué haceMás información
FOOD_DB_API_URLhttps://lowcarbcheck.orgLa base de datos de alimentos de LowCarbCheck en la que el servidor busca los nombres de los alimentos. Un valor vacío desactiva la búsqueda.La clave de la base de datos de alimentos
FOOD_DB_API_KEYsin definir, el nivel anónimoTu clave de LowCarbCheck. Solo la lee el servidor y nunca llega a un navegador.La clave de la base de datos de alimentos
FOOD_DB_BACKFILLfalsetrue envía a LowCarbCheck como propuestas los alimentos que los usuarios guardan a partir de una respuesta de la IA. Necesita FOOD_DB_API_KEY y permanece desactivado sin ella. Cualquier valor distinto de true o false detiene el arranque.Propuestas a la base de datos de alimentos
FOOD_DB_DAILY_CALL_LIMIT3200El máximo de llamadas a LowCarbCheck que este servidor realiza en un día UTC. Al superarlo, las búsquedas de alimentos se pausan hasta la medianoche UTC y la app muestra un aviso. El valor por defecto se ajusta a las 100 000 mensuales de una clave gratuita. Cualquier valor que no sea un número entero positivo detiene el arranque.La clave de la base de datos de alimentos

Analítica, boletín y actualizaciones

VariablePor defectoQué haceMás información
MATOMO_URLsin definir, analítica desactivadaUna instalación de Matomo que administres tú. Configúrala junto con MATOMO_SITE_ID.Analítica
MATOMO_SITE_IDsin definirEl id de sitio de Matomo, un número entero positivo. Configúralo junto con MATOMO_URL.Analítica
MATOMO_EVENT_LEVELproductCuánto cuenta la instancia: pageviews, product o research. Necesita los dos ajustes anteriores.Qué determina un nivel
NEWSLETTER_SUBSCRIBE_URLsin definir, sin formularioA dónde reenvía el servidor el formulario del boletín de la página de inicio. Configúralo junto con NEWSLETTER_TURNSTILE_SITE_KEY.Suscripción al boletín
NEWSLETTER_TURNSTILE_SITE_KEYsin definirLa clave de sitio de Cloudflare Turnstile de ese formulario. No es el captcha de registro, consulta Registro con Turnstile.Suscripción al boletín
UPDATE_CHECKactivadoSi configuras esto en off o false, el servidor dejará de consultar openplate.de/latest.json para buscar nuevas versiones. También detendrá el recuento diario de peticiones del proyecto.La comprobación de nuevas versiones

Registro de eventos

VariablePor defectoQué haceMás información
LOG_LEVELinfoEl nivel de detalle con el que registra el servidor, como nivel de pino: debug, info, warn o error.

Cerrar una instancia

VariablePor defectoQué haceMás información
MOVED_TO_URLsin definirCierra esta instancia y redirige a los usuarios a otra, por ejemplo https://app.openplate.de. Cada solicitud de página sirve una página que indica la nueva dirección, el service worker instalado en los teléfonos borra sus cachés y anula su registro, y la API devuelve 410. El valor debe ser una dirección https:// en un host distinto de APP_URL; cualquier otra cosa detiene el arranque.Trasladar usuarios a otra instancia

El servidor central (openplate-core)

El contenedor del servidor central, ghcr.io/lowcarbcheck/openplate-core. Necesita dos valores: DATABASE_URL, que los archivos de compose rellenan por ti, y SERVER_SECRET. Todo lo demás es opcional y está desactivado hasta que lo definas. el README de openplate-core explica las funciones.

Servidor y direcciones

VariablePor defectoQué haceMás información
NODE_ENVproduction en la imagenSi configuras el correo, production exige que ambas direcciones de enlace a continuación sean direcciones https:// en otro host.El correo necesita las direcciones públicas
PORT3000El puerto en el que escucha el servicio.
HOSTsin definir, todas las interfacesLa dirección en la que escucha el servicio. No la definas dentro de un contenedor. 127.0.0.1 mantiene una instancia de desarrollo en su propia máquina.
TRUST_PROXYfalseCuántos proxies inversos hay delante: un número, true o false. Con un valor incorrecto detrás de un proxy, todas las solicitudes parecerán proceder del proxy. Una sola persona podría agotar entonces el límite de todos los demás.Tres ajustes importantes
SERVER_PUBLIC_URLsin definirLa dirección pública propia de este servicio. Se incluye en los enlaces de los correos de invitación y de restablecimiento de contraseña. Configúrala junto con CLIENT_BASE_URL.El correo necesita las direcciones públicas
CLIENT_BASE_URLsin definirLa dirección de la app openplate, la otra mitad de esos enlaces.El correo necesita las direcciones públicas
INSTANCE_NAMEopenplateEstablece el nombre de la instancia para la negociación /health (instance.name) y el registro de inicio. Los correos no lo usan. Máximo 64 caracteres.
INSTANCE_LANGUAGEenDefine el idioma de los correos si una solicitud no especifica ninguno. Los valores aceptados son en, de, fr, it, es o tr. Cualquier otro valor detiene el arranque.
NUTRIENT_REFERENCE_BASISdgeUna instancia nueva arranca con uno de estos valores de referencia: dge, efsa o us. Quien administre el sistema puede cambiar este ajuste en vivo más adelante mediante la API de administración. Cualquier otro valor detiene el arranque.
CONTENT_DIRsin definirUna carpeta montada en solo lectura con el texto de las cartas de declaración. La app puede leer sus páginas legales desde esta carpeta. El servicio nunca la comprueba al arrancar.Cartas de declaración
LEGAL_DECLARATION_RECEIPTS_PER_DAY200El máximo de acuses de recibo de declaraciones que la instancia envía por correo en un periodo de 24 horas, sumando todas las direcciones. Después de eso, la declaración se sigue registrando y se te envía, pero se omite su acuse de recibo.Cartas de declaración
LEGAL_DECLARATION_RECEIPTS_PER_NETWORK_PER_DAY10El mismo límite para una red emisora, ya sea una dirección IPv4 o una IPv6 /64. Un reinicio restablece este recuento.Cartas de declaración

Base de datos

VariablePor defectoQué haceMás información
DATABASE_URLninguno, obligatoriosLa cadena de conexión de Postgres. Los archivos compose la generan por ti.
DATABASE_SSLfalseEstablécelo en true si Postgres requiere TLS. Acepta true, false, 1 o 0.
MIGRATIONS_DIRdrizzle/migrationsIndica dónde encuentra el servicio sus migraciones de base de datos al arrancar. La imagen ya las contiene ahí, de modo que no lo definas.

Secretos

VariablePor defectoQué haceMás información
SERVER_SECRETninguno, obligatoriosEl secreto raíz debe tener al menos 32 caracteres. Genéralo con openssl rand -hex 32 y guárdalo en una copia de seguridad junto con la base de datos. Si cambias este secreto, bloquearás de forma permanente el acceso a todas las cuentas.Tres ajustes importantes
ADMIN_TOKENsin definirLa credencial de administración del operador debe tener al menos 24 caracteres. La necesitas para crear la primera cuenta. Sin token ni cuenta de administrador, la API de administración devuelve 404.Crea la primera cuenta

Cuentas y registro

VariablePor defectoQué haceMás información
OPEN_SIGNUPsin definir, solo invitacionestrue permite que cualquiera solicite una cuenta con su propia dirección. Esto requiere correo. El servidor solo acepta true. Cualquier otro valor, incluido false, detiene el arranque.Registro con Turnstile
TURNSTILE_SECRET_KEYsin definir, sin captchaLa clave secreta de Cloudflare Turnstile que verifica el captcha de registro. Defínela junto con TURNSTILE_SITE_KEY, y solo con OPEN_SIGNUP=true.Registro con Turnstile
TURNSTILE_SITE_KEYsin definirLa clave pública de sitio de Turnstile. /health la publica y la app la usa para renderizar el captcha.Registro con Turnstile

Invitaciones y periodos de prueba

VariablePor defectoQué haceMás información
MEMBER_INVITE_DAILY_AI_LIMITsin definir, los miembros no pueden invitarEl número de peticiones de IA por día UTC que recibe una cuenta cuando la invita un miembro, de 1 a 10000. Defínelo junto con MEMBER_INVITE_ALLOWANCE_DAYS.Invitaciones de miembros
MEMBER_INVITE_ALLOWANCE_DAYSsin definirEl número de días tras el registro durante los que dura esta cuota.Invitaciones de miembros
MEMBER_INVITE_LIFETIME_CAP5El total de invitaciones que un miembro puede enviar en total: 0 o más. Requiere el par anterior, o MEMBER_INVITE_TRIAL=true.Invitaciones de miembros
MEMBER_INVITE_TRIALfalsetrue hace que una invitación de miembro otorgue la prueba de escaneos indicada abajo en lugar de la cuota por días. Requiere la prueba y no se puede usar con el par anterior.
TRIAL_SCANSsin definir, sin pruebaLos escaneos de IA gratuitos que recibe una cuenta nueva, de 1 a 100. Defínelo junto con TRIAL_DAILY_AI_LIMIT, y define TRIAL_ADDRESS_PEPPER con ellos.
TRIAL_DAILY_AI_LIMITsin definirEl número de peticiones de IA por día UTC durante la prueba, de 1 a 10000.
TRIAL_DAYSsin definir, sin fecha de finLa prueba también termina a medianoche tras este número de días, de 1 a 90, lo que ocurra primero. Requiere el par de la prueba.
TRIAL_TIME_ZONEUTCLa zona horaria de esa medianoche, como nombre IANA como Europe/Berlin. Requiere TRIAL_DAYS. Una zona desconocida detiene el arranque.
TRIAL_ADDRESS_PEPPERsin definirEl secreto que aplica el límite de una prueba por buzón. Debe tener al menos 32 caracteres. Obligatorio con el par de la prueba. Si cambias este valor, se olvidará qué buzones tuvieron una prueba.
TRIAL_HASH_RETENTION_DAYS365Los días que se conserva el hash del buzón de una cuenta eliminada, de 1 a 3650, contados desde la eliminación. Después, un barrido cada hora lo elimina, y el mismo buzón puede volver a tener una prueba. Una instancia sin prueba de escaneo no conserva ningún hash.
AI_TRIAL_INSTANCE_DAILY_LIMITsin definir, sin límiteEl importe total que todas las cuentas de prueba juntas pueden gastar por día UTC. Requiere la prueba.
AI_TRIAL_NETWORK_DAILY_LIMITuna décima parte de AI_TRIAL_INSTANCE_DAILY_LIMIT, al menos 1La cantidad del límite de prueba que las peticiones de prueba de una misma red (una IPv6 /64 o una única dirección IPv4) pueden gastar por día UTC. Está desactivado sin AI_TRIAL_INSTANCE_DAILY_LIMIT, y no debe ser superior a este. Los usuarios detrás de un mismo CGNAT IPv4 lo comparten.
DEFAULT_FREE_DAILY_AI_LIMITsin definir, desactivadoLas solicitudes de IA por día UTC que recibe cada cuenta que no tiene un límite gratuito propio, de 0 a 10000. Nunca termina y no tiene límite de escaneos. Si se agota el día, responde 429 con Retry-After. Sustituye a la prueba de escaneo, por lo que configurarlo junto con el par de prueba detiene el arranque. Una cuenta que todavía tiene una prueba queda bajo este límite.
DEFAULT_CAPABILITIESsin definir, sin comprobaciónLo que puede utilizar una cuenta que no tiene una lista propia de capacidades: etiquetas separadas por comas como scan,recipes, o none para nada. Si no se define o está vacío, el proxy de IA no comprueba ninguna función y cada solicitud pasa. Una solicitud de una función de la que carece la cuenta recibe 403 capability-required.
CAPABILITY_SCHEMA_MAPsin definir, vacíoPares schemaName:label separados por comas. Una solicitud que pida el esquema de salida estructurada que enumeras necesita esa etiqueta, diga lo que diga su cabecera X-Openplate-Feature.

Correo

VariablePor defectoQué haceMás información
SMTP_HOSTsin definirEl nombre o dirección del servidor SMTP, sin esquema, puerto ni ruta.SMTP
SMTP_PORT587465 usa TLS desde el primer byte. Cualquier otro puerto debe actualizarse con STARTTLS, salvo un interceptor de correo en esta máquina.SMTP
SMTP_USERsin definirEl nombre de usuario SMTP. Defínelo junto con SMTP_PASSWORD, o deja ambos sin definir para un servidor sin autenticación.SMTP
SMTP_PASSWORDsin definirLa contraseña SMTP.SMTP
SMTP_FROMsin definirEl remitente, con formato address o Name <address>. SMTP lo requiere.SMTP
MAIL_API_URLsin definirUna API de correo HTTP compatible con Resend. Defínela junto con MAIL_API_KEY, MAIL_API_FROM y MAIL_OPERATOR_EMAIL.Una API de correo HTTP
MAIL_API_KEYsin definirLa clave de la API de correo, enviada como token Bearer.Una API de correo HTTP
MAIL_API_FROMsin definirLa dirección del remitente para la API de correo.Una API de correo HTTP
MAIL_OPERATOR_EMAILsin definirTu propia dirección. Recibe tu copia de una cancelación o de un desistimiento. Ambos transportes la requieren.SMTP
NODE_EXTRA_CA_CERTSsin definirLa ruta dentro del contenedor a un archivo PEM con entidades de certificación adicionales. Node.js lo lee al iniciar. Monta el archivo si usas un relé de correo cuyo certificado esté firmado por una entidad privada.Un relay con una autoridad de certificación privada

Proxy de IA y límites

VariablePor defectoQué haceMás información
UPSTREAM_BASE_URLsin definir, sin IALa dirección compatible con OpenAI del proveedor, por ejemplo https://openrouter.ai/api/v1. Defínela junto con UPSTREAM_API_KEY.Instancias gestionadas
UPSTREAM_API_KEYsin definirLa clave del proveedor. Nunca llega al navegador.Instancias gestionadas
UPSTREAM_ZDRsin definirSolo OpenRouter. Si lo estableces en true, el proxy pide a OpenRouter que enrute una solicitud únicamente a endpoints con retención de datos cero. Cualquier otro host lo ignora. Un valor distinto de true, false o vacío detiene el arranque.El proxy de IA
UPSTREAM_PROVIDER_ONLYsin definirSolo OpenRouter. Una lista de slugs de proveedores separados por comas, por ejemplo google-vertex. Una solicitud va a uno de ellos o falla, y nunca recurre a otro proveedor. Cualquier otro host lo ignora.El proxy de IA
UPSTREAM_TIMEOUT_MS120000El tiempo en milisegundos que el proxy espera a la primera respuesta del proveedor y, después, entre sus partes.
AI_TIERS_FILEsin definirDe dónde procede el modelo de cada tipo de petición. Si no se define, el modelo es AI_ADVERTISED_MODEL, con el enrutamiento de UPSTREAM_ZDR y UPSTREAM_PROVIDER_ONLY, exactamente igual que antes de que existiera el archivo. bundled usa el archivo de la imagen del núcleo, ai-tiers.json, que reúne el modelo, su enrutamiento y su precio. Una ruta absoluta usa un archivo que montes. Un valor incorrecto o un archivo dañado detiene el arranque.El proxy de IA
AI_ADVERTISED_MODELsin definirEl modelo que usa cada escaneo cuando no hay un archivo de niveles. /health le da nombre, y el proxy lo incluye en cada petición. La aplicación no escanea sin un modelo. Con un archivo de niveles solo anula el modelo del nivel por defecto, como medida de emergencia, y el núcleo registra una advertencia en cada arranque.Instancias gestionadas
AI_MAX_OUTPUT_TOKENS8192El máximo de tokens de salida que puede pedir una petición.
AI_RATE_LIMIT_PER_MINUTE20El máximo de peticiones que una cuenta puede hacer en una ventana de 60 segundos.
AI_INSTANCE_DAILY_LIMITsin definir, sin límiteEl límite diario de la instancia en unidades de IA por día UTC. El escaneo de una foto del plato cuesta una unidad.El proxy de IA
AI_BUDGET_ALERT_FRACTION0.2En una clave de OpenRouter, envía un correo a MAIL_OPERATOR_EMAIL una vez por período de restablecimiento cuando quede menos de esta fracción del límite de la clave. Debe ser mayor que 0 y menor que 1.El proxy de IA
AI_MAX_REQUEST_BYTES8000000La petición más grande que acepta el proxy, en bytes.
AI_MAX_IMAGE_PARTS1Máximo de imágenes por solicitud. Las solicitudes que superen este límite devuelven 400 ai-request-too-large antes de iniciar el recuento.
AI_MAX_TEXT_BYTES49152Máximo de bytes de texto por solicitud, sumando el texto del mensaje y response_format. Las solicitudes que lo superen devuelven el mismo 400.
AI_MAX_MESSAGES4Máximo de mensajes por solicitud. Las solicitudes que superen este límite devuelven el mismo 400.
AI_UNIT_INPUT_TOKENS8192Tokens de entrada estimados por cada unidad de IA. Cada solicitud cuesta una unidad, más una por cada AI_UNIT_INPUT_TOKENS adicional. Los límites diarios contabilizan estas unidades.El proxy de IA
AI_IMAGE_INPUT_TOKENS1500Tokens de entrada estimados para una imagen. El texto se calcula dividiendo sus bytes totales entre 4.
VariablePor defectoQué haceMás información
HEALTH_CONSENT_VERSIONsin definir, no se pide consentimientoLa versión del consentimiento sobre datos de salud que debe aceptar cada cuenta, como 2026-09-28. Usa de 1 a 32 letras, dígitos, ., _ o -. Si cambias la versión, se vuelve a pedir a todo el mundo.Consentimiento explícito

Push

VariablePor defectoQué haceMás información
VAPID_PUBLIC_KEYsin definir, no hay notificacionesLa clave pública para web push. Define las tres o ninguna. Genera un par con pnpm core-api push keygen.
VAPID_PRIVATE_KEYsin definirLa clave privada para web push.
VAPID_SUBJECTsin definirLa forma en que te contacta un servicio push: una dirección mailto: o una dirección https://.
PUSH_ENDPOINT_HOSTSsin definirHosts de push adicionales separados por comas que un dispositivo puede registrar. *.example.org cubre todos los hosts bajo example.org. Los servicios push predeterminados del navegador se permiten siempre. Configura esto solo para hosts personalizados. Una entrada mal formada detiene el arranque.

Planes

VariablePor defectoQué haceMás información
PLANS_UPSTREAM_URLsin definir, no hay planesLa dirección interna del servicio de facturación que recibe /v1/plans/*. Defínela junto con PLANS_UPSTREAM_SECRET.Planes de pago
PLANS_UPSTREAM_SECRETsin definirEl secreto compartido que comprueba el servicio de facturación.Planes de pago
BILLING_TOKENsin definirLa credencial propia del servicio de facturación, de al menos 24 caracteres. Solo tiene acceso a tres rutas de administración.Planes de pago
BILLING_MAX_DAILY_AI_LIMIT1000Límite diario máximo de IA que BILLING_TOKEN puede asignar a una cuenta. Mantenlo igual o por encima de tu plan más alto. ADMIN_TOKEN no está sujeto a él.Planes de pago

Comentarios, uso compartido e investigación

VariablePor defectoQué haceMás información
SYNC_FEEDBACKfalsetrue acepta las estimaciones reportadas junto con sus fotos, guardadas durante 30 días. Puedes ver esas fotos.Estimaciones notificadas
FEEDBACK_DAILY_LIMIT5Los informes que puede enviar una cuenta por día UTC.
FEEDBACK_MAX_REQUEST_BYTES8000000El informe más grande que acepta el servicio, en bytes.
SYNC_SHARINGfalsetrue activa compartir un diario con un médico.
SYNC_RESEARCHfalsetrue activa las contribuciones para investigación y la consola del estudio.Sincronización

Registro y otros

VariablePor defectoQué haceMás información
LOG_LEVELinfodebug, info, warn o error. Cualquier otro valor detiene el arranque.
SYNC_NOTICEsin definirUn mensaje corto que muestra cada aplicación al conectarse, de 280 caracteres como máximo.
SYNC_NOTICE_URLsin definirUn enlace junto al aviso, https:// o http://. Necesita SYNC_NOTICE.
SERVICE_VERSIONsin definir, la versión de la imagenSustituye la versión que informa /health. Déjalo sin definir.

El servicio de inferencia (openplate-inference)

El contenedor de inferencia, ghcr.io/lowcarbcheck/openplate-inference. Ejecuta el runtime del modelo y el servicio en un único contenedor. Guía de configuración de openplate-inference explica las opciones en detalle.

Servicio y acceso

VariablePor defectoQué haceMás información
PORT8300El puerto en el que escucha el servicio. Es el único puerto que publica el contenedor.
API_KEYSsin definir, una clave temporalLas claves que quien llama debe enviar, separadas por comas. Si no se define, el servicio crea una clave al iniciar, la muestra una vez y la olvida en el siguiente reinicio.Obtener la clave
LOG_LEVELinfodebug, info, warn o error. Cualquier otro valor detiene el arranque.
PROFILEdefinido a partir de MODEL_PROFILEEl nombre del perfil que muestra el registro de inicio: lite, quality o custom. El contenedor lo establece a partir de MODEL_PROFILE y no cambia nada más.

Modelo y pesos

VariablePor defectoQué haceMás información
MODEL_PROFILEliteLos pesos que el contenedor descarga y ejecuta: lite, lite-apache o quality. external no descarga nada y usa tu propio runtime en MODEL_RUNTIME_URL.Hardware
MODELS_DIR/modelsDónde se guardan los pesos en el contenedor, en un volumen. Cámbialo solo si montas los pesos en otro sitio.
WEIGHTS_MIRROR_BASEsin definirUn servidor espejo desde el que descargar los pesos, con Hugging Face como alternativa. El servicio comprueba las sumas de verificación en ambos casos.
MODEL_RUNTIME_URLhttp://127.0.0.1:8080, el runtime integradoLa dirección de tu propio runtime, sin /v1. MODEL_PROFILE=external la requiere. Con cualquier otro perfil, una dirección diferente detiene el contenedor.Variables del modo externo
MODEL_RUNTIME_API_KEYsin definirUna clave que el servicio envía a tu runtime, para un runtime o proxy que la requiera.Variables del modo externo
MODEL_IDopenplate-plate-1El nombre del modelo que el servicio envía al runtime. vLLM necesita su nombre exacto servido.Variables del modo externo
RUNTIME_PORT8080El puerto del llama-server integrado, solo en la dirección de bucle local del contenedor.
CONTEXT_SIZE8192El contexto para cada escaneo en curso. El contenedor lo multiplica por CONCURRENCY para llama.cpp.
LLAMA_THREADSel número de núcleos menos dos, al menos 1Los hilos de CPU para llama.cpp.
LLAMA_EXTRA_ARGSsin definirFlags adicionales para el final del comando llama-server, separados por espacios. Solo para el runtime integrado.
GPU_LAYERSdetectado: 99 con una GPU, de lo contrario 0Cuántas capas del modelo van a la GPU. 0 fuerza el uso de la CPU.
NVIDIA_VISIBLE_DEVICESestablecido por el runtime de contenedores de NVIDIALo define --gpus all. Cualquier valor distinto de void o none hace que el contenedor use la GPU. No lo configuras tú.

Límites

VariablePor defectoQué haceMás información
CONCURRENCY2Los análisis en curso a la vez. También define las ranuras de llama.cpp.
MAX_QUEUE_DEPTH8Los análisis que pueden esperar. A partir de aquí, quien llama recibe un 429.
RATE_LIMIT_RPM60Las solicitudes por minuto para cada clave.
LATENCY_CEILING_MS0, desactivadoEl servicio rechaza cualquier análisis que no pueda completar en esta cantidad de milisegundos.Hardware
RUNTIME_COMPLETION_TIMEOUT_MS600000El tiempo máximo que puede durar una llamada al runtime, en milisegundos. 0 desactiva el límite.
MAX_IMAGE_BYTES8388608La foto más grande que acepta el servicio tras decodificarla, en bytes (8 MiB).
IMAGE_MAX_LONG_EDGE896El lado largo al que el servicio reduce cada foto, en píxeles, como mínimo 112.

Datos de alimentos

VariablePor defectoQué haceMás información
FOOD_SOURCEfdcDe dónde proceden los macros: fdc (el extracto del USDA en la imagen, sin red), off (Open Food Facts), lcc (LowCarbCheck) o none.Datos de alimentos
FDC_DATASET_PATH./data/fdc-foods.jsonEl extracto del USDA, relativo al directorio de trabajo.
OFF_API_URLhttps://world.openfoodfacts.orgLa dirección de Open Food Facts, leída con FOOD_SOURCE=off.
LCC_API_URLhttps://lowcarbcheck.orgLa dirección de LowCarbCheck, leída con FOOD_SOURCE=lcc.
LCC_API_KEYsin definir, el nivel anónimoTu clave de LowCarbCheck, leída con FOOD_SOURCE=lcc.
EMBEDDING_RUNTIME_URLsin definirUn runtime compatible con OpenAI que sirve /v1/embeddings, para mejorar la correspondencia de alimentos.
EMBEDDING_RUNTIME_API_KEYsin definirLa clave para ese runtime.

Ajustes que detienen el arranque

Un contenedor que no arranca se nota de inmediato y solo cuesta un reinicio. Un ajuste que se ignora en silencio te hace creer que algo funciona cuando no es así. Por eso, cada regla de abajo detiene el arranque y el registro indica la variable.

Nombres rechazados

Estos nombres fueron ajustes en su momento. Ahora el servicio rechaza arrancar mientras alguno esté definido, e indica qué usar en su lugar. El servidor central los rechaza incluso con un valor vacío, así que elimina la línea. La aplicación rechaza GATEWAY_URL solo cuando tiene un valor.

VariableRechazado porUsa en su lugar
GATEWAY_URLla appINSTANCE_MODE=managed. El servidor central asumió el control del proxy de IA.
SIGNUP_MODEel servidor centralNada. Las cuentas proceden de invitaciones y OPEN_SIGNUP=true permite pedir una.
SIGNUPS_OPENel servidor centralNada, por el mismo motivo.
REQUIRE_EMAIL_VERIFICATIONel servidor centralNada. La invitación sirve como verificación de la dirección.
EMAIL_FROMel servidor centralMAIL_API_FROM, o SMTP_FROM.
SMTP_SECUREel servidor centralNada. SMTP_PORT decide el cifrado.
PIGEON_API_KEYel servidor centralMAIL_API_KEY, o SMTP_USER y SMTP_PASSWORD.
PIGEON_BASE_URLel servidor centralMAIL_API_URL, o SMTP_HOST.

Reglas entre variables

La app.

  • MATOMO_URL y MATOMO_SITE_ID: define ambas o ninguna. MATOMO_EVENT_LEVEL necesita ambas.
  • NEWSLETTER_SUBSCRIBE_URL y NEWSLETTER_TURNSTILE_SITE_KEY: define ambas o ninguna.
  • INSTANCE_MODE=managed necesita CORE_URL.
  • CORE_URL y el obsoleto SYNC_SERVER_URL: define uno. Si ambos se definen con direcciones distintas, SYNC_SERVER_URL prevalece para esta versión y el arranque registra una advertencia.
  • APP_URL es obligatorio cuando NODE_ENV=production.
  • MOVED_TO_URL debe ser una dirección https:// en un host distinto de APP_URL, sin nombre de usuario ni contraseña.
  • Un valor ajeno a su lista detiene el arranque: DEFAULT_UI_LANGUAGE, NUTRIENT_REFERENCE_BASIS, INSTANCE_MODE, MATOMO_EVENT_LEVEL y FOOD_DB_BACKFILL. También lo detiene un FOOD_DB_DAILY_CALL_LIMIT que no sea un número entero positivo. Direcciones mal formadas en CORE_URL, DEFAULT_INFERENCE_BASE_URL, MATOMO_URL o NEWSLETTER_SUBSCRIBE_URL también impiden arrancar. El arranque se detiene asimismo si MATOMO_SITE_ID no es un número entero positivo o si CONTENT_DIR no es una carpeta.

El servidor central.

  • DATABASE_URL y SERVER_SECRET son obligatorios.
  • Longitudes mínimas: 32 caracteres para SERVER_SECRET y TRIAL_ADDRESS_PEPPER, 24 para ADMIN_TOKEN y BILLING_TOKEN.
  • El correo utiliza un solo transporte. La API HTTP de correo necesita MAIL_API_URL, MAIL_API_KEY, MAIL_API_FROM y MAIL_OPERATOR_EMAIL, los cuatro. SMTP necesita SMTP_HOST, SMTP_FROM y MAIL_OPERATOR_EMAIL, y SMTP_USER y SMTP_PASSWORD van juntos. Las variables de ambos transportes a la vez detienen el arranque, al igual que MAIL_OPERATOR_EMAIL sin ningún transporte.
  • El correo necesita SERVER_PUBLIC_URL y CLIENT_BASE_URL. Con NODE_ENV=production, ambas deben ser direcciones https:// en otro host, no localhost.
  • Define ambas o ninguna: UPSTREAM_BASE_URL y UPSTREAM_API_KEY; PLANS_UPSTREAM_URL y PLANS_UPSTREAM_SECRET; TURNSTILE_SECRET_KEY y TURNSTILE_SITE_KEY; MEMBER_INVITE_DAILY_AI_LIMIT y MEMBER_INVITE_ALLOWANCE_DAYS; TRIAL_SCANS y TRIAL_DAILY_AI_LIMIT.
  • Define las tres o ninguna: VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY y VAPID_SUBJECT.
  • X requiere Y: OPEN_SIGNUP=true requiere correo. El par de Turnstile requiere OPEN_SIGNUP=true. MEMBER_INVITE_LIFETIME_CAP requiere el par de invitación a miembros o MEMBER_INVITE_TRIAL=true. MEMBER_INVITE_TRIAL=true requiere el par de prueba y rechaza el par de invitación a miembros. El par de prueba requiere TRIAL_ADDRESS_PEPPER. TRIAL_DAYS y AI_TRIAL_INSTANCE_DAILY_LIMIT requieren el par de prueba. AI_TRIAL_NETWORK_DAILY_LIMIT requiere AI_TRIAL_INSTANCE_DAILY_LIMIT. TRIAL_TIME_ZONE requiere TRIAL_DAYS. SYNC_NOTICE_URL requiere SYNC_NOTICE.
  • El cero se rechaza donde se leería como "desactivado" y significaría lo contrario: AI_INSTANCE_DAILY_LIMIT, AI_TRIAL_INSTANCE_DAILY_LIMIT, AI_TRIAL_NETWORK_DAILY_LIMIT, TRIAL_SCANS, TRIAL_DAILY_AI_LIMIT, TRIAL_DAYS, MEMBER_INVITE_DAILY_AI_LIMIT y MEMBER_INVITE_ALLOWANCE_DAYS. Cualquier otro número debe ser positivo también, salvo dos que aceptan 0: TRUST_PROXY y MEMBER_INVITE_LIFETIME_CAP, donde 0 deja a los miembros sin nada que enviar.
  • Límites máximos: TRIAL_SCANS 100, TRIAL_DAYS 90, TRIAL_DAILY_AI_LIMIT y MEMBER_INVITE_DAILY_AI_LIMIT 10000, SYNC_NOTICE 280 caracteres, INSTANCE_NAME 64 caracteres.
  • SYNC_SHARING, SYNC_RESEARCH, SYNC_FEEDBACK, DATABASE_SSL y MEMBER_INVITE_TRIAL admiten true, false, 1 o 0. OPEN_SIGNUP solo admite true.
  • Un valor fuera de su lista detiene el arranque: INSTANCE_LANGUAGE, NUTRIENT_REFERENCE_BASIS, LOG_LEVEL, TRIAL_TIME_ZONE y HEALTH_CONSENT_VERSION. Un VAPID_SUBJECT que no sea mailto: o https: detiene el arranque. También lo hace un SMTP_HOST con esquema, puerto o ruta. Las direcciones con formato incorrecto en SERVER_PUBLIC_URL, CLIENT_BASE_URL, UPSTREAM_BASE_URL, PLANS_UPSTREAM_URL o SYNC_NOTICE_URL también detienen el arranque.

El servicio de inferencia.

  • MODEL_PROFILE=external requiere MODEL_RUNTIME_URL. Con cualquier otro perfil, un MODEL_RUNTIME_URL distinto de la dirección integrada detiene el contenedor.
  • Un MODEL_PROFILE, FOOD_SOURCE, PROFILE o LOG_LEVEL fuera de su lista detiene el arranque. Un MODEL_RUNTIME_URL o EMBEDDING_RUNTIME_URL que no sea una dirección http:// o https:// también detiene el arranque.
  • Los recuentos y tamaños deben ser números enteros positivos. LATENCY_CEILING_MS y RUNTIME_COMPLETION_TIMEOUT_MS también admiten 0. IMAGE_MAX_LONG_EDGE debe ser de al menos 112, y PORT como máximo 65535.

Registro con Turnstile

De forma predeterminada, una cuenta solo se obtiene mediante una invitación. Define OPEN_SIGNUP=true en el servidor central, y cualquiera podrá solicitar una cuenta con su propia dirección. Entonces, el servicio envía una invitación por correo a esa dirección, y el mensaje demuestra que la dirección funciona. Por tanto, el registro abierto necesita correo, y el servicio no arranca sin él. La aplicación muestra el formulario de registro solo cuando el servidor central indica que su acceso está abierto.

Un captcha evita que los scripts saturen el servicio a peticiones. El servidor central comprueba un captcha de Cloudflare Turnstile cuando configuras dos claves:

  1. Inicia sesión en el panel de Cloudflare, abre Turnstile y elige Add widget. Una cuenta gratuita es suficiente. No es necesario que tu dominio use Cloudflare.
  2. Pon un nombre al widget, añade el nombre de host de tu app, como openplate.example.com, y mantén el modo Gestionado. Elige Crear.
  3. Define la clave de sitio en TURNSTILE_SITE_KEY y la clave secreta en TURNSTILE_SECRET_KEY en el servidor central. Define ambas claves o ninguna.
  4. Vuelve a crear el servidor central, por ejemplo con docker compose -f <your file> up -d.

/health publica entonces la clave de sitio. La página de registro de la aplicación muestra el captcha. Su botón de envío permanece inactivo hasta que el usuario lo resuelve. La clave secreta nunca sale del servidor central. El servicio envía a Cloudflare la respuesta del captcha y la clave secreta, no la dirección del visitante.

El servicio comprueba solo la solicitud de registro, POST /v1/auth/signup-request. Iniciar sesión, abrir una invitación y todas las demás rutas no llevan captcha. Cuando el servicio no puede comunicarse con Cloudflare, devuelve 503, y la persona puede intentarlo de nuevo más tarde. La comprobación falla de forma cerrada, por lo que una solicitud sin respuesta nunca se aprueba.

La directiva Content-Security-Policy de la aplicación permite el captcha de Cloudflare solo en una instancia gestionada (INSTANCE_MODE=managed), o cuando el formulario del boletín está activo. En otras instancias, el navegador bloquea el captcha y nadie puede enviar el formulario. Configura la aplicación en modo gestionado antes de activar el captcha.

Sin las dos claves, el registro abierto sigue funcionando. Sus otros límites siguen vigentes. El servicio permite cinco solicitudes por hora desde una misma dirección, y un mensaje al día para un mismo buzón. Bloquea direcciones de servicios de correo desechable conocidos. El servicio registra una advertencia al arrancar.

NEWSLETTER_TURNSTILE_SITE_KEY es un ajuste independiente. Pertenece a la aplicación y protege el formulario del boletín en la página de inicio. Su clave secreta se queda en el servicio que recibe dicho formulario, no en openplate. Suscripción al boletín lo explica.

Compilar una imagen por tu cuenta

Los Dockerfiles aceptan varios argumentos de compilación. No son ajustes para un contenedor en ejecución. OPENPLATE_BUILD_SHA estampa el commit en el paquete de la aplicación. La imagen de inferencia toma BASE_IMAGE, la imagen del servidor de llama.cpp sobre la que se compila. También toma NODE_IMAGE, la imagen de Node.js para la compilación. VITE_ALLOWED_HOSTS se aplica solo al servidor de desarrollo de la aplicación y no tiene hosts predeterminados.

Edita esta página en GitHub