define raspi ( String $dir, String $version, ) { # https://www.kernel.org/doc/html/latest/admin-guide/nfs/nfsroot.html file { $dir: ensure => directory, } $img_file = "${version}-raspios-buster-armhf-lite" file { "${dir}/${img_file}.zip": ensure => file, source => "https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/${img_file}.zip", checksum => 'sha256', checksum_value => 'c5dad159a2775c687e9281b1a0e586f7471690ae28f2f2282c90e7d59f64273c', } ~> exec { "/usr/bin/unzip ${img_file}.zip": creates => "${dir}/${img_file}.img", cwd => $dir, } # see modprobe.d(5) # /sys/module/loop/parameters/max_part file { '/etc/modprobe.d/loop.conf': content => "options loop max_part=8\n", } ['root'].each |$d| { file { "${dir}/${d}": ensure => directory, } ['base', 'export', 'overlays', 'workdirs'].each |$subdir| { file { "${dir}/${d}/${subdir}": ensure => directory, } } } $mounts = { 'root' => ['music',], # 'boot' => ['music',], } # overlay fs not supported for FAT32 filesystems $fstab = "${dir}/fstab" file { $fstab: ensure => file, } File[$fstab] -> File_Line <| path == $fstab |> $mounts.each |$type, $lst| { $lst.each |$name| { $dict = { lowerdir => "${dir}/${type}/base", upperdir => "${dir}/${type}/overlays/${name}", workdir => "${dir}/${type}/workdirs/${name}", nfs_export => 'on', } $target = "${dir}/${type}/export/${name}" file { [ $dict['upperdir'], $dict['workdir'], $target, ] : ensure => directory, } $opts = $dict.map |$k, $v| { "$k=$v" }.join(',') file_line { "Raspi fstab ${type} ${target}": ensure => present, path => $fstab, line => "overlay ${target} overlay ${opts}", } } } ensure_packages ( ['nfs-utils'], { ensure => latest, }) service { 'nfs-server': ensure => running, enable => true, } exports { "${dir}/root/export": options => { '*' => [ 'rw', 'no_subtree_check', 'no_root_squash', # Our mounts under the exported tree are also exported, which is # needed since our export point is simply a mount point 'crossmnt', 'fsid=1', ], }, } # TODO ensure that we are mounted before we start changing stuff $root = "${dir}/root/export/music" file { "${root}/etc/systemd/system/multi-user.target.wants/ssh.service": ensure => link, target => '/lib/systemd/system/ssh.service', } file { "${root}/etc/fstab": ensure => absent, } file { "${root}/root/.ssh": ensure => directory, } file { "${root}/root/.ssh/authorized_keys": ensure => file, } file_line { 'raspbian root key': path => "${root}/root/.ssh/authorized_keys", line => 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC8bdCl6aFmYoWAZIoorFv96oV45Jv75vH0TyNTKyByNV0dr6qgJzt8HJ1J/bVDs+q679f4udA1HLGLncyoJS1rGw9meP36dXCQBPMdfZJN0tIrYWgo2Hb7ZpDjsvxGTHaE9jzWlDUI9DcoWoa1Hy8roqsFZgbEnW4H1QG2Hr1+MkjoKvxhXFZoDxuq5K8WcHpehhEU8YcHSKiL0R5jhGlGbL+Qvb1QUL1sXQquHrgJB4IwrrYt2chX4W9Uo+PMny6VYV8ubuXvYCyQehQqZmkYSWD3iJAu59Ti0MLC+egBVZ6UkWAn4kik5cbboC36ioDCKQfrpvfZuUg4OA01N033QoC3+aKUwic8t+Z9sQz7PKT3JTJA5cLTjV+FMoZfKUiSrgm2jgk2mYl86HyHbjwvVq3I0Ny5xXHX3n2DwY9kT3tV16lA3m6oRPeUwZDo7sCzHuMTj2tQE8mMzpZ6kA/CkwAOotY6S/XSbyynIrYpu0Y2HJ6Rax8XGt09DEc7XAE= hugo@gandalf', } # $ l=$(losetup --show -f ${file}.img) # $ mount "${l}p1" boot/base # $ mount "${l}p2" root/base # $ dd if=/dev/loop0p1 of=boot-sector.img # console=serial0,115200 console=tty1 root=/dev/nfs rootfstype=10.0.0.40:/usr/local/raspi/root,vers=4.1,proto=tcp id=dhcp elevator=deadline rootwait rw # cmdline.txt # root=/dev/nfs # rootfstype=10.0.0.40:/usr/local/raspi/root,vers=4.1,proto=tcp }