Update:
This setup is only for Ubuntu-20.04 live-server not legacy.
subiquity
Subiquity is the Ubuntu server’s new automated installer, which was introduced in 18.04. The setup for autoinstallation is given by the cloud-init configuration. If set, values will be taken from the config file, otherwise default values will be used. There are different ways of delivering cloud-init configuration. User configuration is usually contained in user-data and cloud configuration in meta-data files. For more detailed info you can look The AutoInstall documentation provided by Canonical.
Our installer is based on curtin, netplan and cloud-init.
Overview
- user-data
- packer file
- variable file
Lets take a look one by one
1#cloud-config
2autoinstall:
3 version: 1
4 early-commands:
5 # Stop ssh for packer
6 - sudo systemctl stop ssh
7 locale: en_US
8 keyboard:
9 layout: en
10 variant: us
11 identity:
12 hostname: ubuntu-server
13 username: ubuntu
14 password: '$6$rounds=4096$NYG7e8HxIMgz1$BqP28Ppt0FqXiBQuiE6PxiVBJJJAbm8tJrNz4HC7MEC.7Gv/eOyQIfaLqZ6W6fnMMtxP.BYfHmTBxUFQQs0u91'
15 ssh:
16 install-server: yes
17 allow-pw: yes
18 storage:
19 layout:
20 name: direct
21 apt:
22 primary:
23 - arches: [i386, amd64]
24 uri: "http://ro.archive.ubuntu.com/ubuntu/"
25 user-data:
26 disable_root: false
27 late-commands:
28 - sed -i -e 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/g' /target/etc/ssh/sshd_config
29 - sed -i -e 's/^#\?PermitRootLogin.*/PermitRootLogin yes/g' /target/etc/ssh/sshd_config
30 - echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' > /target/etc/sudoers.d/ubuntu
31 - curtin in-target --target=/target -- chmod 440 /etc/sudoers.d/ubuntu
32 - curtin in-target --target=/target -- apt-get update
33 - curtin in-target --target=/target -- apt-get upgrade --yes
As you see it is .yaml
formatted config. We have specifeied all the details (what we need otherwise will use default) in this config. But we need to understand some tricky parts.
Firstly on identity
part as you see we have used hashed password. It is default requirement of autoinstaller for security purpose. Actually we need more for deeply secure system but at that moment it is okay. But how we generate this hashed password ?
Actually I used ubuntu
as the password for ssh connection and for making it hashed I used below command:
1mkpasswd -m SHA-512 --rounds=4096
Now lets move a little bit up and find out early-commands
. What it means? Actually when we start packer build, packer try to set ssh connection from the beginning to our machine. So During initialization it could gives us error can break the build. So at the first stage we need to be sure that our ssh connection is stopped.
For understanding all the parts you can look Ubuntu Autoinstall Reference. Fortunately documentation are very simple and useful provided by Canonical.
Now we need to create meta-data file. But we will keep it empty. At last we need to create http
directory and put these files into it.
Now we need to define our packer file:
1{
2 "builders": [
3 {
4 "CPUs": 2,
5 "RAM": 2048,
6 "RAM_reserve_all": true,
7 "firmware": "bios",
8 "boot_command": [
9 "<esc><esc><esc>",
10 "<enter><wait>",
11 "/casper/vmlinuz ",
12 "root=/dev/sr0 ",
13 "initrd=/casper/initrd ",
14 "autoinstall ",
15 "ds=nocloud-net;s=http://{{ .HTTPIP }}:{{ .HTTPPort }}/",
16 "<enter>"
17 ],
18 "boot_wait": "2s",
19 "convert_to_template": "true",
20 "create_snapshot": "false",
21 "datacenter": "{{user `vcenter_datacenter`}}",
22 "datastore": "{{user `vcenter_datastore`}}",
23 "disk_controller_type": "pvscsi",
24 "folder": "{{user `vcenter_folder`}}",
25 "guest_os_type": "ubuntu64Guest",
26 "host": "{{user `vcenter_host`}}",
27 "http_directory": "{{user `http_directory`}}",
28 "insecure_connection": "true",
29 "iso_checksum": "{{user `iso_checksum_type`}}:{{user `iso_checksum`}}",
30 "iso_paths": "{{user `iso_paths`}}",
31 "name": "Ubuntu-20.04",
32 "network_adapters": [
33 {
34 "network": "{{user `vcenter_network`}}",
35 "network_card": "vmxnet3"
36 }
37 ],
38 "notes": "Default SSH User: {{user `ssh_username`}}\nDefault SSH Pass: {{user `ssh_password`}}\nBuilt by Packer @ {{isotime \"2006-01-02 03:04\"}}.",
39 "password": "{{user `vcenter_password`}}",
40 "shutdown_command": "echo 'ubuntu'|sudo -S shutdown -P now",
41 "ssh_password": "{{user `ssh_password`}}",
42 "ssh_timeout": "20m",
43 "ssh_handshake_attempts": "100000",
44 "ssh_username": "{{user `ssh_username`}}",
45 "storage": [
46 {
47 "disk_size": 20480,
48 "disk_thin_provisioned": true
49 }
50 ],
51 "type": "vsphere-iso",
52 "username": "{{user `vcenter_username`}}",
53 "vcenter_server": "{{user `vcenter_server`}}",
54 "vm_name": "{{user `vm_name`}}"
55 }
56 ],
57 "provisioners": [
58 {
59 "type": "shell",
60 "execute_command": "echo 'ubuntu' | {{.Vars}} sudo -S -E bash '{{.Path}}'",
61 "script": "scripts/setup_ubuntu2004.sh"
62 }
63 ]
64}
I need mention some tricky points now. So as you see I used user
keyword on packer file. It is for defining variable. Another most important part is ds=nocloud-net;s=http://{{ .HTTPIP }}:{{ .HTTPPort }}/
.
So what it means ? As you remember I created http directory and put config files into it. So we need a web server to serve these files in order packer use them during build process.
When the build is executed, Packer will launch a small HTTP server and replace the {{.HTTPIP}}
and {.HTTPPort}}
variables with the respective IP and port.
You must also set the http_directory
(I already defined in packer file) configuration option to define which directory hosts the files that you want to be served by the HTTP server on your filesystem.
Bu as you wish you can also serve your files with different ways. For example I have uploaded config files to my custom static server and served through this server. I mean instead of http://{{ .HTTPIP }}:{{ .HTTPPort }}/
I used my own server https://ubuntu-cloud-init.vercel.app/
for my enterprise configuration.
At least we need to define variable file. Here is mine:
1{
2 "vm_name": "Ubuntu-2004-Template",
3 "vcenter_server":"",
4 "vcenter_username":"",
5 "vcenter_password":"",
6 "vcenter_datacenter": "",
7 "vcenter_datastore": "",
8 "vcenter_host": "",
9 "vcenter_folder": "",
10 "vcenter_network": "",
11 "guest_os_type": "ubuntu64Guest",
12 "http_directory": "http",
13 "iso_urls": "https://releases.ubuntu.com/focal/ubuntu-20.04.1-live-server-amd64.iso",
14 "iso_checksum_type": "sha256",
15 "iso_checksum": "443511f6bf12402c12503733059269a2e10dec602916c0a75263e5d990f6bb93",
16 "iso_paths": "[Datastore VMS] /packer_cache/ubuntu-20.04.1-live-server-amd64.iso",
17 "ssh_username": "ubuntu",
18 "ssh_password": "ubuntu"
19}
You can use your own custom details for empty vcenter
variables.
I have used iso_path
variable on packer file. But Also I have added iso_url
variable to variable file. So If you dont have ready Ubuntu-20.04 live-server then you can basically change iso_path
variable with iso_url
in packer file.
This builds a VM Template in vSphere based on Ubuntu 20.04, with a predefined ubuntu/ubuntu user. Although this image is still really helpful, I would like to add another phase to my image.
I plan to use this image with Rancher’s vSphere Provisioner which means I need the datasource for vSphere cloud-init. It’s available here as a plugin.
So I added a script in provisioners
line in packer file:
1 "provisioners": [
2 {
3 "type": "shell",
4 "execute_command": "echo 'ubuntu' | {{.Vars}} sudo -S -E bash '{{.Path}}'",
5 "script": "scripts/setup_ubuntu2004.sh"
6 }
7 ]
This sets up the datasource and resets the machine id to reset the state of the machine. You can find both packer file and configs and also script from my github repo.