fix(api): share base-domain API host
Some checks failed
Architecture Governance / architecture (push) Has been cancelled

Tenant subdomains route through api.<base-domain>; nginx forwards the exact storefront host derived from the validated browser origin.
This commit is contained in:
2026-08-20 16:12:37 +04:00
parent e5949c3967
commit 9cd56586fb
15 changed files with 175 additions and 65 deletions

View File

@@ -121,10 +121,17 @@ CONFIGURE_API="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/configure-api-domai
echo "ERROR: configure-api-domain.sh must be executable and next to add-domain.sh" >&2
exit 1
}
"$CONFIGURE_API" --domain "$DOMAIN" --email "$EMAIL"
if [[ $WITH_WWW -eq 1 ]]; then
"$CONFIGURE_API" --domain "www.$DOMAIN" --email "$EMAIL"
IFS=. read -ra DOMAIN_LABELS <<< "$DOMAIN"
LABEL_COUNT=${#DOMAIN_LABELS[@]}
TAKE=2
TLD=${DOMAIN_LABELS[LABEL_COUNT-1]}
SECOND_LEVEL=${DOMAIN_LABELS[LABEL_COUNT-2]}
if (( LABEL_COUNT >= 3 && ${#TLD} == 2 && ${#SECOND_LEVEL} <= 3 )); then
TAKE=3
fi
START=$((LABEL_COUNT - TAKE))
API_BASE_DOMAIN=$(IFS=.; echo "${DOMAIN_LABELS[*]:START}")
"$CONFIGURE_API" --domain "$API_BASE_DOMAIN" --email "$EMAIL"
echo "==> renewal timer"
systemctl enable --now certbot.timer

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Configure api.<storefront-domain> as the TLS/CORS reverse proxy for one tenant.
# Idempotent. Run as root after both storefront and API DNS records resolve here.
# Configure one shared api.<base-domain> for the base storefront and all tenant
# subdomains. Idempotent. Run as root after the API DNS record resolves here.
set -euo pipefail
@@ -30,6 +30,7 @@ done
API_DOMAIN="api.$DOMAIN"
CONF="/etc/nginx/sites-available/$API_DOMAIN"
DOMAIN_REGEX="${DOMAIN//./\\.}"
echo "==> checking DNS for $API_DOMAIN"
getent hosts "$API_DOMAIN" >/dev/null || {
@@ -39,7 +40,7 @@ getent hosts "$API_DOMAIN" >/dev/null || {
cat > "$CONF" <<NGINX
# Managed by marketplaces configure-api-domain.sh. Manual edits are overwritten.
# Storefront $DOMAIN derives this API origin as https://$API_DOMAIN.
# Storefront $DOMAIN and its tenant subdomains share https://$API_DOMAIN.
server {
listen 80;
listen [::]:80;
@@ -49,7 +50,11 @@ server {
error_log /var/log/nginx/$API_DOMAIN.error.log;
set \$cors_origin "";
if (\$http_origin = "https://$DOMAIN") { set \$cors_origin \$http_origin; }
set \$storefront_host "$DOMAIN";
if (\$http_origin ~* "^https://(?<allowed_storefront>([a-z0-9-]+\\.)*$DOMAIN_REGEX)$") {
set \$cors_origin \$http_origin;
set \$storefront_host \$allowed_storefront;
}
add_header Access-Control-Allow-Origin \$cors_origin always;
add_header Access-Control-Allow-Credentials "true" always;
@@ -62,12 +67,11 @@ server {
location / {
proxy_pass $UPSTREAM;
proxy_http_version 1.1;
# Keep the existing backend compatible: it already serves this tenant
# when the storefront Host reaches :445. The original public API host
# remains available in the trusted forwarding headers below.
proxy_set_header Host $DOMAIN;
# Browser Origin selects the storefront tenant while every tenant under
# this base domain shares one public API hostname.
proxy_set_header Host \$storefront_host;
proxy_set_header X-Forwarded-Host $API_DOMAIN;
proxy_set_header X-Storefront-Host $DOMAIN;
proxy_set_header X-Storefront-Host \$storefront_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 https;