Provisioning Subdomains
The platform SDK exposes endpoints to provision a TLS certificate and write a live vhost for a
domain. They are reached over the loopback SDK at http://127.0.0.1/__bext/sdk/*,
authenticated by the X-Bext-App-Id header (see
SDK Overview).
There are four endpoints. For most cases use the one-shot upsert_auto; the individual
certs/provision + vhost/upsert endpoints exist for finer control.
Recommended: one-shot upsert_auto
upsert_auto provisions the certificate in-band (reusing an existing cert with more than 30
days of validity), writes the vhost, and reloads — in a single call.
POST http://127.0.0.1/__bext/sdk/vhost/upsert_auto
X-Bext-App-Id: <app-id>
Content-Type: application/json
{ "domain": "app.example.com", "root": "/path/to/site", "email": "ops@example.com" }
| Field | Required | Notes |
|---|---|---|
domain |
yes | The hostname to serve |
root |
yes | Document root (bext auto-detects the framework) |
email |
no | ACME account email |
Response:
{
"ok": true,
"vhost_path": "…/app.example.com.bext-auto.conf",
"cert_path": "…/fullchain.pem",
"key_path": "…/privkey.pem",
"reloaded_pid": 12345,
"cert_reused": false
}
cert_reused: true means an existing certificate with >30 days validity was used instead of a
fresh ACME issuance.
The individual endpoints
certs/provision
Issues a certificate via ACME HTTP-01.
POST http://127.0.0.1/__bext/sdk/certs/provision
X-Bext-App-Id: <app-id>
Content-Type: application/json
{ "domain": "app.example.com", "email": "ops@example.com", "webroot": "…", "pem_dir": "…", "staging": false }
| Field | Required | Notes |
|---|---|---|
domain |
yes | Hostname to issue for |
email |
no | ACME account email |
webroot |
no | Challenge webroot |
pem_dir |
no | Where to write the PEM files |
staging |
no | Use the ACME staging environment |
Success:
{ "ok": true, "domain": "app.example.com", "staging": false,
"not_before": "…", "not_after": "…", "cert_path": "…", "key_path": "…" }
- Missing
domain→ 400. - Failure → 500
{ "ok": false, "error": "…", "domain": "…" }.
The written cert/key are picked up by the SNI resolver automatically — no reload needed.
Issuance relies on the platform serving /.well-known/acme-challenge/{token} for any host.
vhost/upsert
Atomically writes <domain>.bext-auto.conf and reloads.
POST http://127.0.0.1/__bext/sdk/vhost/upsert
X-Bext-App-Id: <app-id>
Content-Type: application/json
{ "domain": "app.example.com", "cert_path": "…", "key_path": "…", "root": "/path/to/site" }
| Field | Required | Notes |
|---|---|---|
domain |
yes | Hostname |
cert_path |
yes | Certificate path |
key_path |
yes | Private key path |
root / proxy_pass / php_fpm_socket |
no | Backend — mutually exclusive; omit all for a static placeholder |
aliases |
no | Additional hostnames |
Response { "ok": true, "domain": "…", "vhost_path": "…", "reloaded_pid": 12345 }; validation
errors → 400.
vhost/remove
POST http://127.0.0.1/__bext/sdk/vhost/remove
X-Bext-App-Id: <app-id>
Content-Type: application/json
{ "domain": "app.example.com" }
Response { "ok": true, "domain": "…", "removed": true, "reloaded_pid": 12345 }.
*.inklura.fr subdomains: no DNS, auto TLS
*.inklura.fr wildcard DNS already resolves to the platform edge, so a new inklura
subdomain needs no DNS change and its TLS is auto-minted. You still write the vhost
(via upsert_auto), but there is nothing to configure at the DNS or certificate layer.
This is also why a new inklura subdomain is already frameable by the console with no CSP change — see Iframe Embedding.
Evict the edge route table
After adding a brand-new site, the edge caches a route table that won't yet know about it. Evict it so requests reach the new vhost:
POST http://127.0.0.1:8444/nginx-cache/purge-site
Content-Type: application/json
{ "host": "app.example.com" }
Skip this on a brand-new host and requests may not resolve to your new vhost until the route table naturally refreshes. Run it once, right after the vhost upsert.
See also
- Deploying — the full deploy workflow
- Iframe Embedding — framing a new subdomain from the console
- SDK Overview — the loopback SDK and
X-Bext-App-Id