cloud-init
Contents
About
My cloud provider supports it. It's never been so easy to and fast to get a server up'n'running. The glue I was missing for a long time. Hell, yeah it's fast.
Written in python3.
Caveats
In Debian the package cloud-init collides with package firewalld.
- Custom images may be necessary. It cannot replace a full installer.
- Rootfs
- You may not create a custom rootfs different from the image you are using. For example Debian 13 provides a specific partitioning layout and you cannot change it because you cannot cut off the branch you're sitting on. This seams to defeat some classes of use cases. Alternative root filesystems (xfs, btrfs, zfs, subvolumes, snapshots, …) are not provided by the distributions - only ext4.
1 root@localhost:/home/management# parted /dev/vda 'unit MiB print free' 2 Model: Virtio Block Device (virtblk) 3 Disk /dev/vda: 3072MiB 4 Sector size (logical/physical): 512B/512B 5 Partition Table: gpt 6 Disk Flags: 7 8 Number Start End Size File system Name Flags 9 0.02MiB 1.00MiB 0.98MiB Free Space 10 14 1.00MiB 4.00MiB 3.00MiB bios_grub 11 15 4.00MiB 128MiB 124MiB fat16 boot, esp 12 1 128MiB 3071MiB 2943MiB ext4 13 3071MiB 3072MiB 0.98MiB Free Space
- You may not create a custom rootfs different from the image you are using. For example Debian 13 provides a specific partitioning layout and you cannot change it because you cannot cut off the branch you're sitting on.
You may also take a look at:
btrfs-convert
to convert ext2/3/4 (or reiserfs) into btrfs in place. There may be a regular use case with cloud-init.
- Rootfs
Installation
Install cloud-init with
1 apt install cloud-init
This will create lots of directories
find $(dpkg -L cloud-init) -maxdepth 0 -type d
/etc/cloud
/lib/systemd/system/cloud-* and the corresponding links in /etc/systemd
/usr/lib/cloud-init
/usr/lib/python3/dist-packages/cloudinit
/var/lib/cloud
Configure
user-data
Don't forget to add the keyword #cloud-config in front of your cloud-init code.
Otherwise it will fail with:
… Unhandled non-multipart (text/x-not-multipart) userdata: …
Example user-data
1 #cloud-config
2 # Module reference
3 # https://docs.cloud-init.io/en/latest/reference/modules.html
4
5 ### JUST FAILS locale-gen DOES NOT GENERATE THE SPECIFIED LOCALE
6 ### PRIOR TO SETTING IT AS SYSTEM LOCALE
7 #locale: "de_DE.UTF-8"
8 timezone: "Europe/Berlin"
9
10 ### STORAGE
11 resize_rootfs: noblock
12
13 ### PACKAGE MANAGEMENT
14 package_update: true
15 package_upgrade: true
16 package_reboot_if_required: true
17
18 packages:
19 - apt-file
20 - aptitude
21 - bash-completion
22 - byobu
23 - btrfs-progs
24 - ca-certificates
25 - curl
26 - dmidecode
27 - dosfstools
28 - git
29 - htop
30 - iftop
31 - info
32 - iotop
33 - jq
34 - libcrack2
35 - locales
36 - lsb-release
37 - lsof
38 - man-db
39 - mc
40 - plocate
41 - openssl
42 - parted
43 - pigz
44 - psmisc
45 - pv
46 - pwgen
47 - python3-apt
48 - rsync
49 - screen
50 - sqlite3
51 - strace
52 - sudo
53 - sysstat
54 - tmux
55 - unattended-upgrades
56 - vim
57 - wget
58 - zsh
59
60 ### GROUP MANAGEMENT
61 # groups:
62
63 ### USER MANAGEMENT
64 users:
65 - name: root
66 ssh_authorized_keys:
67 - ssh-rsa your_pubkey_goes_here user@host
68 - name: "management"
69 ### DEFAULT lock_passwd: true
70 ### PREVENTS USING PASSWORD IN SUDO
71 # lock_passwd: false
72 ### DOES NOT RUN IF USER EXISTS
73 #passwd: "$6$rounds=500000$lHvPXw/r/zqznQfF$fMJyt.da6dTd2m/d5NURYW2C/SShW0FRIjV3DRQ26k4xbUxgEH62wepVtM8dcAyjIDLHcRqCA.ib6xMSriqB5."
74 ### ALSO RUNS IF USER EXISTS
75 # hashed_passwd: "$6$rounds=500000$lHvPXw/r/zqznQfF$fMJyt.da6dTd2m/d5NURYW2C/SShW0FRIjV3DRQ26k4xbUxgEH62wepVtM8dcAyjIDLHcRqCA.ib6xMSriqB5."
76 # plain_text_passwd: "asdasdasd"
77 shell: "/bin/bash"
78 gecos: "config management,,,"
79 #groups: sudo
80 sudo: "ALL=(ALL) NOPASSWD: ALL"
81 ssh_authorized_keys:
82 - ssh-rsa your_pubkey_goes_here user@host
83 - name: your_user
84 gecos: "First Last,,,"
85 groups: sudo
86 ssh_authorized_keys:
87 - ssh-rsa your_pubkey_goes_here user@host
88
89 ### DNS
90 manage_resolv_conf: true
91 resolv_conf:
92 nameservers:
93 - 176.9.99.233
94 - 195.201.246.253
95 domain: rockstable.it
96 searchdomains:
97 - rockstable.it.
98 - rockstable.org.
99 options:
100 timeout: 5
101
102 ### SSHD CONFIG
103 ssh_pwauth: false
104
105 ### TOOL CONFIG
106 write_files:
107 - path: "/etc/vim/vimrc.local"
108 owner: "root:root"
109 content: |
110 " All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by
111 " the call to :runtime you can find below. If you wish to change any of those
112 " settings, you should do it in this file (/etc/vim/vimrc), since debian.vim
113 " will be overwritten everytime an upgrade of the vim packages is performed.
114 " It is recommended to make changes after sourcing debian.vim since it alters
115 " the value of the 'compatible' option.
116
117 " This line should not be removed as it ensures that various options are
118 " properly set to work with the Vim-related packages available in Debian.
119 runtime! debian.vim
120
121 " Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc.
122 " This happens after /etc/vim/vimrc(.local) are loaded, so it will override
123 " any settings in these files.
124 " If you don't want that to happen, uncomment the below line to prevent
125 " defaults.vim from being loaded.
126 let g:skip_defaults_vim = 1
127
128 " Uncomment the next line to make Vim more Vi-compatible
129 " NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous
130 " options, so any other options should be set AFTER setting 'compatible'.
131 "set compatible
132
133 " Vim5 and later versions support syntax highlighting. Uncommenting the next
134 " line enables syntax highlighting by default.
135 syntax on
136
137 " If using a dark background within the editing area and syntax highlighting
138 " turn on this option as well
139 set background=dark
140
141 " Uncomment the following to have Vim jump to the last position when
142 " reopening a file
143 au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif
144
145 " Uncomment the following to have Vim load indentation rules and plugins
146 " according to the detected filetype.
147 filetype plugin indent on
148
149 " The following are commented out as they cause vim to behave a lot
150 " differently from regular Vi. They are highly recommended though.
151 set showcmd " Show (partial) command in status line.
152 set showmatch " Show matching brackets.
153 "set ignorecase " Do case insensitive matching
154 "set smartcase " Do smart case matching
155 "set incsearch " Incremental search
156 "set autowrite " Automatically save before commands like :next and :make
157 "set hidden " Hide buffers when they are abandoned
158 "set mouse=a " Enable mouse usage (all modes)
159 - path: "/root/.bashrc"
160 owner: "root:root"
161 content: |
162 # ~/.bashrc: executed by bash(1) for non-login shells.
163 #
164 # Note: PS1 and umask are already set in /etc/profile. You should not
165 # need this unless you want different defaults for root.
166 # PS1='${debian_chroot:+($debian_chroot)}\h:\w\$ '
167 umask 022
168
169 # You may uncomment the following lines if you want `ls' to be colorized:
170 export LS_OPTIONS='--color=auto'
171 eval "`dircolors`"
172 alias ls='ls $LS_OPTIONS'
173 alias ll='ls $LS_OPTIONS -l'
174 alias l='ls $LS_OPTIONS -lA'
175
176 alias ..='cd ..'
177 alias ...='cd ../..'
178
179 # Some more alias to avoid making mistakes:
180 # alias rm='rm -i'
181 # alias cp='cp -i'
182 # alias mv='mv -i'
183
184 ### ZSH CONFIG
185 runcmd:
186 - [ git, clone, "https://github.com/grml/grml-etc-core.git", "/opt/grml-etc-core" ]
187 - |-
188 if [ ! -L /etc/zsh ]; then
189 mv /etc/zsh /etc/zsh.dist
190 ln -s "/opt/grml-etc-core/etc/zsh" /etc/zsh
191 fi
192
193 final_message: |
194 ### cloud-init has finished
195 version: $version
196 timestamp: $timestamp
197 datasource: $datasource
198 uptime: $uptime
199
200 # vim: ft=yaml:et:ts=2:sw=2:
Providing the file
The systemd-generators enable the service
/usr/lib/systemd/system-generators/cloud-init-generator
The following script detects the data source
/usr/lib/cloud-init/ds-identify
As a local file:
/var/lib/cloud/seed/user-data
Log
There should be a log at
/var/log/cloud-init.log
Creating a nocloud image
- A disk may probably be anything that is mountable in the guest kernel. These image may be
- an iso9660 image.
- a raw file that contains lightweight filesystem (like vfat).
It seems to be relevant that the filesystem is labeled cidata
Growing an ISO image
Prepare a directory to be included in the image containing the cloud-init data (user-data meta-data) and generate an iso from it.
Generate a raw image
Create a file containing a vfat filesystem
Mount the filesystem, copy the cloud-init data (user-data meta-data) to it and unmount/close the filesystem again.
cloud-image-utils
Installation
Install the cloud-image-utils
Show package contents
1 dpkg -L cloud-image-utils
Usage
I recommend to create a new storage pool for the cloud-init disk images.
Create a raw nocloud image to be mounted via CD-ROM drive in your machine.
1 sudo cloud-localds /var/lib/libvirt/images/cloud-init/nocloud.raw user-data
Attach a CD drive to the virtual machine and select the nocloud image.
The VM will perform a datasource discovery on the next boot, find the image and perform the tasks.