https://github.com/bkahlert/kustomize

Kotlin-based customizer for IoT images like Raspberry Pi OS

https://github.com/bkahlert/kustomize

Science Score: 26.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (8.6%) to scientific vocabulary
Last synced: 11 months ago · JSON representation

Repository

Kotlin-based customizer for IoT images like Raspberry Pi OS

Basic Info
  • Host: GitHub
  • Owner: bkahlert
  • License: mit
  • Language: Kotlin
  • Default Branch: master
  • Size: 16 MB
Statistics
  • Stars: 2
  • Watchers: 2
  • Forks: 0
  • Open Issues: 10
  • Releases: 0
Created about 5 years ago · Last pushed over 3 years ago
Metadata Files
Readme Funding License Codeowners

README.md

Kaomoji customizing image

Kustomize Build Status Repository Size Repository Size

Kotlin-based customizer for IoT images like Raspberry Pi OS
Kustomize applies a HOCON based customization file to a Raspberry Pi compatible image.
All that needs to be done is flash the image to a memory card and boot the fully-customized image on the target device.

Kustomize applying sample.conf to an image

In short: sample.conf + kustomize = sample.img

```hocon os = Raspberry Pi OS Lite timezone = Europe/Berlin

hostname { name: "sample" random-suffix: true }

ethernet over USB with device IP 10.10.10.1

usb.gadget.dhcp-range: 10.10.10.0/29

Bluetooth Private Area Network with device IP 10.10.11.1

bluetooth.pan.dhcp-range: 10.10.11.0/29

automatic WiFi connection

wifi.wpa-supplicant: """ ctrlinterface=DIR=/var/run/wpasupplicant GROUP=netdev update_config=1 country=DE

network={ ssid="My WiFi name" psk="My WiFi password" } """

run scripts

setup = [ { name: setup things scripts: [ { name: Greet content: "echo '👏 🤓 👋'" }, ] }, ] ```

+

```shell kustomize --config-file sample.conf

OR

docker run --rm -it \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /tmp/kommons:/tmp/kommons \ -v "$(pwd)":"$(pwd)" \ -w "$(pwd)" \ bkahlert/kustomize \ --config-file sample.conf ```

=

```log ░░░░░░░ KUSTOMIZE

▶ Configuring · Configuration: file:///home/john/sample/sample.conf (256 B) · Name: .test · OS: Raspberry Pi OS Lite · Env: file:///home/john/sample/.env · Cache: file:///home/sample/john ✔︎ ▶ Preparing · Listing images ✔︎ · Pulling lukechilds/dockerpi:vm image ✔︎ · ▶ Deleting old working directories ✔︎ · ▶ Retrieving image · · ▶ Downloading https://downloads.raspberrypi.org/raspioslitearmhflatest ✔︎ · · ▶ Moving download to file:///home/john/sample/download/raspioslitearmhflatest ✔︎ · · ▶ Unarchiving file:///home/john/sample … und image 2021-05-07-raspios-buster-armhf-lite.img ✔︎ · · ▶ Moving download to file:///home/john/sample/raw/2021-05-07-raspios-buster-armhf-lite.img ✔︎ · ✔︎ ✔︎ ▶ Applying 2 patches to Raspberry Pi OS Lite / 2021-05-07-raspios-buster-armhf-lite.img · ╭──╴Set Hostname to sample · │ Set Time Zone to Central European Standard Time · │ Change Username pi to john.doe · │ · │ ◼ disk · │ ▶ virt-customize (17) · │ · ▶ 17 virt-customize operations 🐳 bkahlert/libguestfs: file:///tmp/kommons/exec/WPG.sh · │ · · [ 0.0] Examining the guest ... · │ · · [ 31.8] Setting a random seed · │ · · [ 32.2] Setting the machine ID in /etc/machine-id · │ · · [ 32.2] Setting the hostname: sample--aTy0 · │ · · [ 43.5] Setting the timezone: Europe/Berlin · │ · · [ 43.6] Appending line to /etc/sudoers.d/privacy · │ · · [ 43.7] Appending line to /etc/sudoers · │ · · [ 43.7] Making directory: /usr/lib/virt-sysprep/scripts · │ · · [ 43.7] Copying: usr/lib/virt-sysp … st-boot-order-fix to /usr/lib/virt-sysprep/scripts · │ · · [ 43.8] Changing permissions of /u … ysprep/scripts/0000---first-boot-order-fix to 0755 · │ · · [ 43.8] Making directory: /etc/systemd/system · │ · · [ 43.8] Copying: etc/systemd/system/firstboot-wait.service to /etc/systemd/system · │ · · [ 43.9] Making directory: /etc/systemd/system/multi-user.target.wants · │ · · [ 43.9] Linking: /etc/systemd/syst … vice -> /etc/systemd/system/firstboot-wait.service · │ · · [ 44.0] Making directory: /etc/systemd/scripts · │ · · [ 44.0] Copying: etc/systemd/scripts/firstboot-wait.sh to /etc/systemd/scripts · │ · · [ 44.1] Changing permissions of /etc/systemd/scripts/firstboot-wait.sh to 0755 · │ · · [ 44.1] Installing firstboot command: usermod -l john.doe pi · │ · · [ 44.6] Installing firstboot command: groupmod -n john.doe pi · │ · · [ 45.0] Installing firstboot command: usermod -d /home/john.doe -m john.doe · │ · · [ 45.9] Finishing off · │ · ✔︎ · │ ✔︎ · │ ◼ guestfish · │ ◼ File Operations · │ ▶ boot · │ · ▶ Running Raspberry Pi OS Lite / 202 … -raspios-buster-armhf-lite.img with · │ · · image: /sdcard/filesystem.img · ┊ · · · │ · · firstboot.sh[385]: === Running /usr … -john-doe-pi === ◀◀ login · │ · · firstboot.sh[385]: === Running /usr … n-john-doe-pi === ◀◀ login · │ · · firstboot.sh[385]: === Running /usr … --home-john-doe--m-john-doe === ◀◀ login · │ · · firstboot-wait.sh[387]: CHECKING SCRIPTS ⮕ SCRIPTS-DONE … COMPLETED ◀◀ login · │ · · [ OK ] Started libguestfs firstboot service completion. ◀◀ login · │ · · [ OK ] Started Serial Getty on ttyAMA0. ◀◀ login · │ · · [ OK ] Reached target Login Prompts. ◀◀ login · │ · · ◀◀ login · │ · · ◀◀ login · │ · · Raspbian GNU/Linux 10 sample--aTy0 ttyAMA0 ◀◀ login · │ · · ◀◀ login · │ · · sample--aTy0 login: ◀◀ login · │ · ·
· │ · · ̣ ˱ ❨ ( Entering "john.doe" )
· │ · · {≧∀≦}
· │ · ·
· │ · · sample--aTy0 login: john.doe ◀◀ login · │ · · ◀◀ login · │ · · Password: ◀◀ login · │ · ·
· │ · · ̣ ˱ ❨ ( Entering "raspberry" )
· │ · · ( ´ー`)
· │ · ·
· │ · · Password: ◀◀ login · │ · · Linux sample--aTy0 4.19.50+ #1 Tue Nov 26 01:49:16 CET 2019 armv6l ◀◀ login · │ · · ◀◀ login · │ · · The programs included with the Debian GNU/Linux system are free software; ◀◀ login · │ · · the exact distribution terms for each program are described in the ◀◀ login · │ · · individual files in /usr/share/doc/
/copyright. ◀◀ login · │ · · ◀◀ login · │ · · Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent ◀◀ login · │ · · permitted by applicable law. ◀◀ login · │ · · [ OK ] Created slice User Slice of UID 1000. ◀◀ login · │ · · Starting User Runtime Directory /run/user/1000... ◀◀ login · │ · · [ OK ] Started User Runtime Directory /run/user/1000. ◀◀ login · │ · · Starting User Manager for UID 1000... ◀◀ login · │ · · [ OK ] Started User Manager for UID 1000. ◀◀ login · │ · · [ OK ] Started Session c1 of user john.doe. ◀◀ login · │ · · john.doe@sample--aTy0:~$ ◀◀ login · │ · ·
· │ · · ̣ ˱ ❨ ( Logged in successfully )
· │ · · (; ̄︶ ̄)
· │ · ·
· │ · ·
· │ · · ̣ ˱ ❨ ( Entering "ls /home/pi" )
· │ · · (´∀`)b
· │ · ·
· │ · · john.doe@sample--aTy0:~$ ls /home/pi ◀◀ finish · │ · · ls: cannot access '/home/pi': No such file or directory ◀◀ finish · │ · · john.doe@sample--aTy0:~$ ◀◀ finish · │ · ·
· │ · · ̣ ˱ ❨ ( Entering "id pi" )
· │ · · ▼ω▼
· │ · ·
· │ · · john.doe@sample--aTy0:~$ id pi ◀◀ finish · │ · · id: ‘pi’: no such user ◀◀ finish · │ · · john.doe@sample--aTy0:~$ ◀◀ finish · │ · ·
· │ · · ̣ ˱ ❨ ( Entering "id john.doe" )
· │ · · (^_^)v
· │ · ·
· │ · · john.doe@sample--aTy0:~$ id john.doe ◀◀ finish · │ · · uid=1000(john.doe) gid=1000(john.doe) groups … (cdrom),27(sudo),29(audio) ◀◀ finish · │ · · john.doe@sample--aTy0:~$ ◀◀ finish · │ · · Watchdog started. Timing out in 5.00s.
· │ · · Watchdog stopped.
· │ · ·
· │ · · ̣ ˱ ❨ ( Entering "'sudo' 'shutdown' '-h' 'now'" )
· │ · · (^^)b
· │ · ·
· │ · · john.doe@sample--aTy0:~$ 'sudo' 'shutdown' '-h' 'now' ◀◀ shutdown · │ · · [ OK ] Stopped target Timers. ◀◀ shutdown · │ · · [ OK ] Stopped Daily Cleanup of Temporary Directories. ◀◀ shutdown · ┊ · · · │ · · [ OK ] Reached target Power-Off. ◀◀ shutdown · │ · · reboot: System halted ◼ · │ · ✔︎ · │ ✔︎ · │ · ╰──╴✔︎ · ╭──╴Set Password of john.doe · │ · │ ◼ disk · │ ▶ virt-customize (1) · │ · ▶ 1 virt-customize operation 🐳 bkahlert/libguestfs: file:///tmp/kommons/exec/6z1.sh · │ · · [ 0.0] Examining the guest ... · │ · · [ 32.1] Setting a random seed · │ · · [ 32.6] Setting passwords · │ · · [ 43.9] Finishing off · │ · ✔︎ · │ ✔︎ · │ ◼ guestfish · │ ◼ File Operations · │ ◼ boot · │ · ╰──╴✔︎ ✔︎

(/ ̄‿ ̄)/~~☆’․・․・﹕☆ sample.img @ file:///home/john/sample/2021-07-19T23-56-57--OJPy/ ```

The just customized sample.img can now be flashed to a memory card and booted on your Raspberry.

Architecture and Debugging

Kustomize is based on the Kotlin library Kommons, applies offline modifications using a dockerized libguestfs (i.e. virt-customize and guestfish), and runs scripts on the guest using the marvelous dockerpi.

Customization options are modelled as patches that are translated to shell scripts. Throughout the customization process all scripts are logged as file locations that can be opened right in your terminal.

Linked script file

If your terminal supports it, Ctrl ⌃ respectively Cmd ⌘ click on /tmp/kommons/exec/ZXv.sh and check the script's content:

```shell

!/bin/sh

'docker' 'run' \ '--name' 'virt-customize--wppn' \ '--workdir' '/shared' \ '--rm' '--interactive' \ '--mount' 'type=bind,source=/home/john/sample/sample/2021-08-04T01-07-52--V5wH/shared,target=/shared' \ '--mount' 'type=bind,source=/home/john/sample/sample/2021-08-04T01-07-52--V5wH/2021-05-07-raspios-buster-armhf-lite.img,target=/images/disk.img' \ 'bkahlert/libguestfs@sha256:de20843ae800c12a8b498c10ec27e2136b55dee4d62d927dff6b3ae360676d00' \ 'virt-customize' \ '--add' '/images/disk.img' \ '--colors' \ '--mkdir' '/usr/lib/virt-sysprep/scripts' \ '--copy-in' 'usr/lib/virt-sysprep/scripts/0000---first-boot-order-fix:/usr/lib/virt-sysprep/scripts' \ '--chmod' '0755:/usr/lib/virt-sysprep/scripts/0000---first-boot-order-fix' \ '--firstboot' 'Greet340--vsv.sh' \ '--firstboot-command' ''"'"'shutdown'"'"' '"'"'-h'"'"' '"'"'now'"'"' ' ```

Tracing

For more detailed information on the customization, the whole process can be traced to a locally started Jaeger instance at http://localhost:16686 using --jaeger-hostname:

```shell kustomize --config-file sample.conf --jaeger-hostname localhost

OR

docker run --rm -it \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /tmp/kommons:/tmp/kommons \ -v "$(pwd)":"$(pwd)" \ -w "$(pwd)" \ bkahlert/kustomize \ --config-file sample.conf \ --jaeger-hostname host.docker.internal ```

There is no need to start a Jaeger yourself as it's automatically launched for you.

Jaeger UI with traces of customization process

Configuration Options

See sample-full.conf for all existing configuration options.

Build

Binaries

shell ./gradlew build -x test

Docker

```shell git clone https://github.com/bkahlert/kustomize.git cd libguestfs

Build image and output to docker (default)

docker buildx bake

Build multi-platform image

docker buildx bake image-all ```

TODO

  • [ ] Bluetooth PAN support
  • [ ] Webcam support; apt-get install -y git streamer
  • [ ] Evaluate Ansible integration
    • https://github.com/garthvh/ansible-raspi-playbooks/tree/master/tasks
    • https://github.com/garthvh/ansible-raspi-playbooks/blob/master/tasks/tzdata.yml
    • https://github.com/garthvh/ansible-raspi-playbooks/blob/master/tasks/internationalization.yml
    • https://github.com/garthvh/ansible-raspi-playbooks/blob/master/playbooks/new-default.yml

Contributing

Want to contribute? Awesome! The most basic way to show your support is to star the project, or to raise issues. You can also support this project by making a Paypal donation to ensure this journey continues indefinitely!

Thanks again for your support, it is much appreciated! :pray:

License

MIT. See LICENSE for more details.

Owner

  • Name: Björn Kahlert
  • Login: bkahlert
  • Kind: user
  • Location: Berlin, Germany

GitHub Events

Total
Last Year

Committers

Last synced: about 1 year ago

All Time
  • Total Commits: 196
  • Total Committers: 1
  • Avg Commits per committer: 196.0
  • Development Distribution Score (DDS): 0.0
Past Year
  • Commits: 0
  • Committers: 0
  • Avg Commits per committer: 0.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
Björn Kahlert m****l@b****m 196
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 12 months ago

All Time
  • Total issues: 0
  • Total pull requests: 111
  • Average time to close issues: N/A
  • Average time to close pull requests: about 2 months
  • Total issue authors: 0
  • Total pull request authors: 2
  • Average comments per issue: 0
  • Average comments per pull request: 0.8
  • Merged pull requests: 2
  • Bot issues: 0
  • Bot pull requests: 109
Past Year
  • Issues: 0
  • Pull requests: 0
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Issue authors: 0
  • Pull request authors: 0
  • Average comments per issue: 0
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
Pull Request Authors
  • dependabot[bot] (59)
  • bkahlert (1)
Top Labels
Issue Labels
Pull Request Labels
dependencies (59) java (48) github_actions (11)

Dependencies

build.gradle.kts maven
  • com.bkahlert.kommons:kommons 1.11.2 implementation
  • com.bkahlert.kommons:kommons 1.12.0-SNAPSHOT implementation
  • com.github.ajalt.clikt:clikt 3.1.0 implementation
  • io.github.config4k:config4k 0.4.2 implementation
  • io.grpc:grpc-netty 1.40.1 implementation
  • io.opentelemetry:opentelemetry-exporter-jaeger 1.5.0 implementation
  • io.opentelemetry:opentelemetry-exporter-logging 1.5.0 implementation
  • io.opentelemetry:opentelemetry-sdk 1.5.0 implementation
  • io.opentelemetry:opentelemetry-sdk-extension-autoconfigure 1.5.0-alpha implementation
  • io.strikt:strikt-core 0.30.1 implementation
  • io.strikt:strikt-jvm 0.30.1 implementation
  • org.apache.commons:commons-compress 1.21 implementation
  • org.jetbrains.kotlin:kotlin-reflect 1.5.21 implementation
  • org.junit.jupiter:junit-jupiter * testImplementation
  • org.junit.jupiter:junit-jupiter-api * testImplementation
  • org.junit.jupiter:junit-jupiter-params * testImplementation
  • org.junit.platform:junit-platform-commons * testImplementation
  • org.junit.platform:junit-platform-launcher * testImplementation
  • org.junit.platform:junit-platform-console * testRuntimeOnly
.github/workflows/build.yml actions
  • actions/cache v2 composite
  • actions/checkout v2 composite
  • actions/setup-java v2 composite
  • actions/upload-artifact v2 composite
  • docker/bake-action v1 composite
  • docker/login-action v1 composite
  • docker/metadata-action v3 composite
  • docker/setup-buildx-action v1 composite
  • docker/setup-qemu-action v1 composite
  • gradle/wrapper-validation-action e6e38bacfdf1a337459f332974bb2327a31aaf4b composite
.github/workflows/manual.yml actions
  • easimon/maximize-build-space v4 composite
Dockerfile docker
  • gradle jre11 build
  • openjdk 18-slim build