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
}
Tip

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 domain400.
  • 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" }
Warning

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