Saltar al contenido principal

Variables de entorno del backend

El backend valida su configuración al arrancar contra src/shared/infrastructure/services/environment-service/env-schema.json, que declara 31 variables.

La mayoría trae un valor por defecto en el propio esquema, así que su ausencia no impide arrancar. Sólo 7 están marcadas como obligatorias y sin defecto —ZERTIAUTH_APP_ID, RADIATION_API, RADIATION_API_CREDENTIALS, ENERGY_PREDICTION_API, TRADE_UPDATE_DAYS, STRIPE_PRODUCT_ID y STRIPE_PRICE_KEY—, y si falta una de ésas el proceso aborta. Las siete están escritas literalmente en el docker-compose.yml, de modo que en la práctica nunca faltan.

Dónde se definen​

No hay archivos .env. Toda la configuración está escrita literalmente en el docker-compose.yml de la raíz, dentro del bloque environment: de cada servicio. Para cambiar un dominio, un puerto o un servicio externo se edita ahí y se vuelve a levantar el stack.

La única excepción son dos valores, que llegan del entorno y no tienen valor por defecto:

DB_PASSWORD · JWT_SECRET

  • En Portainer: se ponen en «Environment variables» del stack.
  • En local: ./setup.sh (o setup.bat) los genera al azar y los escribe en un .env. No hay que elegirlos ni teclearlos.

Si falta alguno, el stack no arranca y dice cuál. Es deliberado: más vale un fallo visible que una base de datos creada con la contraseña vacía. La plantilla está en .env.production.example.

El resto de claves —las de Google, Zertiauth, Stripe, PK…— no detienen el arranque: sin ellas el sistema funciona y sólo se pierde la función que dependa de cada una. Ver Gestión de secretos.

Nunca subas los secretos al repositorio

Entre ellos están la clave secreta de Stripe, una clave privada de blockchain y ZERTIAUTH_APP_SECRET, que es una clave maestra: permite derivar la cartera de cualquier usuario.

Esta página explica qué significa cada valor, esté donde esté definido.

Base de datos​

VariableTipoDescripción
DATABASE_URLstringCadena de conexión que usa Prisma. Formato mysql://usuario:password@host:puerto/base. Con el Docker local: mysql://root:root@127.0.0.1:3306/zertipower-dev.
DB_HOSTstringHost que usan las consultas SQL directas (mysql2), independientes de Prisma.
DB_USERstringUsuario para esas consultas directas.
DB_PASSWORDstringContraseña para esas consultas directas.
DB_DATABASEstringNombre de la base de datos.
Dos rutas de acceso a la misma base

El backend usa Prisma y consultas SQL crudas con mysql2. Prisma lee DATABASE_URL; las consultas crudas leen DB_HOST/DB_USER/DB_PASSWORD/DB_DATABASE. Si ambos grupos no apuntan al mismo sitio, obtendrás errores incoherentes muy difíciles de diagnosticar. Manténlos sincronizados.

Servidor​

VariableTipoDescripción
PORTintPuerto de escucha de la API. Por defecto 3000.
JWT_SECRETstringClave de firma de los tokens JWT — y bastante más, ver el aviso de abajo.
APPLICATION_NAMEstringNombre que aparece en los logs. Normalmente API.
VIEWS_FOLDERstringCarpeta de plantillas hbs (correo, páginas públicas). Valor esperado: src/shared/infrastructure/views/public.
JWT_SECRET es una clave maestra, no sólo la de las sesiones

El backend la reutiliza para cuatro cosas que no tienen nada que ver entre sí:

UsoDónde
Firmar y verificar los tokens de sesiónauth/infrastructure/services/jose-jwt/JoseJWT.service.ts
Cifrar y descifrar las claves privadas guardadas en la base de datosauth/…/auth.controller.ts, communities/communities.controller.ts
Derivar la cartera de cada comunidad — JWT_SECRET + nombrecommunities/communities.controller.ts
Derivar carteras por referencia — keccak256(referencia + JWT_SECRET)shared/infrastructure/services/contract-helpers.ts, minter-service.ts
Cifrar y descifrar las credenciales de Datadis de cada CUPScups/cups.controller.ts, customers/customers.controller.ts, communities/communities.controller.ts

Consecuencia: cambiarla no cierra sólo las sesiones. Deja ilegibles las claves privadas que ya estaban cifradas y las credenciales de Datadis —con lo que el sistema deja de poder descargar los datos de consumo— y cambia las direcciones de las carteras derivadas de comunidades y referencias.

En un sistema que ya tiene datos, rotarla es una migración —hay que descifrar y volver a cifrar con la clave nueva, y asumir que las carteras derivadas cambian—, no un cambio de configuración. Está al mismo nivel que ZERTIAUTH_APP_SECRET.

En una instalación nueva, sin datos, se elige libremente: openssl rand -base64 48.

Lo comparten tres servicios (backend, smart-meter-backend y realtime-energy-api) y el valor debe ser idéntico en los tres, porque unos firman tokens que otros verifican.

URLs de los frontends​

VariableTipoDescripción
FRONTEND_URLstringURL del Panel de Administración (http://localhost:4201). Se usa en redirecciones, no en CORS.
COMPTADOR_FRONTEND_URLstringURL del Contador / Smart Meter (http://localhost:4200).

La Calculadora no tiene variable propia y no la necesita: CORS es permisivo (cors: true en main.ts) y la Calculadora no recibe redirecciones del backend.

Google OAuth​

Estas variables son las del botón «Iniciar sesión con Google» del Panel. El Contador no las usa: delega su login en Zertiauth, que tiene su propio cliente. Cómo crear el cliente, pantalla por pantalla, en Acceso con Google, paso a paso.

VariableTipoDescripción
GOOGLE_CLIENT_IDstringClient ID de OAuth del Panel, propio de cada despliegue. No es secreto: viaja en la URL a la que Google redirige. Opcional: sin él el sistema arranca y sólo deja de funcionar el botón «Iniciar sesión con Google»; se entra con usuario y contraseña.
GOOGLE_CLIENT_SECRETstringClient secret del mismo cliente. Secreto. Opcional, igual que el ID: sin él sólo deja de funcionar ese botón. Mezclarlo con el ID de otro cliente da invalid_client.
GOOGLE_CALLBACK_URLstringA dónde devuelve Google al usuario tras autenticarse. Debe coincidir exactamente con la URI registrada en Google Cloud Console, o Google responde redirect_uri_mismatch.
GOOGLE_MAPS_API_KEYstringClave de Google Maps, para geocodificar direcciones. Opcional: sin ella el sistema arranca y sólo falla esa conversión. La comparten el Panel y la Calculadora, allí como argumento de construcción. Es de navegador: se protege restringiéndola por dominio, no ocultándola.

Derivación de carteras​

VariableTipoDescripción
ZERTIAUTH_APP_IDstringIdentificador de la aplicación. No es secreto: ya aparece en el código de los frontends.
ZERTIAUTH_APP_SECRETstringSecreto de la aplicación (columna secret de la tabla apps de Zertiauth). Clave maestra. Opcional: sólo se usa al derivar la cartera en el primer acceso con Google de cada usuario. Vacía es segura —falla con un error claro—; inventada no, porque deriva carteras equivocadas sin avisar.

La cartera de cada usuario se deriva así:

privateKey = keccak256("<idGoogle>-<ZERTIAUTH_APP_ID>-<ZERTIAUTH_APP_SECRET>")
Cambiarlas invalida todas las carteras

Si cambia cualquiera de las dos, todas las carteras cambian y los usuarios pierden el acceso a sus cuentas y a lo que tengan on-chain. Y como el id de Google no es secreto, quien tenga ZERTIAUTH_APP_SECRET puede derivar la clave privada de cualquier usuario.

Servicios externos​

VariableTipoDescripción
RADIATION_APIstringEndpoint del servicio de radiación solar (Wattabit).
RADIATION_API_CREDENTIALSstringCredenciales en formato literal usuario:password. El separador : es obligatorio.
ENERGY_PREDICTION_APIstringEndpoint del servicio de predicción (repositorio zp_energy_pred).
DATADIS_MONTHSintMeses de histórico a descargar de Datadis en cada sincronización.
TRADE_UPDATE_DAYSstringVentana en días para recalcular los intercambios de energía.

Estos servicios se consumen contra los endpoints reales también en local: no hay mocks. Sin conectividad, las tareas programadas que los usan fallan, pero el arranque del backend no se ve afectado.

Blockchain​

VariableTipoDescripción
PKstringClave privada (64 caracteres hexadecimales) con la que se firman las transacciones on-chain. Opcional: sin ella el sistema arranca y sólo queda inerte la capa blockchain. El instalador genera una al azar para no tener que preguntarla, pero es una cartera nueva, sin fondos ni permisos sobre los contratos: sirve para arrancar, no para firmar.
Secreto crítico

PK es una clave privada. Quien la posea controla la wallet asociada y sus fondos. No la escribas en tickets, capturas ni documentación.

Stripe​

VariableTipoDescripción
STRIPE_PRODUCT_IDstringIdentificador del producto (prod_…).
STRIPE_PRICE_KEYstringIdentificador del precio (price_…).
STRIPE_SECRET_KEYstringClave secreta de la API. Opcional: sin ella el sistema arranca y sólo dejan de funcionar los endpoints /stripe, que usa una única pantalla del Contador. En local debe ser siempre una clave de test (sk_test_…).

SMTP​

VariableTipoDescripción
SMTP_USERstringUsuario del servidor de correo.
SMTP_DISPLAY_EMAILstringDirección que aparece como remitente.
SMTP_PASSWORDstringContraseña SMTP.
SMTP_SERVERstringHost del servidor SMTP.
SMTP_PORTintPuerto, habitualmente 465 (SSL).

En local pueden dejarse valores ficticios: el backend arranca igualmente y sólo fallará el envío real de correo (recuperación de contraseña, notificaciones).

Frontends: no usan .env​

Los tres frontends Angular se configuran mediante archivos TypeScript en src/environments/:

MóduloArchivoClave a apuntar al backend
Panel Adminfrontend/src/environments/environment.development.tsapi_url: "http://localhost:3000"
Calculadoracalculadora/src/environments/environment.development.tsapi_url: "http://localhost:3000"
Contadorris3cat-smart-meter/src/environments/environment.development.tszertipower_url: "http://localhost:3000"

ng serve usa la configuración development, que sustituye environment.ts por environment.development.ts mediante fileReplacements en angular.json.