Want to load user data into an AWS Launch Template without fussing around with base64 encoding? Here’s a handy trick using Terraform and the filebase64
function. Kudos to Loren Gordon for the tip to use a function instead of a data object!
In my scenario, I use a launch template to create any number of Amazon EC2 instances to act as Kubernetes nodes as part of my Certified Kubernetes Administrator Study Guide efforts. It makes sense to bootstrap the instances with a bash script that disables swap, sets up the bridge network, installs Docker, installs all of the Kubernetes dependencies, and then creates desired aliases. Here is the script and the documentation, for those interested.
I use Terraform to do the heavy lifting. And while I could, and originally did, embed the base64 encoded string into the launch template’s user_data
field, this comes with a few problems:
- I can’t read raw base64 encoded text because I’m not a robot.
- Inserting stateful data into a Terraform configuration is an anti-pattern; state should be abstracted and iterated independently.
- Editing, linting, and reviewing encoded user data is tricky because of the required decoding, making a change, and then encoding process. ?
My colleague and highly skilled engineer, Mike Preston, suggested splitting out the user data for these very same reasons.
Contents
Creating a Data Object
Thus, I split out user data into a file named user_data.sh
and rely on the filebase64
function to retrieve the script contents.
user_data = filebase64("user_data.sh")
To my delight, this retrieves the raw content and encodes the results using base64 without the need to use a local_file
data object. This obviates the need to do any encoding on the client side. Let’s go!
Using the Data Object for User Data
Setting the value of the user_data
parameter to filebase64("user_data.sh")
connects the dots between my normal bash script and the base64 encoded string that AWS needs.
resource "aws_launch_template" "cka-node" {
name = var.instance-name
image_id = "ami-07a29e5e945228fa1"
instance_type = var.instance-type
<snip>
user_data = filebase64("user_data.sh")
}
Now I am able to work on the script independently, without any decoding required, and Terraform handles all of the launch template versioning and updates for me.

Later, when the upstream Auto Scaling group uses the launch template to create or rollout new instances, the script is automatically embedded into user_data
. Easy!
Validating User Data
One way that user data can be retrieved and validated is from within the instance. Think of this as a sort of sanity check. The link-local address shown below is used to perform retrieval.
curl http://169.254.169.254/latest/user-data/

Next Steps
Please accept a crisp high five for reaching this point in the post!
If you’d like to learn more about Infrastructure as Code, or other modern technology approaches, head over to the Guided Learning page.