

# Working with Amazon EC2 user data for AWS PCS
Working with Amazon EC2 user data

You can supply EC2 user data in your launch template that `cloud-init` runs when your instances launch. User data blocks with the content type `cloud-config` run before the instance registers with the AWS PCS API, while user data blocks with content type `text/x‑shellscript` run after registration completes, but before the Slurm daemon starts. For more information about content types, see the [cloud-init documentation](https://cloudinit.readthedocs.io/en/latest/explanation/format.html). 

our user data can perform common configuration scenarios, including but not limited to the following:
+  [ Including users or groups ](https://cloudinit.readthedocs.io/en/latest/topics/examples.html#including-users-and-groups) 
+  [ Installing packages ](https://cloudinit.readthedocs.io/en/latest/topics/examples.html#install-arbitrary-packages) 
+  [ Creating partitions and file systems ](https://cloudinit.readthedocs.io/en/latest/topics/examples.html#create-partitions-and-filesystems) 
+  Mounting network file systems 

 User data in launch templates must be in the [MIME multi-part archive](https://cloudinit.readthedocs.io/en/latest/topics/format.html#mime-multi-part-archive) format. This is because your user data is merged with other AWS PCS user data that is required to configure nodes in your node group. You can combine multiple user data blocks together into a single MIME multi-part file. 

 A MIME multi-part file consists of the following components: 
+  The content type and part boundary declaration: `Content-Type: multipart/mixed; boundary="==BOUNDARY=="` 
+  The MIME version declaration: `MIME-Version: 1.0` 
+  One or more user data blocks that contain the following components: 
  +  The opening boundary that signals the beginning of a user data block: `--==BOUNDARY==`. You must keep the line before this boundary blank. 
  +  The content type declaration for the block: `Content-Type: text/cloud-config; charset="us-ascii"` or `Content-Type: text/x-shellscript; charset="us-ascii"`. You must keep the line after the content type declaration blank. 
  +  The content of the user data, such as a list of shell commands or `cloud-config` directives. 
+  The closing boundary that signals the end of the MIME multi-part file: `--==BOUNDARY==--`. You must keep the line before the closing boundary blank. 

**Note**  
 If you add user data to a launch template in the Amazon EC2 console, you can paste it in as plain text. Or, you can upload it from a file. If you use the AWS CLI or an AWS SDK, you must first base64 encode the user data and submit that string as the value of the `UserData` parameter when you call [CreateLaunchTemplate](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateLaunchTemplate.html), as shown in this JSON file. 

```
{
    "LaunchTemplateName": "base64-user-data",
    "LaunchTemplateData": {
        "UserData": "ewogICAgIkxhdW5jaFRlbXBsYXRlTmFtZSI6ICJpbmNyZWFzZS1jb250YWluZXItdm9sdW..."
    }
}
```

**Examples**
+ [Example: Install software from a package repository](working-with_ec2-user-data_repo.md)
+ [Example: Run scripts from an S3 bucket](working-with_ec2-user-data_s3.md)
+ [Example: Set global environment variables](working-with_ec2-user-data_env.md)
+ [Using network file systems with AWS PCS](working-with_file-systems.md)
+ [Example: Use an EFS file system as a shared home directory](working-with_ec2-user-data_efs.md)

# Example: Install software for AWS PCS from a package repository
Example: Install software from a package repository

 Provide this script as the value of `"userData"` in your launch template. For more information, see [Working with Amazon EC2 user data for AWS PCS](working-with_ec2-user-data.md). 

This script uses **cloud-config** to install software packages on node group instances at launch. For more information, see the [User data formats](https://cloudinit.readthedocs.io/en/latest/explanation/format.html) in the *cloud-init documentation*. This example installs `curl` and `llvm`.

**Note**  
Your instances must be able to connect to their configured package repositories.

```
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="

--==MYBOUNDARY==
Content-Type: text/cloud-config; charset="us-ascii"

packages:
- python3-devel
- rust
- golang

--==MYBOUNDARY==--
```

# Example: Run additional scripts for AWS PCS from an S3 bucket
Example: Run scripts from an S3 bucket

 Provide this script as the value of `"userData"` in your launch template. For more information, see [Working with Amazon EC2 user data for AWS PCS](working-with_ec2-user-data.md). 

The following user data script uses **cloud-config** to import a script from an S3 bucket and run it on node group instances at launch. For more information, see the [User data formats](https://cloudinit.readthedocs.io/en/latest/explanation/format.html) in the *cloud-init documentation*.

Replace the following values with your own details:
+ *amzn-s3-demo-bucket* – The name of an S3 bucket your account can read from.
+ *object-key* – The S3 object key of the script to import. This includes the name of the script and its location in the folder structure of the bucket. For example, `scripts/script.sh`. For more information, see [Organizing objects in the Amazon S3 console by using folders](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-folders.html) in the *Amazon Simple Storage Service User Guide*.
+ *shell* – The Linux shell to use to run the script, such as `bash`.

```
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="

--==MYBOUNDARY==
Content-Type: text/cloud-config; charset="us-ascii"

runcmd:
- aws s3 cp s3://amzn-s3-demo-bucket/object-key /tmp/script.sh
- /usr/bin/shell /tmp/script.sh

--==MYBOUNDARY==--
```

The IAM instance profile for the node group must have access to the bucket. The following IAM policy is an example for the bucket in the user data script above.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::amzn-s3-demo-bucket",
                "arn:aws:s3:::amzn-s3-demo-bucket/*"
            ]
        }
    ]
}
```

------

# Example: Set global environment variables for AWS PCS
Example: Set global environment variables

 Provide this script as the value of `"userData"` in your launch template. For more information, see [Working with Amazon EC2 user data for AWS PCS](working-with_ec2-user-data.md). 

The following example uses `/etc/profile.d` to set global variables on node group instances.

```
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="

--==MYBOUNDARY==
Content-Type: text/x-shellscript; charset="us-ascii"

#!/bin/bash
touch /etc/profile.d/awspcs-userdata-vars.sh
echo MY_GLOBAL_VAR1=100 >> /etc/profile.d/awspcs-userdata-vars.sh
echo MY_GLOBAL_VAR2=abc >> /etc/profile.d/awspcs-userdata-vars.sh

--==MYBOUNDARY==--
```

# Example: Use an EFS file system as a shared home directory for AWS PCS
Example: Use an EFS file system as a shared home directory

 Provide this script as the value of `"userData"` in your launch template. For more information, see [Working with Amazon EC2 user data for AWS PCS](working-with_ec2-user-data.md). 

This example extends the example EFS mount in [Using network file systems with AWS PCS](working-with_file-systems.md) to implement a shared home directory. The contents of /home are backed up before the EFS file system is mounted. The contents are then quickly copied into place on the shared storage after the mount completes.

Replace the following values in this script with your own details:
+ */mount-point-directory* – The path on an instance where you want to mount the EFS file system.
+ *filesystem-id* – The file system ID for the EFS file system.

```
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="

--==MYBOUNDARY==
Content-Type: text/cloud-config; charset="us-ascii"

packages:
  - amazon-efs-utils

runcmd:
  - mkdir -p /tmp/home
  - rsync -a /home/ /tmp/home
  - echo "filesystem-id:/ /mount-point-directory efs tls,_netdev" >> /etc/fstab
  - mount -a -t efs defaults
  - rsync -a --ignore-existing /tmp/home/ /home
  - rm -rf /tmp/home/

--==MYBOUNDARY==--
```

# Example: Enabling passwordless SSH


You can build on the shared home directory example to implement SSH connections between cluster instances using SSH keys. For each user using the shared home file system, run a script that resembles the following: 

```
#!/bin/bash

mkdir -p $HOME/.ssh && chmod 700 $HOME/.ssh
touch $HOME/.ssh/authorized_keys
chmod 600 $HOME/.ssh/authorized_keys

if [ ! -f "$HOME/.ssh/id_rsa" ]; then
    ssh-keygen -t rsa -b 4096 -f $HOME/.ssh/id_rsa -N ""
    cat ~/.ssh/id_rsa.pub >> $HOME/.ssh/authorized_keys
fi
```

**Note**  
The instances must use a security group that allows SSH connections between cluster nodes.