Score:1

run a script via cloud-init

gb flag

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.

Score:1
vn flag
rvs

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.

gb flag
That's looking promising! But the docs do not clearly specify the lifecycle. Will the `write_files` for sure be run before `runcmd`?
rvs avatar
vn flag
rvs
@tcurdt not sure either. give it a go and see if it works?
Xerkus avatar
sg flag
@tcurdt I would say it depends on what is in /etc/cloud/cloud.cfg From what I've seen, write-files module is happening during init stage while runcmd happens during config stage.
mx flag
The lifecycle depends on config. E.g. on rockylinux 8.6, `/etc/cloud/cloud.cfg` has `write-files` under `cloud_init_modules`. Whereas `scripts-user` (which the docs state is what actually runs the commands written by runcmd) is under `cloud_final_modules`. Consulting the docs for boot stages https://cloudinit.readthedocs.io/en/latest/topics/boot.html we can see that commands in runcmd can assume files delivered by `write_files` are available.
Score:0
sa flag

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.

ph flag
Since this question is tagged "terraform" I also want to note that [the `cloudinit_config` data source belonging to the `hashicorp/cloudinit` Terraform provider](https://registry.terraform.io/providers/hashicorp/cloudinit/latest/docs/data-sources/cloudinit_config) is effectively a Terraform-integrated equivalent of `cloud-init devel make-mime`, which can avoid the step of creating a separate temporary file if you happen to be setting things up with Terraform.
gb flag
Super interesting details. I didn't realize you can also just pass in a script by itself. Good to know the shebang is good enough.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.