Ensemble deployment

Public docs, private publishing.

Ensemble is deployed as a public Cloud Elephants documentation and preview surface, backed by a private signed build service for CMS publishing. The public site should not expose build webhook handlers.

private - Ensemble build service
publish - local/S3/R2 static artifacts
Service boundary
Layer
Public documentation site

ensemble.cloudelephants.com serves the splash page, block catalog, theme library, website-builder guide, recipe reviews, template previews, sitemap, and llms.txt.

Layer
Private build service

The Cloud Elephants CMS sends signed publish events to a private Ensemble service that validates snapshots, exports tenant sites, writes local generated-root artifacts, or uploads artifacts to S3/R2.

Layer
Tenant static hosting

Published tenant sites are served from the object-store and CDN layer, keeping public traffic separate from the internal build worker.

CMS publish contract

The private build service accepts HMAC-signed requests using X-Ensemble-Timestamp and X-Ensemble-Signature headers. The preferred route is the Cloud Elephants CMS publish endpoint; legacy routes stay available for compatible integrations.

The same private service serves its machine-readable OpenAPI contract at GET /openapi.json. That contract documents the publish payload, required signature headers, receipt lookup route, local directory output fields, and S3/R2 publish fields for the upstream Cloud Elephants CMS.

GET /openapi.json
POST /api/ensemble/cms/publish
POST /api/build/ensemble
POST /api/build/content
POST /api/build/wordpress
GET /receipts/<request_id>

When these handlers are hosted inside the Next app, they require ENSEMBLE_NEXT_BUILD_API_ENABLED=true. The public docs deployment should leave that flag unset so the routes return 404.

AWS go-live

S3 and CloudFront for publicly generated sites

Tenant traffic should terminate at CloudFront, read from a private S3 origin, and never depend on the Render build worker at request time. The starter stack is infra/aws/cloudfront-s3-tenant-sites.yaml.

AWS
Private S3 origin

Store generated tenant artifacts under sites/<tenant_slug>/ with public access blocked.

AWS
CloudFront OAC

Let CloudFront read the private bucket through Origin Access Control with signed S3 origin requests.

AWS
Wildcard HTTPS

Use a us-east-1 ACM certificate and a CloudFront alternate domain for *.mysite.cloudelephants.com.

AWS
Host rewrite

Attach the CloudFront Function from infra/aws/cloudfront-s3-tenant-sites.yaml to map host slugs to S3 prefixes.

s3://<bucket>/sites/<tenant_slug>
https://<tenant_slug>.mysite.cloudelephants.com
CloudFront Origin Access Control
1

Deploy infra/aws/cloudfront-s3-tenant-sites.yaml with TenantSitesBucketName, TenantBaseDomain, PublishPrefix, WildcardCertificateArn, and optional HostedZoneId.

2

Attach the EnsemblePublishManagedPolicyArn output to the Render publish principal used by the private build service.

3

Set ENSEMBLE_TENANT_PUBLISH_TARGET=s3, ENSEMBLE_TENANT_PUBLISH_BUCKET, ENSEMBLE_TENANT_PUBLISH_PREFIX=sites, and ENSEMBLE_TENANT_PUBLIC_BASE_DOMAIN on the private build service.

4

Publish one signed CMS request and verify https://<tenant_slug>.mysite.cloudelephants.com/ from CloudFront before opening traffic.