4

I know cloud-init allows to run commands as part of the cloud-init yml

runcmd:
 - [ pwd ]

but I am looking for a way to execute a full shell script.

Some people just pipe the output of a curl into a shell - but that feels like a very wonky approach. Maybe the script could be integrated into the yml via some templating, but that doesn't sound too great either.

Much better would be to ship the script alongside of the yml to the host and refer to it. But I haven't found any documentation on how to do this.

Is this possible?

I am using terraform to setup the server, but I am wondering if this could also done with pure cloud-init.

tcurdt
  • 423
  • 1
  • 5
  • 12

2 Answers2

5

If you only want to run a script, you can pass the script directly as userdata, instead of using a cloud-config. As long as the script starts with #!, cloud-init will attempt to run it directly, rather than interpreting it as a cloud-config.

If you want to run both cloud-config and a separate script, while the other posted write_files solution will work, you can also pass a mime multi part archive. Cloud-init contains a helper script to make this a little easier. Say you have userdata in a file named my-user-data:

#cloud-config
runcmd:
  - echo 'test-from-cloud-config' > /var/tmp/test_from_cloud_config

And a script you'd like to run callecd test.sh:

#!/bin/bash

echo 'test_from_script' > /var/tmp/test_from_script

You could call:

cloud-init devel make-mime -a test.sh:x-shellscript -a my-user-data:cloud-config > /tmp/userdata

You can take the resulting multi part file and pass it to cloud-init as userdata (e.g. using LXD):

lxc launch ubuntu:focal multi -c user.user-data="$(cat /tmp/userdata)"

You can see that both the cloud-config and the script have run:

root@multi:~# cat /var/tmp/test_from_cloud_config 
test-from-cloud-config
root@multi:~# cat /var/tmp/test_from_script 
test_from_script

See the cloud-init docs for reference.

falcojr
  • 386
3

Try combining it with write_files.

You can write script somewhere (e.g. as /usr/local/bin/myscript.sh) and then do runcmd: /usr/local/bin/myscript.sh

Make sure to set executable permission.

rvs
  • 4,225