A new way to deploy to Amazon S3
Pretty much since I began hosting this site on Amazon S3 I've been using middleman-s3_sync to do the heavy lifting of syncing files to the bucket. Unfortunately, somewhere along the way it stopped picking up certain files that should've been synced. I tried to be a good OSS citizen and find a fix, but after delving into the Middleman innards, I couldn't find the problem.
A new method
A new method of deploying the site was needed and recently I moved to using Amazon's own aws cli utility. After years of providing next to nothing in regards to tooling, Amazon have released their own command line utility for interacting with AWS. And the best part is that it seems very nice .
This is how I now deploy the site.
1
2
3
4
5
aws s3 sync build s3://jordanelver.co.uk \
--profile jordanelver.co.uk \
--delete \
--acl public-read \
--exclude *.DS_Store \
build
is the local directory to be synced, and s3://jordanelver.co.uk
is the remote
S3 bucket.
--delete
says to delete files at the destination that are not in the build/
directory.
--profile
controls which credentials and other settings to use when connecting
to S3. More on this below.
--acl public-read
makes the synced files publicly readable, as required by S3
static website hosting.
--exclude
excludes those pesky .DS_Store
files that OS X litters around the
filesystem.
Credentials
Credentials are stored in ~/.aws/credentials
. I have a section like this.
1
2
3
[jordanelver.co.uk]
aws_access_key_id = <ACCESSKEY>
aws_secret_access_key = <SECRET>
You'll see that this matches the --profile jordanelver.co.uk
line in the
s3 sync
commandline.
That covers authentication, but you can also specify additional configuration
values in ~/.aws/config
. In this case, the S3 bucket region.
1
2
[profile jordanelver.co.uk]
region = eu-west-1
I used aws configure --profile jordanelver.co.uk
to configure these values.
One last thing
One last thing that deserves to be mentioned is the --dryrun
flag. It's very
handy for testing what's going to happen, before it happens. I ended up
wrapping my sync command in a Ruby script to conditionally add --dryrun
as
and when I need it.
Happy syncing!