Day 39: Injecting a Start-up Script Into an AWS Instance Using User Data

Welcome to Day 39 of the “100 Days of DevOps with PowerShell”! For background on our goals in this series, see Announcing the “100 Days of Devops with PowerShell” Series here at SCC.

Whenever you deploy a new server, workstation or virtual machine there is nearly always a requirement to make final changes to the system before it’s ready for use.  Typically this is normally done with a post-deployment script that might be triggered manually on start-up or it might be a final step in a Configuration Manager task sequence or if you using Azure you may use the Custom Script Extension.  So how do you achieve similar functionality using EC2 instances in Amazon Web Services (AWS)?  If you’ve created your own Amazon Machine Image (AMI) you can set the script to run from the Runonce registry key, but than can be a cumbersome approach particularly if you want to make changes to the script and it’s been embedded into the image.   AWS offers a much more dynamic method of injecting a script to run upon start-up through a feature called user data.

User Data and EC2 Instances

Each AWS instance that has been created from an AWS AMI includes the EC2 Config Service.  One of the functions of the EC2 Config Service is to check user data for <script>…</script> or <powershell>…</powershell> tags and execute any scripts contained within them.  Therefore to bootstrap the instance with a script we need to pass that script data within the appropriate tags and in our example we’re obviously going to place our script within the <powershell>…</powershell> tags.  In addition if you are deploying an instance via PowerShell you need to specify the –Userdata parameter of the New-EC2Instance cmdlet and critically you need to base 64 encode the script.

In the example below, we’re going to do some basic post-deployment configuration changes, specifically install the SNMP service because we have a monitoring application that requires it, disable IPv6 and finally enable WMI on the firewall.

We’re going to save this script as post-deployment.ps1 and then read the contents of the script, adding the necessary xml tags and then base 64 encode the data so it can be passed through to the –Userdata parameter when we’re deploying the instance.  Below is our deployment script, much of which will look familiar from Day 34:


As we’ve demonstrated here, deploying a customized VM has just taken a massive leap forward because we can script out exactly how our VM should look like, but without the management overheard of creating and customizing an image.  If we think back to some of the earlier posts on deploying packages and modules with OneGet and PowerShellGet, we can very easily build deployment scripts that are injected with the applications we need.  And yet we’ve not even explored the possibilities of configuring our VMs with DSC, stay tuned!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.