How to use GitHub Actions to build and deploy an 11ty website
I love GitHub Actions. It is my favorite platform for continuous integration and deployment by far. It takes most of the concepts from tools like Jenkins and TeamCity, and packages them into a tight, easy to use framework.
Plus, GitHub Actions has a wonderful free plan. So I use GitHub for hosting the repository for my blog, and I use a simple GitHub Actions script to build and deploy it to AWS.
In this article, I'm not going to show you how to set up AWS to host your static site. I'm just going to give you a basic overview of the setup that I use, and give you the simple example script that I use to build and deploy my blog.
Requirements
This is the simplest and cheapest way that I've found to host a static website on AWS. There are definitely cheaper blog platforms out there, but this way gives you full control over every aspect your site, and leaves you the flexibility to evolve your site in the future.
Here are the prerequisites for using this deploy script on GitHub Actions.
- An 11ty website
- A GitHub repository that contains your website
- An AWS S3 bucket that is configured to host publicly available files
- An AWS cloudfront distribution that serves as a cache for the content on S3
- AWS access credentials that can update the S3 bucket and CloudFront distribution that have been saved into secrets on your GitHub repository called AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.
The CloudFront distribution is necessary for caching, and for applying an SSL certificate to your site so that you can safely use the secure https protocol.
You need to set up each of those things before you can use this script.
Modifying the example script
First you should copy this code into a file that is saved into ".github/workflows/main.yaml", where the ".github" folder is in the root directory of your repository.
Then you will then need to modify the example script below in several ways.
If you're using a static site generator other than 11ty, then you need to modify the part of the example script where it says "Build the website". That script will depend on the framework you are using.
Where it says "<YOUR_S3_BUCKET>", you will need to replace that with the name of your S3 bucket.
You will also need to replace "<YOUR_FOLDER_TO_IGNORE>" in the section "Upload files to s3 with AWS CLI" if there are any files in your S3 bucket that the script shouldn't delete. I have folders for images and documents that I want to stay in the same place no matter what is in the repository. So that part of the script ensures that those folders aren't touched.
Finally, you will need to replace "<YOUR_CLOUDFRONT_DISTRIBUTION_ID>" with the string ID of your actual CloudFront distribution.
Then all you will need to do is push that script to your master branch on github. It should handle the rest.
Example script to deploy an 11ty static site to AWS S3 using GitHub Actions
name: Build and push to s3
on: [push]
jobs:
build_deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@master
- name: Build the website
run: npx @11ty/eleventy
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-1
- name: Upload files to s3 with AWS CLI
run: aws s3 sync _site/ s3://<YOUR_S3_BUCKET> --delete --exclude "images/*" --exclude "<YOUR_FOLDER_TO_IGNORE>"
# Invalidate Cloudfront. Based on https://community.ops.io/jei/deploy-a-web-app-to-s3-with-cloudfront-invalidation-via-github-actions-4433
- name: Issue Cloudfront invalidation
uses: chetan/invalidate-cloudfront-action@master
env:
DISTRIBUTION: '<YOUR_CLOUDFRONT_DISTRIBUTION_ID>'
PATHS: '/*'
AWS_REGION: 'us-west-1'
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Impermanence is a virtue: Why building for forever is folly
When I first started gardening, I was jealous of all the beautiful gardens I saw on social media. On Instagram I saw so many beautiful gardens filled with gorgeous raised beds. Or the gardeners were building these amazing structures for growing their annual vegetables. So, of course, I wanted the same thing for my garden.
I ordered fancy metal raised beds by whatever company was being advertised by the social media gardeners. You know the ones I'm talking about. They're about three two and a half feet tall and they look like they're made from corrugated tin. When they arrived, I assembled them and placed them in my yard, and filled them with some pretty expensive soil.
In fact, I dotted my entire backyard with raised beds. Some of them I purchased online, but others I built for myself from lumber I got at the hardware store. I put raised beds on my lawn, on my patio, and on all the ugly concrete that was laid by the last owner of my home. I was reclaiming that space for garden vegetables!
But there was still some leftover space in my backyard. There were a few spots of neglected, in-ground soil where I decided that I could plant a few seeds directly in the soil.
Then I watched my plants grow, and I was surprised by what happened. The raised beds required much more water than the plants in the ground. In fact, they required thorough watering on every hot day of the summer. The ones on hot concrete required even more water, and I indignantly watched a lot of it filtering out the bottom and into the drain!
In fact, the seeds in the soil germinated more quickly, required less care, and produced far, far more fruit.
Getting the moisture and the soil right in a tall raised bed turned out to be very difficult.
So the following year I decided to change things up. I took apart the raised beds that I'd built from lumber, and I turned them into shallow raised beds directly on the soil. A shallow, 6 inch deep raised bed has some of the advantages of a raised bed along with some of the advantages of planting directly in the ground.

That turned out to be the most successful planting method that I've yet discovered. A shallow raised bed directly on the ground is easy to care for, easy to maintain, and easy to build. It's affordable, too. It requires less lumber, and less soil. It costs a fraction of what the fancy metal beds cost, and it even costs less than tall homemade beds.
Unfortunately, I was then stuck with all the "fancy" raised beds I'd purchased online. They looked more like expensive trash than the key to backyard success.
Buying those metal raised beds was a mistake.

And unfortunately, so much of my yard was taken up by a patio that I didn't have room for a bunch of shallow raised beds directly on the soil.
I knew that in order to install more shallow raised beds, the patio would have to come out, even though it wasn't very old. The previous owner had only put it in to sell the place around six years ago.
Building the patio had also been a mistake.
I know now that building for "permanence" is absurd. Especially in the garden. It's nothing but hubris to think that the thing you're building this year will last forever.
It won't.
And not only that, but you won't even want it to last forever. In a year or two or three, you will start to see the flaws in the thing you built. Maybe you'll see that you put it in a suboptimal place, or that it isn't quite right for what you planned to use it for. Or maybe you'll just tire of whatever motivated you to build it in the first place.
You WILL change. You WILL move on. You WILL see things differently.
Which is why I now build beds that I can easily disassemble, move, and reuse. I build garden beds simply by cutting lumber into one meter square sections, and tacking them into the ground using wooden stakes.
These beds cost next to nothing, they are the BEST way to grow annual vegetables, and they can be easily disassembled and moved every time I decide to do something different.
The thinking that we need to build something to last can be a trap. It's what leads people to build shopping malls that sit empty after shopping trends move on. It's what leads people to build from materials that will be used for a few years at most, then will idle in a landfill for eternity.
Don't get me wrong, the idea of single use items isn't great either.
But there is a middle ground.
Building for impermanence is a virtue because it's an extension of using only what you need.
So build that cheap garden bed out of biodegradable materials. When you inevitably regret it, or want to change it next year, it will be that much easier to do so.
Setting up a rain barrel in Santa Clara County
Last year I set up two rain barrels in my yard. One in the front yard and one in the back yard. But I made some mistakes, and I wanted to write a post about some of the things I learned so that others don't repeat my mistakes.
Earn that rebate
First of all, it's possible to get paid to set up a rain barrel. If you build it yourself and use affordable or secondhand supplies, then you can actually make money on your rain barrel. Rebates vary by county, and Santa Clara County will only pay you $35 per rain barrel, but I can imagine setting up five barrels using cheap equipment from Craigslist and making a tidy $175 for improving my home!
Basic plumbing isn't that difficult
Second, you should spend some time learning the basics of DIY plumbing before starting your project. Building a first flush filter and an overflow system is extremely easy if you bother to take the 30 minutes it takes to understand them. Not only that, but Santa Clara County will only offer you a rebate if you build the basic overflow system that they require.
Mosquitos are pretty lame
Finally, make sure to plan for a fully enclosed rain barrel. You can have a hole in the top to allow water to enter, but it must be sealed or covered with a screen to prevent mosquitos from reproducing in it. Again, this is a requirement of the county I live in, and it's probably a requirement of your county, too.
Learn from my mistakes
So what mistakes did I make when I built my rain barrels?
Well, I opted for aesthetics rather than going for the rebates. I built a system that looks good in my yard, as opposed to one that is robust and that qualifies for the rebates.
I wanted beautiful half wine barrels rather than ugly plastic barrels. Here I am posing with my system during a light fall rain.

And I do think the system looks about as good as a rain barrel can. I like the aesthetic of a half filled wine barrel.
But boy do I need to use that water quickly! If I leave it in there for more than two weeks, then I will start seeing mosquito larvae in there, and that's really not good.
Also, there's no first flush filter or overflow mechanism, and since a half barrel is woefully inadequate for catching even a fraction of the rain from a decent rainstorm, these barrels are constantly overflowing.
I did install an adjustable diverter that allows me to only capture a small portion of the rain coming off my roof, but that's not nearly sufficient to a big storm.
So I am in the process of reworking my rain barrels. I am adding a first flush filter and a proper overflow system that goes back into the downspouts.
But I hope that you learn from my mistakes, and include those basic systems from the start!
My Father's Dragon is for book lovers
I love books so much that I enjoy them in multiple formats. I recently purchased a Supernote, and because of that I'm enjoying reading digital books for the first time in a long time. But I also love good, old fashioned paper books.
I love the way they feel in my hands, I love the way they smell, and I especially love the way they look. A book with good illustrations is entrancing.
Which is why I have a small collection of relatively inexpensive books that are notable only because they are well-illustrated.
Today I want to share a recent discovery called My Father's Dragon. Apparently, I'm late to the party, because Netflix made it into a movie a few years ago, but I only recently discovered it.
It was written by a woman named Ruth Stiles Gannett and illustrated by her stepmother, Ruth Chrisman Gannett.
I'm not going to lie; despite it being only a few dozen pages long, I've never read it. I purchased it only because it is one of the most lavishly illustrated books I've ever seen. Nearly every open fold is illustrated.
And I'm posting about it now because it makes a great gift. You can still get good quality first editions from 1948 for under $20 on ebay.
For someone who loves books, and the art of illustration, it's $20 worth of magic.
Name calling is still rude and ineffective
One of the things I dislike most is black and white thinking: when a person breaks down a situation and decides that there are only two sides, the good and the bad. The right and the wrong. That's almost never a good analysis of... anything.
One of the signs of black and white thinking is name calling, yet name calling seems to be the main form of political discourse these days.
We call people names when we want to turn them into the "other". When we want people to see them as less than human. When we want to justify the way we treat them.
Name calling generally has the intended effect. It pushes people away and separates them from the group in power (the group who is inventing the names). It is drawing a line in the sand and saying that anyone who might fit that name is on the other side (the "bad" side).
What's tragic in today's politics is that people are often unaware that they are even participating in this. I see so many well educated and well intentioned people spouting these weird vocabularies that only make sense to the other people in the increasingly small in-group.
Obviously we hear this from the president the most. His word salad is so dense it's almost impenetrable. To him, his enemies are woke antifa leftist communist snowflakes. I think his leadership is a significant part of the problem.
But we see this equally from the groups in power on the left. The left continues to wonder why men aren't voting for Democrats, while continuing to invent new ways to denigrate men. Today the boogey man is the incel tech bro performative misogynist manosphere. While I generally consider myself a liberal, I think some of the talking heads on the left are nearly as difficult to understand as the president.
In both cases using this rhetoric is shameful, rude, and just plain lazy analysis.
Because most people are good people no matter which "side" they're on. Most people are not racists or misogynists or communists or terrorists. They are good people who disagree with a lot of the rhetoric even from their own side. They have complex feelings toward the government and toward the politics of today.
They love their community, and their country, and they want to do the right thing for the people who live there.
But name calling isn't just lazy analysis, it also accomplishes the opposite of what people usually want to do. When we use words like this, words that turn people into the "other", we push them away. Instead of bringing them alongside us, we are making it more difficult for them to see our side.
On social media this happens every day. People spend 5 minutes venting their rage then move on to whatever is next. They live on anger. In my head I call them "social media rage goblins", but I recognize that making up a name for them is somewhat ironic.
On traditional media I wonder how these people continue to find work.
What I would like to see from leaders and commenters is a refusal to engage with the most fringe beliefs like those spouted on the internet by anonymous people on the far left or far right. Instead of centering the people with the worst beliefs, let's talk to the rational people on the other side. We should lead by showing that we know that fringe beliefs are not the beliefs of most regular people.
Maybe this post is just an old fashioned call for civility. Maybe it's as antiquated and obsolete as the president's tax and tariff policies.
But I still want everyone to recognize the fundamental humanity in their political opponents. Generosity shown to someone you disagree with is the highest human virtue.