Ir al artículo
Aniq-UI

NorthstackDespliega Northstack

Despliega Northstack

Pon en línea el sitio web, el panel y la API: Docker Compose en un servidor, una aplicación por host desde su Dockerfile, o Node.js simple, empezando vacío con tu propio administrador de la plataforma y actualizando las tablas tras una actualización.

Para el paquete Full Stack

Tres formas de desplegar

FormaIdeal paraQué necesitas
Docker Compose en un servidorUn VPS que controlas, las tres aplicaciones juntasEl paquete Full Stack, Docker en el servidor, un proxy inverso para HTTPS
Una aplicación por host, desde su DockerfileRailway, Render, Fly.io y otros hosts que construyen desde un DockerfileLa carpeta de cada aplicación; un volumen o MySQL, y opcionalmente un bucket, para la API
Node.js sin másCualquier host con NodeNode.js 22.13 o una versión 22 posterior, o 24.11 o más reciente, y Yarn 4 en el host

Elijas la forma que elijas, el sitio web y el panel compilan la dirección de la API en su JavaScript cuando se construyen, así que constrúyelos con las direcciones públicas, nunca con las locales.

Docker Compose en un servidor

Copia la carpeta del paquete al servidor y pon un .env junto a docker-compose.yml con las tres direcciones públicas. De ellas se derivan los orígenes permitidos de la API, los enlaces que escribe en invitaciones, restablecimientos de contraseña y retornos del pago, los enlaces de descarga de facturas, la dirección de los archivos y la dirección de la API para los frontends.

.env junto a docker-compose.yml
SITE_URL=https://www.your-domain.com
ADMIN_URL=https://app.your-domain.com
API_URL=https://api.your-domain.com

Luego construye e inicia en segundo plano:

Terminal
docker compose up --build -d
  • Apunta cada dominio al servidor mediante un proxy inverso que sirva HTTPS (Caddy, Nginx o Traefik), reenviando a los puertos 3030, 3031 y 8000.
  • Copia back-end/.env.example a back-end/.env para las claves de pago, correo, almacenamiento, IA y MCP: el contenedor de la API lo lee cuando existe, y docker-compose.yml conserva los valores que deben ser distintos dentro de un contenedor. Detrás del proxy, define allí TRUST_PROXY=1, para que el límite de inicios de sesión cuente a cada visitante y no al proxy.
  • Sin un JWT_SECRET propio, la API genera uno en su primer inicio y lo guarda en el volumen northstack-data. La base de datos y los archivos subidos también viven en ese volumen, así que haz una copia de seguridad.
  • Para una instalación real, inicia el volumen nuevo vacío: pon SEED_SAMPLE_DATA=false en el archivo .env junto a docker-compose.yml (no en back-end/.env: Compose pasa estos tres desde allí), con ADMIN_EMAIL y ADMIN_PASSWORD para tu primer administrador de la plataforma, antes del primer docker compose up. El .env junto a docker-compose.yml no llega a la API para esto. Consulta Empezar vacío más abajo.
  • Con su valor por defecto (SEED_SAMPLE_DATA=true), el primer inicio en un volumen nuevo carga los espacios de trabajo de ejemplo y sus cuentas, todas con la contraseña publicada. Hazlas tuyas antes de que la pila sea accesible, como en Empezar con los datos de ejemplo más abajo.

La API desde su Dockerfile

Apunta el host a la carpeta de la API (back-end/ en el Full Stack). La imagen se ejecuta con NODE_ENV=production, escucha en PORT (8000 salvo que el host defina otro), responde a GET /api/health cuando su base de datos tiene el esquema, y guarda SQLite y los archivos subidos en /data.

  • Monta un volumen persistente en /data. Sin él, cada despliegue empieza con una base de datos nueva.
  • Define SEED_SAMPLE_DATA=false, con ADMIN_EMAIL y ADMIN_PASSWORD, para que un volumen nuevo empiece con tu propio administrador de la plataforma y sin datos de ejemplo. Con true, el valor por defecto, un volumen nuevo se carga con las cuentas de ejemplo y su contraseña publicada.
  • Define CORS_ORIGIN con las direcciones del sitio web y del panel (separadas por comas), FRONTEND_URL y DASHBOARD_URL con la del panel, WEBSITE_URL con la del sitio web, PUBLIC_API_URL con la dirección pública de la API y PUBLIC_MEDIA_URL con esa dirección seguida de /media.
  • En SQLite, un volumen sin base de datos se crea una sola vez, según lo que diga SEED_SAMPLE_DATA; una base de datos existente nunca se vuelve a cargar y sus tablas nunca se cambian al iniciar (consulta Actualizar más abajo).
  • Define tu propio JWT_SECRET, o deja que el contenedor genere uno y lo guarde en /data/.jwt-secret.
  • Define TRUST_PROXY=1: una plataforma de alojamiento pone un proxy delante del contenedor.
  • En MySQL (DB_TYPE=mysql y las cinco variables DB_*), el contenedor no crea las tablas. Ejecuta node dist/database/create-admin.js una vez con el mismo entorno (o node dist/database/seeder.js para una instalación de ejemplo).
  • Las subidas en el volumen sobreviven a un nuevo despliegue; para mantenerlas fuera del servidor, define las cinco variables R2_* para un bucket.

El sitio web y el panel desde sus Dockerfiles

Apunta el host a la carpeta de la aplicación y dale los valores NEXT_PUBLIC_* como argumentos de construcción, no como variables de ejecución: se compilan dentro. Cada imagen sirve el servidor independiente de Next.js en PORT (3030 para el sitio web, 3031 para el panel, salvo que el host defina otro).

Argumento de construcciónAplicaciónValor
NEXT_PUBLIC_API_BASE_URLAmbosLa dirección pública de la API seguida de /api. Con su valor por defecto, http://localhost:8000/api, una aplicación desplegada llama al propio equipo del visitante.
NEXT_PUBLIC_SITE_URLSitio webLa dirección pública del sitio web: enlaces canónicos, alternativas de idioma, el mapa del sitio y las tarjetas para compartir
NEXT_PUBLIC_DASHBOARD_URLSitio webLa dirección pública del panel, que abren Live demo, Explore the demo, See role controls, el Sign in de /error/401 y las direcciones /auth/* del sitio
NEXT_PUBLIC_BASE_URLPanelLa dirección pública del panel: robots.txt, el mapa del sitio y los metadatos
NEXT_PUBLIC_WEBSITE_URLPanelLa dirección pública del sitio web, para los enlaces de Documentation, Privacy y Terms
NEXT_PUBLIC_WEBSOCKET_BASE_URLPanelOpcional. La dirección pública de la API sin /api, para las actualizaciones de permisos en vivo; si está vacía usa NEXT_PUBLIC_API_BASE_URL sin su /api

El servidor del sitio web también lee la API mientras renderiza el pago y su recibo. Con una dirección pública de la API que también funcione desde el servidor, no hace falta nada más; API_INTERNAL_URL en tiempo de ejecución la sustituye cuando el servidor debe usar otra dirección.

Node.js sin más

Construye cada aplicación una vez en el host y luego inicia. Define el .env de los frontends con las direcciones públicas antes de yarn build.

AplicaciónConstrucciónInicio
APIyarn build, y una vez en una base de datos nueva yarn admin:create:prodyarn start:prod
Panel de espacios de trabajoyarn buildyarn start (puerto 3031, o PORT en su .env)
Sitio web públicoyarn buildyarn start (puerto 3030)

La API se enlaza a 0.0.0.0 y lee PORT. Mantén el archivo SQLite y MEDIA_UPLOAD_DIR en un almacenamiento que sobreviva a un despliegue, o usa MySQL y un bucket. En producción la API nunca crea ni cambia las tablas por sí sola: yarn admin:create:prod las crea con tu primer administrador de la plataforma, y yarn schema:prod las actualiza tras una actualización.

Empezar vacío, con tu propio administrador de la plataforma

Una instalación real empieza sin datos de ejemplo y con una cuenta tuya. En la carpeta de la API, después de yarn build:

Terminal
yarn admin:create:prod
  • Crea las tablas, los roles de la plataforma y los ajustes de la plataforma, y el primer administrador de la plataforma a partir de ADMIN_EMAIL y ADMIN_PASSWORD (de 8 a 128 caracteres) en el entorno o en back-end/.env. Pide en la terminal el que esté vacío, y ADMIN_NAME es opcional.
  • No crea ningún espacio de trabajo ni cuenta de ejemplo, y se niega si ya existe un administrador de la plataforma. Inicia sesión con esa cuenta y crea tu espacio de trabajo en el alta inicial.
  • yarn admin:create hace lo mismo desde el código fuente, sin construir.
  • Con Docker, SEED_SAMPLE_DATA=false hace esto en el primer inicio: con ADMIN_EMAIL y ADMIN_PASSWORD definidos crea el administrador, y sin ellos crea solo las tablas y su registro indica el comando que ejecutar después, docker compose exec -u node api node dist/database/create-admin.js (con docker run, docker exec -it -u node <container> node dist/database/create-admin.js).

Nunca cargues datos de ejemplo en un servidor público

yarn seed:prod y yarn seed son solo para una instalación de ejemplo: cargan las cuentas de ejemplo con la contraseña publicada en esta guía. Cualquiera que la lea podría iniciar sesión como tu administrador de la plataforma.

Actualizar: las tablas tras una actualización

No hay migraciones, y en producción la API nunca cambia las tablas por sí sola. Tras una actualización cuyo código cambie las tablas, haz una copia de seguridad de la base de datos, construye y lleva las tablas al nuevo código antes de iniciar la API:

Terminal
yarn build
yarn schema:prod
yarn start:prod
  • yarn schema:prod no escribe datos. Añade lo nuevo, y también elimina una columna que el código ya no tiene, con sus datos, así que la copia de seguridad va primero.
  • Con Docker, un volumen existente se deja como está al iniciar. Cuando la nueva imagen esté en marcha, aplica el esquema en ella: docker compose exec -u node api node dist/database/schema.js (con docker run, docker exec -u node <container> node dist/database/schema.js).

Empezar con los datos de ejemplo

Cada carga de datos crea los espacios de trabajo de ejemplo y sus personas, los seis inicios de sesión documentados y todas las demás cuentas de ejemplo, todos con la misma contraseña publicada, y la imagen de Docker carga un volumen nuevo por sí sola salvo que SEED_SAMPLE_DATA=false. Si empiezas con los datos de ejemplo, haz tuya la instalación antes de que sea accesible desde internet:

  1. Haz tuyo el administrador de la plataforma de ejemplo: inicia sesión como platform@northstack.example, cambia su nombre y correo en Settings, Profile, y su contraseña en Settings, Security.
  2. Para tu propio espacio de trabajo, regístrate en el panel con tu propio correo: el alta inicial crea el espacio de trabajo, contigo como propietario. O haz tuyo el propietario de ejemplo de la misma forma y cambia el nombre de Forma Studio en Settings, General.
  3. En la página Users de la plataforma, Delete las cuentas de ejemplo que no necesites, o usa Change password en las que conserves. Una cuenta que es propietaria de un espacio de trabajo se rechaza hasta que otro miembro lo posea (desde la página Team de ese espacio) o el espacio se elimine (en su Settings, Danger zone).
  4. Define tu propio JWT_SECRET, para que un token de inicio de sesión creado antes del cambio deje de funcionar.

Una carga de datos crea las cuentas y los espacios de trabajo de ejemplo solo en una base de datos que aún no tiene ninguna cuenta. Cuando ya existen cuentas, volver a ejecutar yarn seed o yarn seed:prod no añade ninguna cuenta ni espacio de trabajo y solo devuelve sus permisos a los roles de plataforma integrados, así que una cuenta de ejemplo que renombraste o eliminaste nunca vuelve con la contraseña publicada.

Pasar a producción

Antes de que Northstack sea accesible desde internet:

  1. En el entorno de la API, NODE_ENV=production y un JWT_SECRET propio, largo y aleatorio (Docker genera uno cuando no hay ninguno). En producción la API se niega a iniciar con el secreto de ejemplo o sin CORS_ORIGIN, e indica qué valor está mal.
  2. CORS_ORIGIN con el sitio web y el panel, FRONTEND_URL y DASHBOARD_URL con el panel, WEBSITE_URL con el sitio web, PUBLIC_API_URL con la API y PUBLIC_MEDIA_URL con la API seguida de /media.
  3. Tu clave de Stripe en vivo y su webhook en /api/billing/webhooks/stripe en la dirección de la API, con STRIPE_WEBHOOK_SECRET: sin él la API lo indica en su registro al iniciar y rechaza cada entrega, así que las renovaciones y los pagos fallidos nunca se registran. Para PayPal, las claves de la aplicación en vivo con PAYPAL_ENV=live.
  4. Impuestos configurados para tu país: Northstack no cobra ninguno por sí mismo.
  5. Los ajustes SMTP_*, o nadie recibe invitaciones, restablecimientos de contraseña ni recibos de licencia.
  6. La base de datos y las subidas en almacenamiento persistente, con una copia de seguridad.
  7. La comprobación de estado del host en /api/health, y TRUST_PROXY=1 detrás de un proxy.
  8. Ambos frontends construidos con los valores públicos de NEXT_PUBLIC_*.
  9. Tu marca en cada frontend, y las páginas legales del sitio web reescritas para tu negocio y tu país.
  10. Sin cuentas de ejemplo: iniciado vacío con yarn admin:create:prod o SEED_SAMPLE_DATA=false, o con las de ejemplo eliminadas o sus contraseñas cambiadas, como arriba.
  11. DEMO_MODE=false en la API y NEXT_PUBLIC_DEMO_MODE=false en ambos frontends, tal como se entrega.

¿Te atascaste en un paso?

Busca una solución antes de empezar de nuevo.

Solución de problemas

Preferencias de Cookies

Utilizamos cookies para mejorar tu experiencia de navegación, analizar el tráfico del sitio y personalizar el contenido. Al hacer clic en "Aceptar Todo", consientes nuestro uso de cookies para análisis y publicidad personalizada.