From 18c8a90e267dd06c587229066544d39e91656a0b Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Mon, 5 Sep 2022 00:04:25 +0200 Subject: raspios: image customization works now --- inventory/host_vars/ch-cm4-test.yml | 13 +-- roles/raspios/image/defaults/main.yml | 10 ++- roles/raspios/image/tasks/main.yml | 119 +++++++++++++++++---------- roles/raspios/image/templates/firstrun.sh.j2 | 36 ++++++++ 4 files changed, 127 insertions(+), 51 deletions(-) create mode 100644 roles/raspios/image/templates/firstrun.sh.j2 diff --git a/inventory/host_vars/ch-cm4-test.yml b/inventory/host_vars/ch-cm4-test.yml index 11218262..e6bc9081 100644 --- a/inventory/host_vars/ch-cm4-test.yml +++ b/inventory/host_vars/ch-cm4-test.yml @@ -12,9 +12,10 @@ network: interfaces: - *_network_primary_ -### -# [all] -# dtparam=i2c_vc=on -# dtoverlay=i2c-rtc,pcf85063a,i2c_csi_dsi -# dtoverlay=i2c-fan,emc2301,i2c_csi_dsi - +raspios_boot_config: + - regexp: '^#?dtparam=i2c_vc' + line: 'dtparam=i2c_vc=on' + - regexp: '^#?dtoverlay=i2c-rtc' + line: 'dtoverlay=i2c-rtc,pcf85063a,i2c_csi_dsi' + - regexp: '^#?dtoverlay=i2c-fan' + line: 'dtoverlay=i2c-fan,emc2301,i2c_csi_dsi' diff --git a/roles/raspios/image/defaults/main.yml b/roles/raspios/image/defaults/main.yml index 28dbd5fe..dc9a25d0 100644 --- a/roles/raspios/image/defaults/main.yml +++ b/roles/raspios/image/defaults/main.yml @@ -6,4 +6,12 @@ raspios_download_dir: "{{ global_cache_dir }}/raspios" raspios_output_dir: "{{ global_artifacts_dir }}/{{ inventory_hostname }}/raspios" -raspios_keep_temporary_build_dir: False +raspios_keep_boot_dir_mounted: False + +# raspios_boot_config: +# - regexp: '^#dtparam=i2c_vc' +# line: 'dtparam=i2c_vc=on' + +raspios_locale: en_US.UTF-8 +raspios_timezone: Europe/Vienna +raspios_keyboard_layout: de diff --git a/roles/raspios/image/tasks/main.yml b/roles/raspios/image/tasks/main.yml index 24c7c821..7baf2b35 100644 --- a/roles/raspios/image/tasks/main.yml +++ b/roles/raspios/image/tasks/main.yml @@ -20,63 +20,94 @@ path: "{{ raspios_output_dir }}" state: directory - - name: Create temporary build directory - tempfile: - state: directory - register: tmpdir - - name: extract image decompress: src: "{{ raspios_download_dir }}/{{ raspios_download_image_base_name }}" - dest: "{{ tmpdir.path }}" - register: raspios_image_extract_result + dest: "{{ raspios_output_dir }}" + force: yes + register: raspios_image_extract - set_fact: - raspios_output_image_base_name: "{{ raspios_image_extract_result.files | first | basename }}" + raspios_output_image_base_name: "{{ raspios_image_extract.files | first | basename }}" - name: read partition layout from image - command: "sfdisk -q -r -J '{{ tmpdir.path }}/{{ raspios_output_image_base_name }}'" - register: sfdisk_result + command: "sfdisk -q -r -J '{{ raspios_output_dir }}/{{ raspios_output_image_base_name }}'" + register: raspios_image_sfdisk + + - set_fact: + raspios_image_partitions: "{{ (raspios_image_sfdisk.stdout | from_json)['partitiontable']['partitions'] }}" + + - name: bind loop device for boot partition + command: "udisksctl loop-setup --no-user-interaction -o {{ raspios_image_partitions[0].start * 512 }} -s {{ raspios_image_partitions[0].size * 512 }} -f '{{ raspios_output_dir }}/{{ raspios_output_image_base_name }}'" + register: raspios_image_loop_setup + + - set_fact: + raspios_image_loop_device: "{{ raspios_image_loop_setup.stdout | regex_search('as (/dev/loop[0-9]+)\\.$', '\\1') | first }}" - - debug: - var: sfdisk_result.stdout | from_json + - name: mount boot partition + command: "udisksctl mount --no-user-interaction -b '{{ raspios_image_loop_device }}'" + register: raspios_image_mount - ## TODO: - # udisksctl loop-setup -o {{ partitions[1].start * 512 }} -s {{ partitions[1].start * 512 }} -f '{{ tmpdir.path }}/{{ raspios_download_image_base_name }}.img' - # udisksctl mount -b /dev/loop??? - # - # do customizations.... (needs root?) + - set_fact: + raspios_image_mount_point: "{{ raspios_image_mount.stdout | regex_search('at (/media/.+)\\.$', '\\1') | first }}" + + - name: edit boot/config.txt + when: raspios_boot_config is defined + loop: "{{ raspios_boot_config }}" + loop_control: + label: "{{ item.line }}" + lineinfile: + path: "{{ raspios_image_mount_point }}/config.txt" + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + + - name: install firstrun.sh script + template: + src: firstrun.sh.j2 + dest: "{{ raspios_image_mount_point }}/firstrun.sh" + mode: 0755 + + - name: Generate authorized_keys file + authorized_key: + user: root + manage_dir: no + path: "{{ raspios_image_mount_point }}/firstrun.authorized_keys" + key: "{{ ssh_keys_root | join('\n') }}" - - name: copy newly built raspios image - copy: - src: "{{ tmpdir.path }}/{{ raspios_output_image_base_name }}" - dest: "{{ raspios_output_dir }}/{{ raspios_output_image_base_name }}" + - name: install firstrun.sh script + template: + src: firstrun.sh.j2 + dest: "{{ raspios_image_mount_point }}/firstrun.sh" + mode: 0755 - - name: set output image names - set_fact: - output_images: - - "{{ (raspios_output_dir, raspios_output_image_base_name) | path_join | realpath }}" + - name: edit boot/cmdline.txt + lineinfile: + path: "{{ raspios_image_mount_point }}/cmdline.txt" + regexp: '^(.*)( systemd.run=/boot/firstrun.sh systemd.run_success_action=reboot systemd.unit=kernel-command-line.target)?(.*?)$' + backrefs: yes + line: '\1 systemd.run=/boot/firstrun.sh systemd.run_success_action=reboot systemd.unit=kernel-command-line.target \3' always: - - name: save stdout build-log to output directory - when: raspios_build is defined - copy: - content: "{{ raspios_build.stdout }}\n" - dest: "{{ raspios_output_dir }}/build-stdout.log" - - - name: save stderr build-log to output directory - when: raspios_build is defined - copy: - content: "{{ raspios_build.stderr }}\n" - dest: "{{ raspios_output_dir }}/build-stderr.log" - - - name: delete the temporary build directory - when: not raspios_keep_temporary_build_dir - file: - path: "{{ tmpdir.path }}" - state: absent + - name: unmount image + when: + - not raspios_keep_boot_dir_mounted + - raspios_image_mount_point is defined + - raspios_image_mount_point is mount + command: "udisksctl unmount --no-user-interaction -b '{{ raspios_image_loop_device }}'" + + - name: delete loop_device + when: + - not raspios_keep_boot_dir_mounted + - raspios_image_loop_device is defined + command: "udisksctl loop-delete --no-user-interaction -b '{{ raspios_image_loop_device }}'" - name: print temporary build directory information - when: raspios_keep_temporary_build_dir + when: + - raspios_keep_boot_dir_mounted debug: - msg: "The temporary build directory has not been deleted, the path to the directory is: {{ tmpdir.path }}" + msg: "As per request the boot partition of the image is still mounted to: {{ raspios_image_mount_point }}" + +- name: set output image names + set_fact: + output_images: + - "{{ (raspios_output_dir, raspios_output_image_base_name) | path_join | realpath }}" diff --git a/roles/raspios/image/templates/firstrun.sh.j2 b/roles/raspios/image/templates/firstrun.sh.j2 new file mode 100644 index 00000000..c91c952f --- /dev/null +++ b/roles/raspios/image/templates/firstrun.sh.j2 @@ -0,0 +1,36 @@ +#!/bin/bash +set +e + +{# https://loganmarchione.com/2021/07/raspi-configs-mostly-undocumented-non-interactive-mode/ #} + +raspi-config nonint do_hostname "{{ host_name }}" +raspi-config nonint do_change_locale "{{ raspios_locale }}" +raspi-config nonint do_change_timezone "{{ raspios_timezone }}" +raspi-config nonint do_configure_keyboard "{{ raspios_keyboard_layout }}" + +{# 0 -> predictable interface names, 1 -> legacy (eth0...) #} +raspi-config nonint do_net_names 0 +{% if not (install_dhcp | default(false)) %} +cat <> /etc/dhcpcd.conf + +# +interface eth0 +static ip_address={{ network.primary.address }} +static routers={{ network.primary.gateway }} +static domain_name_servers={{ network.nameservers | join(' ') }} +EOF +{% endif %} + +{% if ansible_port != 22 %} +sed -e 's/^#*Port .*$/Port {{ ansible_port }}/' -i /etc/ssh/sshd_config +{% endif %} +install -m 0700 -d /root/.ssh +install -m 0644 /boot/firstrun.authorized_keys /root/.ssh/authorized_keys +{# 0 -> enable ssh, 1 -> disable ssh #} +raspi-config nonint do_ssh 0 + +DEBIAN_FRONTEND=noninteractive dpkg -P userconf-pi +sed 's#systemd.run=/boot/firstrun.sh systemd.run_success_action=reboot systemd.unit=kernel-command-line.target##' -i /boot/cmdline.txt +sed 's#\s*$##' -i /boot/cmdline.txt +rm /boot/firstrun.authorized_keys +rm /boot/firstrun.sh -- cgit v1.2.3