feat(proxy): plain-HTTP LAN entry for waiter (:80) and manager (:8081), no certs required

Phones can now open the waiter app at http://<LAN IP> with no domain, DNS
record or certificate (works around DNS-rebinding failures, KI-001). The
manager gets http://<LAN IP>:8081, with http://<LAN IP>/manager redirecting
there. waiter.*/manager.* hostnames on :80 still redirect to https, so
legacy domain sites behave as before.

- Both plain-HTTP servers are LAN-only (allow RFC1918/loopback/ULA/link-local,
  deny all -> 403), so a router port-forward can't expose an unencrypted POS
- nginx-proxy/nginx.conf and the install.sh heredoc are now byte-identical
  (one canonical config, routing map in its header)
- install.sh generates a 10-year self-signed cert when certs/ is empty (nginx
  won't start its TLS listeners without one), detects HOST_IP via
  'ip route get', prompts for it on fresh installs and backfills it into an
  existing .env, always starts the stack, prints the LAN URLs
- docker-compose publishes 8081; .env.example documents HOST_IP
- pack README: ports/request path updated, CS-5 byte-identical check

Verified: nginx -t; install.sh in Debian (fresh / upgrade without HOST_IP /
re-run - no duplicate HOST_IP, cert SAN includes HOST_IP, key 600); full
stack from freshly built images: every entry point returns the expected
200/301/302, and removing the gateway's range from the allow list yields 403
on :80 and :8081.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-28 11:50:29 +03:00
co-authored by Claude Opus 5.5
parent 18012c2c95
commit 9fcb4df30e
5 changed files with 330 additions and 54 deletions
+4
View File
@@ -9,6 +9,10 @@ CLOUD_URL=https://xenia-admin.bonamin.gr
SECRET_KEY=generate-with-openssl-rand-hex-32 SECRET_KEY=generate-with-openssl-rand-hex-32
LICENSE_GRACE_HOURS=24 LICENSE_GRACE_HOURS=24
# This machine's LAN IP — the address phones open (http://<HOST_IP>) and the
# pairing QR code encodes. install.sh detects it; reserve it in the router's DHCP.
HOST_IP=
# Break-glass support account (leave blank to disable) # Break-glass support account (leave blank to disable)
MASTER_USERNAME= MASTER_USERNAME=
MASTER_PASSWORD= MASTER_PASSWORD=
+1
View File
@@ -36,6 +36,7 @@ services:
- "80:80" - "80:80"
- "443:443" - "443:443"
- "4443:4443" - "4443:4443"
- "8081:8081" # manager over plain HTTP (LAN only)
volumes: volumes:
- ./nginx-proxy/nginx.conf:/etc/nginx/conf.d/default.conf:ro - ./nginx-proxy/nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./certs:/etc/nginx/certs:ro - ./certs:/etc/nginx/certs:ro
+10 -6
View File
@@ -13,13 +13,15 @@ This folder is its **own git repo**, nested inside the `xenia-pos` parent repo.
| Service | Stack | Dev port | Prod exposure | Image | | Service | Stack | Dev port | Prod exposure | Image |
|---|---|---|---|---| |---|---|---|---|---|
| `local_backend` | FastAPI + SQLAlchemy + SQLite (`/app/data/pos.db`) | 8000 | only through proxy / inner nginx | `pos-backend` | | `local_backend` | FastAPI + SQLAlchemy + SQLite (`/app/data/pos.db`) | 8000 | only through proxy / inner nginx | `pos-backend` |
| `waiter_pwa` | React + Vite + vite-plugin-pwa, axios, zustand, react-query, Dexie (IndexedDB) | 5173 | `https://<host>` (443) | `pos-waiter` | | `waiter_pwa` | React + Vite + vite-plugin-pwa, axios, zustand, react-query, Dexie (IndexedDB) | 5173 | **`http://<LAN IP>`** (80, LAN only) · `https://waiter.<domain>` / `https://<IP>` (443) | `pos-waiter` |
| `manager_dashboard` | React + Vite | 5174 | `https://<host>:4443` | `pos-manager` | | `manager_dashboard` | React + Vite | 5174 | **`http://<LAN IP>:8081`** (LAN only; `http://<IP>/manager` redirects there) · `https://manager.<domain>` (443) · `https://<IP>:4443` | `pos-manager` |
| `proxy` | nginx:alpine, TLS termination | — | 80 → 443 redirect, 443, 4443 | stock | | `proxy` | nginx:alpine | — | 80, 443, 4443, 8081. See the header of `nginx-proxy/nginx.conf` for the full routing map | stock |
### Request path in production ### Request path in production
Phones normally use **plain HTTP by LAN IP** (`http://<HOST_IP>` → proxy:80 default_server). Only private source IPs are allowed; everything else gets 403.
Legacy domain sites use `https://waiter.<domain>` (proxy:443), and `waiter.*`/`manager.*` on port 80 still redirect to https.
``` ```
phone ──https──▶ proxy:443 ──http──▶ waiter_pwa nginx:80 ──┬─ / → static SPA phone ──http(s)──▶ proxy:80/443 ──http──▶ waiter_pwa nginx:80 ──┬─ / → static SPA
├─ /api/ → backend:8000 ├─ /api/ → backend:8000
├─ /api/ws/ → backend:8000 (WebSocket upgrade) ├─ /api/ws/ → backend:8000 (WebSocket upgrade)
└─ /static/ → backend:8000/static/ └─ /static/ → backend:8000/static/
@@ -64,8 +66,10 @@ Waiters walk in and out of WiFi range and phones sleep. Any new waiter flow must
**CS-4. Money and prices are snapshotted.** **CS-4. Money and prices are snapshotted.**
Prices, costs and discounts are copied onto order items and logs when the action happens (snapshot pattern, `PriceEventLog`). Reports read the snapshots, never the live catalogue. Prices, costs and discounts are copied onto order items and logs when the action happens (snapshot pattern, `PriceEventLog`). Reports read the snapshots, never the live catalogue.
**CS-5. The proxy config lives in two places.** **CS-5. The proxy config lives in two places and must stay byte-identical.**
Edit `nginx-proxy/nginx.conf` **and** the heredoc in `install.sh` together (global Rule 9). `install.sh` writes the heredoc on client sites, and `nginx-proxy/nginx.conf` is the repo copy. Edit both together (global Rule 9) and check with:
`sed -n "/<< 'EOF'/,/^EOF/p" install.sh | sed '1d;$d' | diff - nginx-proxy/nginx.conf`
The plain-HTTP servers (80 default_server, 8081) must keep their LAN-only `allow`/`deny` block.
**CS-6. Permissions are checked on the backend.** **CS-6. Permissions are checked on the backend.**
Hiding a button in the UI is not access control. Every new endpoint declares its role or `perm_*` requirement through `routers/deps.py`. Hiding a button in the UI is not access control. Every new endpoint declares its role or `perm_*` requirement through `routers/deps.py`.
+165 -42
View File
@@ -7,6 +7,20 @@ set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# LAN IP of this machine (the address phones use: http://<HOST_IP>).
# `ip route get` picks the interface that actually routes out, which avoids
# docker0 / bridge addresses that `hostname -I` may list first.
detect_host_ip() {
local ip=""
if command -v ip >/dev/null 2>&1; then
ip=$(ip route get 1.1.1.1 2>/dev/null | awk '{for (i=1;i<=NF;i++) if ($i=="src") {print $(i+1); exit}}')
fi
if [ -z "$ip" ]; then
ip=$(hostname -I 2>/dev/null | awk '{print $1}')
fi
echo "$ip"
}
echo "=== Xenia POS Install ===" echo "=== Xenia POS Install ==="
echo "" echo ""
@@ -34,6 +48,9 @@ if [ ! -f "$SCRIPT_DIR/.env" ]; then
read -rp " Enter SITE_ID: " INPUT_SITE_ID read -rp " Enter SITE_ID: " INPUT_SITE_ID
read -rp " Enter SITE_KEY: " INPUT_SITE_KEY read -rp " Enter SITE_KEY: " INPUT_SITE_KEY
read -rp " Enter SECRET_KEY (leave blank to auto-generate): " INPUT_SECRET_KEY read -rp " Enter SECRET_KEY (leave blank to auto-generate): " INPUT_SECRET_KEY
DETECTED_IP=$(detect_host_ip)
read -rp " Enter this machine's LAN IP [${DETECTED_IP}]: " INPUT_HOST_IP
INPUT_HOST_IP=${INPUT_HOST_IP:-$DETECTED_IP}
if [ -z "$INPUT_SECRET_KEY" ]; then if [ -z "$INPUT_SECRET_KEY" ]; then
INPUT_SECRET_KEY=$(openssl rand -hex 32) INPUT_SECRET_KEY=$(openssl rand -hex 32)
@@ -43,30 +60,119 @@ if [ ! -f "$SCRIPT_DIR/.env" ]; then
sed -i "s/^SITE_ID=.*/SITE_ID=${INPUT_SITE_ID}/" "$SCRIPT_DIR/.env" sed -i "s/^SITE_ID=.*/SITE_ID=${INPUT_SITE_ID}/" "$SCRIPT_DIR/.env"
sed -i "s/^SITE_KEY=.*/SITE_KEY=${INPUT_SITE_KEY}/" "$SCRIPT_DIR/.env" sed -i "s/^SITE_KEY=.*/SITE_KEY=${INPUT_SITE_KEY}/" "$SCRIPT_DIR/.env"
sed -i "s/^SECRET_KEY=.*/SECRET_KEY=${INPUT_SECRET_KEY}/" "$SCRIPT_DIR/.env" sed -i "s/^SECRET_KEY=.*/SECRET_KEY=${INPUT_SECRET_KEY}/" "$SCRIPT_DIR/.env"
sed -i "s/^HOST_IP=.*/HOST_IP=${INPUT_HOST_IP}/" "$SCRIPT_DIR/.env"
echo "" echo ""
echo " .env written. Review it at: $SCRIPT_DIR/.env" echo " .env written. Review it at: $SCRIPT_DIR/.env"
echo "" echo ""
else else
echo " .env already exists — skipping." echo " .env already exists — keeping it."
if ! grep -q '^HOST_IP=.\+' "$SCRIPT_DIR/.env"; then
DETECTED_IP=$(detect_host_ip)
sed -i '/^HOST_IP=/d' "$SCRIPT_DIR/.env"
echo "HOST_IP=${DETECTED_IP}" >> "$SCRIPT_DIR/.env"
echo " HOST_IP was not set — added HOST_IP=${DETECTED_IP} (edit .env if wrong)."
fi
fi fi
# ── 3. Write nginx-proxy/nginx.conf ────────────────────────────────────────── # ── 3. Write nginx-proxy/nginx.conf ──────────────────────────────────────────
echo "[ 3/5 ] Writing nginx proxy config..." echo "[ 3/5 ] Writing nginx proxy config..."
cat > "$SCRIPT_DIR/nginx-proxy/nginx.conf" << 'EOF' cat > "$SCRIPT_DIR/nginx-proxy/nginx.conf" << 'EOF'
# Generated by install.sh — keep in sync with nginx-proxy/nginx.conf in the repo. # Xenia POS — on-site proxy config.
# Every proxied location must forward WebSocket upgrades (/api/ws/connect) and # install.sh writes this exact file on client sites; nginx-proxy/nginx.conf in the
# must not buffer (SSE), otherwise live events never reach waiters / KDS. # repo is a byte-identical copy. Change both together (global Working Rule 9).
#
# :80 waiter.* / manager.* hostnames → redirect to https (legacy domain setup)
# :80 anything else (bare LAN IP) → waiter app over plain HTTP, LAN only
# /manager → redirect to :8081
# :8081 → manager dashboard over plain HTTP, LAN only
# :443 waiter.* / manager.* / bare IP → https (needs certs/cert.pem + key.pem)
# :4443 → manager over https
#
# Every proxied location forwards WebSocket upgrades (/api/ws/connect) and
# disables buffering (SSE), otherwise live events never reach phones / KDS.
map $http_upgrade $connection_upgrade { map $http_upgrade $connection_upgrade {
default upgrade; default upgrade;
'' close; '' close;
} }
# ── Plain HTTP ────────────────────────────────────────────────────────────────
server { server {
listen 80; listen 80;
server_name waiter.* manager.*;
return 301 https://$host$request_uri; return 301 https://$host$request_uri;
} }
server {
listen 80 default_server;
server_name _;
# LAN only: plain HTTP must never be reachable from the internet, even if the
# client forwards ports on their router. Relies on Docker preserving the real
# client IP (default iptables port publishing on Linux).
allow 10.0.0.0/8;
allow 172.16.0.0/12;
allow 192.168.0.0/16;
allow 127.0.0.0/8;
allow fc00::/7;
allow fe80::/10;
allow ::1;
deny all;
location ~ ^/manager/?$ {
return 302 http://$host:8081/;
}
location / {
proxy_pass http://waiter_pwa:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
}
server {
listen 8081 default_server;
server_name _;
# LAN only: plain HTTP must never be reachable from the internet, even if the
# client forwards ports on their router. Relies on Docker preserving the real
# client IP (default iptables port publishing on Linux).
allow 10.0.0.0/8;
allow 172.16.0.0/12;
allow 192.168.0.0/16;
allow 127.0.0.0/8;
allow fc00::/7;
allow fe80::/10;
allow ::1;
deny all;
location / {
proxy_pass http://manager_dashboard:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
}
# ── HTTPS ─────────────────────────────────────────────────────────────────────
server { server {
listen 443 ssl; listen 443 ssl;
server_name waiter.*; server_name waiter.*;
@@ -117,6 +223,7 @@ server {
server { server {
listen 443 ssl default_server; listen 443 ssl default_server;
server_name _;
ssl_certificate /etc/nginx/certs/cert.pem; ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem; ssl_certificate_key /etc/nginx/certs/key.pem;
@@ -151,39 +258,53 @@ server {
proxy_buffering off; proxy_buffering off;
} }
} }
server {
listen 4443 ssl default_server;
server_name _;
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://manager_dashboard:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
}
EOF EOF
# ── 4. SSL certificates ─────────────────────────────────────────────────────── # ── 4. SSL certificates ───────────────────────────────────────────────────────
echo "[ 4/5 ] Checking SSL certificates..." echo "[ 4/5 ] Checking SSL certificates..."
# Phones normally use plain HTTP on the LAN (http://<HOST_IP>), which needs no
# certificate. nginx still needs *a* cert to start its HTTPS listeners, so when
# none is present we generate a self-signed one. A real certificate (legacy
# domain setup) can replace certs/cert.pem + certs/key.pem at any time.
if [ -f "$SCRIPT_DIR/certs/cert.pem" ] && [ -f "$SCRIPT_DIR/certs/key.pem" ]; then if [ -f "$SCRIPT_DIR/certs/cert.pem" ] && [ -f "$SCRIPT_DIR/certs/key.pem" ]; then
echo " Certificates already exist — skipping." echo " Certificates already exist — keeping them."
else else
echo "" CERT_IP=$(grep '^HOST_IP=' "$SCRIPT_DIR/.env" 2>/dev/null | cut -d= -f2)
echo " No certificates found in certs/" CERT_SAN="DNS:localhost,IP:127.0.0.1"
echo "" [ -n "$CERT_IP" ] && CERT_SAN="$CERT_SAN,IP:$CERT_IP"
echo " DNS requirement:" openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
echo " Two subdomains must point to this machine's IP:" -keyout "$SCRIPT_DIR/certs/key.pem" \
echo " waiter.YOURDOMAIN → this machine's IP" -out "$SCRIPT_DIR/certs/cert.pem" \
echo " manager.YOURDOMAIN → this machine's IP" -subj "/CN=xenia-pos" \
echo " The waiter domain should also be registered in the sysadmin" -addext "subjectAltName=$CERT_SAN" >/dev/null 2>&1
echo " panel as the 'Waiter Domain' so phones get the QR code." chmod 600 "$SCRIPT_DIR/certs/key.pem"
echo "" echo " No certificates found — generated a self-signed one (valid 10 years)."
echo " Option A — Let's Encrypt (recommended):" echo " Phones use plain HTTP on the LAN, so this is only for the HTTPS ports."
echo " sudo apt install certbot"
echo " sudo certbot certonly --manual --preferred-challenges dns \\"
echo " -d waiter.YOURDOMAIN -d manager.YOURDOMAIN"
echo " sudo cp /etc/letsencrypt/live/waiter.YOURDOMAIN/fullchain.pem certs/cert.pem"
echo " sudo cp /etc/letsencrypt/live/waiter.YOURDOMAIN/privkey.pem certs/key.pem"
echo ""
echo " Option B — Self-signed / mkcert (local testing only):"
echo " sudo apt install mkcert libnss3-tools"
echo " mkcert -install"
echo " mkcert -cert-file certs/cert.pem -key-file certs/key.pem \\"
echo " waiter.YOURDOMAIN manager.YOURDOMAIN"
echo ""
echo " Add certs then run: docker compose up -d"
echo ""
fi fi
# ── 5. Logo ─────────────────────────────────────────────────────────────────── # ── 5. Logo ───────────────────────────────────────────────────────────────────
@@ -195,18 +316,20 @@ if [ ! -s "$SCRIPT_DIR/logo.png" ]; then
fi fi
# ── Done ───────────────────────────────────────────────────────────────────── # ── Done ─────────────────────────────────────────────────────────────────────
HOST_IP_NOW=$(grep '^HOST_IP=' "$SCRIPT_DIR/.env" 2>/dev/null | cut -d= -f2)
HOST_IP_NOW="${HOST_IP_NOW:-SERVER-IP}"
echo "" echo ""
echo "=== Setup complete ===" echo "=== Setup complete ==="
echo "" echo ""
echo "Starting stack..."
if [ -f "$SCRIPT_DIR/certs/cert.pem" ] && [ -f "$SCRIPT_DIR/certs/key.pem" ]; then docker compose -f "$SCRIPT_DIR/docker-compose.yml" up -d
echo "Starting stack..." echo ""
docker compose -f "$SCRIPT_DIR/docker-compose.yml" up -d echo "Done! Services running. From any phone or PC on this network:"
echo "" echo " Waiter app: http://${HOST_IP_NOW}"
echo "Done! Services running." echo " Manager app: http://${HOST_IP_NOW}/manager (→ port 8081)"
echo " Waiter app: https://waiter.YOURDOMAIN" echo ""
echo " Manager app: https://manager.YOURDOMAIN" echo "Tip: reserve ${HOST_IP_NOW} for this machine in the router's DHCP settings"
else echo " so the address never changes."
echo "Add SSL certificates to certs/ then run:" echo ""
echo " docker compose up -d" echo "If the proxy config changed, restart it: docker compose restart proxy"
fi
+150 -6
View File
@@ -1,19 +1,101 @@
# Repo/dev proxy config. install.sh writes its own copy on client sites — keep both in sync. # Xenia POS — on-site proxy config.
# Every proxied location must forward WebSocket upgrades (/api/ws/connect) and # install.sh writes this exact file on client sites; nginx-proxy/nginx.conf in the
# must not buffer (SSE), otherwise live events never reach waiters / KDS. # repo is a byte-identical copy. Change both together (global Working Rule 9).
#
# :80 waiter.* / manager.* hostnames → redirect to https (legacy domain setup)
# :80 anything else (bare LAN IP) → waiter app over plain HTTP, LAN only
# /manager → redirect to :8081
# :8081 → manager dashboard over plain HTTP, LAN only
# :443 waiter.* / manager.* / bare IP → https (needs certs/cert.pem + key.pem)
# :4443 → manager over https
#
# Every proxied location forwards WebSocket upgrades (/api/ws/connect) and
# disables buffering (SSE), otherwise live events never reach phones / KDS.
map $http_upgrade $connection_upgrade { map $http_upgrade $connection_upgrade {
default upgrade; default upgrade;
'' close; '' close;
} }
# ── Plain HTTP ────────────────────────────────────────────────────────────────
server { server {
listen 80; listen 80;
server_name waiter.* manager.*;
return 301 https://$host$request_uri; return 301 https://$host$request_uri;
} }
server {
listen 80 default_server;
server_name _;
# LAN only: plain HTTP must never be reachable from the internet, even if the
# client forwards ports on their router. Relies on Docker preserving the real
# client IP (default iptables port publishing on Linux).
allow 10.0.0.0/8;
allow 172.16.0.0/12;
allow 192.168.0.0/16;
allow 127.0.0.0/8;
allow fc00::/7;
allow fe80::/10;
allow ::1;
deny all;
location ~ ^/manager/?$ {
return 302 http://$host:8081/;
}
location / {
proxy_pass http://waiter_pwa:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
}
server {
listen 8081 default_server;
server_name _;
# LAN only: plain HTTP must never be reachable from the internet, even if the
# client forwards ports on their router. Relies on Docker preserving the real
# client IP (default iptables port publishing on Linux).
allow 10.0.0.0/8;
allow 172.16.0.0/12;
allow 192.168.0.0/16;
allow 127.0.0.0/8;
allow fc00::/7;
allow fe80::/10;
allow ::1;
deny all;
location / {
proxy_pass http://manager_dashboard:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
}
# ── HTTPS ─────────────────────────────────────────────────────────────────────
server { server {
listen 443 ssl; listen 443 ssl;
server_name waiter.* _; server_name waiter.*;
ssl_certificate /etc/nginx/certs/cert.pem; ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem; ssl_certificate_key /etc/nginx/certs/key.pem;
@@ -36,8 +118,70 @@ server {
} }
server { server {
listen 4443 ssl; listen 443 ssl;
server_name manager.* _; server_name manager.*;
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://manager_dashboard:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
}
server {
listen 443 ssl default_server;
server_name _;
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location /api/ {
proxy_pass http://backend:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
location / {
proxy_pass http://waiter_pwa:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
}
server {
listen 4443 ssl default_server;
server_name _;
ssl_certificate /etc/nginx/certs/cert.pem; ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem; ssl_certificate_key /etc/nginx/certs/key.pem;