Solución de problemas
Los errores que puedes encontrar al instalar Northstack, qué causa cada uno y cómo solucionarlo.
Para el paquete Full Stack
Docker no se está ejecutando
failed to connect to the docker API at unix:///…/docker.sock; check if the path is correct and if the daemon is runningLas versiones antiguas de Docker muestran "Cannot connect to the Docker daemon" en su lugar. En ambos casos, el motor de Docker no está iniciado.
Abre Docker Desktop
Inicia Docker Desktop y espera a que indique que el motor está en ejecución. En Linux, inicia el servicio:
sudo systemctl start docker.Comprueba que Docker responde
Terminaldocker infoResultado esperado: Muestra una sección Server en lugar de un error.
Vuelve a ejecutar tu comando de inicio
docker compose up --buildpara el paquete Full Stack, o tus comandosdocker buildydocker runpara una sola aplicación.
Un puerto ya está en uso
ports are not available: exposing port TCP 0.0.0.0:3031 … bind: address already in use
Bind for 0.0.0.0:3031 failed: port is already allocated
Error: listen EADDRINUSE: address already in use :::3031Las dos primeras líneas vienen de Docker, la última de yarn dev. Otro programa ya escucha en el 3030, el 3031 o el 8000: a menudo una ejecución anterior de Northstack, o el servidor de desarrollo de otro proyecto.
Averigua qué ocupa el puerto
En macOS o Linux, con el puerto del mensaje:
Terminallsof -i :3031En Windows, en PowerShell:
Terminalnetstat -ano | findstr :3031Detenlo
Cierra ese programa, o detén la ejecución anterior: Ctrl+C en su terminal,
docker compose downen su carpeta, odocker stoppara un contenedor que iniciaste condocker run. Luego inicia Northstack de nuevo.O ejecuta Northstack en otros puertos
Con el full stack en Docker, crea un archivo llamado
.enven la carpetanorthstack-full-stack, junto adocker-compose.yml, con el puerto que necesites.SITE_PORTmueve el sitio web,ADMIN_PORTel panel yAPI_PORTla API; las direcciones que usan las aplicaciones,CORS_ORIGINincluido, las siguen por sí solas.northstack-full-stack/.envADMIN_PORT=3041Luego ejecuta el mismo comando otra vez. Un inicio fallido continúa donde se detuvo. Docker nombra un solo puerto ocupado cada vez: si se detiene en otro, añade ese también al
.env.Terminalennorthstack-full-stackdocker compose up --buildResultado esperado: La aplicación responde en su nuevo puerto, aquí localhost:3041Local.
Para una sola aplicación iniciada con docker run, cambia el número a la izquierda de -p, por ejemplo -p 3041:3031. Un frontend que habla con una API también se construye con su nueva dirección (NEXT_PUBLIC_BASE_URL para el panel, NEXT_PUBLIC_SITE_URL para el sitio web), y esa dirección va al CORS_ORIGIN de la API, y a su DASHBOARD_URL y FRONTEND_URL (el panel) o WEBSITE_URL (el sitio web). Sin Docker, el puerto del sitio web está en los scripts de su package.json (yarn next dev -p 3040 para otro), el del panel es PORT en su .env, y el de la API es PORT en su .env. Mueve la API junto con PUBLIC_API_URL, PUBLIC_MEDIA_URL y el NEXT_PUBLIC_API_BASE_URL de ambos frontends (también el NEXT_PUBLIC_WEBSOCKET_BASE_URL del panel).
La construcción de Docker falla
La primera construcción descarga las imágenes base y todas las dependencias, y luego construye las imágenes. Si algo lo impide, se detiene con "failed to solve" y el paso que falló.
- Sin conexión o tiempo de espera agotado: la construcción necesita acceso a internet. Vuelve a ejecutar el comando cuando tengas conexión; los pasos terminados quedan en caché.
- No space left on device: libera espacio en Docker Desktop o revisa cuánto usa Docker con
docker system df. - Falla siempre en el mismo paso: vuelve a construir sin la caché y luego inicia.
- Compose rechaza el propio `docker-compose.yml`, nombrando `env_file`: tu Compose es anterior a la 2.24. Actualiza Docker Desktop, o el plugin de Compose en Linux.
northstack-full-stackdocker compose build --no-cache
docker compose upEn un paquete de una sola aplicación, añade --no-cache a tu comando docker build.
Un primer inicio que parece atascado suele seguir cargando los espacios de trabajo de ejemplo y las 732 organizaciones que hay detrás de las cifras de la plataforma. El sitio web y el panel inician solo cuando la API informa de que está sana.
Yarn dice que su versión es 1.22
This project's package.json defines "packageManager": "yarn@4…". However the current global version of Yarn is 1.22…Cada aplicación fija Yarn 4.8.1 mediante Corepack. Este mensaje significa que Corepack aún no está activado, así que respondió el antiguo Yarn global.
corepack enableLuego ejecuta yarn install otra vez. Si tu Node.js no tiene Corepack (Node.js 25 y posteriores lo omiten), instálalo antes con npm install -g corepack. No se usan npm ni pnpm: cada aplicación incluye su propio yarn.lock.
Una instalación o un inicio falla con una versión antigua de Node.js
La API necesita Node.js 22.13 o una versión 22 posterior, o Node.js 24.11 o más reciente; el sitio web y el panel por sí solos necesitan Node.js 22.9 o más reciente. Las imágenes de Docker usan Node.js 24. Un Node.js más antiguo se nota en una instalación que no logra construir un paquete, o en una aplicación que se detiene al iniciar.
node -vSi muestra una versión anterior, instala Node.js 24 (o una versión 22 desde la 22.13), ejecuta corepack enable de nuevo (en Node.js 25 y posteriores, antes npm install -g corepack), luego elimina la carpeta node_modules de la aplicación y ejecuta yarn install de nuevo. Node.js 23, y las versiones 24 anteriores a la 24.11, también quedan fuera del rango de la API. Con Docker nada de esto se aplica: las imágenes traen su propio Node.js.
La API se detiene antes de iniciarse
The API cannot start: JWT_SECRET is not set. Set it in back-end/.env to the output of: …
The API cannot start: JWT_SECRET is still the example value from .env.example, so anyone can sign a token for any account. …
The API cannot start: CORS_ORIGIN is not set. List the website and dashboard origins, comma separated, …La API revisa sus ajustes antes de iniciarse y muestra una línea por cada problema. Las causas:
- No hay archivo `.env`, o `JWT_SECRET` está vacío. Crea el archivo en la carpeta de la API con
cp .env.example .env. - `JWT_SECRET` sigue siendo el valor de ejemplo con `NODE_ENV=production`. Cualquiera podría firmar un token con el ejemplo público, así que un inicio en producción lo rechaza. Genera tu propio secreto.
- `CORS_ORIGIN` está vacío con `NODE_ENV=production`. Escribe las direcciones del sitio web y del panel, separadas por comas.
Genera un secreto con:
node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"Con Docker no necesitas uno: un contenedor sin un JWT_SECRET propio, o con el de ejemplo, genera un secreto y lo guarda en el volumen de datos.
Nadie puede iniciar sesión en una base de datos nueva
Sin Docker, yarn dev con NODE_ENV=development crea las tablas en su primer inicio, pero ninguna cuenta: las cuentas y los espacios de trabajo de ejemplo vienen de yarn seed. Detén la API, ejecútalo en la carpeta de la API e iníciala de nuevo.
yarn seed
yarn devTermina con Seed complete. y las cuentas con las que iniciar sesión. Si falla, muestra Seeding failed: seguido del motivo, como una base de datos MySQL que aún no existe. La imagen de Docker carga un volumen SQLite nuevo por sí sola; en MySQL, ejecuta node dist/database/seeder.js una vez en el contenedor.
Una base de datos iniciada vacía (yarn schema, o Docker con SEED_SAMPLE_DATA=false y sin ADMIN_EMAIL ni ADMIN_PASSWORD) tampoco tiene ninguna cuenta, a propósito. Crea tu primer administrador de la plataforma con yarn admin:create (compilado: yarn admin:create:prod; Docker: docker compose exec -u node api node dist/database/create-admin.js), que pide el correo y los datos de acceso.
El inicio de sesión falla
That email and password do not match an account. Try again.
Too many failed sign-in attempts. Wait 15 minutes, then try again.- Revisa la cuenta. Todas las cuentas inician sesión en el panel, en el puerto
3031; el sitio web no tiene inicio de sesión propio, y sus botones Live demo abren el inicio de sesión del panel. Las cuentas de ejemplo y su contraseña están en la página de instalación. - El mismo mensaje responde a una contraseña incorrecta, a un correo desconocido y a una base de datos que nunca se cargó con los datos de ejemplo. Revisa lo que escribiste; en una base de datos nueva,
yarn seeden la carpeta de la API crea las cuentas. - "Too many failed sign-in attempts. Wait 15 minutes, then try again." Diez inicios de sesión fallidos desde una misma dirección en 15 minutos rechazan todo nuevo intento desde ella, también con la contraseña correcta, hasta que el fallo más antiguo cumple 15 minutos. Espera, o reinicia la API: la cuenta se guarda en su memoria.
RATE_LIMIT_LOGINen el.envde la API cambia el número. - "New sign-ups are closed on this platform right now." en la página de registro o en el alta inicial: el personal de la plataforma ha desactivado New sign-ups en los ajustes de la plataforma. Las cuentas existentes siguen iniciando sesión.
- Cambiaste una contraseña y ya no la tienes: empieza de nuevo con datos de demostración nuevos, más abajo.
- Has iniciado sesión, pero la página muestra el aviso de datos de ejemplo: el panel no pudo llegar a su API y respondió con sus datos de ejemplo. Consulta el siguiente problema.
El inicio de sesión falla
- Revisa la cuenta y la ruta. Todas las cuentas inician sesión en
POST /api/auth/login; las cuentas de ejemplo y su contraseña están en la página de instalación. Un inicio de sesión fallido responde401con el mismo mensaje tanto si el correo como si la contraseña son incorrectos. - Ninguna cuenta funciona: la base de datos se creó sin los datos de ejemplo. Ejecuta
yarn seedpara las cuentas de ejemplo, oyarn admin:createpara tu propio administrador de la plataforma, como en el problema anterior. - Una respuesta `429` significa que una dirección falló 10 inicios de sesión en 15 minutos. Se levanta cuando el fallo más antiguo cumple 15 minutos, o cuando la API se reinicia.
RATE_LIMIT_LOGINcambia el número.
Un aviso de datos de ejemplo aparece al final de cada página
No API is connected, so this dashboard runs on built-in sample data and your changes stay in this browser. …
The API at http://localhost:8000/api is not answering, so this dashboard is showing built-in sample data, not your workspace's. …El sitio web dice lo mismo con sus propias palabras. Cada frontend lleva datos de ejemplo integrados y responde con ellos en dos casos:
- "No API is connected": la aplicación se inició o se construyó con
NEXT_PUBLIC_API_BASE_URLvacío, o sin ningún.env. Así funciona un paquete de un solo frontend por sí solo. Para usar una API, defínela en.envcon la dirección de la API y/api(http://localhost:8000/api, como en.env.example), y reiniciayarn devo construye de nuevo; con Docker, construye sin--build-arg NEXT_PUBLIC_API_BASE_URL=. - "The API at … is not answering": hay una dirección definida, pero el navegador no puede llegar a ella. La API no está en marcha, funciona en otra dirección, o no incluye la dirección de esta aplicación en su
CORS_ORIGIN(consulta el siguiente problema). Comprueba que localhost:8000/api/ healthLocal responde y recarga la página. La aplicación vuelve a intentar con la API por sí sola.
Mientras los datos de ejemplo la sustituyen, lo que cambias se guarda solo en ese navegador, y en el panel entra cualquier contraseña. Entretanto el navegador sigue probando la dirección y registra cada petición rechazada en su consola, así que deja la dirección vacía cuando no hay API. El sitio web muestra el aviso en yarn dev, y en una versión de producción solo si se construyó con NEXT_PUBLIC_SAMPLE_DATA_NOTICE=always (--build-arg NEXT_PUBLIC_SAMPLE_DATA_NOTICE=always con Docker); las páginas que renderiza su servidor nunca recurren a ellos.
El navegador dice "blocked by CORS policy"
Access to XMLHttpRequest at 'http://localhost:8000/api/…' from origin 'http://localhost:3041' has been blocked by CORS policyLa consola del navegador muestra esta línea cuando un frontend funciona en una dirección que la API no acepta. Una petición rechazada cuenta como una API que no responde, así que el frontend recurre a sus datos de ejemplo en el navegador: el panel muestra el aviso de datos de ejemplo, y el sitio web también en yarn dev. La API responde a los navegadores solo desde las direcciones de CORS_ORIGIN, que por defecto son http://localhost:3030 y http://localhost:3031. Un sitio web o un panel movido a otro puerto, o servido en tu propio dominio, se rechaza hasta que figure en la lista.
CORS_ORIGIN=http://localhost:3030,http://localhost:3041
FRONTEND_URL=http://localhost:3041
DASHBOARD_URL=http://localhost:3041- Escribe cada dirección exactamente como la muestra el navegador, con el esquema y el puerto y sin barra final, separadas por comas. Luego reinicia la API.
FRONTEND_URLes la dirección del panel, desde la que se conectan sus actualizaciones de permisos en vivo, yDASHBOARD_URLla que se escribe en los enlaces de invitación y de restablecimiento. Mueve ambas junto con el panel; mueveWEBSITE_URLcon el sitio web.- Para un contenedor de la API, pasa los mismos valores con
-e, por ejemplo-e CORS_ORIGIN=http://localhost:3030,http://localhost:3041. - Con el paquete completo en Docker no editas estos valores: los configuran
SITE_PORT,ADMIN_PORT,SITE_URLyADMIN_URLen el.envjunto adocker-compose.yml. - Un frontend que no llega a la API en absoluto, porque está detenida o en otra dirección, falla de la misma forma pero sin la línea de CORS. Comprueba que localhost:8000/
api/ healthLocal responde y que NEXT_PUBLIC_API_BASE_URLdel frontend apunta a esa API.
El recibo del pago tarda en cargar en Docker
El propio servidor del sitio web lee las opciones del pago y el recibo de un pedido mientras renderiza esas páginas. Dentro de un contenedor localhost es el propio contenedor, así que ese servidor no puede llegar a una API de tu equipo en http://localhost:8000. Las páginas se completan igualmente en el navegador, que llega a la API directamente.
Inicia el contenedor del sitio web con la dirección de la API tal como la ve el servidor:
docker run -p 3030:3030 -e API_INTERNAL_URL=http://host.docker.internal:8000/api --add-host=host.docker.internal:host-gateway northstack-websiteLa pila completa en Docker lo define por ti (http://api:8000/api). Sin Docker no hace falta.
Una invitación o un correo de restablecimiento nunca llega
Mientras no se defina SMTP_HOST en el .env de la API, no se envía ningún correo. La API lo indica al iniciar, y cada mensaje (invitaciones, resúmenes semanales, restablecimientos de contraseña, recibos de licencia, correos de facturación y mensajes de contacto reenviados) se escribe en su registro, con sus enlaces:
Mail is not set up (SMTP_HOST is empty): invitations, weekly digests, billing emails, password resets, licence receipts and forwarded contact messages are written to this log instead of being sent.
Message to …: …- Full stack en Docker: ejecuta
docker compose logs apien la carpeta del paquete y abre el enlace del mensaje más reciente. - Sin Docker: léelo en la terminal donde se ejecuta el
yarn devde la API. - Contenedor de la API:
docker logscon el id del contenedor (docker pslo muestra). - Para enviar correo real, define
SMTP_HOSTy los demás valoresSMTP_*, y reinicia la API. Un mensaje que el servidor rechaza se registra comoCould not sendcon el motivo. - Una invitación dura siete días; después su página dice "This invitation has expired." Envía una nueva desde la página Team.
- No llega ningún correo de facturación (un pago fallido, una prueba terminada, un cambio de plan): van solo al propietario del espacio de trabajo, a sus miembros de facturación y a su correo de facturación, y solo mientras Email notifications esté activado en Settings, Notifications del espacio de trabajo.
- Aún no hay resumen semanal: sale los lunes desde las 08:00 UTC, mientras Weekly digest esté activado. El primer ciclo de una instalación nueva solo marca la semana actual, y el primer resumen de un espacio de trabajo nuevo cubre su primera semana completa.
Un pago abre el pago de prueba
Los dos flujos de pago abren un pago de prueba integrado mientras la API no tiene claves para ellos, y ninguno cobra a nadie:
- Change plan en la página de facturación del panel abre la página Test checkout, "Confirm the … plan", hasta que se define
STRIPE_SECRET_KEY(o siempre, conBILLING_PROVIDER=simulator). Manage payment method dice entonces "The test checkout keeps no card, so there is no payment method to manage." - El pago de licencias del sitio web dice "Test mode: payments go through this site's test checkout and charge nobody." y abre su propia página Test checkout. La tarjeta usa Stripe cuando se define
STRIPE_SECRET_KEY, y PayPal cuando se definenPAYPAL_CLIENT_IDyPAYPAL_CLIENT_SECRET. - Una clave de prueba de Stripe muestra "Test mode: no real money moves." En la página de Stripe, paga con la tarjeta
4242 4242 4242 4242, cualquier fecha futura y cualquier CVC. - "Confirming the payment..." o un recibo que dice que el pago aún se está confirmando: la API pide la sesión a Stripe mientras la página espera, y en un servidor el webhook en
/api/billing/webhooks/stripela confirma al instante. Un plan cambia solo cuando el pago está confirmado. - "The checkout expired. Start again from Change plan." Una sesión de pago que se dejó abierta demasiado tiempo; inicia una nueva.
- Los pagos de Stripe se completan pero las renovaciones, los pagos fallidos o las cancelaciones nunca aparecen en un servidor:
STRIPE_WEBHOOK_SECRETestá vacío o es incorrecto. El registro de la API diceSTRIPE_WEBHOOK_SECRET is emptyal iniciar, y el panel de Stripe muestra cada entrega rechazada con un 400. Defínelo con el secreto de firma del endpoint del webhook y reinicia la API.
Errores tras una actualización
Tras actualizar el código sobre una base de datos que conservas, las peticiones pueden fallar con una tabla o columna ausente en el registro de la API, como no such column en SQLite o Unknown column en MySQL. No hay migraciones, y en producción la API nunca cambia las tablas por sí sola, así que llévalas una vez al nuevo código. Haz antes una copia de seguridad de la base de datos: la actualización también elimina una columna que el código ya no tiene.
yarn build
yarn schema:prodCon Docker, ejecútalo en el contenedor de la API en marcha: docker compose exec -u node api node dist/database/schema.js.
Todos ven "Closed for maintenance."
El ajuste de la plataforma Maintenance mode está activado. Mientras no se desactive, solo el personal de la plataforma puede usar el panel y la API responde a todos los demás con un 503. En la pantalla de mantenimiento pulsa Platform staff sign in, inicia sesión como administrador de la plataforma y desactiva maintenance_mode en la página Settings de la plataforma. Entretanto, el formulario de contacto y el pago de licencias del sitio web siguen funcionando.
Un cambio en el .env de un frontend no tiene efecto
Cada valor NEXT_PUBLIC_* del .env del sitio web y del panel se compila en el JavaScript que carga el navegador cuando se construye la aplicación, así que editar el archivo no cambia nada hasta que se vuelve a construir.
- Con `yarn dev`: deténlo y ejecuta
yarn devde nuevo. - Con `yarn build` y `yarn start`: ejecuta
yarn buildde nuevo. - Con Docker Compose: pon el valor en el
.envjunto adocker-compose.yml(los puertos ySITE_URL,ADMIN_URL,API_URL), no en la carpeta de la aplicación, y ejecutadocker compose up --build. - Para la imagen de una sola aplicación: constrúyela de nuevo con el valor como
--build-arg.
El propio .env de la API solo necesita un reinicio. El PORT del panel y el API_INTERNAL_URL del sitio web se leen cuando la aplicación inicia.
El asistente pide una clave, o un proveedor rechaza
Use your own API key
The server has no key for this provider. Add your own and the assistant works fully. …El asistente responde con Google Gemini, OpenAI o DeepSeek, y el .env de la API no tiene ninguna clave de proveedor hasta que añades una, así que no se factura nada. La API lo indica al iniciar (No AI provider key is set), y al enviar un mensaje se abre Use your own API key. Añade ahí tu propia clave, que se queda en tu navegador y se usa solo para tus peticiones, o dale una al servidor:
- Añade
GOOGLE_API_KEY,OPENAI_API_KEYoDEEPSEEK_API_KEYal.envde la API y reinicia la API. - Con Docker Compose, copia primero
back-end/.env.exampleaback-end/.env, añade la clave y ejecutadocker compose up --buildde nuevo. - La clave propia de quien lee se usa antes que la del servidor, así que quien añadió una se factura con ella aunque el servidor tenga una clave.
… has no requests left on this API key right now. Pick a different model from the list above the chat, or try again in a few minutes.Esa respuesta significa que el proveedor rechazó por sus propios límites. Elige otro modelo en el selector, o espera y pulsa Try again. Cualquier otro rechazo, como una clave que el proveedor no aceptó, muestra el mensaje del propio proveedor. Solo con los datos de ejemplo el asistente no responde en absoluto: dice que necesita la API.
En modo demostración, el asistente pide la clave propia del visitante
Incluido con tu compra. Inicia sesión para leerlo o ábrelo en tu descarga.
Por qué una demostración pública deja de pagar los mensajes del asistente de un visitante.
El formulario de contacto o el pago dice que lo intentes más tarde
You have sent several messages in the last hour. Try again later.
Too many attempts from this address. Try again in an hour.Cada dirección puede enviar cinco mensajes de contacto e iniciar diez pagos de licencia por hora; el registro del panel permite diez por hora, y las peticiones de restablecimiento de contraseña cinco en 15 minutos. La propia respuesta 429 de la API nombra la acción y la espera, como "Too many sign-ups from this address. Wait an hour, then try again." Espera, o reinicia la API mientras pruebas, porque los recuentos viven en su memoria. Detrás de un proxy inverso, define TRUST_PROXY=1 en el .env de la API, o todos los visitantes comparten el único cupo del proxy; lo mismo vale para el límite de inicios de sesión.
MySQL se niega a cargar los datos
yarn seed con DB_TYPE=mysql crea las tablas en una base de datos que ya existe; no crea la base de datos en sí. Seeding failed: seguido de Unknown database significa que falta, y Access denied que DB_USERNAME o DB_PASSWORD es incorrecto.
mysql -u root -p -e "CREATE DATABASE northstack"Luego ejecuta yarn seed de nuevo. La imagen de Docker carga solo SQLite: con MySQL, ejecuta node dist/database/seeder.js (o node dist/database/create-admin.js para empezar vacío) una vez en el contenedor de la API con el mismo entorno.
El comando unzip falla o la carpeta se ve distinta
caution: filename not matched: …zipEsto significa que hay dos ZIP del mismo paquete en la carpeta, como una descarga antigua junto a la nueva, y el * de unzip -q northstack-full-stack-*.zip coincidió con ambos. Borra el ZIP antiguo y ejecuta el comando de nuevo, o escribe el nombre completo del archivo.
- Si falta
unzip, extrae el ZIP en tu gestor de archivos. Algunas herramientas añaden una carpeta extra con el nombre del ZIP: entra en la interior. - El Full Stack se extrae en
northstack-full-stack, conback-end,dashboard,websiteydocker-compose.yml. - Las aplicaciones individuales se extraen en
northstack-website,northstack-dashboardynorthstack-backend, cada una con su propioDockerfile.
Empieza de cero con datos de demostración nuevos
Esto elimina tus datos
Todo lo que creaste (proyectos, miembros, archivos subidos, cambios de plan) desaparece, y los espacios de trabajo de ejemplo vuelven tal como se cargaron.
Con el full stack en Docker, en la carpeta northstack-full-stack:
docker compose down -v
docker compose upCon el contenedor de la API solo, elimina el contenedor (docker rm -f con su nombre), luego el volumen, y ejecútalo de nuevo:
docker volume rm northstack-api-data
docker run -p 8000:8000 -v northstack-api-data:/data northstack-apiSin Docker, detén la API y ejecuta esto en su carpeta (en PowerShell, Remove-Item database.sqlite*; yarn seed):
rm -f database.sqlite* && yarn seedEn MySQL, ejecuta yarn reset (vacía todas las tablas) y luego yarn seed.
Ejecutar yarn seed en una base de datos que conservas no es un reinicio: cuando la base de datos ya tiene cuentas, no añade ninguna cuenta ni espacio de trabajo, y solo devuelve sus permisos a los roles de plataforma integrados.