Infrastructure · Updated Jun 29, 2026
Public Website Deployment
Public Website Deployment
Checklist for taking the SystemLink docs site public with S3 + CloudFront.
#Short Answer
Yes, CloudFront can use your own domain name.
CloudFront calls these alternate domain names or CNAMEs. To use one, the distribution needs:
- The domain added as an alternate domain name, such as
docs.example.com.
- A valid TLS certificate that covers that domain.
- DNS pointed at the CloudFront distribution.
AWS docs:
Important certificate detail: for viewer HTTPS on CloudFront, request or import the ACM certificate in us-east-1 (US East / N. Virginia).
#Recommended Architecture
Use:
- Private S3 bucket for static files.
- CloudFront distribution as the public HTTPS front door.
- Origin Access Control (OAC) so only CloudFront can read the bucket.
- ACM certificate for a custom domain.
- Route 53 alias record if DNS is hosted in Route 53.
Avoid:
- Making the S3 bucket public.
- Publishing from the private Git server instance.
- Uploading anything outside
Docs/Site.
- Uploading private infrastructure notes.
#Repo-Side Preconditions
- [x] Public docs are generated into
Docs/Site.
- [x] Private infrastructure notes are outside
Docs.
- [x] Public safety scan exists:
powershell -ExecutionPolicy Bypass -File Tools\scan_public_docs.ps1
Before every deploy:
python Tools\build_docs_site.py
powershell -ExecutionPolicy Bypass -File Tools\scan_public_docs.ps1
#AWS Setup Checklist
#1. Choose Names
- [ ] Pick public domain or subdomain.
- Example:
docs.systemlink.dev
- [ ] Pick globally unique S3 bucket name.
- Example:
systemlink-docs-public
- [ ] Decide AWS region for S3.
- Example:
us-east-2or whichever region you normally use.
- [ ] Remember: CloudFront certificate must be in
us-east-1.
#2. Create S3 Bucket
- [ ] Create the bucket.
- [ ] Keep Block all public access enabled.
- [ ] Do not enable public bucket policies.
- [ ] Do not rely on the S3 static website endpoint for the final public URL.
- [ ] Optional: enable bucket versioning.
#3. Create CloudFront Distribution
- [ ] Origin points at the S3 bucket REST endpoint, not the S3 website endpoint.
- [ ] Create/use Origin Access Control (OAC).
- [ ] Set default root object to
index.html.
- [ ] Viewer protocol policy: redirect HTTP to HTTPS.
- [ ] Allowed methods:
GET,HEAD.
- [ ] Enable compression.
- [ ] Add custom error response:
404->/index.htmlonly if we later add client-side routing.- For the current static HTML site, normal
404is fine.
#4. Lock S3 To CloudFront
- [ ] Add the bucket policy generated/recommended by CloudFront OAC.
- [ ] Confirm direct public S3 access is denied.
- [ ] Confirm CloudFront can read
index.html.
#5. Add Custom Domain
- [ ] Request ACM cert in
us-east-1.
- [ ] Include the exact domain:
docs.example.com, or- wildcard like
*.example.comif appropriate.
- [ ] Validate the certificate through DNS.
- [ ] Add the domain as a CloudFront alternate domain name.
- [ ] Attach the ACM certificate to the distribution.
- [ ] Point DNS to CloudFront:
- Route 53: use an Alias
Arecord, plusAAAAif IPv6 is enabled. - Other DNS provider: use
CNAMEfor subdomains.
#6. Deploy Site
Initial manual deploy:
python Tools\build_docs_site.py
powershell -ExecutionPolicy Bypass -File Tools\scan_public_docs.ps1
aws s3 sync Docs\Site s3://YOUR_BUCKET_NAME --delete
aws cloudfront create-invalidation --distribution-id YOUR_DISTRIBUTION_ID --paths "/*"
Replace:
YOUR_BUCKET_NAME
YOUR_DISTRIBUTION_ID
#7. Verify
- [ ] CloudFront domain loads.
- [ ] Custom domain loads over HTTPS.
- [ ] Homepage image loads.
- [ ] Docs pages load.
- [ ] Screenshot gallery loads.
- [ ] Filter works on screenshots.
- [ ] Old private infrastructure pages return
404.
- [ ] Direct S3 object URL is not publicly readable unless intentionally allowed.
#Future Deploy Script
Once the AWS bucket and distribution exist, create:
Tools/deploy_docs_site.ps1
It should:
- Build the site.
- Run the public safety scan.
- Sync
Docs/Siteto S3.
- Invalidate CloudFront.
Draft shape:
param(
[Parameter(Mandatory = $true)]
[string]$BucketName,
[Parameter(Mandatory = $true)]
[string]$DistributionId
)
$ErrorActionPreference = "Stop"
python Tools\build_docs_site.py
powershell -ExecutionPolicy Bypass -File Tools\scan_public_docs.ps1
aws s3 sync Docs\Site "s3://$BucketName" --delete
aws cloudfront create-invalidation --distribution-id $DistributionId --paths "/*"
#Open Questions
- [ ] What domain should be used?
- [ ] Is DNS in Route 53 or another registrar/provider?
- [ ] Should screenshots be public?
- [ ] Should the public site include all docs or only a curated subset?
- [ ] Should deployment happen from this machine, private Git CI, or an AWS pipeline later?