Startseite
NexoPOS

Bereitstellung

So führen Sie NexoSaaS aus: Docker-Stack, Host-Reverse-Proxy, Basisdomäne und TLS.

Worauf Sie bereitstellen

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

Kundenseitige NexoPOS-Standorte sind keine separaten Compose-Dienste. Der Agent schreibt Dateien nach HOST_AGENT_HOME_BASE, und nginx bindet seine vhosts ein.

1. Docker-Installation

Voraussetzungen

  • Docker Engine + Docker Compose v2
  • Ports frei (Standard): 8080 (HTTP), 3307 (MySQL-Host), 6380 (Redis-Host)

Schritte

# 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

Einstiegspunkte erstellen typischerweise APP_KEY und führen Migrationen aus, wenn sie konfiguriert sind. Katalog-Seed + Standard-Admin einmalig bereitstellen:

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

Standardmäßig vorab befüllte Konten (nur für Entwicklung):

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

Öffnen Sie die Control-Plane: http://localhost:8080 (oder Ihre APP_URL).

Bereitschaft:

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

Wichtige Umgebungsvariablen

Produkgeheimnisse (Stripe, SMTP, GitHub-PAT, S3, Domain-Richtlinie) sind „Admin → Einstellungen“ und nicht Laufzeitumgebungsvariablen.

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

Host-Agent-Modi

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“ ist allein keine vollständige Geschichte über Multi-Tenant-Produktionsisolierung. Verwenden Sie „script“ auf einem VPS, wenn Sie eine Trennung der Mandanten auf Produktionsniveau benötigen.

2. Nginx vor dem Stack hosten

Empfohlene Produktionsform:

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

Beispiel-Host Nginx (Control Plane)

Ersetzen Sie die Hostnamen und den Upstream-Port durch Ihre eigenen.

# /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;
    }
}

Set:

APP_URL=https://app.yourdomain.com

Laravel vertraut weitergeleiteten Headern, wenn es für Ihre Proxy-Konfiguration eingerichtet ist. Stellen Sie sicher, dass die App HTTPS korrekt erkennt, damit signierte URLs und Cookies sicher bleiben.

Screenshot-Platzhalter: Browser geöffnet für die Anmeldung in der Control-Plane unter Ihrer öffentlichen HTTPS-URL

Mieter-Hostnamen

  • Docker / local agent: Tenant-Nginx-Konfigurationen werden unter {HOST_AGENT_HOME_BASE}/.platform/nginx-enabled/*.conf geschrieben und in das Compose-Nginx (deploy/docker/nginx/default.conf) eingebunden.
  • Lokaler Browser: http://{install-subdomain}.localhost:8080 funktioniert oft ohne /etc/hosts.
  • Produktion: DNS für *.base_domain (und benutzerdefinierte Domains) muss dieselbe Edge erreichen, die an den Platform-nginx weiterleiten kann (oder den vom Script-Agenten verwalteten VPS-nginx).

Wenn der Host-Reverse-Proxy nur app.yourdomain.com weiterleitet, müssen Tenant-Subdomains entweder:

  • dieselbe Proxy-Konfiguration mit einem Platzhalter server_name / getrennte Serverblöcke oder
  • Direkte Exposition der Plattform Nginx / agentverwalteter Vhosts.

Planen Sie DNS und TLS für Mandanten zusammen mit der Basisdomäne (nächster Abschnitt).

3. Basisdomäne

Installationen erhalten einen kostenlosen Plattform-Hostname:

{slug}.{base_domain}

Beispiel: Basisdomain saas.example.com → acme-store.saas.example.com.

Im Admin konfigurieren

  1. Melden Sie sich als Plattformadministrator an (2FA außerhalb des lokalen Bereichs).
  2. Öffnen Sie „Admin“ → „Einstellungen“ → „Domain“.
  3. Set:
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 in .env setzt nur den Admin-Wert bei leeren Einstellungen; zur Laufzeit wird Admin → Domain verwendet.

4. SSL / Let’s Encrypt

Steuerungsebene (Host-Reverse-Proxy)

Mit Certbot (Beispiel):

# 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

Die Verwendung von Caddy ist oft einfacher (automatisches HTTPS); reverse_proxy zu 127.0.0.1:8080.

Mietbescheinigungen

Für die Bereitstellung und die Überprüfung der benutzerdefinierten Domain ist der Host-Agent für TLS für Tenant-Hostnamen zuständig (Let’s-Encrypt-ähnlicher Ablauf auf dem VPS-/Agent-Pfad).

Betreiber sollten:

  1. Stellen Sie sicher, dass der VPS HTTP-01 (oder die vom Agenten gewählte Challenge) für Installationshostnamen abschließen kann.
  2. Setzen Sie die maximalen Änderungen der verifizierten Domains pro Tag sinnvoll (Standard: 3), damit Kunden die LE-Rate-Limits nicht aufbrauchen.
  3. Behalten Sie die öffentliche IPv4-Adresse genau bei, damit die DNS-Anweisungen, die Kunden sehen, korrekt sind.

Hinweis: Lokales Docker mit *.localhost benötigt für das tägliche UI-Testing kein öffentliches LE.

Zahlungs-Webhooks

Produktions-Gateways müssen HTTPS-Endpunkte erreichen, z. B.:

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

Richten Sie Signaturgeheimnisse unter „Admin → Einstellungen → Abrechnungseinstellungen“ ein.

billingsettings

5. Checkliste nach dem Deployment

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

Nützliche Befehle für den Betrieb (Ops)

# 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