1

I am running multipass with cloudinit and I have a bash script which I need to run after the VMs have been deployed once but for each user account. It has simple commands in it mostly for customising vim and bash.rc. How can I achieve this?

I tried playing around with runcmd feature of cloudinit but it is a bit problematic and even simple commands like the below don't output anything.

package_update: true                                                                                                                                                                                  
 package_upgrade: true                                                       
 packages:                                                                   
   - git                                                                     
   - openssh-server                                                          
   - zip                                                                     
   - tree                                                                    
   - vim                                                                     
   - htop                                                                    
   - net-tools                                                               
   - sysstat                                                                 
   - locate                                                                  
 cloud_config_modules:                                                       
   - runcmd                                                                  
 cloud_final_modules:                                                        
   - scripts-user                                                            
 runcmd:                                                                     
   - [ ls, -l, / ]                                                           
   - [ sh, -xc, "echo $(date) ': hello world!'" ]                            
   - [ bash, -c, echo "=========hello world'=========" >>foo.bar]            
 users:                                                                      
   - name: aryan                                                             
     lock_passwd: true                                                       
     sudo: ALL=(ALL) NOPASSWD:ALL                                            
     shell: /bin/bash                                                        
     ssh_authorized_keys:                                                    
       - ...
  • There is a potentially related question, but it has no answers https://stackoverflow.com/questions/46297120/cannot-make-bash-script-work-from-cloud-init – francistheturd May 03 '21 at 21:55

1 Answers1

0

That gist is technically correct, but it's a little misleading. runcmd in cloud_config_modules and scripts-user in cloud_final_modules will already be specified by default in /etc/cloud/cloud.cfg, so unless you want to explicitly turn off the other modules in use by cloud-init (you don't want to do this unless you have a good reason to), you don't need to specify cloud_config_modules or cloud_final_modules in your cloud-config.

Did you include #cloud-config at the top of your userdata script? If not, your cloud config is invalid. If you did include it, these runcmds will all work. The output of ls and the date/echo will be in /var/log/cloud-init-output.log and foo.bar will be in /. If not, there's something else wrong in your cloud config, or something that prevented cloud-init from initializing completely.

On your launched instance, you can run cloud-init status --long to see if cloud-init succeeded or failed. You can also check /var/log/cloud-init.log for Traceback or WARN to get an idea of what failed. Searching for rumcmd or scripts-user should tell you if those commands ran and what was written out where.

falcojr
  • 1,299
  • 1
  • 10
  • 18
  • What about longer scripts (eg. 100+ lines), should they be modified and inserted into the `cloudinit.yaml` file or is there a way to pass a bash script to be run for each account as that user? – francistheturd May 04 '21 at 18:19
  • You can insert them into cloudinit.yaml if you'd like. If you just want to use a script (and not cloud-config), any script that starts with '#!' can be used as userdata. If you want both the cloud-config and a separate user script, that involves creating a mime multi part archive. That is slightly more complicated, but cloud-init provides a helper to make it easier. See https://cloudinit.readthedocs.io/en/latest/topics/format.html#mime-multi-part-archive – falcojr May 05 '21 at 14:12
  • I guess I am having some more basic issues like: (1) cloud-init vs cloud-config (I think the latter is a cofig file used by the former service, (2) where do I put my bash script (eg. `foo.sh`), (3) how do I tell cloud-init/cloud config to call that script? – francistheturd May 05 '21 at 16:23
  • Your (1) is correct. Cloud-init is a service that runs on boot. You are trying to pass "user data" which can be a cloud config, a script, a mime archive, or a few other things listed in the previous URL I linked to. The types of user data are differentiated by a comment at the top of the file. "#cloud-config" means cloud config, "#!" means script, and so on. Since you're running on multipass, if you just want to run a script, you can save it anywhere and have cloud-init use it with `multipass launch --name --cloud-init ` – falcojr May 05 '21 at 17:44
  • That is how I am calling multipass right now (`multipass launch --name foo --cloud-init foo.yaml`) but `foo.yaml` creates the VM with all the user accounts, what if I also need to run a script on each account created, how do I do that? Right now I am using `SSH` – francistheturd May 05 '21 at 20:12
  • There is no built in mechanism to run something per account. Cloud-init runs as root, so you'd have to script that part yourself into a single script. If you want your user data to a combination of the cloud config and a script, you'd need to generate a MIME multi-part file as your user data: https://cloudinit.readthedocs.io/en/latest/topics/format.html#helper-subcommand-to-generate-mime-messages – falcojr May 06 '21 at 22:11
  • Check my new project for reference. I have done same in my project using a bash script. You can also do it with a makefile. https://github.com/nikhiljohn10/step-ca-tutorials – NikzJon Aug 17 '21 at 12:38