Skip to content

Crystal on AWS

David Foster edited this page Mar 27, 2026 · 5 revisions

Crystal can serve an archived website directly from AWS, making it accessible to anyone with a web browser; no need to install Crystal locally. This uses AWS Lambda to run Crystal and Amazon S3 to store the project.

Prerequisites

  1. An AWS account. Create one if you don't have one already.

  2. A .crystalproj uploaded to S3. Create an S3 bucket and upload your project directory to it. See Projects on AWS S3 for details on uploading, including the recommended Pack16 format conversion.

Tip: After uploading, copy the S3 URL of your .crystalproj from the S3 Console; you'll need it in the next step. It looks like: s3://my-bucket/My Site.crystalproj

Deploy

Option 1: Quick Deploy (recommended)

Click one of the buttons below to open the AWS CloudFormation Console with the Crystal template pre-loaded:

Stable (latest release) Launch Stack
Dev (main branch, may be unstable) Launch Stack

Then:

  1. Stack name: Choose a name for this deployment (e.g. crystal-my-site). Each archived site you deploy needs its own stack name.

  2. Project S3 URL: Paste the S3 URL of your .crystalproj (e.g. s3://my-bucket/My Site.crystalproj). You can copy this directly from the S3 Console.

Screenshot of parameter form
  1. Leave the Advanced Options at their defaults.

  2. Scroll down and check the box "I acknowledge that AWS CloudFormation might create IAM resources with custom names." This is required because the template creates an IAM role that allows the Lambda function to read your project from S3.

Screenshot of IAM acknowledgement checkbox
  1. Click Create stack.

  2. Wait for the stack status to reach CREATE_COMPLETE (typically 2-4 minutes).

Screenshot of stack creation in progress / complete
  1. Go to the Outputs tab. The SiteUrl1 value is the public URL where your archived site is now accessible.
Screenshot of Outputs tab with SiteUrl highlighted

Option 2: Manual Deploy

If you prefer to inspect the template before deploying, or if the Quick Deploy links above don't work for your region:

  1. Download the CloudFormation template: crystal.cloudformation.yaml

  2. Open the AWS CloudFormation Console.

  3. Click Create stack > With new resources (standard).

  4. Select Upload a template file, choose the downloaded crystal.cloudformation.yaml, and click Next.

  5. Follow the same steps as Quick Deploy above (fill in stack name, Project S3 URL, acknowledge IAM, create).

(Optional) Add a Custom Domain

By default, your site is served at an auto-generated URL like https://abc123.lambda-url.us-east-2.on.aws/. To use your own domain (e.g. mysite.example.com), you can add a custom domain using AWS CloudShell, a browser-based terminal built into the AWS Console that requires no local setup.

Adding a custom domain

Prerequisites: A domain you own, with access to manage its DNS records at your registrar.

  1. Open AWS CloudShell.

  2. In the top-right corner of the page, select the region matching the one your Crystal stack is deployed in (e.g. "US East (Ohio) us-east-2").

Screenshot of region selector in CloudShell
  1. Paste and run this command, replacing <stack-name> and <domain> with your values:

    curl -sL https://raw.githubusercontent.com/davidfstr/Crystal-Web-Archiver/main/src/crystal_on_aws/custom-domain-add.sh | bash -s <stack-name> <domain>
    

    For example:

    curl -sL https://raw.githubusercontent.com/davidfstr/Crystal-Web-Archiver/main/src/crystal_on_aws/custom-domain-add.sh | bash -s crystal-my-site mysite.example.com
    
  2. The script will display two CNAME records to add at your domain registrar. Add both records, then press Enter in CloudShell to continue.

Screenshot of CNAME records output
  1. Wait for the script to finish (typically 5-10 minutes). When complete, your site will be live at https://mysite.example.com/.

Removing a custom domain

  1. Open AWS CloudShell and select the correct region.

  2. Paste and run:

    curl -sL https://raw.githubusercontent.com/davidfstr/Crystal-Web-Archiver/main/src/crystal_on_aws/custom-domain-remove.sh | bash -s <stack-name>
    
  3. The script will list the resources to be deleted and ask for confirmation. After completion, it will remind you to remove the CNAME records at your registrar.

Managing Your Deployment

Updating to a new Crystal version

When a new version of Crystal is released, the public container image (latest tag) is updated automatically. To pick up the new version:

  1. Open your stack in the CloudFormation Console.
  2. Click Update > Use current template > Next.
  3. Change the Image Refresh Token field (under Advanced Options) to any new value (e.g. 2 or today's date).
  4. Click through Next > Next > check the IAM acknowledgement > Submit.

The stack update will pull the latest Crystal image. This typically takes 2-4 minutes.

Changing the project URL

To point the deployment at a different .crystalproj:

  1. Open your stack in the CloudFormation Console.
  2. Click Update > Use current template > Next.
  3. Change the Project S3 URL to the new S3 URL.
  4. Click through to submit.

Deleting the deployment

  1. If you added a custom domain, remove it first.
  2. Open your stack in the CloudFormation Console.
  3. Click Delete.
  4. Confirm the deletion. All AWS resources created by the stack will be removed.

Note: This does not delete your .crystalproj from S3. Your archived project data is preserved.

What Gets Created

The CloudFormation template creates the following AWS resources:

Resource Purpose
Lambda Function Runs Crystal to serve your archived site
Function URL Provides a public HTTPS endpoint for the Lambda function
IAM Role Grants the Lambda function permission to read your project from S3 and write logs to CloudWatch
URL Parser (helper Lambda) Parses the S3 URL you provide into bucket name and key path (needed because CloudFormation's built-in string functions are limited)
Image Copier (helper Lambda) Copies Crystal's public container image to a private ECR repository in your account (needed because Lambda can only run images from private ECR)
ECR Repository Stores the private copy of the Crystal container image (crystal-on-aws)
CloudWatch Log Groups Stores logs from the Lambda functions (auto-expires after 7 days)

When a custom domain is added, the custom-domain-add.sh script additionally creates:

Resource Purpose
CloudFront Distribution Routes traffic from your custom domain to the Lambda Function URL
ACM Certificate Provides HTTPS for your custom domain

Cost

Crystal on AWS is designed to be inexpensive for typical archival use (low-traffic sites served to occasional visitors).

The main cost components are:

  • Lambda: Billed per request and per GB-second of compute time. A typical page load takes a few hundred milliseconds. Lambda has a generous free tier (1M requests/month).
  • S3: Billed for storage and GET requests. Crystal reads objects on-demand as visitors browse.
  • ECR: Billed for storage of the private container image copy (~350 MB, about $0.04/month).
  • CloudWatch Logs: Log groups are configured with 7-day retention to limit costs.
  • CloudFront (custom domain only): Billed per request and per GB of data transfer. Has a free tier (1 TB/month).

For a low-traffic archived site, expect costs on the order of a few cents per month beyond S3 storage for the project itself. The main ongoing cost is typically S3 storage for your .crystalproj.

Clone this wiki locally