Giter Site home page Giter Site logo

nature40 / pimod Goto Github PK

View Code? Open in Web Editor NEW
118.0 9.0 19.0 139 KB

Reconfigure Raspberry Pi images with an easy, Docker-like configuration file

License: GNU General Public License v3.0

Dockerfile 2.31% Shell 97.69%
raspberry-pi distribution pifile pi-image automation

pimod's Introduction

pimod

CI: Tests CI: Shellcheck CI: Build and upload DockerHub image Docker Hub: Version

Reconfigure Raspberry Pi images with an easy, Docker-like configuration file.

About

pimod overtakes a given Raspberry Pi image file by mounting a copy and modifying it within a QEMU chroot. This allows the execution of a Pi's ARM code on whatever target, e.g., a x86_64 host.

To ease the usability, a Docker-inspired recipe, called the Pifile, is used to instrument pimod.

# Example Pifile to create a customized version of the Raspberry Pi OS Lite

# Based on a remote image, which will be cached locally, create the altered raspi_example.img file
FROM https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2023-02-22/2023-02-21-raspios-bullseye-arm64-lite.img.xz
TO rapsi_example.img

# Increase the image by 100 MB
PUMP 100M

# Install an ssh key from local sources
RUN mkdir -p /home/pi/.ssh
INSTALL id_rsa.pub /home/pi/.ssh/authorized_keys

# Enable the serial console and SSH
RUN raspi-config nonint do_serial 0
RUN raspi-config nonint do_ssh 0

# Install the important cowsay util
RUN apt-get update
RUN apt-get install -y cowsay

Installation, Usage

Usage: pimod.sh [Options] Pifile

Options:
  -c --cache DEST   Define cache location.
  -d --debug        Debug on failure; run an interactive shell before tear down.
  -h --help         Print this help message.
  -r --resolv TYPE  Specify which /etc/resolv.conf file to use for networking.
                    By default, TYPE "auto" is used, which prefers an already
                    existing resolv.conf, only to be replaced by the host's if
                    missing.
                    TYPE "guest" never mounts the host's file within the guest,
                    even when such a file is absent within the image.
                    TYPE "host" always uses the host's file within the guest.
                    Be aware that when run within Docker, the host's file might
                    be Docker's resolv.conf file.
  -t --trace        Trace each executed command for debugging.

Docker

Getting or Building the Docker Image

There are pre-built images available on Docker Hub:

docker pull nature40/pimod

Alternatively, you can simply build the image yourself locally. This is essential for development, among other things:

git clone https://github.com/Nature40/pimod.git
cd pimod
docker build -t nature40/pimod .

Using the Docker Image

Afterwards, the Docker image can either be used by docker or docker compose:

# Using Docker:
docker run --rm --privileged -v $PWD:/pimod nature40/pimod pimod.sh examples/RPi-OpenWRT.Pifile

# Using Docker Compose:
docker compose run nature40/pimod pimod.sh examples/RPi-OpenWRT.Pifile

Debian

Of course, Docker isn't really necessary and pimod can also be used on, e.g., a Debian directly:

sudo apt-get install \
  binfmt-support \
  fdisk \
  file \
  kpartx \
  lsof \
  p7zip-full \
  qemu \
  qemu-user-static \
  unzip \
  wget \
  xz-utils \
  units

sudo ./pimod.sh Pifile

GitHub Actions

Pimod can also be used as a GitHub Action and is available on the marketplace.

name: tests
on: push

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          submodules: recursive
      - name: Run pimod OpenWRT example
        uses: Natur40/pimod@master
        with:
          pifile: examples/RPi-OpenWRT.Pifile

Pifile

The Pifile contains commands to modify the image.

Those commands are grouped in stages which pimod executes in their corresponding order.

  • First, all setup stage commands are being executed to download the base image and configure the output.
  • The prepare stage follows which pre-flight commands, e.g., resizing the output image.
  • The action happens in the chroot stage where the QEMU chroot is built, commands are executed within, files are copied and so on.
  • Finally, the postprocess stage might clean up some things.

However, as the Pifile being just a Bash script by itself and the commands are functions, which are loaded in different stages, Bash scripting is possible within the Pifile to some extend.

More internals are documented in our our scientific paper. If you stumble upon details there that you think belong in this README, feel free to create an issue or pull request.

Example

$ cat Upgrade.Pifile
FROM 2018-11-13-raspbian-stretch-lite.img

PUMP 100M

RUN raspi-config nonint do_serial 0

RUN apt-get update
RUN bash -c 'DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade'
RUN apt-get install -y sl

# The Upgrade.Pifile will create, called by the following command, a new
# Upgrade.img image based on the given Raspbian image. This image's size is
# increased about 100MB, has an enabled UART/serial output, the latest software
# and sl installed.
$ sudo ./pimod.sh Upgrade.Pifile

# Write the new image to a SD card present at /dev/sdc.
$ dd if=Upgrade.img of=/dev/sdc bs=4M status=progress

Further and more expressive examples are available in this repository's ./example directory. Please take a look and feel free to submit your own examples if they are covering a current blind spot.

Commands

Stage independent

INCLUDE PATH_TO_PIFILE

INCLUDE includes the provided Pifile in the current one for modularity and re-use. The included file has to have a .Pifile extension which need not be specified.

1. Setup Stage

FROM PATH_TO_IMAGE [PARTITION_NO], FROM URL [PARTITION_NO]

FROM sets the SOURCE_IMG variable to a target. This might be a local file or a remote URL, which will be downloaded. This file will become the base for the new image.

By default, the Raspberry Pi's default partition number 2 will be used, but can be altered for other targets.

TO PATH_TO_IMAGE

TO sets the DEST_IMG variable to the given file. This file will contain the new image. Existing files will be overridden.

Instead of calling TO, the Pifile's filename can also indicate the output file, if the Pifile ends with ".Pifile". The part before this suffix will be the new DEST_IMG.

If neither TO is called nor the Pifile indicates the output, DEST_IMG will default to rpi.img in the source file's directory.

INPLACE FROM_ARGS...

INPLACE does not create a copy of the image, but performs all further operations on the given image. This is an alternative to FROM and TO.

2. Prepare Stage

PUMP SIZE

PUMP increases the image's size about the given amount (suffixes K, M, G are allowed).

3. Chroot Stage

INSTALL <MODE> SOURCE DEST

INSTALL installs a given file or directory into the destination in the image. The optionally permission mode (chmod) can be set as the first parameter.

EXTRACT SOURCE DEST

EXTRACT copies a given file or directory from the image to the destination.

PATH /my/guest/path

PATH adds the given path to an overlaying PATH variable, used within the RUN command.

WORKDIR /my/guest/path

WORKDIR sets the working directory within the image.

ENV KEY [VALUE]

ENV either sets or unsets an environment variable to be used within the image. If two parameters are given, the first is the key and the second the value. If one parameter is given, the environment variable will be removed.

An environment variable can be either used via $VAR within another sub-shell (sh -c 'echo $VAR') or substituted beforehand via @@VAR@@.

ENV FOO BAR

RUN sh -c 'echo FOO = $FOO'   # FOO = BAR - substituted within a sh in the image
RUN echo FOO = @@FOO@@        # FOO = BAR - substituted beforehand via pimod

ENV FOO
RUN CMD [PARAMS...]

RUN executes a command in the chrooted image based on QEMU user emulation.

Caveat: because the Pifile is just a Bash script, pipes do not work as one might suspect. A possible workaround could be the usage of bash -c:

RUN bash -c 'hexdump /dev/urandom | head'
HOST CMD [PARAMS...]

HOST executed a command on the local host and can be used to prepare files, cross-compile software, etc.

Pifile Extensions

Because the Pifile is just a Bash script, some dirty brilliant hacks and extensions are possible.

Bulk execution

Sub shells can be used with the RUN command.

RUN sh -c '
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
apt-get install -y sl
'

Inplace Files

Here documents can also be used to create files inside of the guest system, e.g., by using tee or dd.

RUN tee /bin/example.sh <<EOF
#!/bin/sh

echo "Example output."
EOF

Scientific Usage & Citation

If you happen to use pimod in a scientific project, we would very much appreciate if you cited our scientific paper:

@inproceedings{hoechst2020pimod,
  author = {{Höchst}, Jonas and Penning, Alvar and Lampe, Patrick and Freisleben, Bernd},
  title = {{PIMOD: A Tool for Configuring Single-Board Computer Operating System Images}},
  booktitle = {{2020 IEEE Global Humanitarian Technology Conference (GHTC 2020)}},
  address = {Seattle, USA},
  days = {29},
  month = oct,
  year = {2020},
  keywords = {Single-Board Computer; Operating System Image; System Provisioning},
}

Notable Mentions

pimod's People

Contributors

aniongithub avatar jonashoechst avatar matt2005 avatar oxzi avatar patrickelectric avatar renovate[bot] avatar sensslen avatar she11sh0cked avatar tve avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pimod's Issues

FROM remote URL not working

When using FROM with the official URL for a lite image (https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip) from this page, I get

### FROM https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip
Fetching remote: https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip
--2021-04-26 17:01:43--  https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip%0D
Resolving downloads.raspberrypi.org (downloads.raspberrypi.org)... 93.93.130.212, 93.93.135.141, 46.235.230.122, ...
Connecting to downloads.raspberrypi.org (downloads.raspberrypi.org)|93.93.130.212|:443... connected.
HTTP request sent, awaiting response... 404 Not Found
2021-04-26 17:01:44 ERROR 404: Not Found.

but a wget with the same url gives me

wget https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip
--2021-04-26 10:03:01--  https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip
Resolving downloads.raspberrypi.org (downloads.raspberrypi.org)... 176.126.240.86, 176.126.240.84, 93.93.135.118, ...
Connecting to downloads.raspberrypi.org (downloads.raspberrypi.org)|176.126.240.86|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 463405209 (442M) [application/zip]
Saving to: ‘2021-03-04-raspios-buster-armhf-lite.zip.1’

buster-armhf-lite.zip.1           11%[=====>                                                    ]  51.60M  7.53MB/s    eta 58s

Change INSTALL to add files recursively

When INSTALL encounters a folder, it should walk the folder recursively and copy all files to their destination. The functionality can be compared to an overlay as used by OpenWrt, but is more dynamic, as multiple overlays can be installed.

Chaining commands with && has unexpected behaviour

RUN apt update && apt install git runs apt install in host environment

RUN apt update
RUN apt install git
fixes the issue, however this can lead to hours wasted in debugging time expecially if you expect it to work similarly to a Dockerfile.
I think a fix is needed if possible, however I did not investigate if the fact that .pimod is just a bash file is a barrier for an actual fix.

Feature request: checkpoints

The build try fix iterate approach does not really work while building a .pimod file, rebuilding an image from scratch because of a typo takes way too much time.
A very cool feature would be Dockerfile-like checkpoints, or, a CHECKPOINT macro to use in the .pimod file

Link / bind mount QEMU

The QEMU static binaries are currently copied to the guest image. This is not necessary as the binaries themselves are not needed in the image afterwards.

Instead, I suggest to either bind mount individual binaries or expand the PATH and bind mount a folder.

Add PASSWD command

The default password of the pi user might be changed in many cases for custom distros, thus I suggest a PASSWD command.

For now it can be done with:

(echo thepassword; echo thepassword) | RUN passwd pi

pimod fails on btrfs mounts

btrfs maintains su bvolumes inside of containers. When mounting a container, the sub volumes are accessible as a folder.

pimod is currently not able to work on operating systems booting from btrfs, as we are only mounting the container not the submodule.

Suggestion for a simple fix:

  • If a btrfs container is found and one sub volume is inside, mount this sub volume.

Implement INSTALL by using rsync

Hidden files are still not copied, when installing whole folder. I suggest to use rsync for installation to install those files as well.

Investigate failing dist-upgrade

A dist-upgrade fails for me, I guess in consequence to the simulated system. Please investigate this behavior and propose a workaround / solution if possible.

Reading package lists... Done
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Calculating upgrade... Done
The following packages will be upgraded:
  apt apt-transport-https apt-utils base-files libapt-inst2.0 libapt-pkg5.0 libpam-systemd libperl5.24 libpolkit-agent-1-0
  libpolkit-backend-1-0 libpolkit-gobject-1-0 libssl1.0.2 libssl1.1 libsystemd0 libudev1 libwbclient0 openssl perl perl-base
  perl-modules-5.24 policykit-1 python-rpi.gpio raspberrypi-sys-mods raspi-config samba-common systemd systemd-sysv udev
28 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 17.0 MB of archives.
After this operation, 134 kB of additional disk space will be used.
Get:1 http://archive.raspberrypi.org/debian stretch/main armhf python-rpi.gpio armhf 0.6.5~stretch-1 [23.5 kB]
Get:2 http://archive.raspberrypi.org/debian stretch/main armhf raspberrypi-sys-mods armhf 20181127 [10.2 kB]
Get:3 http://archive.raspberrypi.org/debian stretch/ui armhf raspi-config all 20181118 [20.2 kB]
Get:4 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf base-files armhf 9.9+rpi1+deb9u6 [67.5 kB]
Get:5 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf libperl5.24 armhf 5.24.1-3+deb9u5 [2837 kB]
Get:6 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf perl armhf 5.24.1-3+deb9u5 [219 kB]
Get:7 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf perl-base armhf 5.24.1-3+deb9u5 [1198 kB]
Get:8 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf perl-modules-5.24 all 5.24.1-3+deb9u5 [2722 kB]
Get:9 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf libapt-pkg5.0 armhf 1.4.9 [833 kB]
Get:10 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf libapt-inst2.0 armhf 1.4.9 [190 kB]
Get:11 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf apt armhf 1.4.9 [1190 kB]
Get:12 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf apt-utils armhf 1.4.9 [392 kB]
Get:13 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf systemd-sysv armhf 232-25+deb9u8 [81.8 kB]
Get:14 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf libpam-systemd armhf 232-25+deb9u8 [174 kB]
Get:15 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf libsystemd0 armhf 232-25+deb9u8 [259 kB]
Get:16 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf systemd armhf 232-25+deb9u8 [2221 kB]
Get:17 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf udev armhf 232-25+deb9u8 [1072 kB]
Get:18 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf libudev1 armhf 232-25+deb9u8 [120 kB]
Get:19 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf libwbclient0 armhf 2:4.5.12+dfsg-2+deb9u4 [121 kB]
Get:20 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf samba-common all 2:4.5.12+dfsg-2+deb9u4 [172 kB]
Get:21 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf libssl1.0.2 armhf 1.0.2q-1~deb9u1 [898 kB]
Get:22 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf libssl1.1 armhf 1.1.0j-1~deb9u1 [1115 kB]
Get:23 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf apt-transport-https armhf 1.4.9 [166 kB]
Get:24 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf policykit-1 armhf 0.105-18+deb9u1 [61.7 kB]
Get:25 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf libpolkit-agent-1-0 armhf 0.105-18+deb9u1 [22.3 kB]
Get:26 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf libpolkit-backend-1-0 armhf 0.105-18+deb9u1 [39.8 kB]
Get:27 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf libpolkit-gobject-1-0 armhf 0.105-18+deb9u1 [37.8 kB]
Get:28 http://mirror.de.leaseweb.net/raspbian/raspbian stretch/main armhf openssl armhf 1.1.0j-1~deb9u1 [712 kB]
Fetched 17.0 MB in 4s (3699 kB/s) 
apt-listchanges: Reading changelogs...
Preconfiguring packages ...
libssl1.0.2 failed to preconfigure, with exit status 1
libssl1.1 failed to preconfigure, with exit status 1
(Reading database ... 34605 files and directories currently installed.)
Preparing to unpack .../base-files_9.9+rpi1+deb9u6_armhf.deb ...
Unpacking base-files (9.9+rpi1+deb9u6) over (9.9+rpi1+deb9u4) ...
Setting up base-files (9.9+rpi1+deb9u6) ...
Installing new version of config file /etc/debian_version ...
(Reading database ... 34605 files and directories currently installed.)
Preparing to unpack .../libperl5.24_5.24.1-3+deb9u5_armhf.deb ...
Unpacking libperl5.24:armhf (5.24.1-3+deb9u5) over (5.24.1-3+deb9u4) ...
Preparing to unpack .../perl_5.24.1-3+deb9u5_armhf.deb ...
Unpacking perl (5.24.1-3+deb9u5) over (5.24.1-3+deb9u4) ...
Preparing to unpack .../perl-base_5.24.1-3+deb9u5_armhf.deb ...
Unpacking perl-base (5.24.1-3+deb9u5) over (5.24.1-3+deb9u4) ...
Setting up perl-base (5.24.1-3+deb9u5) ...
(Reading database ... 34605 files and directories currently installed.)
Preparing to unpack .../perl-modules-5.24_5.24.1-3+deb9u5_all.deb ...
Unpacking perl-modules-5.24 (5.24.1-3+deb9u5) over (5.24.1-3+deb9u4) ...
Preparing to unpack .../libapt-pkg5.0_1.4.9_armhf.deb ...
Unpacking libapt-pkg5.0:armhf (1.4.9) over (1.4.8) ...
Setting up libapt-pkg5.0:armhf (1.4.9) ...
(Reading database ... 34605 files and directories currently installed.)
Preparing to unpack .../libapt-inst2.0_1.4.9_armhf.deb ...
Unpacking libapt-inst2.0:armhf (1.4.9) over (1.4.8) ...
Preparing to unpack .../archives/apt_1.4.9_armhf.deb ...
Unpacking apt (1.4.9) over (1.4.8) ...
Setting up apt (1.4.9) ...
(Reading database ... 34605 files and directories currently installed.)
Preparing to unpack .../apt-utils_1.4.9_armhf.deb ...
Unpacking apt-utils (1.4.9) over (1.4.8) ...
Preparing to unpack .../systemd-sysv_232-25+deb9u8_armhf.deb ...
Unpacking systemd-sysv (232-25+deb9u8) over (232-25+deb9u6) ...
Preparing to unpack .../libpam-systemd_232-25+deb9u8_armhf.deb ...
Unpacking libpam-systemd:armhf (232-25+deb9u8) over (232-25+deb9u6) ...
Preparing to unpack .../libsystemd0_232-25+deb9u8_armhf.deb ...
Unpacking libsystemd0:armhf (232-25+deb9u8) over (232-25+deb9u6) ...
Setting up libsystemd0:armhf (232-25+deb9u8) ...
(Reading database ... 34605 files and directories currently installed.)
Preparing to unpack .../systemd_232-25+deb9u8_armhf.deb ...
Unpacking systemd (232-25+deb9u8) over (232-25+deb9u6) ...
Preparing to unpack .../udev_232-25+deb9u8_armhf.deb ...
Unpacking udev (232-25+deb9u8) over (232-25+deb9u6) ...
Preparing to unpack .../libudev1_232-25+deb9u8_armhf.deb ...
Unpacking libudev1:armhf (232-25+deb9u8) over (232-25+deb9u6) ...
Setting up libudev1:armhf (232-25+deb9u8) ...
(Reading database ... 34605 files and directories currently installed.)
Preparing to unpack .../00-libwbclient0_2%3a4.5.12+dfsg-2+deb9u4_armhf.deb ...
Unpacking libwbclient0:armhf (2:4.5.12+dfsg-2+deb9u4) over (2:4.5.12+dfsg-2+deb9u3) ...
Preparing to unpack .../01-samba-common_2%3a4.5.12+dfsg-2+deb9u4_all.deb ...
Unpacking samba-common (2:4.5.12+dfsg-2+deb9u4) over (2:4.5.12+dfsg-2+deb9u3) ...
Preparing to unpack .../02-libssl1.0.2_1.0.2q-1~deb9u1_armhf.deb ...
Unpacking libssl1.0.2:armhf (1.0.2q-1~deb9u1) over (1.0.2l-2+deb9u3) ...
Preparing to unpack .../03-libssl1.1_1.1.0j-1~deb9u1_armhf.deb ...
Unpacking libssl1.1:armhf (1.1.0j-1~deb9u1) over (1.1.0f-3+deb9u2) ...
Preparing to unpack .../04-apt-transport-https_1.4.9_armhf.deb ...
Unpacking apt-transport-https (1.4.9) over (1.4.8) ...
Preparing to unpack .../05-policykit-1_0.105-18+deb9u1_armhf.deb ...
Unpacking policykit-1 (0.105-18+deb9u1) over (0.105-18) ...
Preparing to unpack .../06-libpolkit-agent-1-0_0.105-18+deb9u1_armhf.deb ...
Unpacking libpolkit-agent-1-0:armhf (0.105-18+deb9u1) over (0.105-18) ...
Preparing to unpack .../07-libpolkit-backend-1-0_0.105-18+deb9u1_armhf.deb ...
Unpacking libpolkit-backend-1-0:armhf (0.105-18+deb9u1) over (0.105-18) ...
Preparing to unpack .../08-libpolkit-gobject-1-0_0.105-18+deb9u1_armhf.deb ...
Unpacking libpolkit-gobject-1-0:armhf (0.105-18+deb9u1) over (0.105-18) ...
Preparing to unpack .../09-openssl_1.1.0j-1~deb9u1_armhf.deb ...
Unpacking openssl (1.1.0j-1~deb9u1) over (1.1.0f-3+deb9u2) ...
Preparing to unpack .../10-python-rpi.gpio_0.6.5~stretch-1_armhf.deb ...
Unpacking python-rpi.gpio (0.6.5~stretch-1) over (0.6.3~stretch-1) ...
Preparing to unpack .../11-raspberrypi-sys-mods_20181127_armhf.deb ...
Error while loading /var/lib/dpkg/tmp.ci/preinst: Exec format error
dpkg: error processing archive /tmp/apt-dpkg-install-CHEtuw/11-raspberrypi-sys-mods_20181127_armhf.deb (--unpack):
 subprocess new pre-installation script returned error exit status 1
Error while loading /var/lib/dpkg/info/raspberrypi-sys-mods.postinst: Exec format error
dpkg: error while cleaning up:
 subprocess installed post-installation script returned error exit status 1
Preparing to unpack .../12-raspi-config_20181118_all.deb ...
Unpacking raspi-config (20181118) over (20180518) ...
Errors were encountered while processing:
 /tmp/apt-dpkg-install-CHEtuw/11-raspberrypi-sys-mods_20181127_armhf.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)

Pifile gets sourced more than once

It seems as if the Pifile is sourced more than once and therefore parts also get executed:

update-binfmts: warning: qemu-arm already enabled in kernel.
UPGRADING
INSTALLING MC
CHANGING PASSWORD
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.11478 s, 188 MB/s
e2fsck 1.43.4 (31-Jan-2017)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
rootfs: 39648/110880 files (0.1% non-contiguous), 271340/443392 blocks
resize2fs 1.43.4 (31-Jan-2017)
The filesystem is already 443392 (4k) blocks long.  Nothing to do!

Disk /dev/loop0: 2 GiB, 2076180480 bytes, 4055040 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7ee80803

Device       Boot Start     End Sectors  Size Id Type
/dev/loop0p1       8192   98045   89854 43.9M  c W95 FAT32 (LBA)
/dev/loop0p2      98304 3645439 3547136  1.7G 83 Linux
loop deleted : /dev/loop0
UPGRADING
INSTALLING MC
CHANGING PASSWORD
Linux fdf54efd2a59 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 armv7l GNU/Linux
Get:1 http://raspbian.raspberrypi.org/raspbian stretch InRelease [15.0 kB]
Get:2 http://archive.raspberrypi.org/debian stretch InRelease [25.4 kB]
Get:3 http://raspbian.raspberrypi.org/raspbian stretch/main armhf Packages [11.7 MB]
Get:4 http://archive.raspberrypi.org/debian stretch/main armhf Packages [200 kB]
Get:5 http://archive.raspberrypi.org/debian stretch/ui armhf Packages [41.6 kB]
Fetched 11.9 MB in 15s (755 kB/s)
Reading package lists... Done
UPGRADING
Reading package lists... Done
Building dependency tree
Reading state information... Done
Calculating upgrade... Done
The following packages will be upgraded:
[...]

See all the ALL-CAPITAL strings in the output..

INPLACE read only mode

I suggest to have INPLACE mount the image read only. Thereby one can test stuff while making sure, that no contents of the original image is modified.

We can discuss on this.

Current version on GitHub Marketplace

It seems like some permissions for GitHub's Marketplace have changed in the meantime.
This results in us - or at least me, as only an organization member - to be unable to publish the latest pimod version as a GitHub Action.

The following screenshot is the view I am getting if I want to draft a new release:
2021-10-04-170905_750x106_scrot

Could you please take a look, @jonashoechst? Thanks a lot.

[Error] pimod fails on Apple M1 devices

When running pimod on Apple M1 devices with Docker for Mac using aarch64, pimod fails to run:

update-binfmts: warning: qemu-arm already enabled in kernel.
update-binfmts: warning: qemu-armeb already enabled in kernel.
update-binfmts: warning: qemu-aarch64 not in database of installed binary formats.
update-binfmts: exiting due to previous errors
### Error 2, cleaning up...

PUMP can result in non-bootable images

We've discovered a case in which PUMP results in a non-bootable image, MWE is presented below:

FROM https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-04-09/2019-04-08-raspbian-stretch-lite.zip

PUMP 1G

Output:

### PUMP 1G
pump conversion to 1M * 1000
pump ceil: 1M * 1000
1000+0 records in
1000+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 15.7714 s, 66.5 MB/s
Model:  (file)
Disk /root/Base.img: 2852MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start   End     Size    Type     File system  Flags
 1      4194kB  49.2MB  45.0MB  primary  fat32        lba
 2      50.3MB  1804MB  1753MB  primary  ext4

add map loop1p1 (253:2): 0 87851 linear 7:1 8192
add map loop1p2 (253:3): 0 5472256 linear 7:1 98304
rootfs: 39794/107072 files (0.1% non-contiguous), 239385/428032 blocks
resize2fs 1.46.2 (28-Feb-2021)
Resizing the filesystem on /dev/mapper/loop1p2 to 684032 (4k) blocks.
The filesystem on /dev/mapper/loop1p2 is now 684032 (4k) blocks long.

del devmap : loop1p2
del devmap : loop1p1
add map loop1p1 (253:2): 0 87851 linear 7:1 8192
add map loop1p2 (253:3): 0 5472256 linear 7:1 98304
update-binfmts: warning: qemu-arm already enabled in kernel.
update-binfmts: warning: qemu-armeb already enabled in kernel.
update-binfmts: warning: qemu-aarch64 already enabled in kernel.
mount: can't find PARTUUID=c1dc39e5-01
### Warning: Mounting image partitions using /etc/fstab failed.

My conjecture is that parted's fix approach introduced here, may change partition UUIDs resulting in errors in some booting configurations.

# Fix the GPT if necessary and resize the partition afterwards.
# The fix is currently kind of hackish..
echo -e "Fix\n" | parted ---pretend-input-tty "${DEST_IMG}" print
parted -s "${DEST_IMG}" resizepart "${IMG_ROOT}" "100%"

Allow target (TO) to be a block device

When deploying images to actual devices, pimod can come in handy, when a block device is allowed as target. When a block device is specified, the image is flashed onto the block device and instead of a loopback mount the relevant partitions are directly mounted.

Required changes:

  • check if block devices, maybe require manual ACK
  • skip image enlargement in PUMP, adjust partition resizing
  • adjust mounting accordingly

Infer image name from Pifile name

When not configured explicitly (via TO ...) the name of the resulting image can also be referred from the Pifile, e.g. BaumBox.Pifile would result in the image being called BaumBox.img.

PUMP not working?

Hello. I'm trying to get to use pimod, but my first test already failed :)
Here is my Pifile

FROM image/2018-11-13-raspbian-stretch.img

PUMP 1500

RUN bash -c 'echo "${CHROOT_MOUNT}"'

and here is the output I get, is this normal? I tried running as non-sudo user:

ignacio@cat:~/pimod$ ./pimod.sh treehouses.Pifile 
### FROM image/2018-11-13-raspbian-stretch.img
### TO treehouses.img
### PUMP 1500
1500+0 records in
1500+0 records out
1572864000 bytes (1,6 GB, 1,5 GiB) copied, 1,00085 s, 1,6 GB/s
/dev/mapper/control: open failed: Permission denied
Failure to communicate with kernel device-mapper driver.
Incompatible libdevmapper 1.02.145 (2017-11-03) and kernel driver (unknown version).
device mapper prerequisites not met
e2fsck 1.44.4 (18-Aug-2018)
e2fsck: No such file or directory while trying to open /dev/mapper/p2
Possibly non-existent device?
ignacio@cat:~/pimod$ 

then with sudo

ignacio@cat:~/pimod$ sudo ./pimod.sh treehouses.Pifile 
### FROM image/2018-11-13-raspbian-stretch.img
### TO treehouses.img
### PUMP 1500
1500+0 records in
1500+0 records out
1572864000 bytes (1,6 GB, 1,5 GiB) copied, 0,803511 s, 2,0 GB/s
loop16p1 is already in use, and a partition of a different device
loop16p2 is already in use, and a partition of a different device
e2fsck 1.44.4 (18-Aug-2018)
e2fsck: No such file or directory while trying to open /dev/mapper/p2
Possibly non-existent device?
ignacio@cat:~/pimod$

also docker

ignacio@cat:~/pimod$ ./pimod-docker.sh treehouses.Pifile image/2018-11-13-raspbian-stretch.img image/aa.img
### FROM 2018-11-13-raspbian-stretch.img
### TO treehouses.img
### PUMP 1500
1500+0 records in
1500+0 records out
1572864000 bytes (1.6 GB, 1.5 GiB) copied, 4.42665 s, 355 MB/s
e2fsck 1.43.4 (31-Jan-2017)
e2fsck: No such file or directory while trying to open /dev/mapper/add map loop16p1 (253:0): 0 89854 linear 7:16 8192p2
Possibly non-existent device?
ignacio@cat:~/pimod

Just wondering if this is normal or to check if I'm doing something wrong

thank you

Proposal: Add WORKDIR command

With a WORKDIR command the following RUN commands would be executed in in this working directory instead of the default (/).

INSTALL does not copy hidden files

When using INSTALL, hidden files are not copied to the guest.
In my case, I try to build nexmon, which in turn requires the .git folder to built.
See the output below.

### RUN bash -c
    cp -r /btp/nexmon_patch /nexmon/patches/bcm43430a1/7_45_41_46/btp/
    cd /nexmon/patches/bcm43430a1/7_45_41_46/btp/ || exit 1
    source /nexmon/setup_env.sh
    make

fatal: Not a git repository: ../.git/modules/nexmon

Feature request: provide some kind of access to host files

For our appliance we do create custom apt packages that we then install on the raspberrry pi image. Currently we have to copy the files to the root fs (by using the install command), execute apt to install the files and then remove them again. It would be really nice if there was a possibility to bind mount a folder to the chroot environment which then would allow to use the files in the bind mounted folder.

Add manual debug option

Simple Idea: when a script fails, the user gets a bash instead of printing the error and shutting everything down.

This feature is not to be implemented as a Pifile command but as a parameter, e.g., --debug.

Implementation is easy achievable by adding a bash call in the trap function.

heredoc bulk execution not working

Not sure when this bug was introduced, as I last used Pimod on 0.2.2, but in 0.5, bulk execution is not working
e.g.

FROM https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-11-08/2021-10-30-raspios-bullseye-armhf-lite.zip
PUMP 1000M

RUN <<EOF
touch test.txt
echo "Hello World" > test.txt
EOF

EXTRACT test.txt test.txt

results in

### RUN 
### EXTRACT test.txt test.txt
cp: cannot stat '/tmp/tmp.SIUScz53RS/test.txt': No such file or directory
### Error: "test.txt" returned 1, cleaning up...

Find clean way to edit resolv.conf if it was replaced/bind mounted

In my attempt to use pimod to build a customized raspberry pi image fro our appliance, I encountered teh followin issue:

  • To provide our custom debian packages for installation I use a docker container hosting an apt repository and then use docker networking capabilities to access it.
  • As the default resolv.conf file does not allow to properly resolve the hostname by said socker container, I rely on the --host-resolv flag
  • The modifications I make require that I replace openresolv with systemd-resolved. This requires me to change the resolv.conf file to link to /run/systemd/resolve/stub-resolv.conf.

Apparently the step described above is not possible in pimod (as resolv.conf is bind mounted to the hosts).
Unfortunately the current implementation of pimod makes it impossible to detect whether a script runs in pimod envidonment and also makes it impossible to change the original resolv.conf file, as it is moved out to the host.

I'm currently looking for a clean way to execute the described procedure. #55 did allow for context aware modifications and also moved the original resolv.conf file to a well known location accessible by the client (thus allowing above descirbed modifications). On the other hand I totally understand that this is not a clean solution!

Can't create image on WSL2

Running the included example with the latest commit from master gives me the following error during umount.

(base) ani@ani-surface:~/pimod$ sudo ./pimod.sh examples/RPi-RaspberryPiOSLite.Pifile 
### FROM https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip
Using cache: /var/cache/pimod/downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,64 bits,8 CPUs Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz (706E5),ASM,AES-NI)

Scanning the drive for archives:
1 file, 465662909 bytes (445 MiB)

Extracting archive: /var/cache/pimod/downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip
--
Path = /var/cache/pimod/downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip
Type = zip
Physical Size = 465662909

Everything is Ok

Size:       1874853888
Compressed: 465662909
Moving temporary /tmp/tmp.B43wH7cX2S to examples/RPi-RaspberryPiOSLite.img
### PUMP 200M
pump conversion to 1M * 200
pump ceil: 1M * 200
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 0.126136 s, 1.7 GB/s
Checking that no-one is using this disk right now ... OK

Disk examples/RPi-RaspberryPiOSLite.img: 1.96 GiB, 2084569088 bytes, 4071424 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x9730496b

Old situation:

Device                              Boot  Start     End Sectors  Size Id Type
examples/RPi-RaspberryPiOSLite.img1        8192  532479  524288  256M  c W95 FAT32 (LBA)
examples/RPi-RaspberryPiOSLite.img2      532480 3661823 3129344  1.5G 83 Linux

examples/RPi-RaspberryPiOSLite.img2: 
New situation:
Disklabel type: dos
Disk identifier: 0x9730496b

Device                              Boot  Start     End Sectors  Size Id Type
examples/RPi-RaspberryPiOSLite.img1        8192  532479  524288  256M  c W95 FAT32 (LBA)
examples/RPi-RaspberryPiOSLite.img2      532480 4071423 3538944  1.7G 83 Linux

The partition table has been altered.
Syncing disks.
add map loop9p1 (252:14): 0 524288 linear 7:9 8192
add map loop9p2 (252:15): 0 3538944 linear 7:9 532480
rootfs: 44957/97920 files (0.4% non-contiguous), 295831/391168 blocks
resize2fs 1.45.5 (07-Jan-2020)
Resizing the filesystem on /dev/mapper/loop9p2 to 442368 (4k) blocks.
The filesystem on /dev/mapper/loop9p2 is now 442368 (4k) blocks long.

del devmap : loop9p2
del devmap : loop9p1
add map loop9p1 (252:14): 0 524288 linear 7:9 8192
add map loop9p2 (252:15): 0 3538944 linear 7:9 532480
umount: bad usage
Try 'umount --help' for more information.
umount: bad usage
Try 'umount --help' for more information.
umount: bad usage
Try 'umount --help' for more information.
umount: bad usage
Try 'umount --help' for more information.

/etc/resolv.conf: networking not working properly

In our build process we are using apt-cacher in order to capture all apt packages being installed. To do so, we spin up an apt cacher docker container (sameersbn/apt-cacher-ng:latest).

Intrestingly HOST curl http://apt-cacher-ng:3142 works as expected when put into a pifile where RUN curl http://apt-cacher-ng:3142 does not (of course I did make sure that curl ist installed both on the host and on the target).

I found that the issue comes from the fact that /etc/resolv.conf is only replaced if it does not exist. When overwriting it with the hosts information all is well (see PR). I currently don't see a reason for the current replacement strategy.

Pass Docker volumes to pimod-docker.sh

The INSTALL command requires access to the file. However, the current pimod-docker.sh script does not allow to pass extra volumes. An option to pass multiple files to the container should be added.

Feat: A `SHRINK` command

SHRINK [SIZE]

SHRINK decreases the size of the image to the minimum possible.
Optionally, you can specify the amount to decrease (suffixes K, M, G are allowed).

Example:

PUMP 10G # Increase the size of the image by 10G
[...] # Do some stuff
SHRINK # Decrease the size of the image to the minimum possible

remove ENABLE_UART cmd

seems to be very distribution specific (raspbian) and since there is the raspi-config wrapper for this kind of configuration already, this should be removed

When FROM download fails, subsequent commands fail because of using cache

First run for an unsuccessful download, see issue 30

Fetching remote: https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip
--2021-04-26 17:15:03--  https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip%0D
Resolving downloads.raspberrypi.org (downloads.raspberrypi.org)... 46.235.227.39, 176.126.240.84, 93.93.135.117, ...
Connecting to downloads.raspberrypi.org (downloads.raspberrypi.org)|46.235.227.39|:443... connected.
HTTP request sent, awaiting response... 404 Not Found
2021-04-26 17:15:04 ERROR 404: Not Found.

second try uses cache even though the first download did not succeed?

docker run --rm --network=host --privileged -v $PWD:/pimod pimod pimod.sh examples/Rpi-Docker.Pifile
### FROM https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip
Using cache: .cache/downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip
### Error: Unknown MIME inode/x-empty

I'm also seeing that the cache has an entry for

ls -al .cache/downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/
total 0
drwxrwxrwx 1 ani ani 4096 Apr 26 10:20  .
drwxrwxrwx 1 ani ani 4096 Apr 26 10:20  ..
-rwxrwxrwx 1 ani ani    0 Apr 26 10:20 '2021-03-04-raspios-buster-armhf-lite.zip'$'\r'

Not sure how to use this with any official pi image without downloading it first...

script stops unexpectedly: FILE SYSTEM WAS MODIFIED

When trying to run the example it stops with following logs

### FROM http://downloads.openwrt.org/releases/18.06.5/targets/brcm2708/bcm2710/openwrt-18.06.5-brcm2708-bcm2710-rpi-3-ext4-factory.img.gz
Fetching remote: http://downloads.openwrt.org/releases/18.06.5/targets/brcm2708/bcm2710/openwrt-18.06.5-brcm2708-bcm2710-rpi-3-ext4-factory.img.gz
--2021-01-07 00:07:52--  http://downloads.openwrt.org/releases/18.06.5/targets/brcm2708/bcm2710/openwrt-18.06.5-brcm2708-bcm2710-rpi-3-ext4-factory.img.gz
Resolving downloads.openwrt.org (downloads.openwrt.org)... 168.119.138.211, 2a01:4f8:251:321::2
Connecting to downloads.openwrt.org (downloads.openwrt.org)|168.119.138.211|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://downloads.openwrt.org/releases/18.06.5/targets/brcm2708/bcm2710/openwrt-18.06.5-brcm2708-bcm2710-rpi-3-ext4-factory.img.gz [following]
--2021-01-07 00:07:53--  https://downloads.openwrt.org/releases/18.06.5/targets/brcm2708/bcm2710/openwrt-18.06.5-brcm2708-bcm2710-rpi-3-ext4-factory.img.gz
Connecting to downloads.openwrt.org (downloads.openwrt.org)|168.119.138.211|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 9268927 (8.8M) [application/octet-stream]
Saving to: '.cache/downloads.openwrt.org/releases/18.06.5/targets/brcm2708/bcm2710/openwrt-18.06.5-brcm2708-bcm2710-rpi-3-ext4-factory.img.gz'

     0K ........                           100%  842K=11s

2021-01-07 00:08:04 (842 KB/s) - '.cache/downloads.openwrt.org/releases/18.06.5/targets/brcm2708/bcm2710/openwrt-18.06.5-brcm2708-bcm2710-rpi-3-ext4-factory.img.gz' saved [9268927/9268927]

Moving temporary /tmp/tmp.yerr1r1Ppy to examples/RPi-OpenWRT.img
### PUMP 10M
1+0 records in
1+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00650014 s, 1.6 GB/s

Welcome to fdisk (util-linux 2.36.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): Partition number (1,2, default 2): 
Partition 2 has been deleted.

Command (m for help): Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): Partition number (2-4, default 2): First sector (2048-602111, default 2048): Last sector, +/-sectors or +/-size{K,M,G,T,P} (57344-602111, default 602111): Partition #2 contains a ext4 signature.

Created a new partition 2 of type 'Linux' and of size 266 MiB.

Command (m for help): 
The partition table has been altered.
Syncing disks.

add map loop0p1 (253:3): 0 40960 linear 7:0 8192
add map loop0p2 (253:4): 0 544768 linear 7:0 57344
e2fsck 1.45.6 (20-Mar-2020)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Padding at end of inode bitmap is not set. Fix? yes


/dev/mapper/loop0p2: ***** FILE SYSTEM WAS MODIFIED *****
/dev/mapper/loop0p2: 1264/16384 files (0.0% non-contiguous), 4278/65536 blocks

cgroup problem when running docker

After installing docker and running dockerd, the following error happens

### RUN sudo dockerd
INFO[2021-11-01T19:58:45.282788937Z] Starting up                                  
INFO[2021-11-01T19:58:45.307226380Z] libcontainerd: started new containerd process  pid=12259
INFO[2021-11-01T19:58:45.307411211Z] parsed scheme: "unix"                         module=grpc
INFO[2021-11-01T19:58:45.307458044Z] scheme "unix" not registered, fallback to default scheme  module=grpc
INFO[2021-11-01T19:58:45.307559820Z] ccResolverWrapper: sending update to cc: {[{unix:///var/run/docker/containerd/containerd.sock  <nil> 0 <nil>}] <nil> <nil>}  module=grpc
INFO[2021-11-01T19:58:45.307622523Z] ClientConn switching balancer to "pick_first"  module=grpc
INFO[2021-11-01T19:58:46.043406825Z] starting containerd                           revision=e25210fe30a0a703442421b0f60afac609f950a3 version=1.4.9
INFO[2021-11-01T19:58:46.165887464Z] loading plugin "io.containerd.content.v1.content"...  type=io.containerd.content.v1
INFO[2021-11-01T19:58:46.166480085Z] loading plugin "io.containerd.snapshotter.v1.aufs"...  type=io.containerd.snapshotter.v1
INFO[2021-11-01T19:58:46.224271936Z] skip loading plugin "io.containerd.snapshotter.v1.aufs"...  error="aufs is not supported (modprobe aufs failed: exit status 1 \"modprobe: FATAL: Module aufs not found in directory /lib/modules/4.19.127-navigator-v7l+\\n\"): skip plugin" type=io.containerd.snapshotter.v1
INFO[2021-11-01T19:58:46.224460785Z] loading plugin "io.containerd.snapshotter.v1.btrfs"...  type=io.containerd.snapshotter.v1
INFO[2021-11-01T19:58:46.225143997Z] skip loading plugin "io.containerd.snapshotter.v1.btrfs"...  error="path /var/lib/docker/containerd/daemon/io.containerd.snapshotter.v1.btrfs (ext4) must be a btrfs filesystem to be used with the btrfs snapshotter: skip plugin" type=io.containerd.snapshotter.v1
INFO[2021-11-01T19:58:46.225255033Z] loading plugin "io.containerd.snapshotter.v1.devmapper"...  type=io.containerd.snapshotter.v1
WARN[2021-11-01T19:58:46.225348865Z] failed to load plugin io.containerd.snapshotter.v1.devmapper  error="devmapper not configured"
INFO[2021-11-01T19:58:46.225430012Z] loading plugin "io.containerd.snapshotter.v1.native"...  type=io.containerd.snapshotter.v1
INFO[2021-11-01T19:58:46.225739026Z] loading plugin "io.containerd.snapshotter.v1.overlayfs"...  type=io.containerd.snapshotter.v1
INFO[2021-11-01T19:58:46.226527459Z] loading plugin "io.containerd.snapshotter.v1.zfs"...  type=io.containerd.snapshotter.v1
INFO[2021-11-01T19:58:46.226969693Z] skip loading plugin "io.containerd.snapshotter.v1.zfs"...  error="path /var/lib/docker/containerd/daemon/io.containerd.snapshotter.v1.zfs must be a zfs filesystem to be used with the zfs snapshotter: skip plugin" type=io.containerd.snapshotter.v1
INFO[2021-11-01T19:58:46.227066821Z] loading plugin "io.containerd.metadata.v1.bolt"...  type=io.containerd.metadata.v1
WARN[2021-11-01T19:58:46.227271467Z] could not use snapshotter devmapper in metadata plugin  error="devmapper not configured"
INFO[2021-11-01T19:58:46.227349077Z] metadata content store policy set             policy=shared
INFO[2021-11-01T19:58:46.270543008Z] loading plugin "io.containerd.differ.v1.walking"...  type=io.containerd.differ.v1
INFO[2021-11-01T19:58:46.270696562Z] loading plugin "io.containerd.gc.v1.scheduler"...  type=io.containerd.gc.v1
INFO[2021-11-01T19:58:46.270854930Z] loading plugin "io.containerd.service.v1.introspection-service"...  type=io.containerd.service.v1
INFO[2021-11-01T19:58:46.271050705Z] loading plugin "io.containerd.service.v1.containers-service"...  type=io.containerd.service.v1
INFO[2021-11-01T19:58:46.271139370Z] loading plugin "io.containerd.service.v1.content-service"...  type=io.containerd.service.v1
INFO[2021-11-01T19:58:46.271250276Z] loading plugin "io.containerd.service.v1.diff-service"...  type=io.containerd.service.v1
INFO[2021-11-01T19:58:46.271334349Z] loading plugin "io.containerd.service.v1.images-service"...  type=io.containerd.service.v1
INFO[2021-11-01T19:58:46.271411737Z] loading plugin "io.containerd.service.v1.leases-service"...  type=io.containerd.service.v1
INFO[2021-11-01T19:58:46.271505569Z] loading plugin "io.containerd.service.v1.namespaces-service"...  type=io.containerd.service.v1
INFO[2021-11-01T19:58:46.271588067Z] loading plugin "io.containerd.service.v1.snapshots-service"...  type=io.containerd.service.v1
INFO[2021-11-01T19:58:46.271661918Z] loading plugin "io.containerd.runtime.v1.linux"...  type=io.containerd.runtime.v1
INFO[2021-11-01T19:58:46.272246039Z] loading plugin "io.containerd.runtime.v2.task"...  type=io.containerd.runtime.v2
INFO[2021-11-01T19:58:46.272667681Z] loading plugin "io.containerd.monitor.v1.cgroups"...  type=io.containerd.monitor.v1
INFO[2021-11-01T19:58:46.273782332Z] loading plugin "io.containerd.service.v1.tasks-service"...  type=io.containerd.service.v1
INFO[2021-11-01T19:58:46.273904849Z] loading plugin "io.containerd.internal.v1.restart"...  type=io.containerd.internal.v1
INFO[2021-11-01T19:58:46.274082791Z] loading plugin "io.containerd.grpc.v1.containers"...  type=io.containerd.grpc.v1
INFO[2021-11-01T19:58:46.274168771Z] loading plugin "io.containerd.grpc.v1.content"...  type=io.containerd.grpc.v1
INFO[2021-11-01T19:58:46.274246029Z] loading plugin "io.containerd.grpc.v1.diff"...  type=io.containerd.grpc.v1
INFO[2021-11-01T19:58:46.274321380Z] loading plugin "io.containerd.grpc.v1.events"...  type=io.containerd.grpc.v1
INFO[2021-11-01T19:58:46.274397971Z] loading plugin "io.containerd.grpc.v1.healthcheck"...  type=io.containerd.grpc.v1
INFO[2021-11-01T19:58:46.274476970Z] loading plugin "io.containerd.grpc.v1.images"...  type=io.containerd.grpc.v1
INFO[2021-11-01T19:58:46.274553228Z] loading plugin "io.containerd.grpc.v1.leases"...  type=io.containerd.grpc.v1
INFO[2021-11-01T19:58:46.274607487Z] loading plugin "io.containerd.grpc.v1.namespaces"...  type=io.containerd.grpc.v1
INFO[2021-11-01T19:58:46.274660375Z] loading plugin "io.containerd.internal.v1.opt"...  type=io.containerd.internal.v1
INFO[2021-11-01T19:58:46.275082795Z] loading plugin "io.containerd.grpc.v1.snapshots"...  type=io.containerd.grpc.v1
INFO[2021-11-01T19:58:46.275197460Z] loading plugin "io.containerd.grpc.v1.tasks"...  type=io.containerd.grpc.v1
INFO[2021-11-01T19:58:46.275258237Z] loading plugin "io.containerd.grpc.v1.version"...  type=io.containerd.grpc.v1
INFO[2021-11-01T19:58:46.275317440Z] loading plugin "io.containerd.grpc.v1.introspection"...  type=io.containerd.grpc.v1
INFO[2021-11-01T19:58:46.275951967Z] serving...                                    address=/var/run/docker/containerd/containerd-debug.sock
INFO[2021-11-01T19:58:46.276146965Z] serving...                                    address=/var/run/docker/containerd/containerd.sock.ttrpc
INFO[2021-11-01T19:58:46.276317592Z] serving...                                    address=/var/run/docker/containerd/containerd.sock
INFO[2021-11-01T19:58:46.276454868Z] containerd successfully booted in 0.236700s  
INFO[2021-11-01T19:58:46.297846577Z] parsed scheme: "unix"                         module=grpc
INFO[2021-11-01T19:58:46.297912947Z] scheme "unix" not registered, fallback to default scheme  module=grpc
INFO[2021-11-01T19:58:46.297981705Z] ccResolverWrapper: sending update to cc: {[{unix:///var/run/docker/containerd/containerd.sock  <nil> 0 <nil>}] <nil> <nil>}  module=grpc
INFO[2021-11-01T19:58:46.298023315Z] ClientConn switching balancer to "pick_first"  module=grpc
INFO[2021-11-01T19:58:46.300877293Z] parsed scheme: "unix"                         module=grpc
INFO[2021-11-01T19:58:46.300939162Z] scheme "unix" not registered, fallback to default scheme  module=grpc
INFO[2021-11-01T19:58:46.300999384Z] ccResolverWrapper: sending update to cc: {[{unix:///var/run/docker/containerd/containerd.sock  <nil> 0 <nil>}] <nil> <nil>}  module=grpc
INFO[2021-11-01T19:58:46.301035346Z] ClientConn switching balancer to "pick_first"  module=grpc
INFO[2021-11-01T19:58:46.468130545Z] [graphdriver] using prior storage driver: overlay2 
WARN[2021-11-01T19:58:46.579388772Z] Your kernel does not support cgroup memory limit 
WARN[2021-11-01T19:58:46.579462845Z] Unable to find cpu cgroup in mounts          
WARN[2021-11-01T19:58:46.579807969Z] Unable to find blkio cgroup in mounts        
WARN[2021-11-01T19:58:46.580029522Z] Unable to find cpuset cgroup in mounts       
WARN[2021-11-01T19:58:46.580156038Z] Unable to find pids cgroup in mounts         
INFO[2021-11-01T19:58:46.581864643Z] stopping healthcheck following graceful shutdown  module=libcontainerd
INFO[2021-11-01T19:58:46.582015974Z] stopping event stream following graceful shutdown  error="context canceled" module=libcontainerd namespace=plugins.moby
failed to start daemon: Devices cgroup isn't mounted

Permissive license

This project seems like a great idea, with tons of potential for not just humanitarian purposes but a lot more to enable people to use commodity hardware. See my pi-bootstrap repo for something similar, but based on pi-gen. I allow injection of secrets for ready-to-connect images as well as complete modification/re-arranging the steps for even a base image via an externally sourced config, among other things.

However, the GPL v3 license on this repo. makes it impossible to use in a commercial setting or derive freely without going GPL myself. Would you consider licensing it under something more permissive, say the MIT license? I believe this would be of benefit to the maker community at large.

Provide an option for Pifile inheritance

As an addition to the FROM definition I suggest to introduce an PARENT statement.

When a Pifile stars with an PARENT statement, pimod first creates the image defined in the parent Pifile and afterwards continues executing the Pifile.

Unable to unmount when based on broken image

Hi there,

this might be a somewhat very special issue, but something that I encountered working with once or twice.

When you start pimod with a FROM statement and stop it with CTRL-C, pimod will stop gracefully.
The subsequent passes, however, will be stuck:

Working inplace BTree.img.
add map loop1p1 (253:2): 0 87851 linear 7:1 8192
device-mapper: reload ioctl on loop1p2 (253:3) failed: Invalid argument
create/reload failed on loop1p2

This error seems legit, as the FROM statement was interruppted in the first run resulting in a damages image.
But then the following happens:

./modules/chroot.sh: line 32: CHROOT_MOUNT: unbound variable
umount: bad usage
Try 'umount --help' for more information.
umount: bad usage
Try 'umount --help' for more information.
umount: bad usage
Try 'umount --help' for more information.
umount: bad usage
Try 'umount --help' for more information.
umount: bad usage
Try 'umount --help' for more information.
umount: bad usage
Try 'umount --help' for more information.
umount: bad usage
Try 'umount --help' for more information.
umount: bad usage
Try 'umount --help' for more information.
umount: bad usage
Try 'umount --help' for more information.
umount: bad usage
Try 'umount --help' for more information.
./modules/chroot.sh: line 42: CHROOT_MOUNT: unbound variable
### Error: "BTree.img" returned 1, cleaning up...

This should be handled gracefully I guess.

PUMP does not work as expected

I want my image to be at least 10 GB in size, so I use PUMP 10G. However, the resulting image is only 3.7 GB in size. The problem is, that you are using dd to increase the image, where you are setting the parameter bs=${1}. But the bs parameter is limited in size, e.g., 2 GB.

### PUMP 10G
0+1 records in
0+1 records out
2147479552 bytes (2.1 GB, 2.0 GiB) copied, 30.6786 s, 70.0 MB/s
Model:  (file)
Disk /root/Base.img: 3951MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      4194kB  49.2MB  45.0MB  primary  fat32        lba
 2      50.3MB  1804MB  1753MB  primary  ext4

add map loop9p1 (253:18): 0 87851 linear 7:9 8192
add map loop9p2 (253:19): 0 7618552 linear 7:9 98304
rootfs: 39794/107072 files (0.1% non-contiguous), 239385/428032 blocks
resize2fs 1.46.2 (28-Feb-2021)
Resizing the filesystem on /dev/mapper/loop9p2 to 952319 (4k) blocks.
The filesystem on /dev/mapper/loop9p2 is now 952319 (4k) blocks long.

del devmap : loop9p2
del devmap : loop9p1
add map loop9p1 (253:18): 0 87851 linear 7:9 8192
add map loop9p2 (253:19): 0 7618552 linear 7:9 98304
update-binfmts: warning: qemu-arm already enabled in kernel.
update-binfmts: warning: qemu-armeb already enabled in kernel.
update-binfmts: warning: qemu-aarch64 already enabled in kernel.

Derive PATH from the guest OS

Currently, the PATH variable is just copied from the source OS. This works when modifying Debian-based OSss on Debian but fails, when targeting some other OSes.

We should generalize this and maybe provide an option which file to source.

Cache for remote FROM targets

Since #15, the FROM command can use a (remote) URL as an image source. However, this does not include any caching, which is desirable for larger images. Consequently, caching should be implemented.

A possible problem is that the remote image for a URL has changed. At least for HTTP/S the Last-Modified field could be considered.

How can we modify pimod to work with Jetson SD card images?

Pimod is awesome and could be even more useful if we could use it work with Jetson Nano/Xavier images.

See an example of a custom-built Jetson image here: https://github.com/aniongithub/jetson-nano-image/releases

While this currently uses Ansible, I thought it would be cool if we could use Pimod to build on top of the custom minimal image generated. Sort of like how Pimod is meant to customize a raspbian-lite image.

Any pointers are appreciated!

Running pimod with such an image currently gives the following error

mount: /tmp/tmp.qsBH33hJgz: wrong fs type, bad option, bad superblock on /dev/mapper/loop40p2, missing codepage or helper program, or other error.
### Error: "test.img" returned 32, cleaning up...
umount: bad usage

Implement option to support different platforms (profiles)

The idea is to abstract pimod as a modification tool for Raspberry Pi to a generic system image modification tool.

A profile would hold information on the platform and on the image to modify, such as:

  • the required qemu binary
  • information on the system image partition layout
  • ...

Multiline RUN command not working on 0.4.0

In Pimod version 0.2.2, I used to use the following code:

RUN bash -c "
  cd somewhere
  do something here
  more commands here
"

But with Pimod 0.4.0, which was uploaded a few days ago, this fails with the following error:

### RUN bash -c
  cd somewhere
  do something here
  more commands here

/bin/bash: $n: command not found
### Error: "bash" returned 127, cleaning up...

INPLACE with URL fails

The image is downloaded correctly, but when setting the DEST_IMG the URL is used and the the build fails, because this is not a valid file path:

### INPLACE http://downloads.openwrt.org/releases/18.06.4/targets/brcm2708/bcm2710/openwrt-18.06.4-brcm2708-bcm2710-rpi-3-ext4-factory.img.gz
losetup: http://downloads.openwrt.org/releases/18.06.4/targets/brcm2708/bcm2710/openwrt-18.06.4-brcm2708-bcm2710-rpi-3-ext4-factory.img.gz: failed to set up loop device: No such file or directory
/pimod/modules/qemu.sh: line 25: QEMU_GUEST: unbound variable
failed to stat() ### Error: "http://downloads.openwrt.org/releases/18.06.4/targets/brcm2708/bcm2710/openwrt-18.06.4-brcm2708-bcm2710-rpi-3-ext4-factory.img.gz" returned 1, cleaning up...
/pimod/modules/qemu.sh: line 25: QEMU_GUEST: unbound variable
### Error: "http://downloads.openwrt.org/releases/18.06.4/targets/brcm2708/bcm2710/openwrt-18.06.4-brcm2708-bcm2710-rpi-3-ext4-factory.img.gz" returned 1, cleaning up...
/pimod/modules/qemu.sh: line 25: QEMU_GUEST: unbound variable

Suggestions:

  • disable use of INPLACE and an URL
  • download the file locally and work on the local copy (semantic-wise not really inplace)

Allow stdin redirection (somehow?)

I tried to set a password in the chroot using RUN bash -c '(echo natur; echo natur) | passwd pi', which failed due to the pipe I used.

There could be a method (some fancy combination of escapes) to have the whole line executed inside the chroot, not only the first part. Please find out and document.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.