Skip to main content
This lesson shows how to use CloudFormation’s cfn-init helper to apply the configuration defined in a template’s Metadata to an EC2 instance. Key concepts covered:
  • How to pass stack and region pseudo-parameters into instance UserData using Fn::Base64 + Fn::Sub.
  • Ensuring the --resource you pass to cfn-init matches the logical resource name that contains AWS::CloudFormation::Init (for example, MyInstance).
  • Placing package, service, file, and other configuration under Metadata: AWS::CloudFormation::Init so cfn-init can read and apply it.
Quick example: minimal Resources snippet that calls cfn-init from UserData and installs + starts Apache (httpd):
How this works
  • UserData is base64-encoded via Fn::Base64. Fn::Sub (or !Sub) injects pseudo-parameters such as ${AWS::StackName} and ${AWS::Region} into the script.
  • cfn-init reads the AWS::CloudFormation::Init metadata for the resource named by --resource (here, MyInstance) and applies that config: installing packages and managing services.
  • IamInstanceProfile must grant the instance permission to call CloudFormation and S3 (if cfn-init needs to fetch files). SecurityGroupIds provides network access (for example, to serve HTTP).
Table of common AWS::CloudFormation::Init sections Parameters example (if you include template parameters):
Best practices and troubleshooting
  • Make sure the --resource passed to cfn-init exactly matches the logical resource name that contains AWS::CloudFormation::Init. If they differ, cfn-init will not find or apply the configuration.
  • Use -v (verbose) with cfn-init to capture logs in /var/log/cfn-init.log and /var/log/cloud-init.log for troubleshooting.
  • Ensure the instance role (IamInstanceProfile) includes permissions for cloudformation:DescribeStackResource, s3:GetObject (if using S3 artifacts), and other actions required by your init tasks.
Ensure the --resource argument passed to cfn-init matches the logical resource name that has AWS::CloudFormation::Init in the template. If they differ, cfn-init will not find the configuration.
Deployment and verification
  1. Upload the template and create the stack.
  2. CloudFormation will create the security group and the EC2 instance. Wait for the EC2 instance status checks to pass before accessing the instance.
  3. Once status checks are complete, select the instance and copy the Public IPv4 address. Paste that address into a browser to confirm Apache is serving the expected page.
A screenshot of the AWS EC2 Instances console showing a single running
t3.micro instance (i-0827c39cca0f17744) in the us-east-2 region with 3/3
status checks passed. The top bar shows controls like Connect, Instance state,
Actions, and Launch
instances.
You should see the Apache landing page, confirming the packages were installed and the service was started by cfn-init. When CloudFormation finishes creating the stack, the CloudFormation console will display the stack with a CREATE_COMPLETE status.
An AWS CloudFormation Stacks console screen showing one stack named
"DemoStack" with status "CREATE_COMPLETE." The stack's created time is listed
as 2025-07-14 12:18:38
UTC+0400.
Cleanup When the demo is complete, delete the stack using CloudFormation’s “Delete stack” action to remove resources and avoid ongoing charges.
Always delete demo stacks (or confirm resources are torn down) to avoid unexpected AWS charges. Verify the EC2 instance and associated EBS volumes are terminated.
Further reading

Watch Video