78

We are starting instances, and accessing the user-data we place. But does anybody understand the internals of this operation (from Amazon's side)? When we pass in the user-data, at what point is that data transmitted to the VM (is this a Xen feature) and where is it stored?

I first thought, it was set as the USER_DATA env var, but we can also pass it as a file. Where is that file stored? Is it generic to all instances or varies depending on AMI?

This is not a problem per se, just wanted to know how Amazon does this.

User data screenshot: http://d.pr/GZlY

bfavaretto
  • 71,580
  • 16
  • 111
  • 150
Devrim
  • 2,826
  • 5
  • 25
  • 31

6 Answers6

91

The user-data is available to the instance with a simple HTTP request at this URL:

http://169.254.169.254/latest/user-data

Amazon EC2 does not put this user-data on the instance directly, though many AMIs have code that instructs the instance to download and process the user-data automatically.

See also:

Eric Hammond
  • 22,089
  • 5
  • 66
  • 75
  • thanks Eric, i did a google search on `what is 169.254.169.254` so it gave me the URL I was looking for. http://docs.amazonwebservices.com/AWSEC2/2007-03-01/DeveloperGuide/AESDG-chapter-instancedata.html – Devrim Mar 19 '12 at 23:38
  • 9
    Here's the latest version of that document: http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html – Eric Hammond Mar 21 '12 at 19:29
  • 3
    Just to add to this answer, if you wish to take advantage of user-data when the VM is booting, my team and I usually have script logic that lives in or is called by /etc/rc.local when using Linux. – linusthe3rd Nov 05 '12 at 01:47
  • @strife25 although I believe the preferred method is to use cloud-init instead of rc.local – Benubird Jul 17 '13 at 15:46
  • Agreed since cloud-init is MUCH more fully featured and general purpose than a straight rc.local script. However it does provide the same exact action - a bootstrap script that is executed at startup time of the VM's lifecycle that will utilize user-data. – linusthe3rd Jul 17 '13 at 20:15
  • 7
    rc.local runs on every boot and reboot. The cloud-init software runs user-data only on the first boot of an instance. You might pass in a user-data script (run by cloud-init) that modifies rc.local, init.d, or upstart to set up an action you want to run on every boot – Eric Hammond Jul 18 '13 at 04:18
  • 2
    You can access this from the instance itself by running ec2metadata. At least it's there on Linux instances. – hookenz Aug 19 '13 at 22:28
  • Actually, it _is_ stored on the instance, but I can never remember the file path to get to it. – foresmac Feb 12 '15 at 23:39
  • 1
    @foresmac EC2 itself does not (and cannot) put the user-data on an instance. EC2 doesn't even know what type of file system the instance is using as it never looks at the content of the block device that is the boot volume. However, the EC2 instance may itself query the user-data and then drop it on the file system. Some published AMIs may do this by default, leading you to believe that EC2 is doing it. Since it is done by each AMI publisher, this means that it is likely not available on all AMIs or even in the same place from AMI to AMI. – Eric Hammond Apr 03 '15 at 21:35
  • 14
    On Ubuntu AMIs, you'll find it here: `/var/lib/cloud/instance/user-data.txt` – foresmac Apr 06 '15 at 14:24
  • Hey @EricHammond where is this IP (169.254.169.254) from? How does it know that it should retrieve instance metadata/user data for my specific instance? – Renato Gama Sep 02 '15 at 17:18
  • 1
    @renatoargh http://serverfault.com/questions/427018/what-is-this-ip-address-169-254-169-254 – Eric Hammond Sep 30 '15 at 23:50
  • 2
    `/var/lib/cloud/instance/user-data.txt` also exists on Amazon Linux AMIs – Ibrahim Apr 21 '17 at 01:11
23

A very easy example for everyone's understanding.

If you want to create the file /tmp/testfile.txt when the machine gets started, you can simply add these two lines on the User data field.

#!/bin/bash
touch /tmp/testfile.txt

Remember to put the #!/bin/bash at the top before your commands.

When you run the instance (Linux AMI), you can see the User data field content at /var/lib/cloud/instance/user-data.txt

Avión
  • 7,963
  • 11
  • 64
  • 105
16

Sorry to post to such an old question, but this seems like the best place to put this additional piece of information.

Most all the AWS documents describe User Data as a property in which to put instance lifecycle startup scripting, that is, the stuff you want to run only when the instance first launches.

This is usually the case, but there has been at least one other person besides myself wanting to perform different scripting on restart, say to fix a broken key or something. And guess what... you can do that using User Data.

Here is the code and the link to the AWS document...

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

--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"

#cloud-config
cloud_final_modules:
- [scripts-user, always]

--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"

#!/bin/bash
/bin/echo "Hello World." >> /tmp/sdksdfjsdlf
--//

I can find no documentation on this formatting of User Data that allows this to happen. I've tried it out and it works. I have tried to see if it runs on every startup, and it does.

So, if you think you need to do this, I recommend that you backup. Make sure you have a copy of the original User Data, and use the code provided modified to suite, and remove the code upon the next time you stop the instance (to avoid multiple runs of the script).

Les
  • 10,335
  • 4
  • 40
  • 60
3

AWS userdata is the set of commands/data you can provide to a instance at launch time. For example if you are launching an ec2 instance and want to have docker installed on the newly launched ec2, than you can provide set of bash commands in the userdata field of aws ec2 config page.

Usecase

Here is a well explained example of AWS userdata with video tutorial

Ajeet Khan
  • 8,582
  • 8
  • 42
  • 65
0

Disclaimer: everything in this answer is public information.

According to their doc on user data, AWS uses cloud-init internally. You can see some interesting processes and the actual commands if you run ps aux | grep cloud-init when the user data script is still running (you can verify that by checking the output of tail -F /var/log/cloud-init-output.txt. When it's done, the last line says for me "Cloud-init v. 19.3-44.amzn2 finished at Thu, 23 Dec 2021 02:16:48 +0000. Datasource DataSourceEc2. Up 111.63 seconds").

root      3689  3.6  3.2 149792 32692 ?        Ss   02:15   0:00 /usr/bin/python /usr/bin/cloud-init modules --mode=final
root      3705  0.0  0.2  13640  2548 ?        S    02:15   0:00 /bin/sh -c (umask 0026; tee -a /var/log/cloud-init-output.log)
root      3706  0.0  0.0  13640   208 ?        S    02:15   0:00 /bin/sh -c (umask 0026; tee -a /var/log/cloud-init-output.log)
root      3707  0.0  0.0   4236   736 ?        S    02:15   0:00 tee -a /var/log/cloud-init-output.log
ec2-user  3725  0.0  0.0 119420   916 pts/0    S+   02:15   0:00 grep --color=auto cloud-init

cat /usr/bin/cloud-init shows

#!/usr/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'cloud-init==19.3','console_scripts','cloud-init'
__requires__ = 'cloud-init==19.3'
import re
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(
        load_entry_point('cloud-init==19.3', 'console_scripts', 'cloud-init')()
    )
Zack Light
  • 167
  • 2
  • 11
-2
#!/bin/bash
yum update -y
yum install httpd -y
echo "<html><h1>webpage 1(whatever you want, give the page name here)</h1></html>"
/var/www/html/index.html
service httpd start
chkconfig httpd on
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
mahwir
  • 33