Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DietPi-PREP | Building using chroot #1775

Closed
pronvit opened this issue May 15, 2018 · 33 comments
Closed

DietPi-PREP | Building using chroot #1775

pronvit opened this issue May 15, 2018 · 33 comments
Assignees
Labels
Installer 💠 Issues related to DietPi-Installer and/or pre-image used
Milestone

Comments

@pronvit
Copy link

pronvit commented May 15, 2018

I'm now using DietPi scripts for my needs (building a minimal image booting to miRack) and I'm doing it in chroot environment. Qemu (you mentioned you don't have experience with it) isn't an issue here as you specify it only once to chroot into a mounted original OS image and then you don't even notice it (apart from being a VM, qemu can just transparently run binaries for other platforms).

I think apart from removing stuff I don't need, the only major thing I had to fix is that since you can't start services in chroot environment, mounting tmpfs on /DietPi needs to be done differently (I don't need it so I just removed all that).

If you're interested, I can provide more details how to set it up - creating images on real boards seems to be an overkill to me.

@Fourdee
Copy link
Collaborator

Fourdee commented May 15, 2018

@pronvit

If you're interested, I can provide more details how to set it up

Please, by all means. This is something i've been meaning to do for a long time, however, without a nudge in the right direction and flooded with other tasks, not been able to start it.

creating images on real boards seems to be an overkill to me.

Yep, it is a nightmare, it would be much more beneficial if we could build/create the images via Qemu and chroot.
Maybe its something we could all work on together? @MichaIng aswell?

@pronvit
Copy link
Author

pronvit commented May 16, 2018

Here you go http://github.com/pronvit/DietPi

Procedure

  1. Install qemu-user-static package
  2. Copy original image to DietPi folder
  3. Do sudo su - don't run chroot with sudo as otherwise it will get your user home folder path instead of /root.
  4. Run ./prep IMAGE_FN
  5. Once inside chroot, run /root/PREP_SYSTEM_FOR_DIETPI.sh
  6. If everything is ok, run ./post IMAGE_FN, this will generate DietPi.img, if not, run ./cancel to unmount stuff.

Notes

Basically I just commented out stuff that doesn't work inside chroot:

  1. dietpi-set_dphys-swapfile 0 fails because swapoff fails, I don't think it's even needed in chroot.
  2. dietpi-set_cpu fails because /sys isn't mounted so it can't determine supported governors. /sys from the host obviously can't be used, so I don't know.
  3. I invoke dietpi-ramdisk directly because starting/stopping a service isn't possible.
  4. I removed dietpi-drive_manager invocation to generate fstab because in chroot nothing is mounted and instead the original fstab content needs to be preserved, so instead I APPEND to it.

A big difference is that with chroot, any board-specific first boot procedures are not performed before running DietPi script. I only have a Tinker Board so could only test on it.
Its /etc/init.d/rockchip.sh script definitely fails but what it does is related to GPU or to stuff that's replaced by DietPi scripts anyway. Need to check per-board if this causes any problems and if any additional packages need to be left for first boot scripts to run.

Unfortunately, even with the original DietPi image I'm having issues with WiFi - it's not getting IP address most of the time, so I didn't test much after the first boot.

Feel free to do whatever with the code as I guess my changes are not really suitable for a proper PR and merging.

@MichaIng
Copy link
Owner

@pronvit @Fourdee
I played around with qemu and chroot for a short time with the aim to create RPi images and do dev/testing.

I used qemu as VM on Windows Host, but found it to be extremely slow and didn't work to boot a DietPi image, as some manual fstab/cmdline.txt adjustments are needed and DietPi overwrites/readjusts them on 1st boot.

I tried chroot then as well with a test system on USB stick, but for development the issue is, that you are not able to somehow "reboot" or re-initiate the system. For just running the preparation script it should work fine, indeed.

How does the combination of qemu and chroot work now? Is it started as real VM then, instead of a "dead" image, where you chroot inside? On the other hand, then /proc /sys /dev etc should be present.

Hardware info

  • To enable, we can mount the related directories to the chroot environment, but of course that only makes much sense, if the target system hardware matches the creation system: https://askubuntu.com/a/551356
    Otherwise it makes sense anyway to do all the hardware info gathering on 1st boot instead of creation.

Swapfile

  • We want to remove it, if present, on the image of course, but there will be other ways to do that, I think.

fstab

  • Appending lines to fstab is dangerous, because of doubled entries (/tmp) etc.
  • But instead of reading the entry infos from mounted drives, we could read those infos from existing fstab and just write them back into our new fstab style.

After all, I guess it is still the safest way to create images directly on the machines. With some SD cards it is also not too much more effort. Flash/install pre-image and running preparation script must be done anyway once, or what do you mean by nightmare @Fourdee ? Performance on slow boards I can think of?

@pronvit
Copy link
Author

pronvit commented May 18, 2018

Why do you want to "reboot", "re-initiate" or somehow boot the system at all?

@MichaIng
Copy link
Owner

@pronvit

Why do you want to "reboot", "re-initiate" or somehow boot the system at all?

Not necessarily for image creation, just mentioned it as I was looking for some testing/development solutions as well, where e.g. some installation/configuration steps need system reboot or sometimes you want to test reboot behaviour especially. But this requires a VM at least. For this reason I am interested in what role qemu plays here.

@pronvit
Copy link
Author

pronvit commented May 18, 2018

For running commands inside chroot. Just look at my prep script, the last line.

@Fourdee
Copy link
Collaborator

Fourdee commented May 20, 2018

@pronvit

Many thanks for this 👍 I really appreciate it. I've got side-tracked with other tasks at the moment, however, once I can, i'll take an in-depth look into your commit and guide.

what do you mean by nightmare @Fourdee ? Performance on slow boards I can think of?

@MichaIng Yep, basically, and the time to read SD card to image, risk of SD card corruption during read, etc etc.
Its just a lengthy process I feel with @pronvit's guide and commit, we may be able to achieve something more refined for image creation and updating them quicker.

@Fourdee Fourdee added this to the v6.9 milestone May 20, 2018
@Fourdee
Copy link
Collaborator

Fourdee commented May 20, 2018

Flagged for v6.9, so it doesn't get put to the bottom of pile.

@Fourdee Fourdee modified the milestones: v6.9, v6.10 Jun 4, 2018
@Fourdee Fourdee modified the milestones: v6.10, v6.11 Jul 2, 2018
@MichaIng MichaIng modified the milestones: v6.11, v6.12 Jul 5, 2018
@Fourdee Fourdee modified the milestones: v6.12, Planned for implementation Jul 16, 2018
@MichaIng MichaIng changed the title Building using chroot DietPi-PREP | Building using chroot Oct 14, 2018
@MichaIng MichaIng added Installer 💠 Issues related to DietPi-Installer and/or pre-image used and removed Question ❔ labels Oct 14, 2018
@MichaIng
Copy link
Owner

I had another look into this. And indeed we might want to give it a try.

Just thought through a bid again. Understand chroot m qemu-arm-static /bin/bash now: Instead of simply chroot with the host system arch it emulates an ARM system inside the chroot, otherwise executing ARM binaries from e.g. x86 host of course fails. No sort of a mix of a simply chroot and a real VM, as far as I understood 😄.

Service starts (systemctl (re)start) can be easily replaced by executing the ExecStart directly, if required. fstab pre-creation can be derived from the present fstab, however we should be careful there, of course using the whole method for each device individually first (and verify).
As well the possible existing swapfile location can be derived from fstab. But I doubt that any fresh images comes with an existing swap file anyway?

All other hardware related steps should be or are already done one first boot of destination system anyway.

Not sure if ARMv6/7/8 need different qemu binaries?

@MichaIng
Copy link
Owner

MichaIng commented Feb 20, 2019

Just tested with a Raspbian Lite image on VM:

root@VM-Stretch:/mnt# chroot /mnt/rpi qemu-arm-static /bin/bash
root@VM-Stretch:/# hostname
bash: /bin/hostname: cannot execute binary file: Exec format error
root@VM-Stretch:/# nano
bash: /bin/nano: cannot execute binary file: Exec format error

Then I remembered that it should not work to emulate inside an emulation. So I tried on x86 notebook, but same.

cat /proc/cpuinfo does not show vmx or svm flag, so it looks like my notebook as well does not support emulation 🤔?
Yeah its an old Acer emachines D725, so not unlikely.

@FredericGuilbault
Copy link
Contributor

FredericGuilbault commented May 2, 2019

Im running qemu emulation this way:

First I Mount the .img,

  • Put the files& scripts I need in the mounted rootfs
  • Add the scripts to run in /etc/rc.local/
  • add && reboot at the end of the row .

Unmount the image and run QEMU with the noreboot flag.

  • Qemu boot,
  • execute the script,
  • The script try to reboot on success (but QEMU exit) or drop to login prompt on fail.

I remount my .img, clean my /etc/rc.local, Unount

Then Im ready for the next step.

--- Qemu is slow cuz it support only one core.


This is my QEMU cmds :
For raspbian:

qemu-system-arm
                -kernel ./qemu-rpi-kernel-master/kernel-qemu-4.14.79-stretch \
                -cpu arm1176 \
                -m 256 \
                -M versatilepb \
                -no-reboot \
                -serial stdio \
                -dtb ./qemu-rpi-kernel-master/versatile-pb.dtb \
                -append  "root=/dev/sda2 panic=1 rootfstype=ext4 rw" \
                -drive file=myimage.img,index=0,media=disk,format=raw \
                -net user,hostfwd=tcp::9002-:22 \
                -net nic

For debian X86_64:

qemu-system-x86_64
                -m 256 \
                -no-reboot \
                -serial stdio \
                -boot d \
                -cdrom "myiso.iso" \
                -drive file=mydrive.img,index=0,media=disk,format=raw \
                -net user,hostfwd=tcp::9003-:22 \
                -net nic
                )

@MichaIng
Copy link
Owner

MichaIng commented May 3, 2019

@FredericGuilbault
Many thanks for sharing

So you run QEMU as VM.

Qemu is slow cuz it support only one core.

And no VT-x/AMD-V acceleration AFAIK.

The idea above is to run QEMU not as VM but only use it to execute ARM binaries: qemu-static vs qemu-system
This reduces much overhead of course but reduces the chance to catch certain issues with the image (boot sequence). So your way to "boot" as VM via QEMU is somewhere in the middle between how we do not (boot on real machine) and the chroot method.

Actually the final image should be anyway ALWAYS tested one time (at least) on a real machine, verifying first run setup + boot sequence runs without issues, checking the boot/journalctl log for any anormalities. As long as we do not create our images from scratch there are simply too much possibilities of changes/conflicting bootloader/kernel configurations, first run scripts that come from the base-image and stuff.

Taken this, the fastest method would be indeed to use:

All these steps can be done within a single script. Then some can test the image on a real machine before it is released.

@FredericGuilbault
Copy link
Contributor

FredericGuilbault commented May 3, 2019

Work for me ™

thisSbc=RPi-ARMv6

IMAGE=./work/$thisSbc/raspbian.img
ROOTFS="$(pwd)/work/$thisSbc/rootfs"
BOOTFS="$(pwd)/work/$thisSbc/rootfs/boot"

#mount partitions
kpartx -sa $IMAGE
mount /dev/mapper/loop0p2 $ROOTFS
mount /dev/mapper/loop0p1 $BOOTFS

# mount binds
mount --bind /dev $ROOTFS/dev/
mount --bind /sys $ROOTFS/sys/
mount --bind /proc $ROOTFS/proc/
mount --bind /dev/pts $ROOTFS/dev/pts

# ld.so.preload fix
sed -i 's/^/#/g' $ROOTFS/etc/ld.so.preload

# copy qemu binary
cp /usr/bin/qemu-arm-static $ROOTFS/usr/bin/

# This is where the magic append
chroot $ROOTFS /bin/bash << EOF
    ls /home/
    apt-get install -y feh
EOF

# revert ld.so.preload fix
sed -i 's/^#//g' $ROOTFS/etc/ld.so.preload

# unmount
umount $ROOTFS/dev/
umount  $ROOTFS/sys/
umount $ROOTFS/proc/
umount $ROOTFS/dev/pts
umount $BOOTFS
umount $ROOTFS
kpartx -d $imgFile

exit

It's obv broken if you try on DietPi due to the fact that the first run scripts haven't been run yet.

@FredericGuilbault
Copy link
Contributor

FredericGuilbault commented May 3, 2019

Emulation, chroot and automation will never replace real world testing and they come with their load of new issues and limitations. The point for me is productivity and reproducibility. It's often just a way to document the steps needed to have something done.

@MichaIng
Copy link
Owner

MichaIng commented May 3, 2019

The point for me is productivity and reproducibility. It's often just a way to document the steps needed to have something done.

Jep that is indeed a large benefit! Having things documented and clear defined steps to reproduce.

@FredericGuilbault
Copy link
Contributor

Hi, im adding this article to the knowlege base.

It explain diff between qemu-armhf and qemu-debootstrap and mainly why qemu-debootstrap is faster.

http://logan.tw/posts/2017/01/21/introduction-to-qemu-debootstrap/

*note that pi-gen is using qemu-debootstrap,
The limitation is: The host operating system MUST be debian or a debian derivative.

@MichaIng
Copy link
Owner

MichaIng commented Jul 14, 2019

@FredericGuilbault
Many thanks for posting. Okay actually reading through it and checking the package docs, this should be indeed the preferred method to create DietPi images from scratch, as long as kernel+bootloader(+other required firmware) is handy to install, e.g. via 3rd party APT repo (archive.raspberrypi.org, apt.armbian.com, fuzon.co.uk/meveric/, ...).

  • Create basic Debian system via debootstrap or qemu-debootstrap, depending on if arch of dev system matches arch of target system or not.
  • schroot seems to automate these bind mount/symlink creation required to access host hardware/devices from within the chroot. Very handy.

I will play around with this soon, first to create an x86_64 image, so basically replacing Debian mini.iso installer with debootstrap + schroot, and see if DietPi-PREP can then run as before, in case after installing systemd to the target system.
When this went well, trying the same with qemu-debootstrap.

  • Actually e.g. the pi-gen steps are very similar to what DietPi-PREP does (core image, DietPi-PREP of course does much more): https://github.com/RPi-Distro/pi-gen
  • The last one is similar to what DietPi-Imager does: https://github.com/RPi-Distro/pi-gen/blob/master/export-image/prerun.sh
    • The root partition of the image is created 800 MiB larger by design then what the actual partition content takes. Interesting...
    • What I am annoyed by with the current DietPi-Imager, is that it seems impossible with usual tools to move all files to the physical start of the partition, so resize2fs and parted can afterwards reduce the size to the real minimum. Having some files created and removed, creates holes in the physical drive location and those can only be closed by copying all files out, reduce the partition sizes and copy files inside again. This is what I did for the current x86_64 BIOS image to have it that small. And this is basically what pi-gen does as well, although they create a new .img file with desired sizes and use rsync to copy, I simply used cp -a. Not 100% sure about the benefit of rsync here since cp -ax has exactly the same result then rsync -aHAXx on an empty target, but is an essential always present tool. However always creating a fresh img file should be also the method of DietPi-Imager by default.
  • We could then even create a FAT boot partition on all our images, so kernel/bootloader and dietpi.txt can always be modified from Windows system?
  • Of having simplicity over functionality here and always create single partition images (besides EFI images of course)? However we would need to find and promote an easy and safe method to edit ext4 on Windows then. Checking the last time the available Windows ext4 driver was very unstable, crashed and broke the file system as far as I remember.

@FredericGuilbault
Copy link
Contributor

FredericGuilbault commented Jul 14, 2019

rsync is sometime/often faster then cp, that might justs be a performance concern.

I wonder if BTRFS also leave holes or it's just an ext4 problem? I remember messing with this when ext4 was new(long time ago enh) and copying to a new partition was the prefered method at the time.

We could then even create a FAT boot partition on all our images, so kernel/bootloader and dietpi.txt can always be modified from Windows system?

+1 I think it's not just about functionality but also performance and SDcard wear. ...And FOSS

@MichaIng
Copy link
Owner

@FredericGuilbault

rsync is sometime/often faster then cp, that might justs be a performance concern.

Possibly, could run some tests on next image creation. However for me at least it doesn't matter if it takes 1 or 1.5 minutes, I think it was even much faster since only ~650M data...

I wonder if BTRFS also leave holes or it's just an ext4 problem? I remember messing with this when ext4 was new(long time ago enh) and copying to a new partition was the prefered method at the time.

The file system type would be bad if it would not leave holes. I mean to reduce disk writes it totally makes sense to not move all data around all the time only to close holes. Usually you do not care where data is stored physically. Of course new data should usually be written into the holes first, but I think this is done on ext4 as well. The issue is that DietPi-PREP removes much more data than it adds, so holes are just expected. It would be just nice to have a tool that explicitly moves all data physically to the partition/disk start.

BTRFS is nothing that makes sense too soon, I think, there are simply too much boards with old kernel versions. E.g. I think swapfiles on BRTFS just became possible with kernel 4.18 or something.

+1 I think it's not just about functionality but also performance and SDcard wear. ...And FOSS

I just remember (will verify before attempting the first debootstrap RPi image) that RPi cannot boot from ext4 actually, so the FAT boot partition is required anyway 😅.

You mean performance and SDcard wear will benefit from a single ext4 partition? Only bootloader and kernel are there, read a single time on boot and never touched afterwards on usual operation. So I guess there is no measurable impact of having a separate /boot partition.

https://sourceforge.net/projects/ext2fsd/ no dev since 2 years, many open bug reports in relation with Windows 10. Seems to be still not safe to use for writing to an ext4 partition. I guess Windows Subsystem for Linux (WSL) is capable of doing this safely, but it is only available on Windows 10 Pro edition and upwards (AFAIK?). And of course it is quite an overhead of installing it just to edit a single text file...

@FredericGuilbault
Copy link
Contributor

You mean performance and SDcard wear will benefit from a single ext4 partition?

From what I have read on armbian forum BRTFS cause less internal less read and write then ext4 but I did not validate this info, take it as a rhumor.

I would vouch for having /boot partition in FAT32 for all SBC (even if it's not needed in some case like VirtualBox) it's a question of conviency and standardisation across OS and a tradition when it come about booting on SDcard/USB.

I also agree that 99% of W$ users won't install an outdated driver for editing a single file. This would be a suicide move in term of adoption of Dietpi.


Im working slowly on this but im working on a script to build lysmarine on top of dietpi. Wich is quite similar to building Dietpi in top other OS ( + lysmarine include compiling C++ projects and some nodejs library not available for armV6 )

IK it's not anyone priority ATM but I would totally agree Make it a common ground for both project. I kinda just need a repo to push to and some feedpack from DietPi people to make sure it stay in the common ground and you guys/girls will be happy to use it.

("A repo to push to" as I think the build tool should be seperated form the build content )

@MichaIng
Copy link
Owner

@FredericGuilbault

From what I have read on armbian forum BRTFS cause less internal less read and write then ext4

Perhaps we could create some testing images based on BTRFS for systems which offer a current enough kernel (with latest BTRFS support improvements, e.g. swap files). I have to check again the kernel changelogs where I found this.
Basis is indeed a build script that creates images from source. Converting/migrating an existing image is not a nice solution IMO.
Then we can get some feedback and can ask for some FS benchmarks across different devices to verify the change is worth it.

I would vouch for having /boot partition in FAT32 for all SBC

I was thinking the same. However this is sadly not possible that easy, as in many cases the kernel, bootloader and dtoverlay packages either rely on symlinks and/or POSIX permissions, which is both not supported on FAT. We would require custom packages and e.g. initramfs hooks to work around this, which is currently impossible due to lack of man power and experience.
So this can only be implemented on a per-device basis, for those devices where the kernel/bootloader/initramfs/firmware packages/scripts can handle it.

Im working slowly on this but im working on a script to build lysmarine on top of dietpi.

I hope that I find time soon to start with some build from scratch attempts, based on debootstrap and (s)chroot. That would be a much more transparent and cleaner solution.

@FredericGuilbault
Copy link
Contributor

I have check about schroot and I Don't think it ca do well for distribution purpus as it rely on configuration files located in the /etc/ of the host system. And I found it intrusive. I ended up using proot.

@MichaIng
Copy link
Owner

@FredericGuilbault
Jep, testing will show if it is still easier than chroot (or proot, don't know that) and manually setup the chroot environment (/dev /proc /sys /run(?) mounts and some others possibly).

@MichaIng
Copy link
Owner

Tried to fiddle around with qemu system emulation to get the RPi image booting on my Windows machine. No success with "native" methods, so using the kernel and dtb files from the image and any combination of machine, CPU and image/drive invocation that is usually mentioned on online guides.

Interesting is that the "raspi2" machine is never mentioned, seems to not work at all, what is it for then? There is a "raspi3" machine available as well, but aarch64 only, so cannot boot Raspbian, and no network support.

It seems that booting any Raspbian requires a special kernel file, most likely a dtb file as well. Those I could find in various guides, are totally outdated, not matching the current Raspbian images.

I am a bid disappointed that, if there are already "raspi" machines available, that those are not able to boot an image right the same way an RPi would do, so using the contained bootloader to then load kernel, dtb files etc right from the image. But perhaps that is not even possible, not sure about the borders or qemu hardware emulation in general.

IMO there is not much point (for our image creation process) in using ARM emulation, if one needs to use an external custom kernel and dtb (and in some cases even initrd), that do not match the ones from the image you want to create, CPU that does not match the one form the actual SBC, RAM size as well (in case of versatilepb) etc. And we would need to fiddle around for every single SBC again, to find a working machine/CPU/kernel/dtb/initrd combination.


So qemu-static is what I will go for instead. DietPi-PREP requires some adjustment for this: #1775 (comment)

  • Replacing service starts with direct script calls.
  • Find probably existing swap file via fstab (or better method?) and remove it manually.
  • Before creating fresh fstab, preserve existing / /boot and /boot/efi mounts and re-add afterwards, since it is created without any physical mounts from within chroot.

@MichaIng
Copy link
Owner

MichaIng commented Sep 21, 2019

Finally chroot + qemu-static works very well inside a VM. I just forgot to install binfmt-support.

Currently running large APT updates, mounting and some other tasks inside an DietPi RPi image. Works very well, only minor adjustments need to be done, e.g. /etc/ld.so.preload which loads the raspi-copies-and-fills overrides of course fails on an VM, leading to an error prompt on every single command. However this can be backed up and restored on chroot exit.

Very nice for cross-compiling as well, which was the initial reason to go on with this topic.


Ah now I found https://wiki.debian.org/RaspberryPi/qemu-user-static which mentions the ld.so.preload issue as well 😄.


Since resolvconf is not and cannot be started, a temporary DNS entry must be created:

mv /etc/resolv.conf /etc/resolv.conf_bak
echo 'nameserver 8.8.8.8' > /etc/resolv.conf # Google DNS should always work, but can of course be chosen different
...
# Do your stuff ...
...
mv /etc/resolv.conf_bak /etc/resolv.conf

@FredericGuilbault
Copy link
Contributor

Hi, I think i might have some time in the next 2 weeks to work on dietpi. The thing I would like to do is having a way to avoid using ramfs in qemu. This would allow me to use dietpi software and partition stretching tool in on my build script.

  1. Would you accept such PR
  2. what would be the best place to work on this (And discuss about it ) ? Fork, project, PR.... ???

--Fred

@MichaIng
Copy link
Owner

MichaIng commented Oct 20, 2019

@FredericGuilbault
Not sure what you mean by "avoid ramfs in qemu"? You mean skip DietPi-RAMdisk?

I just created the first RPi image on VirtualBox VM via systemd-nspawn: https://dietpi.com/downloads/images/testing/DietPi_RPi-ARMv6-Buster.7z
This allows to kinda "boot" the image. It invokes qemu-static automatically with the required architecture, using in combination with binfmt-support, and runs /sbin/init inside the container. /dev /sys /proc and such are mounted automatically correctly and systemctl works, knowing its inside a container.
There are some minor workarounds required, e.g. dhcpcd will completely spam the syslog (systemd-journald) with hundreds of error messages every second. I needed a failed (corrupted) build first to recognise this, and was wondering why the container/VM had such a high CPU consumption, being very slow, all the time 😆. And when testing/doing this for more images, most likely other workarounds need to be added before chrooting.

Here the script I'm having so far:

#!/bin/bash

FP_IMG='DietPi_RPi-ARMv6-Buster.img'
FS_IMG='3' # GiB

[[ -f $FP_IMG ]] || exit 1
apt-install dosfstools systemd-container binfmt-support qemu-user-static
LOOP_DEV=$(losetup -f)
ROOT_DEV="${LOOP_DEV}p2"
BOOT_DEV="${LOOP_DEV}p1"

# Raise image+partition+fs size if required, always run fsck
if (( $(stat -c %s $FP_IMG) < $FS_IMG*1024*1024*1024 )); then
        truncate -s $(($FS_IMG*1024*1024*1024)) $FP_IMG
        losetup -f $FP_IMG
        partx -u $LOOP_DEV
        e2fsck -f $ROOT_DEV
        dosfsck $BOOT_DEV
        sfdisk $LOOP_DEV -fN 2 <<< ',+,,,'
        partx -u $LOOP_DEV
        resize2fs $ROOT_DEV
else
        losetup -f $FP_IMG
        partx -u $LOOP_DEV
        e2fsck -f $ROOT_DEV
        dosfsck $BOOT_DEV
fi

[[ -d 'm' ]] || mkdir m
mount $ROOT_DEV m
mount $BOOT_DEV m/boot

# Workarounds
# - RPi on non-RPi: Move raspi-copies-and-fills ARM-specific mem*-versions out of the way
[[ -f 'm/etc/ld.so.preload' ]] && mv m/etc/ld.so.preload m/etc/ld.so.preload_bak
# - Mask services which cannot succeed in container
ln -sf /dev/null m/etc/systemd/system/dropbear.service
ln -sf /dev/null m/etc/systemd/system/dhcpcd.service

# dbus and systemd-logind required for container spawn
systemctl unmask dbus.socket dbus systemd-logind
systemctl start dbus.socket dbus systemd-logind
systemd-nspawn -bD m
systemctl stop systemd-logind dbus dbus.socket
systemctl mask systemd-logind dbus dbus.socket

# Revert workarounds
[[ -f 'm/etc/ld.so.preload_bak' ]] && mv m/etc/ld.so.preload_bak m/etc/ld.so.preload
rm m/etc/systemd/system/{dropbear,dhcpcd}.service

umount $BOOT_DEV
umount $ROOT_DEV
losetup -d $LOOP_DEV
  • Requires to manually log in and run DietPi-PREP so far. Since mounts are not identified correctly and the cmdline init is not executed, /etc/fstab and /boot/cmdline.txt need to be fixed. But I guess at least for fstab it is possible to configure systemd-nspawn to solve it.
  • Can be easily automated by creating an auto-login drop-in config and downloading DietPi-PREP right into /etc/profile.d/ of the mounted image.
  • Anything else like automated reboot and first run setup+installs can be added of course. I aim to add optional dietpi-software installs right into DietPi-PREP, so one can create real pre-installed images without having to trigger firstrun steps and manually reverting install_stage and such.
  • Finally DietPi-Imager can be added to the script to check, shrink and pack the image with readme and hashes. And then upload as last part of course.

Will create some more images the next days, add env vars for DietPi-Imager to completely automate it, so that all steps from pre-image til archive upload are one automated script call with variables.


However back to your initial idea, if I understood it correctly:

  • I am opened to make DietPi-RAMdisk optional, in the first place it should be not to hard by either placing a symlink or copying the DietPi-related /boot content to /DietPi directly. There are just some other scripts (updater/patch_file) which call dietpi-ramdisk scripts to sync content, which is then obsolete. So implementing it correctly to be used by end user, it requires some more work.
  • Before opening a PR, I think it would be good to discuss the basic concept first within a new issue, to see if the final goals match.

@MichaIng MichaIng modified the milestones: Planned for implementation, v6.27 Oct 20, 2019
@FredericGuilbault
Copy link
Contributor

FredericGuilbault commented Oct 23, 2019

DietPi-RAMdisk is what I meant. If the chroot env can handle the mounts and syncs. There is no much need for my feature in reality. I would push this on some wishlist far away


On lysmarine Im using : https://github.com/lysmarine/lysmarine_gen/blob/0.9.x/buildscript/rpi_build.sh
With : https://github.com/lysmarine/lysmarine_gen/blob/0.9.x/buildscript/common.sh

caching at every step and reusing them is a huge time saver on repetitive compilation,


Have you been able to make nodejs work in the chroot env ?

@MichaIng
Copy link
Owner

@FredericGuilbault

If the chroot env can handle the mounts and syncs. There is no much need for my feature in reality.

Normal chroot needs much tinkering to allow mounts and even systemctl use, AFAIK, but systemd-nspawn can handle all of this correctly, at least if it calls the target systems init to "boot" it. What I like about it is that you can validate correct systemd unit order and execution (besides some, like hardware-dependent services are expected to fail of course), something I was missing from ordinary chroot. Its does not save the need to a real machine test (bootloader/kernel/firmware test/config), but allows deeper checking/cleaning right during the build process.

caching at every step and reusing them is a huge time saver on repetitive compilation,

Makes sense, however for DietPi itself it is minimal, since it's 2.6M only. I wished GitHub would allow to download the archive as bz2 or even 7z/xz 🤔.

Have you been able to make nodejs work in the chroot env ?

I did not try Node.js, will keep it in mind for next session.

@FredericGuilbault
Copy link
Contributor

but systemd-nspawn can handle all of this correctly, at least if it calls the target systems init to "boot" it.

Oh I didin't know about systemd-nspawn. Seem like a nice tool.

This is just a feeling but as is not a real environement booting seem like a receipt for overheads problems for something that is mainly just file manipulation. in all case it worth exploring.

I will check if it's possible to make DietPi-RAMdisk mount in chroot.

@MichaIng
Copy link
Owner

@FredericGuilbault

This is just a feeling but as is not a real environement booting seem like a receipt for overheads problems for something that is mainly just file manipulation. in all case it worth exploring.

Yeah it depends on what you want to of course. In case of our image building, IMO it makes sense, since we want to have all installers and systemctl behave as it was a real system, as close as possible, to trigger possible issues in the first place before doing real machine tests. As well simple things like having APT installs enabling and starting services do not work in simple chroot, so the end result would be simply different. For our own services of course we could place the required symlinks and trigger the ExecStart commands manually, but APT AFAIK cannot do this, thus steps are missing or installs can even fail. Same for /dev /proc /sys access. which of course can be manually mounted into chroot, but systemd-nspawn automates this and handles/limits access reasonably. It is not yet everything perfect, e.g. I am still dealing with the issue that it can see its own loop mounts, but not their UUID or PARTUUID, which leads to missing /boot and / mounts in fstab after DietPi-PREP.

@FredericGuilbault
Copy link
Contributor

I made a quick test and DietPi-RAM disk mount in chroot.

@MichaIng MichaIng modified the milestones: v6.27, v6.28 Nov 13, 2019
@MichaIng MichaIng modified the milestones: v6.28, v6.29 Jan 3, 2020
@MichaIng
Copy link
Owner

MichaIng commented Mar 3, 2020

Nearly all new images have been created via systemd-nspawn, proving it a very well working method: #2979

And DietPi-RAMdisk btw is about to be removed: #3402

I mark this issue as closed. I'll create a wrapper build script which:

  1. Downloads base-image based on Model + distro version choice, or custom input, or present img file, based on either input mask or env vars, cmd options or settings file.
  2. Apply autologin + run DietPi-PREP automated + shutdown to the image and run it via systemd-nspawn.
  3. Run DietPi-Imager automated (ToDo: Allow to run it automated with env vars, cmd options or settings file)
  4. Run an upload script, if present

So this is then something that can be done on any systemd-capable OS, basically 🙂.

However this is something I gonna start with after v6.29 release.

@MichaIng MichaIng closed this as completed Mar 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Installer 💠 Issues related to DietPi-Installer and/or pre-image used
Projects
None yet
Development

No branches or pull requests

4 participants