fix(deploy): provision tenant API domains
Some checks failed
Architecture Governance / architecture (push) Failing after 6m16s

Reconcile TLS, exact CORS, and backend proxying before release activation so every storefront uses its derived API host.
This commit is contained in:
2026-08-20 15:04:03 +04:00
parent 66a0ccfdb8
commit e5949c3967
8 changed files with 315 additions and 6 deletions

View File

@@ -1,6 +1,9 @@
# Deployment — server provisioning, CD, TLS
Frontend only. The backend service (`:8080`) is a separate developer's responsibility. API hostnames are separate reverse proxies and will return `502` until their upstream exists.
Frontend deployment plus API-domain edge configuration. The backend service is a
separate developer's responsibility. API hostnames are separate reverse proxies
and return `502` until their configured upstream exists (production currently
defaults to `https://127.0.0.1:445`).
**Multi-tenant, one bundle.** Every customer domain is served by the same build. The SPA resolves its tenant from the `Host` header ([BACKEND-HANDOFF §1a](backend/BACKEND-HANDOFF.md)). One deploy updates every domain simultaneously — there is no per-tenant build and no per-tenant deploy.
@@ -18,6 +21,7 @@ nested names such as `api.store1.example.com`.
|---|---|
| `scripts/deploy/server-setup.sh` | One-time server provisioning. Idempotent. Run as root. |
| `scripts/deploy/add-domain.sh` | Attach one domain + issue TLS. Run per domain, as root, after DNS resolves. |
| `scripts/deploy/configure-api-domain.sh` | Configure `api.<full storefront host>` TLS, exact CORS, backend proxy, and JSON bootstrap verification. |
| `.github/workflows/deploy.yml` | CD: build → upload → atomic swap → verify. Triggers on push to `main`. |
---
@@ -56,7 +60,10 @@ Copy `scripts/deploy/` to the server and run:
sudo bash server-setup.sh --pubkey "$(cat marketplaces_deploy.pub)"
```
This installs nginx + certbot, creates a **key-only** `deploy` user with no password, writes the catch-all nginx config, opens 80/443/OpenSSH in ufw, and grants `deploy` exactly one sudo right: `systemctl reload nginx`.
This installs nginx + certbot, creates a **key-only** `deploy` user with no
password, writes the catch-all nginx config, opens 80/443/OpenSSH in ufw, and
installs a root-owned, argument-validating API-domain helper. The deploy user may
run that helper and reload nginx, but cannot replace the helper.
Verify before continuing:
@@ -82,6 +89,15 @@ The output is the `DEPLOY_KNOWN_HOSTS` secret. Pinning it means a rebuilt or imp
| `DEPLOY_USER` | `deploy` |
| `DEPLOY_SSH_KEY` | contents of the **private** key file |
| `DEPLOY_KNOWN_HOSTS` | output of `ssh-keyscan -H <server-ip>` |
| `STOREFRONT_DOMAINS` | space-separated full hosts, e.g. `gorbushka.market store1.example.com` |
| `CERTBOT_EMAIL` | operations email used for Let's Encrypt |
| `BACKEND_UPSTREAM` | optional; defaults to `https://127.0.0.1:445` |
Before deploying, point every derived API hostname at the server. For the
example above, DNS must resolve both `api.gorbushka.market` and
`api.store1.example.com`. The workflow deliberately stops before release
activation if DNS, certificate issuance, nginx validation, or the JSON
`/bootstrap` check fails.
### 3.5 Deploy