Re: Cloud-init success
Had a chance to "refresh" some cloud-init configs for some later distros (Debian 12, Ubuntu 24.04, Rocky Linux 9.3, etc.) so thought I would share some example configs that are used mainly for bootstrapping new VM's and or containers.
This first one is targeted at deb based distros and sets up an Incus container host. Like most configs I use this one is pretty specific pulling key files and configs from an NFS share, rsyslog target, etc., but gives an idea what can be done for detailed provisioning of instances, aside from just slapping your SSH keys on and letting ansible take over. With this I can have a fresh VM provisioned in about 5 minutes.
I always like to run a status check after init:
root@IncusTEST20:~# cloud-init status --long
status: done
boot_status_code: enabled-by-generator
last_update: Sat, 26 Jul 2024 17:29:50 +0000
detail:
DataSourceNoCloud [seed=/dev/xvdc][dsmode=net]
Then we can query the user-data to see how it rendered from the config injected into the nocloud datasource:
root@IncusTEST20:~# cloud-init query userdata
#cloud-config
hostname: IncusTEST20
users:
- name: foo
groups: sudo
lock_passwd: false
passwd: $6$10023$EKz8eWTDXQO3x7.4ff0ZNJLsl9q6RB.l8pZN9nq8BzT42zzOn7O4r./ybHeVa/l0W0/FARK/2Ttg177ywAP0Z1
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEqTfKkUKEGxOi62A9tCWMslqF5i9xm0aMN+ZxWgHuR6 foobar-ed25519-20240725
shell: /bin/bash
- name: bar
groups: sudo
lock_passwd: false
passwd: $6$10023$EKz8eWTDXQO3x7.4ff0ZNJLsl9q6RB.l8pZN9nq8BzT42zzOn7O4r./ybHeVa/l0W0/FARK/2Ttg177ywAP0Z1
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEqTfKkUKEGxOi62A9tCWMslqF5i9xm0aMN+ZxWgHuR6 foobar-ed25519-20240725
shell: /bin/bash
locale: en_US.UTF-8
timezone: America/New_York
resize_rootfs: true
mounts:
- ["192.168.99.2:/mnt/Vault/lxd", "/mnt/lxd", "nfs", "auto,nofail,noatime,nolock,intr,tcp,actimeo=1800,user,suid", "0", "0"]
- ["192.168.0.54:/mnt/raid/backup", "/mnt/nas", "nfs", "auto,nofail,noatime,nolock,intr,tcp,actimeo=1800,user,suid", "0", "0"]
rsyslog:
remotes:
log_serv: "192.168.50.35:5140"
write_files:
- path: /etc/init.d/incus.sh
owner: root:root
permissions: 0o755
defer: true
content: |
#!/bin/bash
curl -fsSL https://pkgs.zabbly.com/key.asc -o /etc/apt/keyrings/zabbly.asc
sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-lts-6.0.sources
Enabled: yes
Types: deb
URIs: https://pkgs.zabbly.com/incus/lts-6.0
Suites: $(. /etc/os-release && echo ${VERSION_CODENAME})
Components: main
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/zabbly.asc
EOF'
apt update -y
dpkg --configure -a
apt install incus incus-ui-canonical -y
mkdir -p /root/.config
mkdir -p /root/.config/rclone
mount -a
cp /mnt/lxd/.config/.encode /root/.encode
cp /mnt/lxd/.config/rclone.conf /root/.config/rclone/rclone.conf
chmod 600 /root/.config/rclone/rclone.conf
# Delete self
rm "${0}"
runcmd:
- mkdir /mnt/lxd
- mkdir /mnt/nas
- date > /etc/birth_certificate
- [ mount /dev/cdrom /mnt ]
- [ bash /mnt/Linux/install.sh ]
- [ umount /dev/cdrom ]
- [ sh, /etc/init.d/incus.sh ]
package_update: true
package_upgrade: true
packages:
- htop
- nano
- curl
- wget
- nfs-common
- btrfs-progs
- bridge-utils
- build-essential
- rclone
Here is a more universal config with jinja templating syntax that can be targeted at many distros and using an 'if distro' will configure the instance based on the distro value in metadata:
This one targets debian, ubuntu, centos, redhat and rocky linux 8 and up - notice the ##template: jinja at the top, this allows jinja to render and process:
## template: jinja
#cloud-config
{% set u1 = 'foobar' %}
{% set u1pass = '$6$10023$EKz8eWTDXQO3x7.4ff0ZNJLsl9q6RB.l8pZN9nq8BzT42zzOn7O4r./ybHeVa/l0W0/FARK/2Ttg177ywAP0Z1' %}
{% set u1key = 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEqTfKkUKEGxOi62A9tCWMslqF5i9xm0aMN+ZxWgHuR6 foobar-ed25519-20240725' %}
{% set u2 = 'ansible' %}
{% set u2pass = '$6$10023$EKz8eWTDXQO3x7.4ff0ZNJLsl9q6RB.l8pZN9nq8BzT42zzOn7O4r./ybHeVa/l0W0/FARK/2Ttg177ywAP0Z1' %}
{% set u2key = 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEqTfKkUKEGxOi62A9tCWMslqF5i9xm0aMN+ZxWgHuR6 foobar-ed25519-20240725' %}
locale: en_US.UTF-8
timezone: America/New_York
runcmd:
- mkdir /mnt/v-nas
- mkdir /mnt/home
- date > /etc/birth_certificate
rsyslog:
remotes:
log_serv: "192.168.50.35:5140"
{% if distro == 'rocky' or distro == 'centos' or distro == 'redhat' %}
{% set group = 'wheel' %}
repo_update: true
repo_upgrade: all
yum_repos:
epel-release:
name: Extra Packages for Enterprise Linux 9 - Release
baseurl: http://download.fedoraproject.org/pub/epel/9/Everything/$basearch
enabled: true
failovermethod: priority
gpgcheck: true
gpgkey: http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9
package_upgrade: true
packages:
- htop
- nano
{% elif distro == 'ubuntu' or distro == 'debian' %}
{% set group = 'sudo' %}
package_update: true
package_upgrade: true
packages:
- htop
- nano
- build-essential
users:
- name: {{ u1 }}
groups: {{ group }}
lock_passwd: false
passwd: {{ u1pass }}
ssh_authorized_keys:
- {{ u1key }}
shell: /bin/bash
- name: {{ u2 }}
groups: {{ group }}
lock_passwd: false
passwd: {{ u2pass }}
ssh_authorized_keys:
- {{ u2key }}
shell: /bin/bash
{%- endif %}
Just a note, to consume jinja templating, you need cloud-init 22.x or higher, with the jinja package installed in your template/image.
For anyone wanting to tinker with these, (these are not my keys or password hashes, these I just threw in for demonstration purposes and for the wiki page). The password for the accounts is "foobar" and the matching private key is:
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACBKk3ypFChBsToutgPbQljLJaheYvcZtGjDfmcVoB7kegAAAKADtgJ2A7YC
dgAAAAtzc2gtZWQyNTUxOQAAACBKk3ypFChBsToutgPbQljLJaheYvcZtGjDfmcVoB7keg
AAAEC1DHPxJPEU3Ywf14x7k7IMXt1nKPvwBmG6vAXsZceiVUqTfKkUKEGxOi62A9tCWMsl
qF5i9xm0aMN+ZxWgHuR6AAAAF2Zvb2Jhci1lZDI1NTE5LTIwMjQwNzI1AQIDBAUG
-----END OPENSSH PRIVATE KEY-----
Enjoy!