summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2022-09-05 00:04:25 +0200
committerChristian Pointner <equinox@spreadspace.org>2022-09-05 00:04:25 +0200
commit18c8a90e267dd06c587229066544d39e91656a0b (patch)
treeed8a022d0b437779927e7e0451fff63382c0648a
parentraspios: major refactoring for image fetching, TODO: customization (diff)
raspios: image customization works now
-rw-r--r--inventory/host_vars/ch-cm4-test.yml13
-rw-r--r--roles/raspios/image/defaults/main.yml10
-rw-r--r--roles/raspios/image/tasks/main.yml119
-rw-r--r--roles/raspios/image/templates/firstrun.sh.j236
4 files changed, 127 insertions, 51 deletions
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 <<EOF >> /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