Inicio
NexoPOS

Despliegue

Cómo ejecutar NexoSaaS: stack de Docker, proxy inverso del host, dominio base y TLS.

Lo que estás implementando

Component Role
app (PHP-FPM) Laravel control plane
nginx (compose) Serves control plane + generated tenant vhosts
horizon Queue workers (provision, backups, mail, etc.)
scheduler schedule:work (billing lifecycle, backup waves, …)
mysql Control plane + per-install tenant databases (Docker)
redis Cache, sessions, queues
Host agent Creates tenant paths, nginx snippets, SSL, DBs

Los sitios de NexoPOS del cliente no son servicios Compose separados. El agente escribe archivos en HOST_AGENT_HOME_BASE, y nginx incluye sus vhosts.

1. Instalación de Docker

Requisitos previos

  • Motor de Docker + Docker Compose v2
  • Puertos libres (predeterminados): 8080 (HTTP), 3307 (host de MySQL), 6380 (host de Redis)

Pasos

# From the repository root
cp deploy/.env.docker.example .env

# Optional: set a stable public URL early (production example)
# APP_URL=https://app.yourdomain.com
# APP_ENV=production
# APP_DEBUG=false

docker compose -f deploy/docker-compose.yml up -d --build

Los puntos de entrada de Compose normalmente generan APP_KEY y ejecutan migraciones cuando está configurado. Sembrar el catálogo + el administrador predeterminado una vez:

docker compose -f deploy/docker-compose.yml exec app php artisan db:seed --force

Cuentas presembradas predeterminadas (solo para desarrollo):

Role Email Password
Platform admin [email protected] password
Test user [email protected] password

Abre el plano de control: http://localhost:8080 (o tu APP_URL).

Preparación:

docker compose -f deploy/docker-compose.yml exec app php artisan platform:launch-check

Variables de entorno importantes

Los secretos del producto (Stripe, SMTP, GitHub PAT, S3, política de dominio) están en Admin → Settings, no como variables de entorno en tiempo de ejecución.

Variable Typical Docker Notes
APP_URL http://localhost:8080 Must match the URL browsers use (payment return URLs)
APP_ENV / APP_DEBUG local / true Production: production / false
PLATFORM_BASE_DOMAIN localhost Seed-only default for Admin Domain base_domain
HOST_AGENT_DRIVER local Docker/CI. Production VPS isolation: script
HOST_AGENT_HOME_BASE /home Tenant homes + .platform/nginx-enabled
HOST_AGENT_LOCAL_REAL_CLONE false true = real NexoPOS tarball (needs network + GitHub)
HOST_AGENT_TENANT_DB_* MySQL service Per-install DB creation in Docker
QUEUE_CONNECTION redis Required for Horizon

Modos del agente anfitrión

Driver Use when
local Docker / evaluation. Same path layout as production, shared FPM, no real useradd.
script Real Linux VPS: OS users, per-user FPM, system nginx, true isolation.

Compose no es, por sí solo, una historia completa de aislamiento de producción multi-tenant. Usa un script en un VPS cuando necesites una separación de tenants a nivel de producción.

2. Aloja Nginx delante del stack

Forma de producción recomendada:

Internet
   │
   ▼
Host Nginx / Caddy  (TLS termination, :443)
   │  proxy_pass → 127.0.0.1:8080
   ▼
Compose nginx       (control plane + tenant includes)
   │
   ▼
Compose app (PHP-FPM) + tenant docroots on volume

Ejemplo de host Nginx (plano de control)

Reemplaza los nombres de host y el puerto upstream por los tuyos.

# /etc/nginx/sites-available/nexosaas-control.conf
server {
    listen 80;
    server_name app.yourdomain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name app.yourdomain.com;

    # ssl_certificate     /etc/letsencrypt/live/app.yourdomain.com/fullchain.pem;
    # ssl_certificate_key /etc/letsencrypt/live/app.yourdomain.com/privkey.pem;

    client_max_body_size 64M;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 120s;
    }
}

Conjunto:

APP_URL=https://app.yourdomain.com

Laravel confía en los encabezados reenviados cuando se configura para tu configuración de proxy; asegúrate de que la aplicación vea HTTPS correctamente para que las URL firmadas y las cookies se mantengan seguras.

Marcador de captura de pantalla: Navegador abierto en el inicio de sesión del plano de control en tu URL HTTPS pública

Nombres de host del inquilino

  • Docker / agente local: las configuraciones de nginx del tenant se escriben en {HOST_AGENT_HOME_BASE}/.platform/nginx-enabled/*.conf y se incluyen mediante el nginx de Compose (deploy/docker/nginx/default.conf).
  • Navegador local: http://{install-subdomain}.localhost:8080 a menudo funciona sin /etc/hosts.
  • Producción: El DNS para *.base_domain (y los dominios personalizados) debe llegar al mismo borde que puede enrutar a la plataforma nginx (o al nginx del VPS administrado por el agente del script).

Si el proxy inverso del host solo reenvía  app.yourdomain.com, los subdominios del inquilino necesitan, ya sea:

  • el mismo proxy con un comodín server_name / separar bloques de servidor, o
  • exposición directa de la plataforma nginx / vhosts gestionados por el agente.

Planifica DNS y TLS para los tenants junto con el dominio base (siguiente sección).

3. Dominio base

Las instalaciones obtienen un nombre de host de plataforma gratuito:

{slug}.{base_domain}

Ejemplo: dominio base saas.example.com → acme-store.saas.example.com.

Configurar en el administrador

  1. Inicia sesión como administrador de la plataforma (2FA fuera de la red local).
  2. Abrir Admin → Configuración → Dominio.
  3. Conjunto:
domains-1

DNS

Record Name Target
A app.yourdomain.com (control plane) VPS public IP
A (or CNAME) *.saas.example.com Same IP (or load balancer)
Optional AAAA same hosts Public IPv6

PLATFORM_BASE_DOMAIN en .env solo inicializa el valor de Admin en configuraciones vacías; en tiempo de ejecución, usa Admin → Domain.

4. SSL / Let’s Encrypt

Plano de control (proxy inverso del host)

Usando Certbot (ejemplo):

# After DNS for app.yourdomain.com points at the VPS
sudo certbot --nginx -d app.yourdomain.com
# or: certbot certonly --webroot ... then point ssl_certificate paths

Usar Caddy a menudo es más sencillo (HTTPS automático); reverse_proxy a 127.0.0.1:8080.

Certificados del inquilino

En la provisión y verificación de dominios personalizados, el agente host es responsable del TLS para los nombres de host del inquilino (flujo tipo Let’s Encrypt en la ruta del VPS / agente).

Los operadores deben:

  1. Asegúrate de que el VPS pueda completar HTTP-01 (o el desafío elegido por el agente) para los nombres de host de instalación.
  2. Establece razonablemente los cambios de dominio verificado por día (predeterminado 3) para que los clientes no agoten los límites de velocidad de LE.
  3. Mantenga la precisión de la IPv4 pública para que las instrucciones de DNS que vean los clientes sean correctas.

Nota: El Docker local con *.localhost no necesita un LE público para las pruebas de la interfaz de usuario del día a día.

Webhooks de pago

Las puertas de enlace de producción deben llegar a puntos finales HTTPS, por ejemplo:

  • https://app.yourdomain.com/webhooks/stripe
  • https://app.yourdomain.com/webhooks/paddle
  • https://app.yourdomain.com/webhooks/mollie

Configura los secretos de firma en Admin → Configuración → Configuración de facturación.

billingsettings

5. Lista de verificación posterior al despliegue

Step Command / action
Stack healthy docker compose -f deploy/docker-compose.yml ps
Seed catalog / admin (once) exec app php artisan db:seed --force
Launch check exec app php artisan platform:launch-check
Horizon running Compose horizon service Up
Scheduler running Compose scheduler service Up
First admin usable Verify email + 2FA
Product config SMTP, payments, GitHub, S3, domain
Fake payments Not allowed in production launch-check

Comandos útiles de operaciones

# Shell into app
docker compose -f deploy/docker-compose.yml exec app bash

# Logs
docker compose -f deploy/docker-compose.yml logs -f app horizon nginx

# Rebuild frontend assets
docker compose -f deploy/docker-compose.yml run --rm -e DOCKER_FORCE_BUILD_ASSETS=true assets

# Wipe evaluation installs (keeps users/catalog/settings)
docker compose -f deploy/docker-compose.yml exec app \
  php artisan platform:reset-evaluation --force