Skip to content

Commit

Permalink
Ubuntu 22.04 Bug Fixes / Minor Enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
reefland committed Sep 20, 2023
1 parent 4de31ac commit f5a3543
Show file tree
Hide file tree
Showing 36 changed files with 281 additions and 311 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
vars/secrets/*.yml
.vscode/
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ _NOTE: This Ansible role is not structured as rigid as a typical Ansible role sh

---

Originally based on the OpenZFS 'ZFS on Root' Guide, but no longer. Now with many enhancements:
Originally based on the [OpenZFS ZFS on Root](https://openzfs.github.io/openzfs-docs/Getting%20Started/Ubuntu/Ubuntu%2022.04%20Root%20on%20ZFS.html) Guide, but no longer!! Now with many enhancements:

* Uses ZFSbootMenu / rEFInd / Syslinux to manage boot environments
* rEFInd provides graphical boot loader menu and roll-back to previous kernels on UEFI systems
Expand All @@ -22,6 +22,7 @@ Originally based on the OpenZFS 'ZFS on Root' Guide, but no longer. Now with man
* If encryption is enabled, LUKS is used to encrypt Swap partitions
* Native ZFS Encryption Support
* UEFI and Legacy Booting supported (can even switch between them)
* Support for [Ubuntu Hardware Enablement](https://ubuntu.com/kernel/lifecycle) (newer kernel and hardware support)
* Multiple non-root user account creation (each user gets own ZFS dataset)
* Customized SSH Configuration Options
* DropBear support for unlocking ZFS encrypted pool remotely
Expand All @@ -45,14 +46,14 @@ Originally based on the OpenZFS 'ZFS on Root' Guide, but no longer. Now with man

## Environments Tested

* Ubuntu 22.04.1 Live CD Boot on Bare Metal or within VirtualBox
* Ubuntu 22.04.x Live CD Boot on Bare Metal or within VirtualBox

---

## Requirements

* [Ansible](https://www.ansible.com/) (Built with Ansible Core 2.12 or newer)
* [Ubuntu 22.04.1 "Jammy" Live CD](https://ubuntu.com/download/desktop/) (22.04 LTS Desktop - DO NOT use server images)
* [Ubuntu 22.04.x "Jammy" Live CD](https://ubuntu.com/download/desktop/) (22.04 LTS Desktop - DO NOT use server images)
* _NOTE: you can configure for command-line only server build even when using the desktop image._
* Computers that have less than 2 GiB of memory run ZFS slowly. 4 GiB of memory is recommended for normal performance in basic workloads.

Expand Down
11 changes: 4 additions & 7 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ domain_name: "localdomain"
# rEFInd Boot Menu Timeout by default is 20 seconds.
refind_boot_menu_timeout: "10"

# Enables background image for refind / syslinux (see files/logo.jpg)
refind_boot_menu_logo: true

# For Full GUI Desktop installation (set to false) or command-line only server
# environment (set to true)
command_line_only: true

# The Ubuntu LTS enablement (also called HWE or Hardware Enablement) stacks
# provide newer kernel and X support for existing Ubuntu LTS releases.
enable_ubuntu_lts_hwe: false
enable_ubuntu_lts_hwe: true

# Define the local pre-fix to enable in /etc/locale.gen
locale_prefix: "en_US.UTF-8"
Expand All @@ -57,12 +60,6 @@ ipv6:
- "net.ipv6.conf.lo.disable_ipv6 = 1"
apply_cmd: "sysctl -p"

# "Partprobe" is used to let the kernel know that partition tables have changed.
# Sometimes it gets in the way with weird messaged such as:
# "The driver descriptor says the physical block size is 2048 bytes, but Linux
# says it is 512 bytes."
disable_partprobe: false

# Define additional packages to install once the build has completed.
additional_install_packages:
- man
Expand Down
12 changes: 0 additions & 12 deletions docs/computer-config-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,6 @@ ipv6:
apply_cmd: "sysctl -p"
```

### Disable Partprobe

`partprobe` is used to let the kernel know that partition tables have been updated. It is required when partitions are created or deleted. It should always be enabled, but can be disabled if required.

```yaml
# "Partprobe" is used to let the kernel know that partition tables have changed.
# Sometimes it gets in the way with weird messaged such as:
# "The driver descriptor says the physical block size is 2048 bytes, but Linux
# says it is 512 bytes."
disable_partprobe: false
```

## Additional Installed Packages

These are the packages to be be applied to the towards the end of the build process to be included as part of the base system installation.
Expand Down
Binary file added files/code-wave-logo-sm.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added files/code-wave-logo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added files/logo-sm.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added files/logo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added files/low-wave-logo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added files/low-wave-logo_sm.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added files/os_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions tasks/01_basic_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,10 @@
- always
block:
- name: Generate disk by-id for devices
ansible.builtin.set_fact: # noqa yaml[line-length]
disk_by_id: "{{ disk_devices | map('extract', hostvars[inventory_hostname]['ansible_devices'], ['links', 'ids', 0]) | list | map('regex_replace', '^(.*)', '/dev/disk/by-id/\\g<1>') | list }}"
ansible.builtin.set_fact:
disk_by_id: "{{ disk_devices |
map('extract', hostvars[inventory_hostname]['ansible_devices'], ['links', 'ids', 0]) | list |
map('regex_replace', '^(.*)', '/dev/disk/by-id/\\g<1>') | list }}"

- name: Display disk by-id for disk_devices
ansible.builtin.debug:
Expand Down
8 changes: 4 additions & 4 deletions tasks/01_test_virtualbox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
block:
- name: Checking lspci device list
ansible.builtin.command: "lspci"
register: PCI_Devices
changed_when: PCI_Devices.rc == 0
register: pci_devices
changed_when: pci_devices.rc == 0

# Under virtual box there will be a PCI device
- name: Check if VirtualBox is within PCI_Devices
- name: Check if VirtualBox is within pci_devices
ansible.builtin.set_fact:
virtual_box: "{{ (PCI_Devices.stdout.find('VirtualBox') == -1) | ternary(false, true) }}"
virtual_box: "{{ (pci_devices.stdout.find('VirtualBox') == -1) | ternary(false, true) }}"

- name: Display Debug Message
ansible.builtin.debug:
Expand Down
1 change: 1 addition & 0 deletions tasks/02_confirm_defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
Environment Installation: {% if command_line_only | default(false) | bool %}Command-line only{% else %}Full GUI Environment{% endif %}
Ubuntu HWE Kernel: {{ enable_ubuntu_lts_hwe }}
Create Swap Partitions: {{ enable_swap_partitions }}
{% if enable_swap_partitions | default(true) | bool%}
{% if disk_by_id | length | int == 1 %}
Expand Down
17 changes: 4 additions & 13 deletions tasks/04_clear_partition_tables.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@
changed_when: cmd_output.rc == 0

- name: Unmount any mdadm disks that might have been automounted and Stop all found mdadm arrays
ansible.builtin.shell: # noqa yaml[line-length]
cmd: find /dev -iname md* -type b -exec bash -c "umount {} > /dev/null 2>&1 ; mdadm --stop --force {} > /dev/null 2>&1 ; mdadm --remove {} > /dev/null 2>&1" \;
ansible.builtin.shell: |
find /dev -iname md* -type b -exec bash -c \
"umount {} > /dev/null 2>&1 ; mdadm --stop --force {} > /dev/null 2>&1 ; mdadm --remove {} > /dev/null 2>&1" \;
register: cmd_output
changed_when:
cmd_output.rc == 0
ignore_errors: true

- name: Remove ZFS labels from previous usage
ansible.builtin.command:
cmd: "zpool labelclear -f {{ item }}"
cmd: "zpool labelclear -f {{ item }}-part3"
register: cmd_output
changed_when:
cmd_output.rc == 0
Expand Down Expand Up @@ -75,13 +76,3 @@
- name: Pause for 5 seconds to settle
ansible.builtin.pause:
seconds: 5

- name: Notify Kernel of Updated Partitions
ansible.builtin.command:
cmd: "partprobe"
register: cmd_output
changed_when: cmd_output.rc == 0
when:
- not disable_partprobe | default(false) | bool

# #############################################################################
14 changes: 5 additions & 9 deletions tasks/05_create_partitions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,12 @@
loop:
"{{ disk_by_id }}"

- name: Pause for 5 seconds to settle
ansible.builtin.pause:
seconds: 5

- name: Notify Kernel of Updated Partitions
- name: Wait for kernel notification of changes to be processed
ansible.builtin.command:
cmd: "partprobe"
cmd: "udevadm settle"
register: cmd_output
changed_when: cmd_output.rc == 0
when:
- not disable_partprobe | default(false) | bool

###############################################################################
- name: Pause for 5 seconds to settle
ansible.builtin.pause:
seconds: 5
5 changes: 3 additions & 2 deletions tasks/09_config_system.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@

# Update Netplan Network file - not tested on multiple adapters, might break
- name: Get Network adapter name on Ubuntu
ansible.builtin.shell:
"nmcli device status | grep 'ethernet' | grep 'connected' | cut -d' ' -f1"
ansible.builtin.shell: |
set -o pipefail
nmcli device status | grep 'ethernet' | grep 'connected' | cut -d' ' -f1
changed_when: nic_name.rc == 0
register:
nic_name
Expand Down
42 changes: 38 additions & 4 deletions tasks/11_config_boot_filesystem.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,40 @@
loop:
"{{ disk_by_id }}"

- name: Unmount any mdadm disks that might have been automounted and Stop all found mdadm arrays
ansible.builtin.shell: >
find /dev -iname md* -type b -exec bash -c
"umount {} > /dev/null 2>&1 ; mdadm --stop --force {} > /dev/null 2>&1 ; mdadm --remove {} > /dev/null 2>&1" \;
register: cmd_output
changed_when:
cmd_output.rc == 0
ignore_errors: true

- name: Wipe mdadm superblock from partitions
ansible.builtin.command:
cmd: "mdadm --zero-superblock --force {{ item }}-part1"
register: cmd_output
changed_when:
cmd_output.rc == 0
ignore_errors: true
loop:
"{{ disk_by_id }}"

# The "-R" - is needed to suppress the "Continue creating array?" prompt
- name: Run chroot command to create mdadm device for multi-disk boot partition
ansible.builtin.command: # noqa yaml[line-length]
cmd: "mdadm --create --verbose -R --metadata=1.0 --force --level=mirror --raid-devices={{ disk_by_id | length | int }} --homehost={{ inventory_hostname_short }} --name=efi --assume-clean {{ boot_dev_name }} {{ mdadm_device_list }}"
ansible.builtin.command:
cmd: >
mdadm --create {{ boot_dev_name }} --verbose -R --metadata=1.0 --force --level=mirror
--raid-devices={{ disk_by_id | length | int }} --homehost={{ inventory_hostname_short }}
--name=efi --assume-clean {{ mdadm_device_list }}
creates: "{{ boot_dev_name }}"
register: cmd_output
changed_when: cmd_output.rc == 0

- name: Run chroot command to create mdadm.conf file multi-disk boot partition
ansible.builtin.command:
cmd:
mdadm --examine --scan >> {{ live_cd_mountpoint }}/etc/mdadm/mdadm.conf
creates: "{{ boot_dev_name }}"
register: cmd_output
changed_when: cmd_output.rc == 0
Expand Down Expand Up @@ -53,6 +83,8 @@
- name: Run chroot command to install dosfstool
ansible.builtin.command:
cmd: "{{ chroot_cmd }} bash -c 'apt-get install --yes dosfstools'"
register: cmd_output
changed_when: cmd_output.rc == 0
when:
- ansible_os_family == "Debian"

Expand Down Expand Up @@ -92,15 +124,17 @@

- name: Add EFI Filesystems to /etc/fstab
ansible.builtin.shell:
cmd:
echo /dev/disk/by-uuid/$(blkid -s UUID -o value "{{ boot_dev_name }}") /boot/efi vfat nofail,x-systemd.device-timeout=1,x-systemd.after=zfs-mount.service 0 1 >>"{{ live_cd_mountpoint }}/etc/fstab"
cmd: >
echo /dev/disk/by-uuid/$(blkid -s UUID -o value "{{ boot_dev_name }}")
/boot/efi vfat nofail,x-systemd.device-timeout=1,x-systemd.after=zfs-mount.service 0 1 >>"{{ live_cd_mountpoint }}/etc/fstab"
register: cmd_output
changed_when: cmd_output.rc == 0

- name: Debug get contents of chroot /etc/fstab
ansible.builtin.command:
cmd: "cat {{ live_cd_mountpoint }}/etc/fstab"
register: cmd_output
changed_when: cmd_output.rc == 0
when:
debug | default(false)

Expand Down
76 changes: 76 additions & 0 deletions tasks/12_0-install_dracut.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,79 @@
path: "{{ live_cd_mountpoint }}/usr/lib/dracut/modules.d/90zfs/module-setup.sh"
regexp: '\/\*\*\/'
replace: '/*/*/'

# Fix zfs bootfs systemd services
# https://github.com/openzfs/zfs/pull/13585/files
# https://github.com/openzfs/zfs/issues/14475
# /usr/lib/dracut/modules.d/90zfs/zfs-rollback-bootfs.service
# /usr/lib/dracut/modules.d/90zfs/zfs-snapshot-bootfs.service
- name: Fix zfs bootfs systemd services ExecStart
ansible.builtin.replace:
path: "{{ live_cd_mountpoint }}/usr/lib/dracut/modules.d/90zfs/{{ item }}"
regexp: '^-ExecStart=(.*$)'
replace: 'ExecStart=\1'
with_items:
- "zfs-snapshot-bootfs.service"
- "zfs-rollback-bootfs.service"

- name: Fix zfs bootfs systemd services Semicolon
ansible.builtin.replace:
path: "{{ live_cd_mountpoint }}/usr/lib/dracut/modules.d/90zfs/{{ item }}"
regexp: '^(.*)BOOTFS" SNAPNAME(.*$)'
replace: '\1BOOTFS"; SNAPNAME\2'
with_items:
- "zfs-snapshot-bootfs.service"
- "zfs-rollback-bootfs.service"

- name: Create /etc/cmdline.d directory
ansible.builtin.file:
path: "/etc/cmdline.d"
mode: "0755"
state: directory

- name: Configure Dracut Network without Dropbear
ansible.builtin.lineinfile:
path: "{{ live_cd_mountpoint }}/etc/dracut.conf.d/network.conf"
line: 'install_items+=" /etc/cmdline.d/dracut-network.conf "'
create: true
mode: "0644"
state: present
backup: true
when:
- not enable_dropbear_support | default(false) | bool

# [ Setup Dracut Networking without Dropbear ]#############################

# With rd.neednet=1 it will fail to boot if no network available
# This can be a problem with laptops and docking stations, if the dock
# is not connected (no ethernet) it can fail to boot. Setting to 1 really
# only needed with for Dropbear support
- name: Create file /etc/cmdline.d/dracut-network.conf for DHCP
ansible.builtin.lineinfile:
path: "/etc/cmdline.d/dracut-network.conf"
regexp: '(^.*ip=.*$)'
line: 'ip={{ apply_dropbear_settings.remoteaccess_ip_config }} rd.neednet=0'
create: true
mode: "0644"
state: present
backup: true
when:
- not apply_dropbear_settings.remoteaccess_ip_config == "static"
- not enable_dropbear_support | default(false) | bool

# With rd.neednet=1 it will fail to boot if no network available
# This can be a problem with laptops and docking stations, if the dock
# is not connected (no ethernet) it can fail to boot. Setting to 1 really
# only needed with for Dropbear support
- name: Create file /etc/cmdline.d/dracut-network.conf for Static IP
ansible.builtin.lineinfile:
path: "/etc/cmdline.d/dracut-network.conf"
regexp: '(^.*ip=.*$)'
line: 'ip={{ apply_dropbear_settings.remoteaccess_ip }}:::{{ apply_dropbear_settings.remoteaccess_netmask }}:::none rd.neednet=0 rd.break'
create: true
mode: "0644"
state: present
backup: true
when:
- apply_dropbear_settings.remoteaccess_ip_config == "static"
- not enable_dropbear_support | default(false) | bool
32 changes: 31 additions & 1 deletion tasks/12_3-install_refind.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
changed_when: cmd_output.rc == 0
with_items:
- "DEBIAN_FRONTEND=noninteractive apt-get install --yes refind"
- "refind-install"
- "refind-install --yes"
- "mkdir -p {{ zfs_boot_menu_path }}"
- "mkdir -p {{ refind_path }}"
when:
- ansible_os_family == "Debian"

Expand Down Expand Up @@ -42,6 +43,35 @@
regexp: '^timeout .*'
replace: 'timeout {{ refind_boot_menu_timeout }}'

- name: Copy Logo Images and Icons
ansible.builtin.copy:
src: "files/{{ item.source }}"
dest: "{{ live_cd_mountpoint }}/{{ item.dest }}"
owner: "root"
group: "root"
mode: "0644"
with_items:
- { source: "logo.jpg", dest: "{{ refind_path }}/" }
- { source: "os_linux.png", dest: "{{ refind_path }}/icons/"}
when:
- refind_boot_menu_logo | default(false)

- name: Enable banner_scale for Logo Images
ansible.builtin.replace:
path: "{{ live_cd_mountpoint }}{{ refind_path }}/refind.conf"
regexp: '^#banner_scale (.*$)'
replace: 'banner_scale \1'
when:
- refind_boot_menu_logo | default(false)

- name: Set Banner Logo Images
ansible.builtin.replace:
path: "{{ live_cd_mountpoint }}{{ refind_path }}/refind.conf"
regexp: '^#banner hostname.bmp(.*$)'
replace: 'banner logo.jpg'
when:
- refind_boot_menu_logo | default(false)

- name: Copy startup script with multiple disks template to /mnt/boot/efi/startup.nsh
ansible.builtin.template:
src: startup.nsh.j2
Expand Down
Loading

0 comments on commit f5a3543

Please sign in to comment.