beps/infrastructure/README.md
Infrastructure as code for hosting BAML Enhancement Proposals (BEPs) with subdomain-based previews.
Uses AWS CDK (TypeScript) for declarative, type-safe infrastructure management.
beps.boundaryml.com → S3 root{branch-name}.beps.boundaryml.com → S3 /{branch-name}/aws sso login --profile your-profileaws configurenpm install -g aws-cdk
If using AWS SSO:
aws sso login --profile boundaryml-dev
export AWS_PROFILE=boundaryml-dev
If using static credentials, ensure they're configured:
aws sts get-caller-identity # Should show your AWS account
cd beps/infrastructure
npm install
npm run bootstrap
# Or: cdk bootstrap aws://ACCOUNT-ID/us-east-1
Create a .env file or export environment variables:
export BEPS_DOMAIN="beps.boundaryml.com"
export GITHUB_ORG="boundaryml"
export GITHUB_REPO="baml"
# Optional: Use existing certificate
# export CERTIFICATE_ARN="arn:aws:acm:us-east-1:..."
npm run diff
npm run deploy
The deployment will output all the GitHub secrets you need to configure.
Add these CNAME records to your domain registrar:
Type: CNAME
Name: beps.boundaryml.com
Value: <from-output>.cloudfront.net
Type: CNAME
Name: *.beps.boundaryml.com
Value: <from-output>.cloudfront.net
Add these secrets to your GitHub repository (Settings → Secrets → Actions):
The deploy command outputs these values:
AWS_ROLE_ARNS3_BUCKET_BEPSCLOUDFRONT_DISTRIBUTION_ID_BEPSBEPS_DOMAINbaml-beps-{account-id}beps.boundaryml.com and *.beps.boundaryml.comGitHubActions-BEPs-Deploybeps.boundaryml.com*.beps.boundaryml.com# Install dependencies
npm install
# Compile TypeScript
npm run build
# Watch for changes
npm run watch
# Show what will be deployed
npm run diff
# Deploy to AWS
npm run deploy
# Synthesize CloudFormation template
npm run synth
# Destroy the stack (careful!)
cdk destroy
After deployment, the stack outputs:
| Output | Description |
|---|---|
BucketName | S3 bucket name |
DistributionId | CloudFront distribution ID |
DistributionDomain | CloudFront domain for DNS |
DeployRoleArn | IAM role ARN for GitHub |
Domain | Your configured domain |
GitHubSecrets | JSON with all secrets |
If you already have an ACM certificate:
export CERTIFICATE_ARN="arn:aws:acm:us-east-1:123456789012:certificate/..."
npm run deploy
export BEPS_DOMAIN="docs.example.com"
npm run deploy
Edit lib/beps-stack.ts:
lifecycleRules: [
{
id: 'DeleteOldPreviews',
enabled: true,
expiration: cdk.Duration.days(30), // Change to 30 days
prefix: '',
},
],
Create separate stacks for dev/staging/prod:
// In bin/app.ts
new BepsStack(app, 'BepsStack-Dev', {
domain: 'beps-dev.boundaryml.com',
// ...
});
new BepsStack(app, 'BepsStack-Prod', {
domain: 'beps.boundaryml.com',
// ...
});
If using a new certificate, you need to add DNS validation records:
aws acm describe-certificate \
--certificate-arn <arn> \
--region us-east-1
Add the CNAME records shown in the output.
Make sure the Origin Access Control (OAC) is properly configured. The stack automatically sets this up, but if you're having issues:
id-token: write permission in workflowcurl -H "Host: branch.beps.boundaryml.com" https://cloudfront-domain/Based on moderate usage:
| Service | Cost |
|---|---|
| S3 Storage (10 GB) | ~$0.23/month |
| S3 Requests (100K) | ~$0.04/month |
| CloudFront (100 GB) | ~$8.50/month |
| ACM Certificate | Free |
| Route 53 (optional) | $0.50/month |
| Total | ~$9-10/month |
To completely remove all resources:
# This will delete everything!
cdk destroy
# Confirm when prompted
Note: The S3 bucket is set to RETAIN by default. If you want to delete it:
aws s3 rm s3://bucket-name --recursivecdk destroyThis CDK stack is designed to work with .github/workflows/deploy-beps.yml. The workflow:
For issues or questions: