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 | 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
- Melden Sie sich als Plattformadministrator an (2FA außerhalb des lokalen Bereichs).
- Öffnen Sie „Admin“ → „Einstellungen“ → „Domain“.
- Set:
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:
- Stellen Sie sicher, dass der VPS HTTP-01 (oder die vom Agenten gewählte Challenge) für Installationshostnamen abschließen kann.
- Setzen Sie die maximalen Änderungen der verifizierten Domains pro Tag sinnvoll (Standard: 3), damit Kunden die LE-Rate-Limits nicht aufbrauchen.
- 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.
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