EC2 User Data in AWS CloudFormation

In AWS CloudFormation, EC2 user data refers to the script or commands that can be passed to an EC2 instance during its launch or bootstrapping process. It allows you to automate the configuration and customization of your EC2 instances by executing scripts or running commands when the instance starts.

EC2 user data is typically used to perform tasks such as installing software, configuring applications, or setting up the environment on an EC2 instance. It provides a convenient way to automate these tasks without the need for manual intervention.

Hands-on with EC2 User Data

Here's an example of how you can use EC2 user data in AWS CloudFormation:

    Type: "AWS::EC2::KeyPair"
      KeyName: "my-keypair"
      PublicKeyMaterial: "AAAAB3NzaC1yc2EAAAADAQABAAAB...your-public-key... user@host"

    Type: "AWS::EC2::SecurityGroup"
      GroupDescription: "Allow SSH access"
        - CidrIp: "<your_ip_address>/32"
          FromPort: 22
          ToPort: 22
          IpProtocol: "tcp"

    Type: "AWS::EC2::Instance"
      ImageId: "ami-053b0d53c279acc90" # Ubuntu 22.04
      InstanceType: "t2.micro"
      KeyName: !Ref MyKeyPair
        - !Ref MySecurityGroup
        Fn::Base64: !Sub |
          apt-get update
          apt-get install -y apache2
          echo "Hello, World!" > /var/www/html/index.html
          systemctl start apache2

In this CloudFormation template snippet, we define an EC2 instance (MyEC2Instance) with a specific Amazon Machine Image (AMI) and instance type. The important part is the UserData property.

The UserData property is a base64-encoded string that contains the user data script. In this case, we're using the Fn::Base64 function to encode a multi-line Bash script. The script does the following:

  1. Writes "Hello, World!" to a file named index.html in the /var/www/html directory.

  2. Starts the apache2 service, assuming the instance is running a Linux-based operating system with Apache HTTP Server installed.

When the EC2 instance is launched using this CloudFormation template, the user data script will be executed automatically during the instance's bootstrapping process. It ensures that the specified commands are run, enabling you to configure the instance as needed.

Note that user data scripts can vary depending on the operating system running on the EC2 instance and the requirements of your application or environment.

Fn::Base64 function

The Fn::Base64 function is an intrinsic function in AWS CloudFormation that allows you to encode a string as a base64 representation. It is commonly used in CloudFormation templates to encode sensitive data, such as user data scripts or configuration files, that need to be passed as parameters or properties.

The syntax for using Fn::Base64 function is as follows:

Fn::Base64: <string-to-encode>

You provide the string you want to encode as the argument to the Fn::Base64 function, and CloudFormation will encode it as a base64 string during the template execution.

For example, if you have a user data script in your CloudFormation template and you want to encode it using Fn::Base64, you can use it as follows:

  Fn::Base64: |
    echo "Hello, World!" > /var/www/html/index.html
    systemctl start apache2

In this example, the user data script is provided as a multi-line string. The Fn::Base64 function is used to encode the entire user data script, ensuring that it will be passed as a base64-encoded string to the EC2 instance during its launch.

The Fn::Base64 function is a convenient way to encode sensitive information or preserve the integrity of multiline strings in your CloudFormation templates. It is often used in conjunction with properties like UserData, UserDataOverride, or any other property where encoding as base64 is required.

Create SSH key pair and allow connection on port 22

For connecting to the MyEC2Instance resource in your CloudFormation template, you need to specify the KeyName property under the Properties section of the AWS::EC2::Instance resource.

At the same time, you need to allow SSH connection on port 22 from your IP address

To generate SSH keys on Linux machines, you can use the ssh-keygen command, which is a built-in tool for managing SSH keys. Here's how you can generate SSH keys:

  1. Open a terminal on your machine.

  2. Run the following command to generate an SSH key pair:

ssh-keygen -t rsa -b 4096

This command generates an RSA key pair with a key length of 4096 bits. You can adjust the key type (-t) and key length (-b) according to your needs.

  1. You'll be prompted to enter a file to save the key pair. By default, it will be saved in the ~/.ssh directory with the filenames id_rsa (private key) and (public key). If you want to use a different file name or location, you can specify it here.

  2. You'll also be prompted to enter a passphrase for the key pair. It's recommended to set a passphrase for added security. The passphrase is used to encrypt the private key, so you'll need to enter it each time you use the key.

  3. Once you've entered the file name and passphrase (if any), the key pair will be generated. You'll see output similar to the following:

Generating public/private rsa key pair.
Enter file in which to save the key (/home/your-username/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/your-username/.ssh/id_rsa.
Your public key has been saved in /home/your-username/.ssh/
The key fingerprint is:
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx your-username@your-hostname
The key's randomart image is:
+---[RSA 4096]----+
|      .+.        |
|     . .o        |
|    .  o..       |
|   . .o.  .      |
|  o .  ..S .     |
| . +..=.o o o    |
|  Eo+o=.+. =     |
|   =oo=.++ o     |
|  .+=oo.*.o      |

The private key (id_rsa) and the public key ( files are now generated and saved in the specified location.

Change permissions:

chmod 400 id_rsa*

You can use the public key ( to authenticate with remote servers by adding it to the appropriate ~/.ssh/authorized_keys file on the remote machine. The private key (id_rsa) should be kept secure and not shared with anyone.

That's it! You've successfully generated SSH keys.

Deploy CloudFormation Stack

To deploy your CloudFormation stack use the following command:

aws cloudformation create-stack --stack-name MyEC2Stack --template-body file://ec2-userdata.yaml

To delete your stack use the following command:

aws cloudformation delete-stack --stack-name MyEC2Stack

Verify EC2 User Data script execution

To check if the user data script was successfully executed on the EC2 instance launched with the template mentioned above, you can access the instance and inspect the execution logs or verify the changes made by the script. Here's how you can do it:

  1. Connect to the EC2 instance using SSH, as explained in a previous response. Run the following command:
ssh -i /path/to/your/private-key.pem ec2-user@<public-ip-address-or-dns-name>

Replace /path/to/your/private-key.pem with the actual path to your private key file, and <public-ip-address-or-dns-name> with the public IP address or DNS name of your EC2 instance.

  1. Once connected to the instance, you can check the execution logs of the user data script. The logs can be found in the /var/log/cloud-init-output.log file. You can use the cat command to view the contents of the file:
cat /var/log/cloud-init-output.log

This file contains the output generated during the execution of the user data script. It will provide information about the commands executed and any errors or messages generated by the script.

  1. Additionally, you can verify the changes made by the user data script. In the example template provided, the script writes "Hello, World!" to the /var/www/html/index.html file and starts the apache2 service. You can check if these changes were applied successfully by examining the content of the file or accessing the web server running on the instance.

To view the content of the index.html file, you can use the cat command:

cat /var/www/html/index.html

If the user data script ran successfully, it should display "Hello, World!".

curl localhost

To check if the apache2 service is running, you can use the systemctl command:

sudo systemctl status apache2

This command will show the status of the apache2 service. If it is active (running), then the service was started successfully by the user data script.

By inspecting the execution logs and verifying the changes made by the user data script, you can determine if it was successfully executed on the EC2 instance launched with the CloudFormation template.


  1. Run commands on your Linux instance at launch

  2. AWS::EC2::Instance

  3. User data workshop