Skip to content

Instantly share code, notes, and snippets.

@conradfuhrman
Last active October 29, 2024 00:45
Show Gist options
  • Save conradfuhrman/7a18539ac6d52039e6a4299e85a801e4 to your computer and use it in GitHub Desktop.
Save conradfuhrman/7a18539ac6d52039e6a4299e85a801e4 to your computer and use it in GitHub Desktop.
A Working Doc for AWS S3/CloudFront and Statamic SSG

WIP, 10/28/2024

AWS Setup for Statamic with SSG

This is a setup guide for how I've managed SSG with Statamic. First and foremost, this guide assumes that you have existing knowedlge of Statamic and some general AWS expereince as well. Secondly, this is purely a setup guide on what we have found to be what we prefer. There are plenty of other setups/configurations that others in the community use and the Statamic Discord is where that discussion should be had.

Overview

For this setup we are going to focus on a staging environment. This is identical to what we do with production, just with altered variables and secrets, along with different buckets. For dev, we only use two of the three buckets shown since we test locally for the compile. We'll also be tying this into GitHub actions for deployment.

Initial Setup

To get started we're going to create three buckets. I'll use the word project to reference whatever the sitename is.

project-staging-assets project-staging-glide project-staging-ssg

project-staging-assets will act as our general assets bucket. There are one or two items to configure with code, but we'll get there in a further step. project-staging-glide will hold all our glide assets. If you are not using Glide then you will not need this, but we use it heavily to optimzie and transform images for performance. project-staging-ssg is our compile bucket that will contain all our final compiled files.

In setting these up there are some general items to setup on S3 for each bucket.

Asset Bucket & Glide Bucket

For the assets bucket you'll want to ensure the following:

All Block public access is turned off.

Next, the Bucket Policy should be edited to make items public.

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "PublicReadForGetBucketObjects",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "THE-ARN-OF-YOUR-BUCKET/*"
        }
    ]
}

Lastly, we edit the Object Ownership to enable ACL's

SSG Bucket

The SSG bucket largely is the same as the asset and the glide bucket for the main items, but the only difference is that you need to enabled Website Hosting.

Next up is ensuring your Statamic project is setup with the items needed.

Statamic Setup

We'll update the .env with sne new variables and replace some existing ones.

AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_DEFAULT_REGION=us-east-1
AWS_USE_PATH_STYLE_ENDPOINT=false

AWS_BUCKET=project-staging-assets
AWS_BUCKET_GLIDE=project-staging-glide

AWS_URL=https://project-staging-assets.s3.amazonaws.com
AWS_URL_GLIDE=https://project-glide-glide.s3.amazonaws.com

Ensure that you have configured your assets to use the S3 bucket.

We'll also need to add the glide to the config/filesystems.php file for Laravel:

's3' => [
    'driver' => 's3',
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION'),
    'bucket' => env('AWS_BUCKET'),
    'url' => env('AWS_URL'),
    'endpoint' => env('AWS_ENDPOINT'),
    'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
    // 'visibility' => 'public', // https://statamic.dev/assets#visibility
    'throw' => false,
],

'glide' => [
    'driver' => 's3',
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION'),
    'bucket' => env('AWS_BUCKET_GLIDE'),
    'url' => env('AWS_URL_GLIDE'),
    'endpoint' => env('AWS_ENDPOINT'),
    'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
    'visibility' => 'public', // https://statamic.dev/assets#visibility
    'throw' => false,
],

Next in the config/statamic/assets.php file, you'll want to update the Save Cached Images area to use the glide driver that you now added in the filesystems.php config.

/*
|--------------------------------------------------------------------------
| Save Cached Images
|--------------------------------------------------------------------------
|
| Enabling this will make Glide save publicly accessible images. It will
| increase performance at the cost of the dynamic nature of HTTP based
| image manipulation. You will need to invalidate images manually.
|
*/

'cache' => 'glide',
'cache_path' => public_path('img'),

GitHub Action Setup

name: Deploy SSG to Staging

on:
  push:
    branches:
      - main

env:
  # Statamic Variables
  STATAMIC_LICENSE_KEY: ${{ secrets.STATAMIC_LICENSE_KEY }}
  APP_KEY: ADD AN APP KEY HERE
  APP_URL:  ${{ vars.APP_URL }}

  # AWS Variables
  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY }}
  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET }}
  AWS_DEFAULT_REGION: ${{ vars.AWS_REGION }}
  AWS_REGION: ${{ vars.AWS_REGION }}
  AWS_USE_PATH_STYLE_ENDPOINT: 'false'

  # SSG Bucket for S3 Sync 
  AWS_S3_BUCKET: ${{ vars.AWS_BUCKET_SSG }}

  # Assets Bucket
  AWS_BUCKET: ${{ vars.AWS_BUCKET }}
  AWS_URL: ${{ vars.AWS_URL }}

  # Glide Bucket
  AWS_BUCKET_GLIDE: ${{ vars.AWS_BUCKET_GLIDE }}
  AWS_URL_GLIDE: ${{ vars.AWS_URL_GLIDE }}

  SOURCE_DIR: ${{ vars.SOURCE_DIR }}
  DISTRIBUTION: ${{ vars.AWS_CF }}
  
  PATHS: '/*'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4  

      - name: Setup PHP (w/ extensions) & Composer
        uses: shivammathur/setup-php@v2
        with:
          php-version: 8.3
          tools: composer
  
      - name: Get Composer Cache Directory
        id: composer-cache
        run: |
          echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
      - uses: actions/cache@v4
        with:
          path: ${{ steps.composer-cache.outputs.dir }}
          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
          restore-keys: |
            ${{ runner.os }}-composer-

      - name: Install Composer dependencies
        run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader

      - name: Setup NPM & Build
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci
      - run: npm run build

      - name: Compile the SSG
        run: php please ssg:generate

      - name: S3 Sync
        uses: jakejarvis/[email protected]
        with:
          args: --acl public-read

      - name: Invalidate Cloudfront
        uses: chetan/[email protected]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment