Skip to content

Deployment Guide

Deploy Kukui to AWS S3/CloudFront or rsync, and set up CI/CD

Deployment Guide

For: Anyone who ships a Kukui site to production (DevOps, operators, developers).

In this guide you'll: Configure deployment targets in sites.json, deploy to S3/CloudFront (default) or rsync, use the deploy-tool for verification and rollback, and set up CI/CD (e.g. GitHub Actions).


Overview

  • Default path: AWS S3 + CloudFront. Build output is synced to an S3 bucket; CloudFront serves the site (optional custom domain and SSL).
  • Alternative: Rsync to an EC2 instance or any server. Set rsync.host in sites.json and use yarn deploy-rsync.
  • Deploy tool: For S3 deployments, the deploy-tool provides sync (dry-run), deploy, status, history, and rollback. It can use DynamoDB for deployment state (optional).

Default deployment architecture (S3 + CloudFront)

Deploy flow


Prerequisites

  • AWS CLI installed and configured (for S3/CloudFront)
  • Node.js and build environment (so yarn build runs)
  • Credentials: AWS credentials with access to the S3 bucket and (if used) CloudFront invalidation
  • Domain and DNS (optional): for a custom domain, you'll need a certificate in ACM and a DNS record pointing to CloudFront

Config (sites.json and content.json)

sites.json (under site root)

Deployment target is read only from sites.json for the active site (no .env for S3 bucket). Set SITE_ID or DEPLOY_SITE when you have multiple sites.

S3/CloudFront (default):

{
  "defaultSiteId": "example.com",
  "sites": {
    "example.com": {
      "hostname": "example.com",
      "s3": {
        "bucket": "your-bucket-name",
        "region": "us-east-1"
      },
      "cloudfront": {
        "distributionId": "E1XXXXXXXXXX"
      },
      "outDir": "./out"
    }
  }
}

Optional: dynamodb (region, tablePrefix) for deploy-tool state and rollback.

Rsync (alternative): In the same site entry, set:

"rsync": {
  "host": "user@host.example.com:/var/www/site"
}

Or set DEPLOY_HOST in .env for rsync.

content.json (per site)

In your site directory (<siteRoot>/<siteId>/content.json), set:

  • cdn.hostname — CDN domain (e.g. your CloudFront domain or custom domain) for asset URLs
  • cdn.basePath — e.g. /assets
  • siteURL — Full site URL (e.g. https://example.com)

Important: After changing cdn.hostname or siteURL, run yarn build again so album indexes and other generated data use the new URLs.


AWS setup (concise)

  1. ACM (certificate): Request a public certificate in us-east-1 (required for CloudFront). Validate via DNS.
  2. S3: Create a bucket; configure Origin Access Control (OAC) so only CloudFront can access it; set a bucket policy that allows CloudFront using the distribution ARN.
  3. CloudFront: Create a distribution with the S3 bucket as origin; attach the ACM certificate; set alternate domain name (CNAME); set default root object index.html and error pages (e.g. 404 → /404.html or /index.html for SPA).
  4. DNS: Create a CNAME (or Route 53 alias) from your domain to the CloudFront distribution domain.

For step-by-step instructions and exact policy examples, see the repo docs (e.g. AWS Deployment guide).


Deploy commands

Default: yarn deploy (or deploy.sh)

Builds (if needed), syncs the out directory to S3, and invalidates the CloudFront cache when cloudfront.distributionId is set:

yarn deploy

Uses sites.json for bucket, region, and distribution ID. No .env needed for S3 target.

Deploy tool (S3)

CommandDescription
yarn deploy:setupSet up deploy-tool config and DynamoDB tables (if used)
yarn deploy:pullPull latest deployment state
yarn deploy:syncShow diff between local and remote (dry-run)
yarn deployDeploy to S3 (same as above; deploy-tool can add verification)
yarn deploy:statusShow deployment status
yarn deploy:historyShow deployment history
yarn deploy:rollbackRollback to previous deployment

Use --site <siteId> or --sites-root <path> when needed.

Rsync

Set rsync.host in sites.json (or DEPLOY_HOST in .env), then:

yarn deploy-rsync

Use this for EC2 or any server where you deploy via rsync instead of S3.


Verification

  • Pre-deploy: The deploy flow can verify that the out directory exists and contains HTML, and that critical routes (e.g. homepage, section roots) exist. Configure in sites.json under a verification object (e.g. verifyRoutes, failOnMissingRoutes, criticalRoutes).
  • Post-deploy: Deploy-tool can verify that files were uploaded successfully.

Cache and invalidation

  • CloudFront: After uploading new or changed files, run a cache invalidation (e.g. /* or /assets/*). yarn deploy typically triggers this when a distribution ID is set.
  • Cache headers: HTML and dynamic content (e.g. JSON) use short or no-cache headers; static assets (e.g. hashed JS/CSS, images) can use long-lived cache (e.g. max-age=31536000, immutable). The deploy script and deploy-tool apply appropriate headers.

CI/CD (example: GitHub Actions)

  1. On push to main, checkout repo, install dependencies, run yarn build.
  2. Configure AWS credentials (e.g. aws-actions/configure-aws-credentials) using secrets (e.g. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY). Do not put the S3 bucket name in secrets — it comes from sites.json (or set SITE_ID so the right site is used).
  3. Sync out to S3 (e.g. aws s3 sync out/ s3://$BUCKET/ --delete ...) and run CloudFront invalidation.

Example snippet:

- name: Build site
  run: yarn build
 
- name: Configure AWS credentials
  uses: aws-actions/configure-aws-credentials@v2
  with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    aws-region: us-east-1
 
- name: Deploy to S3
  run: yarn deploy

Adjust for your SITE_ID (e.g. set env in the workflow) so the correct site and bucket from sites.json are used.


Deployment issues

Images not loading? 404s? SSL problems? Slow updates? See Troubleshooting for CDN config, rebuild, error pages, certificate region, and cache invalidation.


Security and cost

  • Security: Use Origin Access Control (OAC) so only CloudFront can read from S3. Enforce HTTPS (redirect HTTP to HTTPS in CloudFront). Keep AWS credentials in secrets (e.g. GitHub Actions secrets), not in repo or .env committed to git.
  • Cost (rough): For a low-traffic static site, S3 is typically under $1/month and CloudFront under ~$5/month. See AWS pricing for current rates.

See also