├── files ├── etc │ ├── hostname.template │ ├── local.d │ │ ├── 11-up_eth0.start │ │ └── 10-remount_root.start │ ├── hosts.template │ └── rc.local ├── mender │ ├── device_type │ ├── artifact_info │ ├── fw_env.config │ ├── boot.cmd │ ├── mender.conf.template │ ├── fstab │ └── mender.service ├── firstboot │ ├── 99-finish.sh │ ├── 10-begin.sh │ ├── README.md │ └── 20-expandroot.sh ├── network │ ├── wpa_supplicant.conf │ └── interfaces.j2 ├── desktop │ ├── 06xfce4.desktop │ └── lxdm.conf └── opi │ ├── boot-zero.cmd │ └── boot-pc-plus.cmd ├── test ├── assets │ ├── hosts │ ├── hosts.j2 │ ├── kali-rolling-armhf_pieman.yml │ └── ubuntu-focal-armhf_pieman.yml ├── mocks.sh └── test_essentials.sh ├── devices ├── rpi-3-b │ ├── alpine-3.12-armhf │ ├── ubuntu-bionic-armhf │ ├── raspberrypios-buster-armhf │ ├── meta.yml │ ├── ubuntu-bionic-arm64 │ │ ├── cmdline.txt │ │ ├── meta.yml │ │ ├── pre-kernel-installation │ │ │ └── 10-patch-flash-kernel.sh │ │ ├── fix-kernel-installation-in-chroot.patch │ │ ├── pieman.yml │ │ ├── README.md │ │ └── config.txt │ └── meta_raspberrypios-buster-armhf.yml ├── rpi-3-b-plus │ ├── alpine-3.12-armhf │ ├── ubuntu-bionic-armhf │ ├── meta.yml │ └── ubuntu-focal-armhf │ │ ├── cmdline.txt │ │ ├── meta.yml │ │ ├── pieman.yml │ │ ├── README.md │ │ └── config.txt ├── rpi-2-b │ ├── raspberrypios-buster-armhf │ ├── meta.yml │ ├── alpine-3.12-armhf │ │ ├── cmdline.txt │ │ ├── meta.yml │ │ ├── config.txt │ │ ├── pieman.yml │ │ └── README.md │ ├── ubuntu-xenial-armhf │ │ ├── cmdline.txt │ │ ├── meta.yml │ │ ├── pre-kernel-installation │ │ │ └── 10-patch-flash-kernel.sh │ │ ├── pieman.yml │ │ ├── fix-kernel-installation-in-chroot.patch │ │ ├── README.md │ │ └── config.txt │ └── ubuntu-bionic-armhf │ │ ├── cmdline.txt │ │ ├── meta.yml │ │ ├── pre-kernel-installation │ │ └── 10-patch-flash-kernel.sh │ │ ├── fix-kernel-installation-in-chroot.patch │ │ ├── pieman.yml │ │ ├── config.txt │ │ └── README.md ├── rpi-4-b │ ├── raspberrypios-buster-armhf │ └── meta.yml ├── rpi-zero-w │ ├── raspberrypios-buster-armhf │ └── meta.yml ├── rpi-zero │ ├── raspberrypios-buster-armhf │ └── meta.yml ├── requirements.txt ├── opi-zero │ ├── meta.yml │ ├── kali-rolling-armhf │ │ ├── meta.yml │ │ ├── README.md │ │ └── pieman.yml │ └── debian-buster-armhf │ │ ├── meta.yml │ │ ├── pieman.yml │ │ └── README.md ├── opi-pc-plus │ ├── meta.yml │ ├── kali-rolling-armhf │ │ ├── meta.yml │ │ ├── README.md │ │ └── pieman.yml │ └── debian-buster-armhf │ │ ├── meta.yml │ │ ├── pieman.yml │ │ └── README.md ├── rpi-b │ ├── meta.yml │ └── raspberrypios-buster-armhf │ │ ├── cmdline.txt │ │ ├── meta.yml │ │ ├── pieman.yml │ │ ├── config.txt │ │ └── README.md ├── README.md └── __init__.py ├── keys ├── devuan │ ├── raspberry-pi-archive-signing.key │ └── primary-devuan-signing.key ├── raspberrypios │ ├── raspberry-pi-archive-signing.key │ └── mike-thompson.key └── ubuntu │ └── ubuntu-archive-automatic-signing.key ├── logo ├── 380x400.png └── pieman.svg ├── pieman ├── pieman │ ├── __init__.py │ ├── build_status_codes │ ├── codes.py │ ├── util.py │ ├── attrs.py │ └── preprocessor.py ├── requirements.txt ├── test │ ├── toolset.yml │ └── pieman.yml ├── bin │ ├── check_mutually_exclusive_params.py │ ├── wget.py │ ├── check_redis.py │ ├── check_wpa_passphrase.py │ ├── depend_on.py │ ├── image_attrs.py │ ├── preprocessor.py │ ├── bsc.py │ ├── render.py │ ├── du.py │ └── apk_tools_version.py ├── setup.py └── README.md ├── .gitignore ├── docker ├── Makefile ├── docker-entrypoint.sh ├── README.md ├── rollout_fixes.sh └── Dockerfile ├── bootstrap ├── 99-reduce.sh ├── 40-deskop.sh ├── 13-kernel.sh ├── 30-fixes.sh ├── 20-users.sh ├── 10-rootfs-partition.sh ├── 50-firstboot.sh ├── 11-locale.sh ├── 14-boot-partition.sh ├── 15-networking.sh └── 12-pm.sh ├── depend_on.sh ├── AUTHORS.md ├── mutually_exclusive_params.sh ├── .github ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── linter.yml ├── helpers ├── misc.sh ├── templates.sh ├── image-attribs.sh ├── apk.sh ├── users.sh ├── chroot.sh ├── network.sh ├── uboot.sh ├── toolset.sh ├── others.sh ├── deb.sh ├── pm.sh ├── mender.sh └── bsc.sh ├── docker-pieman.sh └── doc ├── components.md └── bsc_server_and_client.md /files/etc/hostname.template: -------------------------------------------------------------------------------- 1 | {HOSTNAME} 2 | -------------------------------------------------------------------------------- /test/assets/hosts: -------------------------------------------------------------------------------- 1 | 127.0.1.1 pieman 2 | 3 | -------------------------------------------------------------------------------- /files/mender/device_type: -------------------------------------------------------------------------------- 1 | device_type=raspberrypi3 2 | -------------------------------------------------------------------------------- /devices/rpi-3-b/alpine-3.12-armhf: -------------------------------------------------------------------------------- 1 | ../rpi-2-b/alpine-3.12-armhf/ -------------------------------------------------------------------------------- /devices/rpi-3-b-plus/alpine-3.12-armhf: -------------------------------------------------------------------------------- 1 | ../rpi-2-b/alpine-3.12-armhf -------------------------------------------------------------------------------- /devices/rpi-3-b/ubuntu-bionic-armhf: -------------------------------------------------------------------------------- 1 | ../rpi-2-b/ubuntu-bionic-armhf -------------------------------------------------------------------------------- /files/mender/artifact_info: -------------------------------------------------------------------------------- 1 | artifact_name={MENDER_ARTIFACT_NAME} 2 | -------------------------------------------------------------------------------- /devices/rpi-3-b-plus/ubuntu-bionic-armhf: -------------------------------------------------------------------------------- 1 | ../rpi-2-b/ubuntu-bionic-armhf -------------------------------------------------------------------------------- /devices/rpi-2-b/raspberrypios-buster-armhf: -------------------------------------------------------------------------------- 1 | ../rpi-b/raspberrypios-buster-armhf/ -------------------------------------------------------------------------------- /devices/rpi-3-b/raspberrypios-buster-armhf: -------------------------------------------------------------------------------- 1 | ../rpi-b/raspberrypios-buster-armhf/ -------------------------------------------------------------------------------- /devices/rpi-4-b/raspberrypios-buster-armhf: -------------------------------------------------------------------------------- 1 | ../rpi-b/raspberrypios-buster-armhf/ -------------------------------------------------------------------------------- /test/assets/hosts.j2: -------------------------------------------------------------------------------- 1 | 127.0.1.1 {{ 'default' | getenv('HOST_NAME') }} 2 | 3 | -------------------------------------------------------------------------------- /devices/rpi-zero-w/raspberrypios-buster-armhf: -------------------------------------------------------------------------------- 1 | ../rpi-b/raspberrypios-buster-armhf/ -------------------------------------------------------------------------------- /devices/rpi-zero/raspberrypios-buster-armhf: -------------------------------------------------------------------------------- 1 | ../rpi-b/raspberrypios-buster-armhf/ -------------------------------------------------------------------------------- /files/etc/local.d/11-up_eth0.start: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ifconfig eth0 up 4 | 5 | -------------------------------------------------------------------------------- /devices/requirements.txt: -------------------------------------------------------------------------------- 1 | PyYAML==5.4 2 | pypandoc # only for converting README.md 3 | -------------------------------------------------------------------------------- /files/etc/local.d/10-remount_root.start: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mount -o remount,rw / 4 | -------------------------------------------------------------------------------- /files/firstboot/99-finish.sh: -------------------------------------------------------------------------------- 1 | logger -t "rc.firstboot" "First boot actions finished" 2 | -------------------------------------------------------------------------------- /keys/devuan/raspberry-pi-archive-signing.key: -------------------------------------------------------------------------------- 1 | ../raspbian/raspberry-pi-archive-signing.key -------------------------------------------------------------------------------- /logo/380x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tolstoyevsky/pieman/HEAD/logo/380x400.png -------------------------------------------------------------------------------- /pieman/pieman/__init__.py: -------------------------------------------------------------------------------- 1 | """The Pieman tools. """ 2 | 3 | __version__ = '0.19.0' 4 | -------------------------------------------------------------------------------- /devices/opi-zero/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: "Orange Pi" 3 | generation: 4 | model: "Zero" 5 | -------------------------------------------------------------------------------- /devices/opi-pc-plus/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: "Orange Pi" 3 | generation: 4 | model: "PC Plus" 5 | -------------------------------------------------------------------------------- /devices/rpi-zero/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: "Raspberry Pi" 3 | generation: 4 | model: "Zero" 5 | -------------------------------------------------------------------------------- /files/firstboot/10-begin.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | logger -t "rc.firstboot" "Starting first boot actions" 3 | -------------------------------------------------------------------------------- /devices/rpi-2-b/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: "Raspberry Pi" 3 | generation: 2 4 | model: "Model B" 5 | -------------------------------------------------------------------------------- /devices/rpi-3-b/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: "Raspberry Pi" 3 | generation: 3 4 | model: "Model B" 5 | -------------------------------------------------------------------------------- /devices/rpi-4-b/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: "Raspberry Pi" 3 | generation: 4 4 | model: "Model B" 5 | -------------------------------------------------------------------------------- /devices/rpi-b/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: "Raspberry Pi" 3 | generation: 4 | model: "Model B and B+" 5 | -------------------------------------------------------------------------------- /devices/rpi-zero-w/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: "Raspberry Pi" 3 | generation: 4 | model: "Zero W" 5 | -------------------------------------------------------------------------------- /devices/rpi-3-b-plus/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: "Raspberry Pi" 3 | generation: 3 4 | model: "Model B+" 5 | -------------------------------------------------------------------------------- /files/mender/fw_env.config: -------------------------------------------------------------------------------- 1 | /dev/mmcblk0 0x400000 0x4000 2 | /dev/mmcblk0 0x800000 0x4000 3 | -------------------------------------------------------------------------------- /files/network/wpa_supplicant.conf: -------------------------------------------------------------------------------- 1 | ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev 2 | update_config=1 3 | -------------------------------------------------------------------------------- /devices/README.md: -------------------------------------------------------------------------------- 1 | The directory contains a tree-like representation of the devices and operating systems supported by Pieman. 2 | -------------------------------------------------------------------------------- /pieman/requirements.txt: -------------------------------------------------------------------------------- 1 | Jinja2==2.11.3 2 | PyYAML==5.4 3 | pypandoc # only for converting README.md 4 | python-daemon==2.2.* 5 | redis==3.0.* 6 | -------------------------------------------------------------------------------- /devices/rpi-2-b/alpine-3.12-armhf/cmdline.txt: -------------------------------------------------------------------------------- 1 | console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 fsck.repair=yes rw rootwait quiet 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .idea 3 | .PKGINFO 4 | .SIGN.RSA.alpine-* 5 | .vscode 6 | build 7 | debootstrap 8 | dist 9 | pieman.egg-info 10 | toolset 11 | venv 12 | __pycache__ 13 | 14 | -------------------------------------------------------------------------------- /pieman/test/toolset.yml: -------------------------------------------------------------------------------- 1 | toolset: 2 | apk: 3 | armhf: 4 | arch: ${parent_node_name} 5 | version: '3.13' 6 | dst: ${TOOLSET_DIR}/apk/${version}/apk-${parent_node_name}.static 7 | 8 | -------------------------------------------------------------------------------- /test/assets/kali-rolling-armhf_pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Evgeny Golyshev 2 | 3 | kali-rolling-armhf: 4 | codename: kali-rolling 5 | repos: 6 | - http://http.kali.org/kali/ 7 | 8 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-xenial-armhf/cmdline.txt: -------------------------------------------------------------------------------- 1 | dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rw rootwait quiet init=/bin/systemd 2 | -------------------------------------------------------------------------------- /files/etc/hosts.template: -------------------------------------------------------------------------------- 1 | 127.0.0.1 localhost 2 | 127.0.1.1 {HOSTNAME} 3 | 4 | ::1 localhost ip6-localhost ip6-loopback 5 | ff02::1 ip6-allnodes 6 | ff02::2 ip6-allrouters 7 | -------------------------------------------------------------------------------- /devices/opi-zero/kali-rolling-armhf/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: "Kali Rolling" 3 | codename: 4 | version: 5 | port: armhf 6 | bits: 32 7 | packages_url: "https://pkg.kali.org/pkg/" 8 | build_types: 9 | - classic 10 | -------------------------------------------------------------------------------- /devices/opi-pc-plus/kali-rolling-armhf/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: "Kali Rolling" 3 | codename: 4 | version: 5 | port: armhf 6 | bits: 32 7 | packages_url: "https://pkg.kali.org/pkg/" 8 | build_types: 9 | - classic 10 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-bionic-armhf/cmdline.txt: -------------------------------------------------------------------------------- 1 | net.ifnames=0 biosdevname=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rw rootwait quiet init=/bin/systemd 2 | -------------------------------------------------------------------------------- /devices/rpi-3-b/ubuntu-bionic-arm64/cmdline.txt: -------------------------------------------------------------------------------- 1 | net.ifnames=0 biosdevname=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rw rootwait quiet init=/bin/systemd 2 | -------------------------------------------------------------------------------- /test/assets/ubuntu-focal-armhf_pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Evgeny Golyshev 2 | 3 | ubuntu-focal-armhf: 4 | repos: 5 | - http://ports.ubuntu.com/ubuntu-ports/ 6 | kernel: 7 | package: linux-image-raspi2 8 | 9 | -------------------------------------------------------------------------------- /devices/rpi-3-b-plus/ubuntu-focal-armhf/cmdline.txt: -------------------------------------------------------------------------------- 1 | net.ifnames=0 biosdevname=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rw rootwait quiet init=/bin/systemd 2 | -------------------------------------------------------------------------------- /devices/rpi-b/raspberrypios-buster-armhf/cmdline.txt: -------------------------------------------------------------------------------- 1 | net.ifnames=0 biosdevname=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rw rootwait quiet init=/bin/systemd 2 | -------------------------------------------------------------------------------- /docker/Makefile: -------------------------------------------------------------------------------- 1 | default: docker_build 2 | 3 | docker_build: 4 | @docker build \ 5 | --build-arg VCS_REF=`git rev-parse --short HEAD` \ 6 | --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \ 7 | -t cusdeb/pieman . 8 | 9 | -------------------------------------------------------------------------------- /devices/opi-zero/debian-buster-armhf/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: Debian 3 | codename: Buster 4 | version: 10 5 | port: armhf 6 | bits: 32 7 | packages_url: "https://packages.debian.org/buster/" 8 | build_types: 9 | - classic 10 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-bionic-armhf/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: Ubuntu 3 | codename: Bionic 4 | version: 18.04 5 | port: armhf 6 | bits: 32 7 | packages_url: "https://packages.ubuntu.com/bionic/" 8 | build_types: 9 | - classic 10 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-xenial-armhf/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: Ubuntu 3 | codename: Xenial 4 | version: 16.04 5 | port: armhf 6 | bits: 32 7 | packages_url: "https://packages.ubuntu.com/xenial/" 8 | build_types: 9 | - classic 10 | -------------------------------------------------------------------------------- /devices/rpi-3-b/ubuntu-bionic-arm64/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: Ubuntu 3 | codename: Bionic 4 | version: 18.04 5 | port: arm64 6 | bits: 64 7 | packages_url: "https://packages.ubuntu.com/bionic/" 8 | build_types: 9 | - classic 10 | -------------------------------------------------------------------------------- /devices/opi-pc-plus/debian-buster-armhf/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: Debian 3 | codename: Buster 4 | version: 10 5 | port: armhf 6 | bits: 32 7 | packages_url: "https://packages.debian.org/buster/" 8 | build_types: 9 | - classic 10 | -------------------------------------------------------------------------------- /devices/rpi-3-b-plus/ubuntu-focal-armhf/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: Ubuntu 3 | codename: Focal 4 | version: 20.04 5 | port: armhf 6 | bits: 32 7 | packages_url: "https://packages.ubuntu.com/focal/" 8 | build_types: 9 | - classic 10 | -------------------------------------------------------------------------------- /devices/rpi-2-b/alpine-3.12-armhf/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: Alpine 3 | codename: 4 | version: 3.12 5 | port: armhf 6 | bits: 32 7 | packages_url: "https://pkgs.alpinelinux.org/package/v3.12/main/armhf/" 8 | build_types: 9 | - classic 10 | -------------------------------------------------------------------------------- /files/mender/boot.cmd: -------------------------------------------------------------------------------- 1 | fdt addr ${fdt_addr} && fdt get value bootargs /chosen bootargs 2 | run mender_setup 3 | mmc dev ${mender_uboot_dev} 4 | load ${mender_uboot_root} ${kernel_addr_r} /boot/zImage 5 | bootz ${kernel_addr_r} - ${fdt_addr} 6 | run mender_try_to_recover 7 | -------------------------------------------------------------------------------- /files/desktop/06xfce4.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Encoding=UTF-8 3 | Name=Xfce4 4 | Comment=Use this session to run Xfce4 as your desktop environment 5 | TryExec=/usr/bin/startxfce4 6 | Exec=/usr/bin/startxfce4 7 | Icon=/usr/local/share/pixmaps/xfce4_xicon1.png 8 | Type=Application 9 | -------------------------------------------------------------------------------- /devices/rpi-b/raspberrypios-buster-armhf/meta.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: Raspberry Pi OS 3 | former_name: Raspbian 4 | codename: Buster 5 | version: 10 6 | port: armhf 7 | bits: 32 8 | packages_url: "https://packages.debian.org/buster/" 9 | build_types: 10 | - classic 11 | -------------------------------------------------------------------------------- /devices/rpi-3-b/meta_raspberrypios-buster-armhf.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: Raspberry Pi OS 3 | former_name: Raspbian 4 | codename: Buster 5 | version: 10 6 | port: armhf 7 | bits: 32 8 | packages_url: "https://packages.debian.org/buster/" 9 | build_types: 10 | - classic 11 | - mender 12 | - artifact 13 | -------------------------------------------------------------------------------- /files/etc/rc.local: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # rc.local 4 | # 5 | # This script is executed at the end of each multiuser runlevel. 6 | # Make sure that the script will "exit 0" on success or any other 7 | # value on error. 8 | # 9 | # In order to enable or disable this script just change the execution 10 | # bits. 11 | # 12 | # By default this script does nothing. 13 | 14 | exit 0 15 | -------------------------------------------------------------------------------- /docker/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | cd /root/pieman && ./pieman.sh 6 | 7 | # Cannot build images in a volume because it causes the following problem on 8 | # some platforms: 9 | # E: Cannot install into target '/build//chroot' mounted with 10 | # noexec or nodev 11 | mv $(ls /root/pieman/build/*{.img,.mender}{.bz2,.gz,.xz,} 2> /dev/null) /result 12 | -------------------------------------------------------------------------------- /files/opi/boot-zero.cmd: -------------------------------------------------------------------------------- 1 | setenv bootargs earlyprintk console=ttyS0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rw rootwait init=/bin/systemd 2 | setenv fdt_high ffffffff 3 | fatload mmc 0 ${kernel_addr_r} zImage 4 | fatload mmc 0 ${fdt_addr_r} sun8i-h2-plus-orangepi-zero.dtb 5 | fatload mmc 0 ${ramdisk_addr_r} initrd.img 6 | bootz ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r} 7 | -------------------------------------------------------------------------------- /files/opi/boot-pc-plus.cmd: -------------------------------------------------------------------------------- 1 | setenv bootargs earlyprintk console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rw rootwait init=/bin/systemd 2 | setenv fdt_high ffffffff 3 | fatload mmc 0 ${kernel_addr_r} zImage 4 | fatload mmc 0 ${fdt_addr_r} sun8i-h3-orangepi-pc-plus.dtb 5 | fatload mmc 0 ${ramdisk_addr_r} initrd.img 6 | bootz ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r} 7 | -------------------------------------------------------------------------------- /devices/rpi-2-b/alpine-3.12-armhf/config.txt: -------------------------------------------------------------------------------- 1 | disable_splash=1 2 | boot_delay=0 3 | gpu_mem=256 4 | gpu_mem_256=64 5 | 6 | hdmi_drive=1 7 | hdmi_group=2 8 | hdmi_mode=1 9 | hdmi_mode=87 10 | hdmi_cvt 800 480 60 6 0 0 0 11 | 12 | [pi2] 13 | kernel=vmlinuz-rpi2 14 | initramfs initramfs-rpi2 15 | 16 | [pi3] 17 | kernel=vmlinuz-rpi2 18 | initramfs initramfs-rpi2 19 | 20 | [all] 21 | include usercfg.txt 22 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | Here are the sources of the [Pieman Docker image](https://hub.docker.com/r/cusdeb/pieman/). Run `make` inside the directory to build `cusdeb/pieman` image. Read the corresponding [section](https://github.com/tolstoyevsky/pieman#docker) of the documentation to know how to use it. Makefile is intended to simplify adding the metadata labels to the image which are used by [MicroBadger](https://microbadger.com/). 2 | 3 | -------------------------------------------------------------------------------- /files/mender/mender.conf.template: -------------------------------------------------------------------------------- 1 | { 2 | "InventoryPollIntervalSeconds": {MENDER_INVENTORY_POLL_INTERVAL}, 3 | "RetryPollIntervalSeconds": {MENDER_RETRY_POLL_INTERVAL}, 4 | "RootfsPartA": "/dev/mmcblk0p2", 5 | "RootfsPartB": "/dev/mmcblk0p3", 6 | "ServerURL": "{MENDER_SERVER_URL}", 7 | "TenantToken": "{MENDER_TENANT_TOKEN}", 8 | "UpdatePollIntervalSeconds": {MENDER_UPDATE_POLL_INTERVAL} 9 | } 10 | -------------------------------------------------------------------------------- /files/firstboot/README.md: -------------------------------------------------------------------------------- 1 | The scripts in this directory are merged into one script `/etc/rc.firstboot` which runs on the first system boot. Then it's removed. The main purpose of `/etc/rc.firstboot` is to resize the root partition to fill SD card. The code of the scripts was borrowed from [rpi23-gen-image](https://github.com/drtyhlpr/rpi23-gen-image) and is available under [the GNU General Public License version 2](https://gnu.org/licenses/old-licenses/gpl-2.0.en.html). -------------------------------------------------------------------------------- /devices/opi-zero/kali-rolling-armhf/README.md: -------------------------------------------------------------------------------- 1 | Kali Linux is a security-focused Debian-based distribution with pre-installed tools for penetration testing. 2 | It is maintained by Offensive Security Ltd. `opi-zero/kali-rolling-armhf` allows building custom 32-bit Kali Linux images for [OrangePi Zero](http://www.orangepi.org/orangepizero/). 3 | 4 | ## What's in the distribution? 5 | 6 | Kali Linux is a rolling release distribution, so it's pointless to list the packages with their versions here since the versions may change every day. -------------------------------------------------------------------------------- /files/network/interfaces.j2: -------------------------------------------------------------------------------- 1 | # interfaces(5) file used by ifup(8) and ifdown(8) 2 | # Include files from /etc/network/interfaces.d: 3 | source-directory /etc/network/interfaces.d 4 | 5 | auto lo 6 | iface lo inet loopback 7 | {% set enable_wireless = '' | getenv('ENABLE_WIRELESS') %} 8 | {% if enable_wireless %}allow-hotplug eth0{% else %}auto eth0{% endif %} 9 | iface eth0 inet dhcp 10 | {% if enable_wireless %} 11 | auto wlan0 12 | iface wlan0 inet dhcp 13 | wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf 14 | {% endif %} 15 | -------------------------------------------------------------------------------- /devices/opi-pc-plus/kali-rolling-armhf/README.md: -------------------------------------------------------------------------------- 1 | Kali Linux is a security-focused Debian-based distribution with pre-installed tools for penetration testing. 2 | It is maintained by Offensive Security Ltd. `opi-pc-plus/kali-rolling-armhf` allows building custom 32-bit Kali Linux images for [OrangePi PC Plus](http://www.orangepi.org/orangepipcplus/). 3 | 4 | ## What's in the distribution? 5 | 6 | Kali Linux is a rolling release distribution, so it's pointless to list the packages with their versions here since the versions may change every day. -------------------------------------------------------------------------------- /files/mender/fstab: -------------------------------------------------------------------------------- 1 | /dev/root / auto defaults 1 1 2 | proc /proc proc defaults 0 0 3 | devpts /dev/pts devpts mode=0620,gid=5 0 0 4 | tmpfs /run tmpfs mode=0755,nodev,nosuid,strictatime 0 0 5 | tmpfs /var/volatile tmpfs defaults 0 0 6 | 7 | /dev/mmcblk0p1 /uboot auto defaults,sync 0 0 8 | /dev/mmcblk0p4 /data auto defaults 0 0 9 | -------------------------------------------------------------------------------- /pieman/pieman/build_status_codes: -------------------------------------------------------------------------------- 1 | PREPARED_CHROOT_ENV_CODE=10 2 | 3 | SET_UP_LOCALE_CODE=20 4 | 5 | SET_UP_TIMEZONE_CODE=21 6 | 7 | UPDATED_CODE=30 8 | 9 | INSTALLED_PACKAGES_CODE=31 10 | 11 | UPGRADED_CODE=32 12 | 13 | INSTALLED_KERNEL_CODE=33 14 | 15 | PREPARED_BOOT_PARTITION_CODE=40 16 | 17 | DONE_WITH_NETWORKING_CODE=50 18 | 19 | DONE_WITH_USERS_CODE=60 20 | 21 | DONE_WITH_CLEAN_UP_CODE=70 22 | 23 | CREATED_IMAGE_CODE=80 24 | 25 | FORMATTED_PARTITION_CODE=81 26 | 27 | SYNCED_CODE=82 28 | 29 | SUCCESSFUL_CODE=1000 30 | 31 | FAILED_CODE=1001 32 | -------------------------------------------------------------------------------- /devices/opi-zero/debian-buster-armhf/pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Evgeny Golyshev 2 | 3 | debian-buster-armhf: 4 | repos: 5 | - http://deb.debian.org/debian 6 | boot: 7 | - /boot/initrd.img-4.19.0-*-armmp:initrd.img 8 | - /boot/vmlinuz-4.19.0-*-armmp:zImage 9 | - /usr/lib/linux-image-4.19.0-*-armmp/sun8i-h2-plus-orangepi-zero.dtb 10 | spl_bin: ${TOOLSET_DIR}/${TOOLSET_CODENAME}/uboot-${UBOOT_VER}/u-boot-sunxi-with-spl-for-opi-zero.bin 11 | base: 12 | - gnupg 13 | includes: systemd 14 | kernel: 15 | package: linux-image-armmp 16 | params: 17 | - ENABLE_GOOGLE_DNS 18 | -------------------------------------------------------------------------------- /devices/opi-pc-plus/debian-buster-armhf/pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Evgeny Golyshev 2 | 3 | debian-buster-armhf: 4 | repos: 5 | - http://deb.debian.org/debian 6 | boot: 7 | - /boot/initrd.img-4.19.0-*-armmp:initrd.img 8 | - /boot/vmlinuz-4.19.0-*-armmp:zImage 9 | - /usr/lib/linux-image-4.19.0-*-armmp/sun8i-h3-orangepi-pc-plus.dtb 10 | spl_bin: ${TOOLSET_DIR}/${TOOLSET_CODENAME}/uboot-${UBOOT_VER}/u-boot-sunxi-with-spl-for-opi-pc-plus.bin 11 | base: 12 | - gnupg 13 | includes: systemd 14 | kernel: 15 | package: linux-image-armmp 16 | params: 17 | - ENABLE_GOOGLE_DNS 18 | -------------------------------------------------------------------------------- /devices/opi-zero/kali-rolling-armhf/pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Polina Popova 2 | 3 | kali-rolling-armhf: 4 | codename: kali-rolling 5 | repos: 6 | - http://http.kali.org/kali/ 7 | boot: 8 | - /boot/initrd.img-*-armmp:initrd.img 9 | - /boot/vmlinuz-*-armmp:zImage 10 | - /usr/lib/linux-image-*-armmp/sun8i-h2-plus-orangepi-zero.dtb 11 | spl_bin: ${TOOLSET_DIR}/${TOOLSET_CODENAME}/uboot-${UBOOT_VER}/u-boot-sunxi-with-spl-for-opi-zero.bin 12 | base: 13 | - gnupg 14 | includes: systemd 15 | kernel: 16 | package: linux-image-armmp 17 | params: 18 | - ENABLE_GOOGLE_DNS 19 | -------------------------------------------------------------------------------- /devices/opi-pc-plus/kali-rolling-armhf/pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Polina Popova 2 | 3 | kali-rolling-armhf: 4 | codename: kali-rolling 5 | repos: 6 | - http://http.kali.org/kali/ 7 | boot: 8 | - /boot/initrd.img-*-armmp:initrd.img 9 | - /boot/vmlinuz-*-armmp:zImage 10 | - /usr/lib/linux-image-*-armmp/sun8i-h3-orangepi-pc-plus.dtb 11 | spl_bin: ${TOOLSET_DIR}/${TOOLSET_CODENAME}/uboot-${UBOOT_VER}/u-boot-sunxi-with-spl-for-opi-pc-plus.bin 12 | base: 13 | - gnupg 14 | includes: systemd 15 | kernel: 16 | package: linux-image-armmp 17 | params: 18 | - ENABLE_GOOGLE_DNS 19 | -------------------------------------------------------------------------------- /files/mender/mender.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Mender OTA update service 3 | After=systemd-resolved.service 4 | 5 | [Service] 6 | Type=idle 7 | User=root 8 | Group=root 9 | ExecStartPre=/bin/mkdir -p -m 0700 /data/mender 10 | ExecStartPre=/bin/ln -sf /etc/mender/tenant.conf /var/lib/mender/authtentoken 11 | ExecStart=/usr/bin/mender -daemon 12 | Restart=on-abort 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /docker/rollout_fixes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | mkdir packages 6 | 7 | wget http://ftp.debian.org/debian/dists/stretch/main/binary-amd64/Packages.xz 8 | 9 | xz -d Packages.xz 10 | 11 | cd packages 12 | 13 | # 14 | # zlib1g 15 | # 16 | 17 | # There are three packages: zlib1g, zlib1g-dbg and zlib1g-dev. Use -m1 to get 18 | # the first one. 19 | package=$(grep -m1 "Filename: pool/main/z/zlib/zlib1g" ../Packages | awk '{print $2}') 20 | 21 | wget http://ftp.debian.org/debian/${package} 22 | 23 | ar x $(basename ${package}) 24 | 25 | tar xJvf data.tar.xz 26 | 27 | cp lib/x86_64-linux-gnu/libz.so.1.2.8 /usr/glibc-compat/lib/libz.so.1 28 | 29 | cd .. 30 | 31 | # cleanup 32 | rm Packages 33 | rm -r packages 34 | 35 | -------------------------------------------------------------------------------- /bootstrap/99-reduce.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | clean 17 | 18 | send_request_to_bsc_server DONE_WITH_CLEAN_UP_CODE 19 | -------------------------------------------------------------------------------- /depend_on.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Dmitriy Ivanko 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | depend_on WPA_SSID ENABLE_WIRELESS 17 | 18 | depend_on WPA_PSK ENABLE_WIRELESS WPA_SSID 19 | -------------------------------------------------------------------------------- /bootstrap/40-deskop.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Eduard Lemmer 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | if ${XFCE4}; then 17 | install_exec files/desktop/06xfce4.desktop "${R}"/usr/share/xsessions/06xfce4.desktop 18 | fi 19 | 20 | if ${XFCE4}; then 21 | install_exec files/desktop/lxdm.conf "${R}"/etc/lxdm.conf 22 | fi -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | Pieman is written by [Evgeny Golyshev](https://github.com/eugulixes) and [Denis Mosolov](https://github.com/denismosolov). It's currently maintained by Evgeny Golyshev and [Denis Gavrilyuk](https://github.com/karpa4o4). 2 | 3 | ## Acknowledgements 4 | 5 | We thank all the contributors to the project. Here is the full list of the people who have contributed to Pieman: 6 | * [Dmitry Poloskin](https://github.com/dimapaloskin) 7 | * [Polina Popova](https://github.com/polina-popova) 8 | * [Dominick Han](https://github.com/dominick-han) 9 | * [Anton Demushkin](https://github.com/fremail) 10 | * [Daniil Molotkov](https://github.com/mdanil007) 11 | * [Semyon Suprun](https://github.com/BehindLoader) 12 | * [Eduard Lemmer](https://github.com/leocoan) 13 | * [Aram Grigoryan](https://github.com/Aramgrigoryanwb) 14 | * [Anton Maksimovich](https://github.com/ABSLord) 15 | * [Dmitriy Ivanko](https://github.com/Themanwhosmellslikesugar) 16 | * [Vladislav Iarovoy](https://github.com/IrovoyVlad) 17 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-bionic-armhf/pre-kernel-installation/10-patch-flash-kernel.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | check_if_variable_is_set R SOURCE_DIR 4 | 5 | # There are two problems related to the flash-kernel package during the kernel 6 | # installation. 7 | # 8 | # 1) /usr/share/initramfs-tools/hooks/flash_kernel_set_root from flash-kernel 9 | # shows the following message and pauses the kernel installation. 10 | # Warning: root device does not exist 11 | # Press Ctrl-C to abort build, or Enter to continue 12 | # 13 | # 2) flash-kernel can't check the platform the system is running on because 14 | # flash kernel doesn't provide for running in a chroot environment. 15 | # 16 | # To workaround it, install flash-kernel and patch it. 17 | 18 | install_packages flash-kernel patch 19 | 20 | cp "${SOURCE_DIR}"/fix-kernel-installation-in-chroot.patch "${R}" 21 | 22 | chroot_exec_sh "patch -p0 < fix-kernel-installation-in-chroot.patch" 23 | 24 | # Clean up 25 | 26 | rm "${R}"/fix-kernel-installation-in-chroot.patch 27 | 28 | purge_packages patch 29 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-xenial-armhf/pre-kernel-installation/10-patch-flash-kernel.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | check_if_variable_is_set R SOURCE_DIR 4 | 5 | # There are two problems related to the flash-kernel package during the kernel 6 | # installation. 7 | # 8 | # 1) /usr/share/initramfs-tools/hooks/flash_kernel_set_root from flash-kernel 9 | # shows the following message and pauses the kernel installation. 10 | # Warning: root device does not exist 11 | # Press Ctrl-C to abort build, or Enter to continue 12 | # 13 | # 2) flash-kernel can't check the platform the system is running on because 14 | # flash kernel doesn't provide for running in a chroot environment. 15 | # 16 | # To workaround it, install flash-kernel and patch it. 17 | 18 | install_packages flash-kernel patch 19 | 20 | cp "${SOURCE_DIR}"/fix-kernel-installation-in-chroot.patch "${R}" 21 | 22 | chroot_exec_sh "patch -p0 < fix-kernel-installation-in-chroot.patch" 23 | 24 | # Clean up 25 | 26 | rm "${R}"/fix-kernel-installation-in-chroot.patch 27 | 28 | purge_packages patch 29 | -------------------------------------------------------------------------------- /devices/rpi-3-b/ubuntu-bionic-arm64/pre-kernel-installation/10-patch-flash-kernel.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | check_if_variable_is_set R SOURCE_DIR 4 | 5 | # There are two problems related to the flash-kernel package during the kernel 6 | # installation. 7 | # 8 | # 1) /usr/share/initramfs-tools/hooks/flash_kernel_set_root from flash-kernel 9 | # shows the following message and pauses the kernel installation. 10 | # Warning: root device does not exist 11 | # Press Ctrl-C to abort build, or Enter to continue 12 | # 13 | # 2) flash-kernel can't check the platform the system is running on because 14 | # flash kernel doesn't provide for running in a chroot environment. 15 | # 16 | # To workaround it, install flash-kernel and patch it. 17 | 18 | install_packages flash-kernel patch 19 | 20 | cp "${SOURCE_DIR}"/fix-kernel-installation-in-chroot.patch "${R}" 21 | 22 | chroot_exec_sh "patch -p0 < fix-kernel-installation-in-chroot.patch" 23 | 24 | # Clean up 25 | 26 | rm "${R}"/fix-kernel-installation-in-chroot.patch 27 | 28 | purge_packages patch 29 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-xenial-armhf/pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Evgeny Golyshev 2 | 3 | ubuntu-xenial-armhf: 4 | repos: 5 | - http://ports.ubuntu.com/ubuntu-ports/ 6 | boot: 7 | - cmdline.txt 8 | - config.txt 9 | - /boot/vmlinuz-4.4.0-*-raspi2:kernel7.img 10 | - /lib/firmware/4.4.0-*-raspi2/device-tree/bcm2709-rpi-2-b.dtb 11 | - /lib/firmware/4.4.0-*-raspi2/device-tree/bcm2710-rpi-3-b.dtb 12 | - https://github.com/raspberrypi/firmware/raw/master/boot/bootcode.bin 13 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup.dat 14 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_cd.dat 15 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_x.dat 16 | - https://github.com/raspberrypi/firmware/raw/master/boot/start.elf 17 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_cd.elf 18 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_x.elf 19 | params: 20 | # The kernel package is available in the universe archive area. 21 | - ENABLE_UNIVERSE 22 | kernel: 23 | package: linux-image-raspi2 24 | -------------------------------------------------------------------------------- /pieman/test/pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Evgeny Golyshev 2 | 3 | raspberrypios-buster-armhf: 4 | repos: 5 | - http://archive.raspbian.org/raspbian 6 | - http://archive.raspberrypi.org/debian 7 | boot: 8 | - cmdline.txt 9 | - config.txt 10 | # For RPi B Plus and RPi Zero 11 | - /boot/bcm2708-rpi-b-plus.dtb 12 | - /boot/bcm2709-rpi-2-b.dtb 13 | - /boot/bcm2710-rpi-3-b.dtb 14 | - /boot/overlays 15 | - /boot/kernel.img 16 | - /boot/kernel7.img 17 | - https://github.com/raspberrypi/firmware/raw/master/boot/bootcode.bin 18 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup.dat 19 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_cd.dat 20 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_x.dat 21 | - https://github.com/raspberrypi/firmware/raw/master/boot/start.elf 22 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_cd.elf 23 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_x.elf 24 | includes: systemd-sysv 25 | kernel: 26 | package: raspberrypi-kernel 27 | unknown: some-value 28 | -------------------------------------------------------------------------------- /devices/rpi-2-b/alpine-3.12-armhf/pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Evgeny Golyshev 2 | 3 | alpine-3.12-armhf: 4 | repos: 5 | - http://dl-cdn.alpinelinux.org/alpine/ 6 | boot: 7 | - cmdline.txt 8 | - config.txt 9 | - /boot/initramfs-rpi2 10 | - /boot/vmlinuz-rpi2 11 | - /boot/dtbs-rpi2/bcm2709-rpi-2-b.dtb 12 | - /boot/dtbs-rpi2/bcm2836-rpi-2-b.dtb 13 | - /boot/dtbs-rpi2/bcm2710-rpi-3-b.dtb 14 | - /boot/dtbs-rpi2/bcm2710-rpi-3-b-plus.dtb 15 | - /boot/dtbs-rpi2/overlays 16 | - https://github.com/raspberrypi/firmware/raw/master/boot/bootcode.bin 17 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup.dat 18 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_cd.dat 19 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_x.dat 20 | - https://github.com/raspberrypi/firmware/raw/master/boot/start.elf 21 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_cd.elf 22 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_x.elf 23 | base: tzdata 24 | params: 25 | - ENABLE_GOOGLE_DNS 26 | kernel: 27 | package: linux-rpi2 28 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-bionic-armhf/fix-kernel-installation-in-chroot.patch: -------------------------------------------------------------------------------- 1 | diff --git a/functions b/functions 2 | index b889c1a..6cc1943 100644 3 | --- usr/share/flash-kernel/functions 4 | +++ usr/share/flash-kernel/functions 5 | @@ -710,6 +710,10 @@ 6 | } 7 | 8 | main() { 9 | +if systemd-detect-virt --chroot; then 10 | + echo "A chroot environment has been detected. Interrupt flash-kernel." >&2 11 | + exit 0 12 | +fi 13 | force="no" 14 | if [ "x$1" = "x--force" ]; then 15 | force="yes" 16 | diff --git a/initramfs-tools/hooks/flash_kernel_set_root b/initramfs-tools/hooks/flash_kernel_set_root 17 | index ac57d12..98d76ab 100755 18 | --- usr/share/initramfs-tools/hooks/flash_kernel_set_root 19 | +++ usr/share/initramfs-tools/hooks/flash_kernel_set_root 20 | @@ -62,6 +62,11 @@ if systemd-detect-virt --quiet --container; then 21 | exit 0 22 | fi 23 | 24 | +# Do not run inside a chroot environment as well 25 | +if systemd-detect-virt --chroot; then 26 | + exit 0 27 | +fi 28 | + 29 | # Record the root filesystem device for use during boot 30 | rootdev=$(egrep '^[^# ]+[ ]+/[ ]' /etc/fstab | awk '{print $1}') || true 31 | 32 | -------------------------------------------------------------------------------- /devices/rpi-3-b/ubuntu-bionic-arm64/fix-kernel-installation-in-chroot.patch: -------------------------------------------------------------------------------- 1 | diff --git a/functions b/functions 2 | index b889c1a..6cc1943 100644 3 | --- usr/share/flash-kernel/functions 4 | +++ usr/share/flash-kernel/functions 5 | @@ -710,6 +710,10 @@ 6 | } 7 | 8 | main() { 9 | +if systemd-detect-virt --chroot; then 10 | + echo "A chroot environment has been detected. Interrupt flash-kernel." >&2 11 | + exit 0 12 | +fi 13 | force="no" 14 | if [ "x$1" = "x--force" ]; then 15 | force="yes" 16 | diff --git a/initramfs-tools/hooks/flash_kernel_set_root b/initramfs-tools/hooks/flash_kernel_set_root 17 | index ac57d12..98d76ab 100755 18 | --- usr/share/initramfs-tools/hooks/flash_kernel_set_root 19 | +++ usr/share/initramfs-tools/hooks/flash_kernel_set_root 20 | @@ -62,6 +62,11 @@ if systemd-detect-virt --quiet --container; then 21 | exit 0 22 | fi 23 | 24 | +# Do not run inside a chroot environment as well 25 | +if systemd-detect-virt --chroot; then 26 | + exit 0 27 | +fi 28 | + 29 | # Record the root filesystem device for use during boot 30 | rootdev=$(egrep '^[^# ]+[ ]+/[ ]' /etc/fstab | awk '{print $1}') || true 31 | 32 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-xenial-armhf/fix-kernel-installation-in-chroot.patch: -------------------------------------------------------------------------------- 1 | diff --git a/functions b/functions 2 | index b889c1a..6cc1943 100644 3 | --- usr/share/flash-kernel/functions 4 | +++ usr/share/flash-kernel/functions 5 | @@ -380,6 +380,11 @@ include_only_flavors() { 6 | } 7 | 8 | main() { 9 | +if systemd-detect-virt --chroot; then 10 | + echo "A chroot environment has been detected. Interrupt flash-kernel." >&2 11 | + exit 0 12 | +fi 13 | + 14 | if [ "x$1" = "x--machine" ]; then 15 | machine="$2" 16 | shift 2 17 | diff --git a/initramfs-tools/hooks/flash_kernel_set_root b/initramfs-tools/hooks/flash_kernel_set_root 18 | index ac57d12..98d76ab 100755 19 | --- usr/share/initramfs-tools/hooks/flash_kernel_set_root 20 | +++ usr/share/initramfs-tools/hooks/flash_kernel_set_root 21 | @@ -62,6 +62,11 @@ if systemd-detect-virt --quiet --container; then 22 | exit 0 23 | fi 24 | 25 | +# Do not run inside a chroot environment as well 26 | +if systemd-detect-virt --chroot; then 27 | + exit 0 28 | +fi 29 | + 30 | # Record the root filesystem device for use during boot 31 | rootdev=$(egrep '^[^# ]+[ ]+/[ ]' /etc/fstab | awk '{print $1}') || true 32 | 33 | -------------------------------------------------------------------------------- /bootstrap/13-kernel.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017-2021 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | for var in OS SOURCE_DIR; do 17 | check_if_variable_is_set ${var} 18 | done 19 | 20 | kernel_package="$(get_attr kernel package)" 21 | 22 | info "installing kernel package" 23 | 24 | run_scripts "${SOURCE_DIR}"/pre-kernel-installation 25 | 26 | install_packages "${kernel_package}" 27 | 28 | run_scripts "${SOURCE_DIR}"/post-kernel-installation 29 | 30 | send_request_to_bsc_server INSTALLED_KERNEL_CODE 31 | -------------------------------------------------------------------------------- /mutually_exclusive_params.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Dmitriy Ivanko 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | check_mutually_exclusive_params \ 17 | BASE_DIR \ 18 | CREATE_ONLY_CHROOT 19 | 20 | check_mutually_exclusive_params \ 21 | ENABLE_GOOGLE_DNS \ 22 | ENABLE_BASIC_YANDEX_DNS \ 23 | ENABLE_FAMILY_YANDEX_DNS \ 24 | ENABLE_CUSTOM_DNS 25 | 26 | check_mutually_exclusive_params \ 27 | COMPRESS_WITH_BZIP2 \ 28 | COMPRESS_WITH_GZIP \ 29 | COMPRESS_WITH_XZ 30 | 31 | check_mutually_exclusive_params \ 32 | CREATE_ONLY_MENDER_ARTIFACT \ 33 | CREATE_ONLY_CHROOT \ 34 | ENABLE_MENDER 35 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Please make sure all below checkboxes in the Mandatory section have been checked before submitting your PR (also don't forget to pay attention to the Depending on Circumstances section) 2 | 3 | ## Mandatory 4 | 5 | - [ ] The commit message is an imperative and starts with a capital letter (for example, `Add something`, `Remove something`, `Fix something`, etc.). 6 | - [ ] I made sure I hadn't put a period at the end of the the commit message(s). 7 | 8 | ## Depending on Circumstances 9 | 10 | Some of the items in the section become mandatory if you are a first-time contributor and/or your changes are relevant to the items. 11 | 12 | - [ ] Adding a new parameter I didn't forget to reflect it in `README.md`. 13 | - [ ] Adding a new parameter or modifying an existing one I didn't break the alphabetical order. 14 | - [ ] Adding a new utility written in Python I didn't forget to reflect it in `pieman/README.md`. 15 | - [ ] Adding a new utility written in Python I didn't forget to increase the version number of the [pieman](https://pypi.org/project/pieman/) package in `pieman/setup.py`, `pieman/pieman/__init__.py` and `essentials.sh`. 16 | - [ ] (for first-time contributors) One of the commits in the pull request adds me to the **Acknowledgements** section in `AUTHORS.md`. 17 | -------------------------------------------------------------------------------- /bootstrap/30-fixes.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | if is_alpine; then 17 | # For some reason the rw parameter in cmdline.txt is ignored, so the rootfs 18 | # should be remounted at startup. 19 | install_exec files/etc/local.d/10-remount_root.start "${ETC}"/local.d/10-remount_root.start 20 | 21 | # Since the system is already installed, the message may confuse users. 22 | sed -i '/You can setup the system/,+1d' "${ETC}/motd" 23 | 24 | # Of course, none of the supported single board computers has any cdrom. 25 | sed -i '/cdrom/d' "${ETC}/fstab" 26 | fi 27 | 28 | 29 | -------------------------------------------------------------------------------- /pieman/pieman/codes.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | """Module intended for parsing the build_status_codes text file. """ 17 | 18 | import os 19 | import sys 20 | 21 | 22 | BUILD_STATUS_CODES = os.path.join(os.path.dirname(__file__), 23 | 'build_status_codes') 24 | 25 | MODULE = sys.modules[__name__] 26 | 27 | LINES = [line.rstrip('\n').strip() for line in open(BUILD_STATUS_CODES)] 28 | for line in LINES: 29 | if line and not line.startswith('#'): 30 | nam, val = line.split('=') 31 | setattr(MODULE, nam, val.encode()) # values must be bytes 32 | -------------------------------------------------------------------------------- /helpers/misc.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Denis Gavrilyuk 2 | # Copyright (C) 2019-2020 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | # Encrypts the specified password using the SHA-512 method. 18 | # Globals: 19 | # PYTHON 20 | # Arguments: 21 | # Password 22 | # Returns: 23 | # Encrypted password 24 | do_mkpasswd() { 25 | "${PYTHON}" -c "import crypt; print(crypt.crypt('$1', crypt.mksalt(crypt.METHOD_SHA512)))" 26 | } 27 | 28 | # Downloads files from the Web non-interactively. 29 | # Globals: 30 | # None 31 | # Arguments: 32 | # wget options (only -O and -q are supported) 33 | # URL 34 | # Returns: 35 | # None 36 | do_wget() { 37 | wget.py "$@" 38 | } 39 | 40 | -------------------------------------------------------------------------------- /devices/rpi-3-b-plus/ubuntu-focal-armhf/pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Evgeny Golyshev 2 | 3 | ubuntu-focal-armhf: 4 | repos: 5 | - http://ports.ubuntu.com/ubuntu-ports/ 6 | boot: 7 | - cmdline.txt 8 | - config.txt 9 | - /boot/vmlinuz-5.4.0-*-raspi:kernel7.img 10 | - /lib/firmware/5.4.0-*-raspi/device-tree/bcm2709-rpi-2-b.dtb 11 | - /lib/firmware/5.4.0-*-raspi/device-tree/bcm2710-rpi-3-b.dtb 12 | - /lib/firmware/5.4.0-*-raspi/device-tree/bcm2710-rpi-3-b-plus.dtb 13 | - https://github.com/raspberrypi/firmware/raw/master/boot/bootcode.bin 14 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup.dat 15 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_cd.dat 16 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_x.dat 17 | - https://github.com/raspberrypi/firmware/raw/master/boot/start.elf 18 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_cd.elf 19 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_x.elf 20 | base: 21 | - gnupg 22 | - tzdata 23 | includes: 24 | # /usr/share/initramfs-tools/hooks/flash_kernel_set_root will be looking for 25 | # systemd-detect-virt during installation of the kernel. 26 | - systemd 27 | - tzdata 28 | params: 29 | # The kernel package is available in the universe archive area. 30 | - ENABLE_UNIVERSE 31 | kernel: 32 | package: linux-image-raspi2 33 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-bionic-armhf/pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Evgeny Golyshev 2 | 3 | ubuntu-bionic-armhf: 4 | repos: 5 | - http://ports.ubuntu.com/ubuntu-ports/ 6 | boot: 7 | - cmdline.txt 8 | - config.txt 9 | - /boot/vmlinuz-4.15.0-*-raspi2:kernel7.img 10 | - /lib/firmware/4.15.0-*-raspi2/device-tree/bcm2709-rpi-2-b.dtb 11 | - /lib/firmware/4.15.0-*-raspi2/device-tree/bcm2710-rpi-3-b.dtb 12 | - /lib/firmware/4.15.0-*-raspi2/device-tree/bcm2710-rpi-3-b-plus.dtb 13 | - https://github.com/raspberrypi/firmware/raw/master/boot/bootcode.bin 14 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup.dat 15 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_cd.dat 16 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_x.dat 17 | - https://github.com/raspberrypi/firmware/raw/master/boot/start.elf 18 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_cd.elf 19 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_x.elf 20 | base: 21 | - gnupg 22 | - tzdata 23 | includes: 24 | # /usr/share/initramfs-tools/hooks/flash_kernel_set_root will be looking for 25 | # systemd-detect-virt during installation of the kernel. 26 | - systemd 27 | - tzdata 28 | params: 29 | # The kernel package is available in the universe archive area. 30 | - ENABLE_UNIVERSE 31 | kernel: 32 | package: linux-image-raspi2 33 | -------------------------------------------------------------------------------- /devices/rpi-3-b/ubuntu-bionic-arm64/pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Evgeny Golyshev 2 | 3 | ubuntu-bionic-arm64: 4 | repos: 5 | - http://ports.ubuntu.com/ubuntu-ports/ 6 | boot: 7 | - cmdline.txt 8 | - config.txt 9 | - /boot/vmlinuz-4.15.0-*-raspi2:kernel8.img 10 | # bcm2837-rpi-3-b.dtb works in QEMU, but doesn't work on a real device, so 11 | # use bcm2710-rpi-3-b.dtb. It works both in the emulator and on a real device. 12 | - /lib/firmware/4.15.0-*-raspi2/device-tree/broadcom/bcm2710-rpi-3-b.dtb 13 | - https://github.com/raspberrypi/firmware/raw/master/boot/bootcode.bin 14 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup.dat 15 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_cd.dat 16 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_x.dat 17 | - https://github.com/raspberrypi/firmware/raw/master/boot/start.elf 18 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_cd.elf 19 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_x.elf 20 | base: 21 | - gnupg 22 | - tzdata 23 | # /usr/share/initramfs-tools/hooks/flash_kernel_set_root will be looking for 24 | # systemd-detect-virt during installation of the kernel. 25 | includes: systemd 26 | params: 27 | # The kernel package is available in the universe archive area. 28 | - ENABLE_UNIVERSE 29 | kernel: 30 | package: linux-image-raspi2 31 | -------------------------------------------------------------------------------- /files/desktop/lxdm.conf: -------------------------------------------------------------------------------- 1 | [base] 2 | ## uncomment and set autologin username to enable autologin 3 | # autologin=dgod 4 | 5 | ## uncomment and set timeout to enable timeout autologin, 6 | ## the value should >=5 7 | # timeout=10 8 | 9 | ## default session or desktop used when no systemwide config 10 | session=/usr/bin/startxfce4 11 | 12 | ## uncomment and set to set numlock on your keyboard 13 | # numlock=0 14 | 15 | ## set this if you don't want to put xauth file at ~/.Xauthority 16 | # xauth_path=/tmp 17 | 18 | # not ask password for users who have empty password 19 | # skip_password=1 20 | 21 | ## greeter used to welcome the user 22 | greeter=/usr/lib/lxdm/lxdm-greeter-gtk 23 | 24 | [server] 25 | ## arg used to start xserver, not fully function 26 | # arg=/usr/bin/X -background vt1 27 | # uncomment this if you really want xserver listen to tcp 28 | # tcp_listen=1 29 | 30 | [display] 31 | ## gtk theme used by greeter 32 | gtk_theme=Clearlooks 33 | 34 | ## background of the greeter 35 | #bg=/usr/share/backgrounds/default.png 36 | bg=/usr/share/images/desktop-base/login-background.svg 37 | 38 | ## if show bottom pane 39 | bottom_pane=1 40 | 41 | ## if show language select control 42 | lang=1 43 | 44 | ## if show keyboard layout select control 45 | keyboard=0 46 | 47 | ## the theme of greeter 48 | theme=Industrial 49 | 50 | [input] 51 | 52 | [userlist] 53 | ## if disable the user list control at greeter 54 | disable=0 55 | 56 | ## whitelist user 57 | white= 58 | 59 | ## blacklist user 60 | black= 61 | 62 | -------------------------------------------------------------------------------- /bootstrap/20-users.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | check_if_variable_is_set ENABLE_USER PASSWORD USER_NAME USER_PASSWORD 17 | 18 | if ${ENABLE_USER}; then 19 | info "creating regular user ${USER_NAME}" 20 | add_user "${USER_NAME}" "${USER_PASSWORD}" 21 | 22 | if ${ENABLE_SUDO}; then 23 | info "add regular user ${USER_NAME} to /etc/sudoers" 24 | 25 | if ${SUDO_REQUIRE_PASSWORD}; then 26 | permission="ALL=(ALL:ALL) ALL" 27 | else 28 | permission="ALL=(ALL) NOPASSWD: ALL" 29 | fi 30 | 31 | echo "${USER_NAME} ${permission}" > "${ETC}"/sudoers.d/01_allow_executing_any_command 32 | fi 33 | fi 34 | 35 | info "setting root password" 36 | set_root_password "${PASSWORD}" 37 | 38 | send_request_to_bsc_server DONE_WITH_USERS_CODE 39 | -------------------------------------------------------------------------------- /test/mocks.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2021 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Mocks the debootstrap executable, storing the arguments passed to it to be 17 | # checked later. 18 | # Globals: 19 | # DEBOOTSTRAP_CMD_LINE 20 | # Arguments: 21 | # deboostrap arguments 22 | # Returns: 23 | # None 24 | debootstrap_mock() { 25 | # appears unused 26 | # shellcheck disable=SC2034 27 | DEBOOTSTRAP_CMD_LINE=$* 28 | } 29 | 30 | # Mocks install_user_mode_emulation_binary. The origianl function is invoked by 31 | # run_first_stage and changes the rootfs of the target image. When 32 | # run_first_stage is tested, install_user_mode_emulation_binary must do 33 | # nothing. 34 | # Globals: 35 | # None 36 | # Arguments: 37 | # None 38 | # Returns: 39 | # None 40 | install_user_mode_emulation_binary() { 41 | true 42 | } 43 | -------------------------------------------------------------------------------- /helpers/templates.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2020 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Renders Jinja2 templates. 17 | # Globals: 18 | # None 19 | # Arguments: 20 | # Template to be rendered 21 | # Result path 22 | # Returns: 23 | # None 24 | render() { 25 | local error_msg="rendering error: " 26 | local template_path=$1 27 | local result_path=$2 28 | 29 | { render.py "${template_path}" "${result_path}"; exit_code="$?"; } || true 30 | case "${exit_code}" in 31 | 0) 32 | ;; 33 | 1) 34 | fatal "${error_msg}${template_path} does not exist" 35 | exit 1 36 | ;; 37 | 2) 38 | fatal "${error_msg}$(dirname "${result_path}") does not exist" 39 | exit 1 40 | ;; 41 | *) 42 | fatal "unknown error" 43 | exit 1 44 | ;; 45 | esac 46 | } 47 | -------------------------------------------------------------------------------- /devices/opi-zero/debian-buster-armhf/README.md: -------------------------------------------------------------------------------- 1 | Debian is one of the oldest GNU/Linux distributions, well-known for its stability and its strong devotion to free software principles. `opi-zero/debian-buster-armhf` allows building custom 32-bit Debian [Buster](https://debian.org/releases/buster/) images for [Orange Pi Zero](http://www.orangepi.org/orangepizero/). 2 | 3 | ## What's in the distribution? 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
PackageVersion
Essential components
Linux kernel4.19
glibc2.28
GCC8.2
systemd241
Development tools
Go1.11
PHP7.3
Python3.7.2
Ruby2.5.1
Server software
Apache HTTP Server2.4.38
Nginx1.14.2
PostgreSQL11.2
MariaDB10.3
68 | -------------------------------------------------------------------------------- /devices/opi-pc-plus/debian-buster-armhf/README.md: -------------------------------------------------------------------------------- 1 | Debian is one of the oldest GNU/Linux distributions, well-known for its stability and its strong devotion to free software principles. `opi-pc-plus/debian-buster-armhf` allows building custom 32-bit Debian [Buster](https://debian.org/releases/buster/) images for [Orange Pi PC Plus](http://www.orangepi.org/orangepipcplus/). 2 | 3 | ## What's in the distribution? 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
PackageVersion
Essential components
Linux kernel4.19
glibc2.28
GCC8.2
systemd241
Development tools
Go1.11
PHP7.3
Python3.7.2
Ruby2.5.1
Server software
Apache HTTP Server2.4.38
Nginx1.14.2
PostgreSQL11.2
MariaDB10.3
68 | -------------------------------------------------------------------------------- /docker-pieman.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright (C) 2017 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | set -e 18 | 19 | if [[ ${BASH_VERSINFO[0]} -lt 4 ]]; then 20 | >&2 echo "$0 requires bash 4 or higher" 21 | exit 1 22 | fi 23 | 24 | x=0 25 | while getopts e: OPTION 26 | do 27 | case ${OPTION} in 28 | e) 29 | VARS[$x]=$OPTARG 30 | x=$((x + 1)) 31 | ;; 32 | esac 33 | done 34 | 35 | ARGS=() 36 | for var in ${VARS[@]}; do 37 | IFS='=' read -ra VAR_VALUE <<< ${var} 38 | if [[ ${#VAR_VALUE[@]} != 2 ]]; then 39 | >&2 echo "To assign environment variables, specify them as VAR=VALUE." 40 | exit 1 41 | fi 42 | 43 | ARGS+=(--env=${var}) 44 | done 45 | 46 | docker run \ 47 | --privileged \ 48 | --rm ${ARGS[@]} \ 49 | --env IMAGE_OWNERSHIP="$(id -u $(stat -c "%U" $0)):$(id -g $(stat -c "%G" $0))" \ 50 | -v `pwd`:/result -v /dev:/dev cusdeb/pieman 51 | -------------------------------------------------------------------------------- /bootstrap/10-rootfs-partition.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017-2021 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | check_if_variable_is_set R 17 | 18 | # Expand the base system. 19 | 20 | if is_debian_based; then 21 | add_package_to_base_packages locales 22 | fi 23 | 24 | base_packages="$(get_attr_or_nothing base)" 25 | if [[ -n ${base_packages} ]]; then 26 | for package in ${base_packages}; do 27 | add_package_to_base_packages "${package}" 28 | done 29 | fi 30 | 31 | if [[ -n ${BASE_DIR} ]] && [[ -n ${BASE_DIR} ]]; then 32 | info "using ${BASE_DIR} instead of creating chroot environment." 33 | cp -r --preserve "${BASE_DIR}" "${R}" 34 | else 35 | info "BASE_DIR is not specified or does not exist. Creating chroot environment." 36 | 37 | create_chroot_environment 38 | fi 39 | 40 | send_request_to_bsc_server PREPARED_CHROOT_ENV_CODE 41 | 42 | info "mounting proc and sys filesystems to chroot environment" 43 | mount_required_filesystems 44 | -------------------------------------------------------------------------------- /pieman/bin/check_mutually_exclusive_params.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (C) 2018 Denis Gavrilyuk 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | """Utility intended for checking if two specified environment variables are 18 | defined. If so, the utility exits with a non-zero code. Otherwise it exits 19 | normally. 20 | """ 21 | 22 | import argparse 23 | import os 24 | import sys 25 | 26 | 27 | def main(): 28 | """The main entry point. """ 29 | 30 | parser = argparse.ArgumentParser() 31 | parser.add_argument('var1', help='first environment variable name') 32 | parser.add_argument('var2', help='second environment variable name') 33 | args = parser.parse_args() 34 | 35 | var1 = os.getenv(args.var1, None) 36 | var2 = os.getenv(args.var2, None) 37 | 38 | var1 = '' if var1 == 'false' else var1 39 | var2 = '' if var2 == 'false' else var2 40 | if var1 and var2: 41 | sys.exit(1) 42 | 43 | 44 | if __name__ == '__main__': 45 | main() 46 | -------------------------------------------------------------------------------- /.github/workflows/linter.yml: -------------------------------------------------------------------------------- 1 | name: Linter and Tests Runners 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | lint: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Set up Python 3.8 17 | uses: actions/setup-python@v1 18 | with: 19 | python-version: 3.8 20 | 21 | - name: Run shellcheck 22 | run: | 23 | shellcheck -x pieman.sh 24 | shellcheck -e SC2148 helpers/*.sh 25 | shellcheck -e SC2148,SC2153 bootstrap/*.sh 26 | find devices/ -name "*.sh" | xargs shellcheck -e SC2148 27 | find test/ -name "*.sh" | xargs shellcheck -x -e SC2148 28 | 29 | - name: Install pylint 30 | run: pip install pylint 31 | 32 | - name: Install pieman package 33 | run: cd pieman && python3 setup.py install 34 | 35 | - name: Run pylint 36 | run: find -name "*.py" -not -path "./.git/*" | xargs pylint --disable=R0801 37 | 38 | test: 39 | runs-on: ubuntu-latest 40 | 41 | env: 42 | TERM: xterm 43 | 44 | steps: 45 | - uses: actions/checkout@v2 46 | 47 | - name: Set up Python 3.8 48 | uses: actions/setup-python@v1 49 | with: 50 | python-version: 3.8 51 | 52 | - name: Install shunit2 53 | run: sudo apt install shunit2 54 | 55 | - name: Install pieman package 56 | run: cd pieman && python3 setup.py install 57 | 58 | - name: Run tests 59 | run: | 60 | python3 pieman/test/runtest.py 61 | ./test/test_essentials.sh 62 | ./test/test_functions.sh 63 | 64 | -------------------------------------------------------------------------------- /pieman/setup.py: -------------------------------------------------------------------------------- 1 | """ Script for building the Pieman package. """ 2 | 3 | from setuptools import setup 4 | 5 | try: 6 | import pypandoc 7 | LONG_DESCRIPTION = pypandoc.convert('README.md', 'rst') 8 | except (ImportError, OSError): 9 | # OSError is raised when pandoc is not installed. 10 | LONG_DESCRIPTION = ('Utilities written in Python which are used by ' 11 | 'Pieman, script for creating custom OS images for ' 12 | 'single-board computers.') 13 | 14 | 15 | with open('requirements.txt') as outfile: 16 | REQUIREMENTS_LIST = outfile.read().splitlines() 17 | 18 | 19 | setup(name='pieman', 20 | version='0.19.0', 21 | description='Pieman package', 22 | long_description=LONG_DESCRIPTION, 23 | url='https://github.com/tolstoyevsky/pieman', 24 | author='Evgeny Golyshev', 25 | maintainer='Evgeny Golyshev', 26 | maintainer_email='eugulixes@gmail.com', 27 | license='https://gnu.org/licenses/gpl-3.0.txt', 28 | scripts=[ 29 | 'bin/apk_tools_version.py', 30 | 'bin/bsc.py', 31 | 'bin/bscd.py', 32 | 'bin/check_mutually_exclusive_params.py', 33 | 'bin/check_redis.py', 34 | 'bin/check_wpa_passphrase.py', 35 | 'bin/depend_on.py', 36 | 'bin/du.py', 37 | 'bin/image_attrs.py', 38 | 'bin/preprocessor.py', 39 | 'bin/render.py', 40 | 'bin/wget.py', 41 | ], 42 | packages=['pieman'], 43 | include_package_data=True, 44 | data_files=[ 45 | ('', ['requirements.txt']), 46 | ('pieman', ['pieman/build_status_codes']), 47 | ], 48 | install_requires=REQUIREMENTS_LIST) 49 | -------------------------------------------------------------------------------- /pieman/bin/wget.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (C) 2019 Denis Gavrilyuk 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | """Very limited alternative of GNU Wget, but enough to be a drop-in 18 | replacement in Pieman. 19 | """ 20 | 21 | import argparse 22 | import sys 23 | 24 | from pieman.util import download 25 | 26 | 27 | def main(): 28 | """The main entry point.""" 29 | 30 | parser = argparse.ArgumentParser() 31 | parser.add_argument('url', help='the URL to be downloaded') 32 | parser.add_argument('--output-document', '-O', 33 | help='writes the document to the specified file') 34 | parser.add_argument('-quiet', '-q', action='store_true', 35 | help='makes {} mute'.format(sys.argv[0])) 36 | args = parser.parse_args() 37 | 38 | url = args.url 39 | output_document = args.output_document 40 | quiet = args.quiet 41 | 42 | path = output_document if output_document else url.split('/')[-1] 43 | download(url, path, quiet) 44 | 45 | 46 | if __name__ == '__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /devices/rpi-2-b/alpine-3.12-armhf/README.md: -------------------------------------------------------------------------------- 1 | Alpine Linux is a lightweight, independently developed and non-commercial Linux distribution. `rpi-2-b/alpine-3.12-armhf` allows building custom 32-bit Alpine [3.12](https://alpinelinux.org/posts/Alpine-3.12.0-released.html) images for [Raspberry Pi 2 B](https://raspberrypi.org/products/raspberry-pi-2-model-b/), [Raspberry Pi 3 B](https://raspberrypi.org/products/raspberry-pi-3-model-b/) and [Raspberry Pi 3 B+](https://raspberrypi.org/products/raspberry-pi-3-model-b-plus/). 2 | 3 | ## What's in the distribution? 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
PackageVersion
Essential components
Linux kernel5.4.43
musl1.1.24
GCC9.3.0
OpenRC0.42.1
Development tools
Go1.13.11
PHP7.3.19
Python3.8.3
Ruby2.7.1
Server software
Apache HTTP Server2.4.43
Nginx1.18.0
PostgreSQL12.3
MariaDB10.4.13
68 | -------------------------------------------------------------------------------- /devices/rpi-b/raspberrypios-buster-armhf/pieman.yml: -------------------------------------------------------------------------------- 1 | # Maintainer: Evgeny Golyshev 2 | 3 | raspberrypios-buster-armhf: 4 | repos: 5 | - http://archive.raspbian.org/raspbian 6 | - http://archive.raspberrypi.org/debian 7 | boot: 8 | - cmdline.txt 9 | - config.txt 10 | # For RPi B Plus and RPi Zero 11 | - /boot/bcm2708-rpi-b-plus.dtb 12 | - /boot/bcm2708-rpi-zero-w.dtb 13 | - /boot/bcm2709-rpi-2-b.dtb 14 | - /boot/bcm2710-rpi-3-b.dtb 15 | - /boot/bcm2711-rpi-4-b.dtb 16 | - /boot/overlays 17 | - /boot/kernel.img 18 | - /boot/kernel7.img 19 | - /boot/kernel7l.img 20 | - https://github.com/raspberrypi/firmware/raw/master/boot/bootcode.bin 21 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup.dat 22 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_cd.dat 23 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup_x.dat 24 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup4.dat 25 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup4cd.dat 26 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup4db.dat 27 | - https://github.com/raspberrypi/firmware/raw/master/boot/fixup4x.dat 28 | - https://github.com/raspberrypi/firmware/raw/master/boot/start.elf 29 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_cd.elf 30 | - https://github.com/raspberrypi/firmware/raw/master/boot/start_x.elf 31 | - https://github.com/raspberrypi/firmware/raw/master/boot/start4.elf 32 | - https://github.com/raspberrypi/firmware/raw/master/boot/start4cd.elf 33 | - https://github.com/raspberrypi/firmware/raw/master/boot/start4db.elf 34 | - https://github.com/raspberrypi/firmware/raw/master/boot/start4x.elf 35 | includes: systemd-sysv 36 | kernel: 37 | package: raspberrypi-kernel 38 | -------------------------------------------------------------------------------- /pieman/bin/check_redis.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Copyright (C) 2019 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | """Utility intended to check if the Redis server is available. 18 | It returns a zero exit status if everything is ok and non-zero exit status if 19 | there is a problem to connect to the specified Redis server. 20 | """ 21 | 22 | import sys 23 | from argparse import ArgumentParser 24 | 25 | from redis.exceptions import RedisError 26 | 27 | from pieman import util 28 | 29 | 30 | def main(): 31 | """The main entry point. """ 32 | 33 | parser = ArgumentParser() 34 | parser.add_argument('-H', '--redis-host', default='127.0.0.1', 35 | help='Redis server host', metavar='REDIS_HOST') 36 | parser.add_argument('-P', '--redis-port', default='6379', 37 | help='server pid file name', metavar='REDIS_PORT', 38 | type=int) 39 | 40 | args = parser.parse_args() 41 | 42 | try: 43 | util.connect_to_redis(args.redis_host, args.redis_port) 44 | except RedisError: 45 | sys.exit(1) 46 | 47 | 48 | if __name__ == '__main__': 49 | main() 50 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-xenial-armhf/README.md: -------------------------------------------------------------------------------- 1 | Ubuntu is a free and open source software which is developed by [Canonical](https://canonical.com/). `rpi-2-b/ubuntu-xenial-armhf` allows building custom 32-bit Ubuntu [Xenial](https://wiki.ubuntu.com/XenialXerus/ReleaseNotes) images for [Raspberry Pi 2 B](https://raspberrypi.org/products/raspberry-pi-2-model-b/). Note that the kernel package, which the system is based on, is located in the universe area of the official archive. It means that the package is a [community-maintained](https://wiki.ubuntu.com/MOTU/) and not supported by the Ubuntu Security team. 2 | 3 | ## What's in the distribution? 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
PackageVersion
Essential components
Linux kernel4.4
glibc2.23
GCC5.3
systemd229
Development tools
Go1.6
PHP7.0
Python3.5.1
Ruby2.3
Server software
Apache HTTP Server2.4.18
Nginx1.10.3
PostgreSQL9.5
MariaDB10.0.31
68 | -------------------------------------------------------------------------------- /devices/rpi-3-b/ubuntu-bionic-arm64/README.md: -------------------------------------------------------------------------------- 1 | Ubuntu is a free and open source software which is developed by [Canonical](https://canonical.com/). `rpi-3-b/ubuntu-bionic-arm64` allows building custom 64-bit Ubuntu [Bionic](https://wiki.ubuntu.com/BionicBeaver/ReleaseNotes) images for [Raspberry Pi 3 B](https://raspberrypi.org/products/raspberry-pi-3-model-b/). Note that the kernel package, which the system is based on, is located in the universe area of the official archive. It means that the package is a [community-maintained](https://wiki.ubuntu.com/MOTU/) and not supported by the Ubuntu Security team. 2 | 3 | ## What's in the distribution? 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
PackageVersion
Essential components
Linux kernel4.15
glibc2.27
GCC7.3
systemd237
Development tools
Go1.10
PHP7.2
Python3.6.5
Ruby2.5.1
Server software
Apache HTTP Server2.4.29
Nginx1.14.0
PostgreSQL10.4
MariaDB10.1.29
68 | -------------------------------------------------------------------------------- /bootstrap/50-firstboot.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | check_if_variable_is_set ETC 17 | 18 | if is_alpine; then 19 | info "Adding the local service to the default runlevel" 20 | chroot_exec rc-update add local default 21 | fi 22 | 23 | info "Preparing ${FIRSTBOOT}" 24 | 25 | touch "${FIRSTBOOT}" 26 | chmod +x "${FIRSTBOOT}" 27 | 28 | for script in files/firstboot/*.sh; do 29 | cat "${script}" >> "${FIRSTBOOT}" 30 | done 31 | 32 | if is_alpine; then 33 | install_exec "${FIRSTBOOT}" "${ETC}"/local.d/90-firstboot.start 34 | echo "rm -f /etc/local.d/90-firstboot.start" >> "${ETC}"/local.d/90-firstboot.start 35 | elif is_debian_based; then 36 | install_exec "${FIRSTBOOT}" "${ETC}"/rc.firstboot 37 | install_exec files/etc/rc.local "${ETC}"/rc.local 38 | 39 | # /etc/rc.firstboot has to destroy itself and its traces after first run. 40 | cat <> "${ETC}"/rc.firstboot 41 | rm -f /etc/rc.firstboot 42 | sed -i '/.*rc.firstboot/d' /etc/rc.local 43 | EOT 44 | 45 | sed -i "/exit 0/d" "${ETC}"/rc.local 46 | echo "/etc/rc.firstboot" >> "${ETC}"/rc.local 47 | echo "exit 0" >> "${ETC}"/rc.local 48 | fi 49 | -------------------------------------------------------------------------------- /devices/rpi-3-b-plus/ubuntu-focal-armhf/README.md: -------------------------------------------------------------------------------- 1 | Ubuntu is a free and open source software which is developed by [Canonical](https://canonical.com/). `rpi-3-b-plus/ubuntu-focal-armhf` allows building custom 32-bit Ubuntu [Focal](https://wiki.ubuntu.com/FocalFossa/ReleaseNotes) images for [Raspberry Pi 3 B+](https://www.raspberrypi.org/products/raspberry-pi-3-model-b-plus/). Note that the kernel package, which the system is based on, is located in the universe area of the official archive. It means that the package is a [community-maintained](https://wiki.ubuntu.com/MOTU/) and not supported by the Ubuntu Security team. 2 | 3 | ## What's in the distribution? 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
PackageVersion
Essential components
Linux kernel5.4.0
glibc2.31
GCC9.3.0
systemd245.4
Development tools
Go1.13
PHP7.4
Python3.8.2
Ruby2.7
Server software
Apache HTTP Server2.4.41
Nginx1.17.10
PostgreSQL12
MariaDB10.3.22
68 | -------------------------------------------------------------------------------- /helpers/image-attribs.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018-2021 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Gets the values the specified image attribute using image_attrs.py. If its 17 | # exit code is different from 0, interrupt the execution of the script and 18 | # exit. 19 | # Globals: 20 | # OS 21 | # YML_FILE 22 | # Arguments: 23 | # Image attribute 24 | # Returns: 25 | # Image attribute value 26 | get_attr() { 27 | local output="" 28 | 29 | if ! output=$(preprocessor.py "${YML_FILE}" "${OS}" | image_attrs.py "${OS}" "$@" 2>&1); then 30 | fatal "while getting the specified attribute from ${YML_FILE}" \ 31 | "occurred the following error: ${output}." 32 | do_exit 33 | fi 34 | 35 | echo "${output}" 36 | } 37 | 38 | # Gets the values the specified image attribute using image_attrs.py. 39 | # If image_attrs.py could not succeed, the function does nothing. 40 | # Globals: 41 | # OS 42 | # YML_FILE 43 | # Arguments: 44 | # Image attribute 45 | # Returns: 46 | # Image attribute value 47 | get_attr_or_nothing() { 48 | preprocessor.py "${YML_FILE}" "${OS}" | image_attrs.py "${OS}" "$@" 2> /dev/null || /bin/true 49 | } 50 | -------------------------------------------------------------------------------- /keys/raspberrypios/raspberry-pi-archive-signing.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: GnuPG v1.4.12 (GNU/Linux) 3 | 4 | mQENBE/d7o8BCACrwqQacGJfn3tnMzGui6mv2lLxYbsOuy/+U4rqMmGEuo3h9m92 5 | 30E2EtypsoWczkBretzLUCFv+VUOxaA6sV9+puTqYGhhQZFuKUWcG7orf7QbZRuu 6 | TxsEUepW5lg7MExmAu1JJzqM0kMQX8fVyWVDkjchZ/is4q3BPOUCJbUJOsE+kK/6 7 | 8kW6nWdhwSAjfDh06bA5wvoXNjYoDdnSZyVdcYCPEJXEg5jfF/+nmiFKMZBraHwn 8 | eQsepr7rBXxNcEvDlSOPal11fg90KXpy7Umre1UcAZYJdQeWcHu7X5uoJx/MG5J8 9 | ic6CwYmDaShIFa92f8qmFcna05+lppk76fsnABEBAAG0IFJhc3BiZXJyeSBQaSBB 10 | cmNoaXZlIFNpZ25pbmcgS2V5iQE4BBMBAgAiBQJP3e6PAhsDBgsJCAcDAgYVCAIJ 11 | CgsEFgIDAQIeAQIXgAAKCRCCsSmSf6MwPk6vB/9pePB3IukU9WC9Bammh3mpQTvL 12 | OifbkzHkmAYxzjfK6D2I8pT0xMxy949+ThzJ7uL60p6T/32ED9DR3LHIMXZvKtuc 13 | mQnSiNDX03E2p7lIP/htoxW2hDP2n8cdlNdt0M9IjaWBppsbO7IrDppG2B1aRLni 14 | uD7v8bHRL2mKTtIDLX42Enl8aLAkJYgNWpZyPkDyOqamjijarIWjGEPCkaURF7g4 15 | d44HvYhpbLMOrz1m6N5Bzoa5+nq3lmifeiWKxioFXU+Hy5bhtAM6ljVb59hbD2ra 16 | X4+3LXC9oox2flmQnyqwoyfZqVgSQa0B41qEQo8t1bz6Q1Ti7fbMLThmbRHiuQEN 17 | BE/d7o8BCADNlVtBZU63fm79SjHh5AEKFs0C3kwa0mOhp9oas/haDggmhiXdzeD3 18 | 49JWz9ZTx+vlTq0s+I+nIR1a+q+GL+hxYt4HhxoA6vlDMegVfvZKzqTX9Nr2VqQa 19 | S4Kz3W5ULv81tw3WowK6i0L7pqDmvDqgm73mMbbxfHD0SyTt8+fk7qX6Ag2pZ4a9 20 | ZdJGxvASkh0McGpbYJhk1WYD+eh4fqH3IaeJi6xtNoRdc5YXuzILnp+KaJyPE5CR 21 | qUY5JibOD3qR7zDjP0ueP93jLqmoKltCdN5+yYEExtSwz5lXniiYOJp8LWFCgv5h 22 | m8aYXkcJS1xVV9Ltno23YvX5edw9QY4hABEBAAGJAR8EGAECAAkFAk/d7o8CGwwA 23 | CgkQgrEpkn+jMD5Figf/dIC1qtDMTbu5IsI5uZPX63xydaExQNYf98cq5H2fWF6O 24 | yVR7ERzA2w33hI0yZQrqO6pU9SRnHRxCFvGv6y+mXXXMRcmjZG7GiD6tQWeN/3wb 25 | EbAn5cg6CJ/Lk/BI4iRRfBX07LbYULCohlGkwBOkRo10T+Ld4vCCnBftCh5x2OtZ 26 | TOWRULxP36y2PLGVNF+q9pho98qx+RIxvpofQM/842ZycjPJvzgVQsW4LT91KYAE 27 | 4TVf6JjwUM6HZDoiNcX6d7zOhNfQihXTsniZZ6rky287htsWVDNkqOi5T3oTxWUo 28 | m++/7s3K3L0zWopdhMVcgg6Nt9gcjzqN1c0gy55L/g== 29 | =mNSj 30 | -----END PGP PUBLIC KEY BLOCK----- 31 | -------------------------------------------------------------------------------- /bootstrap/11-locale.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017 Denis Mosolov 2 | # Copyright (C) 2018 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | if ! check_if_variable_is_set TIME_ZONE; then 18 | >&2 echo "TIME_ZONE is not specified" 19 | exit 1 20 | fi 21 | 22 | info "setting up locale" 23 | 24 | if is_debian_based; then 25 | if ! grep -q "${LOCALE}" "${ETC}"/locale.gen; then 26 | fatal "could not find locale ${LOCALE}" 27 | do_exit 28 | fi 29 | fi 30 | 31 | if is_debian || is_devuan || is_raspberrypios; then 32 | sed -i "s/^# *\($LOCALE\)/\1/" "${ETC}"/locale.gen 33 | 34 | chroot_exec locale-gen 35 | elif is_ubuntu; then 36 | chroot_exec locale-gen "${LOCALE}" 37 | fi 38 | 39 | send_request_to_bsc_server SET_UP_LOCALE_CODE 40 | 41 | info "setting up timezone" 42 | # Set timezone 43 | # https://bugs.launchpad.net/ubuntu/+source/tzdata/+bug/1554806 44 | chroot_exec ln -fs /usr/share/zoneinfo/"${TIME_ZONE}" /etc/localtime 45 | 46 | 47 | if is_alpine; then 48 | echo "${TIME_ZONE}" > "${ETC}"/timezone 49 | elif is_debian_based; then 50 | chroot_exec dpkg-reconfigure -f noninteractive tzdata 51 | fi 52 | 53 | send_request_to_bsc_server SET_UP_TIMEZONE_CODE 54 | -------------------------------------------------------------------------------- /keys/raspberrypios/mike-thompson.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: GnuPG v1.4.12 (GNU/Linux) 3 | 4 | mQENBE94wmkBCADPW5ga8ZyIsW0pym3c+o7l/N1ipRfs2+9HaEWeyPZS6wdTdSp3 5 | Wo0OOv3rGQDGclbvsrMZoJFzxfsADoMfPkToWg+pY4w3xkjZt4Mh7gO/kDsaOMDz 6 | OQS2JCHQ3BgysEdiSzy1dMf2N/ziKItOUK8t2gI3QWLwe9eXg+Uv4VUtQO+TRz7o 7 | qLMvbg32C1ahDfi416+Y7mopFTHh8qBOhZNGgdq240Vr6B9NCGywO2tl+8Nd87BS 8 | fVgCTPtvabcf1RChQd6yH4K5WS0IFt8h5vkcgpJXa7sxUyJH/ysnUchsYA+2B0cP 9 | UKUZrraRMfHuXhI2VNpRuZZSoSUn7/hkX4BlABEBAAG0Sk1pa2UgVGhvbXBzb24g 10 | KFJhc3BiZXJyeSBQaSBEZWJpYW4gYXJtaGYgQVJNdjYrVkZQKSA8bXB0aG9tcHNv 11 | bkBnbWFpbC5jb20+iQE4BBMBAgAiBQJPeMJpAhsDBgsJCAcDAgYVCAIJCgsEFgID 12 | AQIeAQIXgAAKCRCRZZONkP3dLqEKCADE++X4BtDYxB1mONtOsKSPWE7dPzOP/Is/ 13 | x0+BnJahVf9rSZh26NWANwUMfVrZ9ImU+SHnFsuYGpJhb6mjauScXtfN4BrdptC3 14 | aPBhlyAUst23r/Cw4r4zWJuYerLNAsKmzO3Gjk8Yi6mH80UtgwWFKdQcdVTelyVI 15 | zRB/2RtilHtjpzHZGDeWi6wFxTGnd2wtHJ+h+HGSySofKAzM12ZtniTHZuTSijii 16 | I90thwiydBEG4uIcuMQRyBeu3r5wCk4v+L0a/HZ4hrH2nU/65OxQdSSnCSjSHqcg 17 | 19T/+NN8hFQ51BSXdNJeGQRbPqB//6yA9zRMjFOhLhTod1sIeWEVuQENBE94wmkB 18 | CACgDGyg0/0h2cgf5BrEXtDAwvPwPDH4IxCgmHA7fqZ+IeXFXDCIKtOdFVEmLGQY 19 | yr6jL6M4P+DtgVnoru7jB8oPt0YcWRFztdPdIZgtL5E5rBDNusdSHn8DNXQizILm 20 | KBRdoVywqS4Peesu1RuW4srQk/5vaXtCTuAjANISJsOIa+NIHIXufFERZN2kdO+W 21 | Ch/IMYlmTsm3ino5a4kHL48H1LhVzUKLHR4yJ2K6W4HPCJZe6q8rJSqeyjtFUTu1 22 | bXZ0PI/AVAHfCTY3z6BXhhVrx64ArwxcWvsbOurnKVaypO47Dvn0k4z9QCasFu6i 23 | rmermJTDSmCEvqHDTm93xY5fABEBAAGJAR8EGAECAAkFAk94wmkCGwwACgkQkWWT 24 | jZD93S4swwgAojOdjjQh0PFy/2qpHlVBJiDW2PJIrgMtuy8JHgVOHFq1vNB5FEoj 25 | W/bxiok69OyKawu2cs6rg2eE3Ft5BoWErkXyBFYd77aa+E4wLp2bh5lNoY3TAO9y 26 | FhfDAkwViZ3P/BozL4uOcMKXLi+D5JmuTtRgtlI9/UjYG38kMju2wvZDxOiokA+S 27 | mpS3eF+NTMy5wxxHcMwBilX+Xm64cQp8EQROYXgjW4lEuJAaKWsS/ZEBqIeZHlaM 28 | RYDJ6Y2ubJVFpp8YYCvbU/CuUzPTs1wnTBseXAskwdUEms+5IxJV3ovy44gU8d73 29 | kDxVdsBg/Yhd7QORY6ZRi27AxYAsM3329g== 30 | =gzRN 31 | -----END PGP PUBLIC KEY BLOCK----- 32 | -------------------------------------------------------------------------------- /pieman/bin/check_wpa_passphrase.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (C) 2019 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | """Utility intended for checking if the specified WPA passphrase is valid. The 18 | following two checks were borrowed from wpa_supplicant/wpa_passphrase.c. 19 | The utility exits with: 20 | * 0 when everything is fine; 21 | * 1 when the length of the specified passphrase is not between 8 and 63 22 | characters; 23 | * 2 when the specified passphrase contains special characters. 24 | """ 25 | 26 | import argparse 27 | import sys 28 | 29 | 30 | SPECIAL_CHARACTERS = [chr(n) for n in range(32)] + ['\x7f'] 31 | 32 | 33 | def main(): 34 | """The main entry point. """ 35 | 36 | parser = argparse.ArgumentParser() 37 | parser.add_argument('passphrase', help='WPA passphrase which is going to ' 38 | 'be passed to wpa_passphrase') 39 | args = parser.parse_args() 40 | 41 | passphrase_len = len(args.passphrase) 42 | if passphrase_len < 8 or passphrase_len > 63: 43 | sys.exit(1) 44 | 45 | for char in args.passphrase: 46 | if char in SPECIAL_CHARACTERS: 47 | sys.exit(2) 48 | 49 | 50 | if __name__ == '__main__': 51 | main() 52 | -------------------------------------------------------------------------------- /helpers/apk.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018-2021 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Gets the Alpine Package Keeper (APK) version for the specified version of 17 | # Alpine Linux. 18 | # Globals: 19 | # None 20 | # Arguments: 21 | # Version of Alpine Linux 22 | # Returns: 23 | # Alpine Package Keeper version 24 | get_apk_tools_version() { 25 | local alpine_version=$1 26 | 27 | apk_tools_version.py --alpine-version="${alpine_version}" 28 | } 29 | 30 | # Runs apk.static to build a chroot environment. 31 | # Globals: 32 | # BASE_PACKAGES 33 | # ETC 34 | # OS 35 | # PIECES 36 | # R 37 | # TOOLSET_FULL_PATH 38 | # Arguments: 39 | # None 40 | # Returns: 41 | # None 42 | run_apk_static() { 43 | local primary_repo 44 | 45 | primary_repo="$(get_attr repos | head -n1)" 46 | 47 | mkdir -p "${R}"/usr/bin 48 | 49 | install_user_mode_emulation_binary 50 | 51 | # Ignore SC2086 since BASE_PACKAGES shouldn't be double-quoted. 52 | # shellcheck disable=SC2086 53 | "${TOOLSET_FULL_PATH}/apk/${PIECES[1]}/apk.static" -X "${primary_repo}/v${PIECES[1]}/main" -U --allow-untrusted --root "${R}" --initdb add alpine-base ${BASE_PACKAGES} 54 | 55 | echo "nameserver 8.8.8.8" > "${ETC}"/resolv.conf 56 | } 57 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-bionic-armhf/config.txt: -------------------------------------------------------------------------------- 1 | # For more options and information see 2 | # http://rpf.io/configtxt 3 | # Some settings may impact device functionality. See link above for details 4 | 5 | # uncomment if you get no picture on HDMI for a default "safe" mode 6 | #hdmi_safe=1 7 | 8 | # uncomment this if your display has a black border of unused pixels visible 9 | # and your display can output without overscan 10 | #disable_overscan=1 11 | 12 | # uncomment the following to adjust overscan. Use positive numbers if console 13 | # goes off screen, and negative if there is too much border 14 | #overscan_left=16 15 | #overscan_right=16 16 | #overscan_top=16 17 | #overscan_bottom=16 18 | 19 | # uncomment to force a console size. By default it will be display's size minus 20 | # overscan. 21 | #framebuffer_width=1280 22 | #framebuffer_height=720 23 | 24 | # uncomment if hdmi display is not detected and composite is being output 25 | #hdmi_force_hotplug=1 26 | 27 | # uncomment to force a specific HDMI mode (this will force VGA) 28 | #hdmi_group=1 29 | #hdmi_mode=1 30 | 31 | # uncomment to force a HDMI mode rather than DVI. This can make audio work in 32 | # DMT (computer monitor) modes 33 | #hdmi_drive=2 34 | 35 | # uncomment to increase signal to HDMI, if you have interference, blanking, or 36 | # no display 37 | #config_hdmi_boost=4 38 | 39 | # uncomment for composite PAL 40 | #sdtv_mode=2 41 | 42 | #uncomment to overclock the arm. 700 MHz is the default. 43 | #arm_freq=800 44 | 45 | # Uncomment some or all of these to enable the optional hardware interfaces 46 | #dtparam=i2c_arm=on 47 | #dtparam=i2s=on 48 | #dtparam=spi=on 49 | 50 | # Uncomment this to enable the lirc-rpi module 51 | #dtoverlay=lirc-rpi 52 | 53 | # Additional overlays and parameters are documented /boot/overlays/README 54 | 55 | # Enable audio (loads snd_bcm2835) 56 | dtparam=audio=on 57 | 58 | hdmi_drive=1 59 | hdmi_group=2 60 | hdmi_mode=1 61 | hdmi_mode=87 62 | hdmi_cvt 800 480 60 6 0 0 0 63 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-xenial-armhf/config.txt: -------------------------------------------------------------------------------- 1 | # For more options and information see 2 | # http://rpf.io/configtxt 3 | # Some settings may impact device functionality. See link above for details 4 | 5 | # uncomment if you get no picture on HDMI for a default "safe" mode 6 | #hdmi_safe=1 7 | 8 | # uncomment this if your display has a black border of unused pixels visible 9 | # and your display can output without overscan 10 | #disable_overscan=1 11 | 12 | # uncomment the following to adjust overscan. Use positive numbers if console 13 | # goes off screen, and negative if there is too much border 14 | #overscan_left=16 15 | #overscan_right=16 16 | #overscan_top=16 17 | #overscan_bottom=16 18 | 19 | # uncomment to force a console size. By default it will be display's size minus 20 | # overscan. 21 | #framebuffer_width=1280 22 | #framebuffer_height=720 23 | 24 | # uncomment if hdmi display is not detected and composite is being output 25 | #hdmi_force_hotplug=1 26 | 27 | # uncomment to force a specific HDMI mode (this will force VGA) 28 | #hdmi_group=1 29 | #hdmi_mode=1 30 | 31 | # uncomment to force a HDMI mode rather than DVI. This can make audio work in 32 | # DMT (computer monitor) modes 33 | #hdmi_drive=2 34 | 35 | # uncomment to increase signal to HDMI, if you have interference, blanking, or 36 | # no display 37 | #config_hdmi_boost=4 38 | 39 | # uncomment for composite PAL 40 | #sdtv_mode=2 41 | 42 | #uncomment to overclock the arm. 700 MHz is the default. 43 | #arm_freq=800 44 | 45 | # Uncomment some or all of these to enable the optional hardware interfaces 46 | #dtparam=i2c_arm=on 47 | #dtparam=i2s=on 48 | #dtparam=spi=on 49 | 50 | # Uncomment this to enable the lirc-rpi module 51 | #dtoverlay=lirc-rpi 52 | 53 | # Additional overlays and parameters are documented /boot/overlays/README 54 | 55 | # Enable audio (loads snd_bcm2835) 56 | dtparam=audio=on 57 | 58 | hdmi_drive=1 59 | hdmi_group=2 60 | hdmi_mode=1 61 | hdmi_mode=87 62 | hdmi_cvt 800 480 60 6 0 0 0 63 | -------------------------------------------------------------------------------- /devices/rpi-3-b/ubuntu-bionic-arm64/config.txt: -------------------------------------------------------------------------------- 1 | # For more options and information see 2 | # http://rpf.io/configtxt 3 | # Some settings may impact device functionality. See link above for details 4 | 5 | # uncomment if you get no picture on HDMI for a default "safe" mode 6 | #hdmi_safe=1 7 | 8 | # uncomment this if your display has a black border of unused pixels visible 9 | # and your display can output without overscan 10 | #disable_overscan=1 11 | 12 | # uncomment the following to adjust overscan. Use positive numbers if console 13 | # goes off screen, and negative if there is too much border 14 | #overscan_left=16 15 | #overscan_right=16 16 | #overscan_top=16 17 | #overscan_bottom=16 18 | 19 | # uncomment to force a console size. By default it will be display's size minus 20 | # overscan. 21 | #framebuffer_width=1280 22 | #framebuffer_height=720 23 | 24 | # uncomment if hdmi display is not detected and composite is being output 25 | #hdmi_force_hotplug=1 26 | 27 | # uncomment to force a specific HDMI mode (this will force VGA) 28 | #hdmi_group=1 29 | #hdmi_mode=1 30 | 31 | # uncomment to force a HDMI mode rather than DVI. This can make audio work in 32 | # DMT (computer monitor) modes 33 | #hdmi_drive=2 34 | 35 | # uncomment to increase signal to HDMI, if you have interference, blanking, or 36 | # no display 37 | #config_hdmi_boost=4 38 | 39 | # uncomment for composite PAL 40 | #sdtv_mode=2 41 | 42 | #uncomment to overclock the arm. 700 MHz is the default. 43 | #arm_freq=800 44 | 45 | # Uncomment some or all of these to enable the optional hardware interfaces 46 | #dtparam=i2c_arm=on 47 | #dtparam=i2s=on 48 | #dtparam=spi=on 49 | 50 | # Uncomment this to enable the lirc-rpi module 51 | #dtoverlay=lirc-rpi 52 | 53 | # Additional overlays and parameters are documented /boot/overlays/README 54 | 55 | # Enable audio (loads snd_bcm2835) 56 | dtparam=audio=on 57 | 58 | hdmi_drive=1 59 | hdmi_group=2 60 | hdmi_mode=1 61 | hdmi_mode=87 62 | hdmi_cvt 800 480 60 6 0 0 0 63 | -------------------------------------------------------------------------------- /devices/rpi-3-b-plus/ubuntu-focal-armhf/config.txt: -------------------------------------------------------------------------------- 1 | # For more options and information see 2 | # http://rpf.io/configtxt 3 | # Some settings may impact device functionality. See link above for details 4 | 5 | # uncomment if you get no picture on HDMI for a default "safe" mode 6 | #hdmi_safe=1 7 | 8 | # uncomment this if your display has a black border of unused pixels visible 9 | # and your display can output without overscan 10 | #disable_overscan=1 11 | 12 | # uncomment the following to adjust overscan. Use positive numbers if console 13 | # goes off screen, and negative if there is too much border 14 | #overscan_left=16 15 | #overscan_right=16 16 | #overscan_top=16 17 | #overscan_bottom=16 18 | 19 | # uncomment to force a console size. By default it will be display's size minus 20 | # overscan. 21 | #framebuffer_width=1280 22 | #framebuffer_height=720 23 | 24 | # uncomment if hdmi display is not detected and composite is being output 25 | #hdmi_force_hotplug=1 26 | 27 | # uncomment to force a specific HDMI mode (this will force VGA) 28 | #hdmi_group=1 29 | #hdmi_mode=1 30 | 31 | # uncomment to force a HDMI mode rather than DVI. This can make audio work in 32 | # DMT (computer monitor) modes 33 | #hdmi_drive=2 34 | 35 | # uncomment to increase signal to HDMI, if you have interference, blanking, or 36 | # no display 37 | #config_hdmi_boost=4 38 | 39 | # uncomment for composite PAL 40 | #sdtv_mode=2 41 | 42 | #uncomment to overclock the arm. 700 MHz is the default. 43 | #arm_freq=800 44 | 45 | # Uncomment some or all of these to enable the optional hardware interfaces 46 | #dtparam=i2c_arm=on 47 | #dtparam=i2s=on 48 | #dtparam=spi=on 49 | 50 | # Uncomment this to enable the lirc-rpi module 51 | #dtoverlay=lirc-rpi 52 | 53 | # Additional overlays and parameters are documented /boot/overlays/README 54 | 55 | # Enable audio (loads snd_bcm2835) 56 | dtparam=audio=on 57 | 58 | hdmi_drive=1 59 | hdmi_group=2 60 | hdmi_mode=1 61 | hdmi_mode=87 62 | hdmi_cvt 800 480 60 6 0 0 0 63 | -------------------------------------------------------------------------------- /devices/rpi-b/raspberrypios-buster-armhf/config.txt: -------------------------------------------------------------------------------- 1 | # For more options and information see 2 | # http://rpf.io/configtxt 3 | # Some settings may impact device functionality. See link above for details 4 | 5 | # uncomment if you get no picture on HDMI for a default "safe" mode 6 | #hdmi_safe=1 7 | 8 | # uncomment this if your display has a black border of unused pixels visible 9 | # and your display can output without overscan 10 | #disable_overscan=1 11 | 12 | # uncomment the following to adjust overscan. Use positive numbers if console 13 | # goes off screen, and negative if there is too much border 14 | #overscan_left=16 15 | #overscan_right=16 16 | #overscan_top=16 17 | #overscan_bottom=16 18 | 19 | # uncomment to force a console size. By default it will be display's size minus 20 | # overscan. 21 | #framebuffer_width=1280 22 | #framebuffer_height=720 23 | 24 | # uncomment if hdmi display is not detected and composite is being output 25 | #hdmi_force_hotplug=1 26 | 27 | # uncomment to force a specific HDMI mode (this will force VGA) 28 | #hdmi_group=1 29 | #hdmi_mode=1 30 | 31 | # uncomment to force a HDMI mode rather than DVI. This can make audio work in 32 | # DMT (computer monitor) modes 33 | #hdmi_drive=2 34 | 35 | # uncomment to increase signal to HDMI, if you have interference, blanking, or 36 | # no display 37 | #config_hdmi_boost=4 38 | 39 | # uncomment for composite PAL 40 | #sdtv_mode=2 41 | 42 | #uncomment to overclock the arm. 700 MHz is the default. 43 | #arm_freq=800 44 | 45 | # Uncomment some or all of these to enable the optional hardware interfaces 46 | #dtparam=i2c_arm=on 47 | #dtparam=i2s=on 48 | #dtparam=spi=on 49 | 50 | # Uncomment this to enable the lirc-rpi module 51 | #dtoverlay=lirc-rpi 52 | 53 | # Additional overlays and parameters are documented /boot/overlays/README 54 | 55 | # Enable audio (loads snd_bcm2835) 56 | dtparam=audio=on 57 | 58 | hdmi_drive=1 59 | hdmi_group=2 60 | hdmi_mode=1 61 | hdmi_mode=87 62 | hdmi_cvt 800 480 60 6 0 0 0 63 | -------------------------------------------------------------------------------- /pieman/bin/depend_on.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (C) 2019 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | """Utility intended for checking if the dependency environment variables, 18 | passed as the 2nd, 3rd, etc arguments to the utility, are set to true (if bool) 19 | or simply specified (in other cases) when the dependent environment variable, 20 | passed as the first argument to the utility, is set to true (if bool) or simply 21 | specified (in other cases). 22 | """ 23 | 24 | import argparse 25 | import os 26 | import sys 27 | 28 | 29 | def main(): 30 | """The main entry point. """ 31 | 32 | parser = argparse.ArgumentParser() 33 | parser.add_argument('var', help='name of dependent environment variable') 34 | parser.add_argument('dependency_var', help='name of environment variable ' 35 | 'var1 depends on') 36 | args = parser.parse_args() 37 | 38 | var = os.getenv(args.var, None) 39 | dependency_var = os.getenv(args.dependency_var, None) 40 | 41 | var = '' if var == 'false' else var 42 | dependency_var = '' if dependency_var == 'false' else dependency_var 43 | if not var: 44 | sys.exit(0) 45 | 46 | if not dependency_var: 47 | sys.exit(1) 48 | 49 | 50 | if __name__ == '__main__': 51 | main() 52 | -------------------------------------------------------------------------------- /devices/rpi-2-b/ubuntu-bionic-armhf/README.md: -------------------------------------------------------------------------------- 1 | Ubuntu is a free and open source software which is developed by [Canonical](https://canonical.com/). `rpi-2-b/ubuntu-bionic-armhf` allows building custom 32-bit Ubuntu [Bionic](https://wiki.ubuntu.com/BionicBeaver/ReleaseNotes) images for [Raspberry Pi 2 B](https://raspberrypi.org/products/raspberry-pi-2-model-b/), [Raspberry Pi 3 B](https://raspberrypi.org/products/raspberry-pi-3-model-b/) and [Raspberry Pi 3 B+](https://raspberrypi.org/products/raspberry-pi-3-model-b-plus/). Note that the kernel package, which the system is based on, is located in the universe area of the official archive. It means that the package is a [community-maintained](https://wiki.ubuntu.com/MOTU/) and not supported by the Ubuntu Security team. 2 | 3 | ## What's in the distribution? 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
PackageVersion
Essential components
Linux kernel4.15
glibc2.27
GCC7.3
systemd237
Development tools
Go1.10
PHP7.2
Python3.6.5
Ruby2.5.1
Server software
Apache HTTP Server2.4.29
Nginx1.14.0
PostgreSQL10.4
MariaDB10.1.29
68 | -------------------------------------------------------------------------------- /pieman/bin/image_attrs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (C) 2017-2021 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | """A utility that reads pieman.yml from stdin and fetches the specified attribute from it. """ 18 | 19 | import sys 20 | from argparse import ArgumentParser 21 | 22 | from pieman import attrs 23 | 24 | 25 | def fail(message): 26 | """Writes the specified message to stderr and exits with a non-zero exit 27 | code. """ 28 | sys.stderr.write(message + '\n') 29 | sys.exit(1) 30 | 31 | 32 | def main(): 33 | """The main entry point. """ 34 | parser = ArgumentParser() 35 | parser.add_argument('root', nargs='*') 36 | args = parser.parse_args() 37 | 38 | attributes_list = attrs.AttributesList(sys.stdin) 39 | 40 | try: 41 | attr = attributes_list.get_attribute(args.root) 42 | except attrs.RootDoesNotExist: 43 | fail('There is no root named {}'.format(args.root)) 44 | except attrs.AttributeDoesNotExist as exc: 45 | fail(str(exc)) 46 | except attrs.UnknownAttribute: 47 | fail('{} attribute is unknown'.format(args.root[-1])) 48 | 49 | try: 50 | attr.echo() 51 | except attrs.UnprintableType: 52 | fail('{} attribute is not supposed to be printed'.format(args.root[-1])) 53 | 54 | 55 | if __name__ == "__main__": 56 | main() 57 | -------------------------------------------------------------------------------- /helpers/users.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Adds a regular user with the specified password to the target system. 17 | # Globals: 18 | # None 19 | # Arguments: 20 | # Username 21 | # Password 22 | # Returns: 23 | # None 24 | add_user() { 25 | local encrypted_password="" 26 | local username=$1 27 | local password=$2 28 | 29 | if is_alpine; then 30 | chroot_exec adduser -h "/home/${username}" -s /bin/sh "${username}" << EOF 31 | ${password} 32 | ${password} 33 | EOF 34 | elif is_debian_based; then 35 | chroot_exec useradd -m "${username}" -s /bin/bash 36 | 37 | encrypted_password="$(do_mkpasswd "${password}")" 38 | 39 | chroot_exec usermod -p "${encrypted_password}" "${username}" 40 | fi 41 | } 42 | 43 | # Sets the root password in the target system. 44 | # Globals: 45 | # None 46 | # Arguments: 47 | # Password 48 | # Returns: 49 | # None 50 | set_root_password() { 51 | local encrypted_password="" 52 | local password=$1 53 | 54 | if is_alpine; then 55 | chroot_exec passwd << EOF 56 | ${password} 57 | ${password} 58 | EOF 59 | elif is_debian_based; then 60 | encrypted_password="$(do_mkpasswd "${password}")" 61 | 62 | chroot_exec usermod -p "${encrypted_password}" root 63 | fi 64 | } 65 | -------------------------------------------------------------------------------- /devices/rpi-b/raspberrypios-buster-armhf/README.md: -------------------------------------------------------------------------------- 1 | Raspberry Pi OS (formerly Raspbian) is an official operating system for Raspberry Pi. It's based on Debian GNU/Linux and supports all models of the single-board computer. `rpi-b/raspberrypios-buster-armhf` allows building custom 32-bit Raspberry Pi OS [Buster](https://raspberrypi.org/blog/buster-the-new-version-of-raspbian/) images for 2 | 3 | * [Raspberry Pi B and B+](https://raspberrypi.org/products/raspberry-pi-1-model-b/) 4 | * [Raspberry Pi 2 B](https://raspberrypi.org/products/raspberry-pi-2-model-b/) 5 | * [Raspberry Pi 3 B](https://raspberrypi.org/products/raspberry-pi-3-model-b/) 6 | * [Raspberry Pi 4 B](https://raspberrypi.org/products/raspberry-pi-4-model-b/) 7 | * [Raspberry Pi Zero](https://raspberrypi.org/products/raspberry-pi-zero/) 8 | * [Raspberry Pi Zero W](https://raspberrypi.org/products/raspberry-pi-zero-w/) 9 | 10 | ## What's in the distribution? 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
PackageVersion
Essential components
Linux kernel4.19
glibc2.28
GCC8.3.0
systemd241
Development tools
Go1.11
PHP7.3
Python3.7.3
Ruby2.5.1
Server software
Apache HTTP Server2.4.38
Nginx1.14
PostgreSQL11
MariaDB10.3
75 | -------------------------------------------------------------------------------- /pieman/bin/preprocessor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (C) 2021 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | """A utility that takes a YAML file and prints it to stdout, substituting variables for their 18 | values. The preprocessor supports the ${VAR} syntax to reference variables values. There are 19 | three types of variables: 20 | * environment variables (for example, ${USER} or ${HOME}); 21 | * the ${parent_node_name} builtin which contains parent nodes names, as it's seen from the name of 22 | the variable; 23 | * every string type node. 24 | """ 25 | 26 | import os 27 | import sys 28 | from argparse import ArgumentParser 29 | 30 | from yaml.scanner import ScannerError 31 | 32 | from pieman.preprocessor import ( 33 | Preprocessor, 34 | RootNameCouldNotBeFound, 35 | UndefinedVariable, 36 | ) 37 | 38 | 39 | def main(): 40 | """The main entry point. """ 41 | 42 | parser = ArgumentParser() 43 | parser.add_argument('infile', help='path to the YAML file to be processed') 44 | parser.add_argument('root_name', help='root name in the YAML file') 45 | args = parser.parse_args() 46 | 47 | if not os.path.isfile(args.infile): 48 | sys.stderr.write(f'{args.file} does not exist\n') 49 | sys.exit(1) 50 | 51 | try: 52 | Preprocessor(args.infile, sys.stdout, args.root_name) 53 | except (ScannerError, RootNameCouldNotBeFound, UndefinedVariable) as exp: 54 | sys.stderr.write(f'{exp}\n') 55 | sys.exit(1) 56 | 57 | 58 | if __name__ == '__main__': 59 | main() 60 | -------------------------------------------------------------------------------- /helpers/chroot.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Create a chroot environment based on one of the supported operating systems. 17 | # Globals: 18 | # SOURCE_DIR 19 | # Arguments: 20 | # None 21 | # Returns: 22 | # None 23 | create_chroot_environment() { 24 | run_scripts "${SOURCE_DIR}"/pre-create-chroot 25 | 26 | if is_alpine; then 27 | run_apk_static 28 | elif is_debian_based; then 29 | create_keyring 30 | 31 | run_scripts "${SOURCE_DIR}"/pre-first-stage 32 | 33 | run_first_stage 34 | 35 | run_scripts "${SOURCE_DIR}"/post-first-stage 36 | 37 | run_scripts "${SOURCE_DIR}"/pre-second-stage 38 | 39 | run_second_stage 40 | 41 | run_scripts "${SOURCE_DIR}"/post-second-stage 42 | 43 | # To prevent NO_PUBKEY when the packages will be installed a bit later. 44 | mark_keys_as_trusted 45 | fi 46 | 47 | run_scripts "${SOURCE_DIR}"/post-create-chroot 48 | } 49 | 50 | # Executes the specified command in the chroot environment. 51 | # Globals: 52 | # R 53 | # Arguments: 54 | # Command line to be passed to the chroot environment 55 | # Returns: 56 | # None 57 | chroot_exec() { 58 | chroot "${R}" "$@" 1>&2 59 | } 60 | 61 | # Executes the specified command in the chroot environment using shell. 62 | # Globals: 63 | # R 64 | # Arguments: 65 | # Command line to be passed to the chroot environment 66 | # Returns: 67 | # None 68 | chroot_exec_sh() { 69 | chroot "${R}" sh -c "$@" 1>&2 70 | } 71 | -------------------------------------------------------------------------------- /doc/components.md: -------------------------------------------------------------------------------- 1 | # Components 2 | 3 | Pieman is divided into toolset, utilities and Pieman itself. The page is devoted to the first two. 4 | 5 | ## Toolset 6 | 7 | To build an operating system image, Pieman must seek assistance from different tools. For example, every single operating system image is unthinkable without a chroot environment it's based on. To build a Debian-based chroot environment, one must use the tool named [debootstrap](https://salsa.debian.org/installer-team/debootstrap). The tool can be easily obtained in Alpine, Debian/Ubuntu, Fedora and other distributions via their repositories, but there is one problem here – not always the version of debootstrap will be suitable for preparing chroot environments of newest distributions, because it will generally be outdated. Pieman undertakes the task to install the required version of this and other tools. When the tools come together, they form something which has been named *toolset* in Pieman. 8 | 9 | Not to make the section debootstrap-oriented, I suggest we will have a look at other tools which are part of the Pieman toolset. 10 | * [apk.static](https://wiki.alpinelinux.org/wiki/Installing_Alpine_Linux_in_a_chroot) is used to prepare the chroot environments based on Alpine Linux. 11 | * [Das U-Boot](https://denx.de/wiki/U-Boot) and related utilities are used to make booting the built images on some single-board computers possible. 12 | 13 | ## Utilities 14 | 15 | The larger part of Pieman is written in Bash. The main task of Pieman is to run a certain program (`dd`, `parted`, etc) with certain options under certain conditions and Bash does a great job of doing this. However, the certain program does not always exist. In this case the Pieman utilities come to the rescue. The utilities are 16 | * written in Python; 17 | * distributed in the Python package named [pieman](https://pypi.org/project/pieman/); 18 | * built in the best tradition of Unix – do one thing and do it well (there is one particular program for one particular task). 19 | 20 | Since Pieman depends on Python it tries to make the most of the interpreter. Thus, the pieman package contains alternatives written in Python for well-known programs, such as `uuidgen` and GNU [Wget](https://gnu.org/software/wget/). It helps keeping the Pieman dependencies list as compact as possible. 21 | -------------------------------------------------------------------------------- /helpers/network.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2020 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Checks if the specified WPA passphrase is valid. 17 | # Globals: 18 | # WPA_PSK 19 | # Arguments: 20 | # Name of the environment variable, containing the WPA passphrase 21 | # Returns: 22 | # None 23 | check_if_wpa_psk_is_valid() { 24 | local error_msg="WPA_PSK is not valid: " 25 | 26 | { check_wpa_passphrase.py "${WPA_PSK}"; exit_code="$?"; } || true 27 | case "${exit_code}" in 28 | 0) 29 | ;; 30 | 1) 31 | fatal "${error_msg}passphrase must be 8..63 characters" 32 | exit 1 33 | ;; 34 | 2) 35 | fatal "${error_msg}invalid passphrase character" 36 | exit 1 37 | ;; 38 | *) 39 | fatal "${error_msg}unknown error" 40 | exit 1 41 | ;; 42 | esac 43 | } 44 | 45 | # Invokes wpa_passphrase if both WPA_SSID and WPA_PSK are specified. If WPA_PSK 46 | # is not specified (or it's empty), the network is considered as open, so the 47 | # function prepares and returns a string, containing a network block which 48 | # allows the target device to be connected to the open network. 49 | # Globals: 50 | # R 51 | # WPA_SSID 52 | # WPA_PSK 53 | # Arguments: 54 | # None 55 | # Returns: 56 | # String, containing a network block 57 | do_wpa_passphrase() { 58 | if [[ -n ${WPA_SSID} ]] && [[ -n ${WPA_PSK} ]]; then 59 | chroot "${R}" wpa_passphrase "${WPA_SSID}" "${WPA_PSK}" 60 | else 61 | echo "network={" 62 | echo " ssid=\"${WPA_SSID}\"" 63 | echo " key_mgmt=NONE" 64 | echo "}" 65 | fi 66 | } 67 | -------------------------------------------------------------------------------- /pieman/bin/bsc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Copyright (C) 2019 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | """BSC client. BSC stands for Build Status Codes. """ 18 | 19 | import os 20 | import socket 21 | import sys 22 | from argparse import ArgumentParser 23 | 24 | import bscd 25 | 26 | 27 | def main(): 28 | """The main entry point. """ 29 | 30 | parser = ArgumentParser() 31 | parser.add_argument('-a', '--unix-socket-name', 32 | default='/var/run/{}.sock'.format(bscd.DAEMON_NAME), 33 | help='Unix domain socket file name', 34 | metavar='UNIX_SOCKET_NAME') 35 | parser.add_argument('-H', '--redis-host', default='127.0.0.1', 36 | help='Redis server host', metavar='REDIS_HOST') 37 | parser.add_argument('-P', '--redis-port', default='6379', 38 | help='server pid file name', metavar='REDIS_PORT', 39 | type=int) 40 | parser.add_argument('request', metavar='REQUEST', 41 | help='request to be sent to bsc server') 42 | 43 | args = parser.parse_args() 44 | 45 | if not os.path.exists(args.unix_socket_name): 46 | sys.stderr.write('{} does not exist\n'.format(args.unix_socket_name)) 47 | sys.exit(1) 48 | 49 | client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 50 | 51 | try: 52 | client.connect(args.unix_socket_name) 53 | except ConnectionRefusedError: 54 | sys.stderr.write('Connection refused\n') 55 | sys.exit(1) 56 | 57 | client.send(args.request.encode('utf-8')) 58 | client.close() 59 | 60 | 61 | if __name__ == '__main__': 62 | main() 63 | -------------------------------------------------------------------------------- /files/firstboot/20-expandroot.sh: -------------------------------------------------------------------------------- 1 | logger -t "rc.firstboot" "Expanding root partition" 2 | 3 | # Detect root partition device 4 | ROOT_PART=$(mount | sed -n 's|^/dev/\(.*\) on / .*|\1|p') 5 | if [ -z "$ROOT_PART" ] ; then 6 | log_warning_msg "unable to detect root partition device" 7 | return 1 8 | fi 9 | 10 | # Extract root device name 11 | case "${ROOT_PART}" in 12 | mmcblk0*) ROOT_DEV=mmcblk0 ;; 13 | sda*) ROOT_DEV=sda ;; 14 | esac 15 | 16 | # Check detected root partition name 17 | PART_NUM=$(echo ${ROOT_PART} | grep -o '[1-9][0-9]*$') 18 | if [ "$PART_NUM" = "$ROOT_PART" ] ; then 19 | logger -t "rc.firstboot" "$ROOT_PART is not an SD card. Don't know how to expand" 20 | return 0 21 | fi 22 | 23 | # NOTE: the NOOBS partition layout confuses parted. For now, let's only 24 | # agree to work with a sufficiently simple partition layout 25 | if [ "$PART_NUM" -gt 2 ] ; then 26 | logger -t "rc.firstboot" "Your partition layout is not currently supported by this tool." 27 | return 0 28 | fi 29 | 30 | # Check if last partition number 31 | LAST_PART_NUM=$(parted /dev/${ROOT_DEV} -ms unit s p | tail -n 1 | cut -f 1 -d:) 32 | if [ $LAST_PART_NUM -ne $PART_NUM ]; then 33 | logger -t "rc.firstboot" "$ROOT_PART is not the last partition. Don't know how to expand" 34 | return 0 35 | fi 36 | 37 | # Get the starting offset of the root partition 38 | PART_START=$(parted /dev/${ROOT_DEV} -ms unit s p | grep "^${PART_NUM}" | cut -f 2 -d: | sed 's/[^0-9]//g') 39 | if [ -z "$PART_START" ] ; then 40 | logger -t "rc.firstboot" "${ROOT_DEV} unable to get starting sector of the partition" 41 | return 1 42 | fi 43 | 44 | # Get the possible last sector for the root partition 45 | PART_LAST=$(fdisk -l /dev/${ROOT_DEV} | grep '^Disk.*sectors' | awk '{ print $7 - 1 }') 46 | if [ -z "$PART_LAST" ] ; then 47 | logger -t "rc.firstboot" "${ROOT_DEV} unable to get last sector of the partition" 48 | return 1 49 | fi 50 | 51 | ### Since rc.local is run with "sh -e", let's add "|| true" to prevent premature exit 52 | fdisk /dev/${ROOT_DEV} < 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | # The script must be run only after 11-pm.sh and 12-kernel.sh because it 18 | # requires some of the files which are available only after installation all 19 | # of the specified packages, including the kernel package. 20 | 21 | check_if_variable_is_set SOURCE_DIR 22 | 23 | # Get the files, which must present on the boot partition, from different 24 | # sources and put them in the directory specified via BOOT. 25 | boot="$(get_attr boot)" 26 | for f in ${boot}; do 27 | if echo "${f}" | grep -Eq "^https://|^http://|^ftp://"; then 28 | info "downloading ${f} to ${BOOT}" 29 | do_wget -q -O "${BOOT}/$(basename "${f}")" "${f}" 30 | elif [[ ${f:0:1} == "/" ]]; then 31 | # Split the name of the target file or directory into two parts: 32 | # original name and copy name. 33 | IFS=':' read -ra FILE_NAMES <<< "${R}/${f}" 34 | 35 | info "copying ${FILE_NAMES[0]} to ${BOOT}" 36 | 37 | if [ -z "${FILE_NAMES[1]}" ]; then 38 | # If the name of the copy is not specified, use the original one. 39 | 40 | # globbing doesn't work when quoted, so 41 | # shellcheck disable=SC2086 42 | cp -r ${FILE_NAMES[0]} "${BOOT}" 43 | else 44 | info "$(basename "${FILE_NAMES[0]}") was renamed into ${FILE_NAMES[1]}" 45 | 46 | # shellcheck disable=SC2086 47 | cp -r ${FILE_NAMES[0]} "${BOOT}/${FILE_NAMES[1]}" 48 | fi 49 | else 50 | info "copying $(dirname "${YML_FILE}")/${f} to ${BOOT}" 51 | cp "${SOURCE_DIR}/${f}" "${BOOT}" 52 | fi 53 | done 54 | 55 | send_request_to_bsc_server PREPARED_BOOT_PARTITION_CODE 56 | -------------------------------------------------------------------------------- /helpers/uboot.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Checks if the Das U-Boot dependencies are satisfied. 17 | # Globals: 18 | # None 19 | # Arguments: 20 | # None 21 | # Returns: 22 | # 0 or 1 depending on the result. 23 | are_uboot_dependencies_satisfied() { 24 | local ret=0 25 | 26 | >&2 echo -n "checking /usr/include/python2.7/Python.h... " 27 | yes_or_no "[ -f /usr/include/python2.7/Python.h ]" || ret=1 28 | 29 | >&2 echo -n "checking bison... " 30 | yes_or_no "[ ! -z $(command -v bison) ]" || ret=1 31 | 32 | >&2 echo -n "checking cc... " 33 | yes_or_no "[ ! -z $(command -v cc) ]" || ret=1 34 | 35 | >&2 echo -n "checking flex... " 36 | yes_or_no "[ ! -z $(command -v flex) ]" || ret=1 37 | 38 | >&2 echo -n "checking git... " 39 | yes_or_no "[ ! -z $(command -v git) ]" || ret=1 40 | 41 | >&2 echo -n "checking make... " 42 | yes_or_no "[ ! -z $(command -v make) ]" || ret=1 43 | 44 | >&2 echo -n "checking python2... " 45 | yes_or_no "[ ! -z $(command -v python2) ]" || ret=1 46 | 47 | >&2 echo -n "checking swig... " 48 | yes_or_no "[ ! -z $(command -v swig) ]" || ret=1 49 | 50 | # Required by the toolchain which is going to be used for building U-Boot. 51 | >&2 echo -n "checking xz... " 52 | yes_or_no "[ ! -z $(command -v xz) ]" || ret=1 53 | 54 | return "${ret}" 55 | } 56 | 57 | # Installs SPL (secondary program loader) if it's specified in pieman.yml. 58 | # Globals: 59 | # LOOP_DEV 60 | # Arguments: 61 | # None 62 | # Returns: 63 | # None 64 | install_spl() { 65 | spl_bin="$(get_attr_or_nothing spl_bin)" 66 | if [[ -n ${spl_bin} ]]; then 67 | dd if="${spl_bin}" of="${LOOP_DEV}" bs=1024 seek=8 68 | sync 69 | fi 70 | } 71 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.10 2 | 3 | ENV BRANCH master 4 | 5 | ENV PATH "/root/pieman/pieman/bin:${PATH}" 6 | 7 | ENV PYTHONPATH "/root/pieman/pieman" 8 | 9 | ENV TERM linux 10 | 11 | ENV TOOLSET_VER v4-amy 12 | 13 | ARG VCS_REF 14 | 15 | LABEL org.label-schema.vcs-ref=$VCS_REF \ 16 | org.label-schema.vcs-url="https://github.com/tolstoyevsky/pieman" 17 | 18 | COPY rollout_fixes.sh /usr/bin/rollout_fixes.sh 19 | 20 | RUN touch .dockerenv \ 21 | && apk --update add \ 22 | bash \ 23 | # for ar 24 | binutils \ 25 | # u-boot-sunxi-with-spl.bin needs to be written to images by dd from 26 | # GNU Coreutils instead of dd from Busybox 27 | coreutils \ 28 | dosfstools \ 29 | dpkg \ 30 | # for tune2fs 31 | e2fsprogs-extra \ 32 | git \ 33 | gnupg \ 34 | # for tput 35 | ncurses \ 36 | parted \ 37 | # for pkgdetails 38 | perl \ 39 | rsync \ 40 | # for losetup 41 | util-linux \ 42 | # debootstrap needs GNU tar instead of tar from Busybox 43 | tar \ 44 | xz \ 45 | # The following packages are necessary for building 2 different versions of 46 | # U-Boot (vanilla and Mender flavour) and Mender client 47 | bc \ 48 | bison \ 49 | ca-certificates \ 50 | dtc \ 51 | flex \ 52 | gcc \ 53 | go \ 54 | make \ 55 | musl-dev \ 56 | python2-dev \ 57 | python3 \ 58 | swig \ 59 | # Provide a compatibility layer for the cross-compiler which is linked 60 | # against glibc. 61 | && wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub \ 62 | && wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.28-r0/glibc-2.28-r0.apk \ 63 | && apk add glibc-2.28-r0.apk \ 64 | \ 65 | && mkdir /result \ 66 | && /usr/bin/rollout_fixes.sh \ 67 | && cd \ 68 | && git clone -b $BRANCH --depth 1 https://github.com/tolstoyevsky/pieman.git \ 69 | && cd pieman \ 70 | && pip3 install -r "${PYTHONPATH}"/requirements.txt \ 71 | && env PREPARE_ONLY_TOOLSET=true ./pieman.sh \ 72 | && cp toolset/$TOOLSET_VER/qemu-user-static/qemu-arm-static /usr/bin \ 73 | && cp toolset/$TOOLSET_VER/qemu-user-static/qemu-aarch64-static /usr/bin \ 74 | && apk del \ 75 | bc \ 76 | bison \ 77 | ca-certificates \ 78 | dtc \ 79 | flex \ 80 | gcc \ 81 | go \ 82 | make \ 83 | musl-dev \ 84 | python2-dev \ 85 | swig \ 86 | && rm -rf /var/cache/apk/* 87 | 88 | COPY docker-entrypoint.sh /entrypoint.sh 89 | 90 | ENTRYPOINT ["/entrypoint.sh"] 91 | -------------------------------------------------------------------------------- /doc/bsc_server_and_client.md: -------------------------------------------------------------------------------- 1 | # Build status codes server and client 2 | 3 | Pieman, as a server-side software, is capable of informing in real time the clients about build status codes allowing them, in turn, to show the users the current progress of building images. 4 | 5 | Using the `ENABLE_BSC_CHANNEL` parameter set to `true` it is possible to run the build status codes server (also known as bscd). The server will require the Redis server (specified via `REDIS_HOST` and `REDIS_PORT`) to act as a broker. When Pieman sees that Redis is available, Pieman will be pushing the build status codes via the built-in client intended for communicating with the server. At the same time, any client-side software may subscribe to the channel named `bscd-${PROJECT_NAME}` and receive the build status codes in real time. 6 | 7 | ## Build status codes 8 | 9 | Here is the full list of the build status codes with their description. 10 | * 10 – done with preparing the chroot environment. Either `debootstrap` or `apk.static` is invoked at this stage (of course if only `CREATE_ONLY_CHROOT` is not set to `true`). 11 | * 20 – done with setting up locale. 12 | * 21 – done with setting up time zone. 13 | * 30 – done with updating indexes (`apt-get update` in case of Debian-based distribution and `apk update` in case of Alpine Linux). 14 | * 31 – done with installing the packages specified by the user (via the `INCLUDES` parameter). 15 | * 32 – done with upgrading the operating system the target image is based on. 16 | * 33 – done with installing the kernel. 17 | * 40 – done with preparing the boot partition. 18 | * 50 – done with networking. 19 | * 60 – done with users. 20 | * 70 – done with cleaning up (removing the cached packages, indexes, etc). 21 | * 80 – done with creating the target image. 22 | * 81 – done with formatting partitions. 23 | * 82 – done with syncing the chroot environment directory located on the host with the rootfs partition. 24 | * 1000 – success (if everything was fine). 25 | * 1001 – fail (if something went wrong). 26 | 27 | ## See also 28 | 29 | * The [pieman/pieman/build_status_codes](/pieman/pieman/build_status_codes) module containing the list of the build status codes which is shared by both the server and client. 30 | * The [INCLUDES](https://github.com/tolstoyevsky/pieman#includes) parameter. 31 | * The [PROJECT_NAME](https://github.com/tolstoyevsky/pieman#project_namexxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx) parameter. 32 | * The [Extra](https://github.com/tolstoyevsky/pieman#extra) section of the Documentation for the details related to `ENABLE_BSC_CHANNEL`, `REDIS_HOST` and `REDIS_PORT`. 33 | -------------------------------------------------------------------------------- /pieman/bin/render.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (C) 2019 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | """Utility intended for rendering Jinja2 templates. 18 | The utility exits with: 19 | * 0 when everything is fine; 20 | * 1 when the specified template does not exist; 21 | * 2 when the directory of the specified result path does not exist. 22 | """ 23 | 24 | import argparse 25 | import os 26 | import sys 27 | 28 | from jinja2 import Environment, FileSystemLoader 29 | 30 | 31 | def getenv(value, key): 32 | """Acts like any Jinja2 filter and gets the value of the specified 33 | environment variable. 34 | Note that the filter returns the native Python boolean if the environment 35 | variable contains 'false' . It's necessary for using the values in 36 | conditions. 37 | """ 38 | 39 | val = os.getenv(key, value) 40 | return False if val == 'false' else val 41 | 42 | 43 | def main(): 44 | """The main entry point. """ 45 | 46 | parser = argparse.ArgumentParser() 47 | parser.add_argument('template_path', help='path to the template to be ' 48 | 'rendered') 49 | parser.add_argument('result_path', help='path to the result of rendering') 50 | args = parser.parse_args() 51 | 52 | template_dir = os.path.dirname(args.template_path) 53 | template_name = os.path.basename(args.template_path) 54 | result_dir = os.path.dirname(args.result_path) 55 | 56 | if not os.path.isfile(args.template_path): 57 | sys.exit(1) 58 | 59 | if not os.path.isdir(result_dir): 60 | sys.exit(2) 61 | 62 | env = Environment(loader=FileSystemLoader(template_dir)) 63 | env.filters['getenv'] = getenv 64 | 65 | template = env.get_template(template_name) 66 | output = template.render() 67 | 68 | with open(args.result_path, 'w') as outfile: 69 | outfile.write(output) 70 | 71 | 72 | if __name__ == '__main__': 73 | main() 74 | -------------------------------------------------------------------------------- /devices/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Denis Gavrilyuk 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | """Module containing the interface for serving the devices and operating systems supported 17 | by Pieman to clients. 18 | """ 19 | 20 | import os 21 | from pathlib import Path 22 | 23 | import yaml 24 | 25 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 26 | 27 | 28 | def _get_abs_path(rel_path): 29 | """Returns the full path which is the result of concatenation of BASE_DIR and the specified 30 | relative path. 31 | """ 32 | 33 | return os.path.join(BASE_DIR, rel_path) 34 | 35 | 36 | def get_devices(): 37 | """Returns the list of the devices and operating systems supported by Pieman. """ 38 | 39 | devices = {} 40 | 41 | for dev_name in os.listdir(BASE_DIR): 42 | path_to_dev = _get_abs_path(dev_name) 43 | if not Path(path_to_dev).is_dir(): 44 | continue # skip __init__.py and other regular files 45 | if dev_name in ['__pycache__']: 46 | continue 47 | 48 | with open(f'{path_to_dev}/meta.yml') as outfile: 49 | dev_meta = yaml.safe_load(outfile)['meta'] 50 | 51 | distros = {} 52 | 53 | for distro_name in os.listdir(path_to_dev): 54 | path_to_distro = _get_abs_path(f'{path_to_dev}/{distro_name}') 55 | if not Path(path_to_distro).is_dir(): 56 | continue # skip meta.yml of device and other file 57 | 58 | path_to_distro_meta = f'{path_to_dev}/{distro_name}/meta.yml' 59 | path_to_overridden_distro = _get_abs_path(f'{path_to_dev}/meta_{distro_name}.yml') 60 | if Path(path_to_overridden_distro).exists(): 61 | path_to_distro_meta = path_to_overridden_distro 62 | 63 | with open(path_to_distro_meta) as outfile: 64 | distro_meta = yaml.safe_load(outfile)['meta'] 65 | distros[distro_name] = distro_meta 66 | 67 | devices[dev_name] = {**dev_meta, 'distros': distros} 68 | 69 | return devices 70 | -------------------------------------------------------------------------------- /pieman/README.md: -------------------------------------------------------------------------------- 1 | [![pypi](https://badge.fury.io/py/pieman.svg)](https://badge.fury.io/py/pieman) 2 | 3 | # pieman 4 | 5 | The package contains the utilities which are used by [Pieman](https://github.com/tolstoyevsky/pieman), script for creating custom OS images for single-board computers. The utilities are: 6 | 7 | * `apk_tools_version.py`: fetches the latest version of the apk-tools-static package. 8 | * `bsc.py`: BSC (Build Status Codes) [client](https://github.com/tolstoyevsky/pieman/blob/master/doc/bsc_server_and_client.md). 9 | * `bscd.py`: BSC (Build Status Codes) [server](https://github.com/tolstoyevsky/pieman/blob/master/doc/bsc_server_and_client.md). 10 | * `check_mutually_exclusive_params.py`: checks if two specified environment variables are defined. 11 | * `check_redis.py`: checks if the Redis server, needed by [BSC server and client](https://github.com/tolstoyevsky/pieman/blob/master/doc/bsc_server_and_client.md), is available. 12 | * `check_wpa_passphrase.py`: checks if WPA passphrases are valid. A passphrase is considered as valid when 1) it's between 8 and 63 characters and 2) it doesn't contain any special characters. These two simple checks were borrowed from the original wpa_supplicant codebase and rewritten in Python (see `wpa_supplicant/wpa_passphrase.c`). 13 | * `depend_on.py`: sometimes one environment variable (A) can't be specified without another one (B), so this utility helps Pieman explicitly say that A depends on B and check if B is set to true (if bool) or simply specified (in other cases) when A is set to true (if bool) or simply specified (in other cases). 14 | * `du.py`: provides the disk usage of the specified directory. It was developed primarily for estimating chroot environments disk usage. In some cases the utility provides more accurate result than `du` from GNU [coreutils](https://gnu.org/software/coreutils/). 15 | * `image_attrs.py`: allows getting image attributes which are stored in the `pieman.yml` files. The utility is more high-level tool than [PyYAML](https://pyyaml.org) because it's aware of the `pieman.yml` specifics. 16 | * `preprocessor.py`: takes a YAML file and prints it to stdout, substituting variables for their values. The preprocessor supports the `${VAR}` syntax to reference variables values. There are three types of variables: 17 | * environment variables (for example, `${USER}` or `${HOME}`); 18 | * the `${parent_node_name}` builtin which contains parent nodes names, as it's seen from the name of the variable; 19 | * every string type node. 20 | * `render.py`: renders config templates (which are [Jinja2](https://jinja.palletsprojects.com) templates under the hood). 21 | * `wget.py`: very limited GNU [Wget](https://www.gnu.org/software/wget/) alternative. 22 | 23 | ## Installation 24 | 25 | ```sudo pip3 install pieman``` 26 | 27 | -------------------------------------------------------------------------------- /helpers/toolset.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Removes 17 | # * the specified files and directories; 18 | # * the .partial file in the current directory. 19 | # Globals: 20 | # None 21 | # Arguments: 22 | # Target directory 23 | # Returns: 24 | # None 25 | finalise_installation() { 26 | for i in "$@"; do 27 | rm -rf "${i}" 28 | done 29 | 30 | rm -f .partial 31 | } 32 | 33 | # Gets qemu-user-static 3.1 from Ubuntu 19.04 "Disco Dingo". 34 | # Globals: 35 | # None 36 | # Arguments: 37 | # None 38 | # Returns: 39 | # None 40 | get_qemu_emulation_binary() { 41 | local package 42 | 43 | do_wget http://mirrors.kernel.org/ubuntu/dists/focal/universe/binary-amd64/Packages.xz 44 | 45 | xz -d Packages.xz 46 | 47 | package="$(grep "Filename: pool/universe/q/qemu/qemu-user-static" Packages | awk '{print $2}')" 48 | 49 | do_wget http://security.ubuntu.com/ubuntu/"${package}" 50 | 51 | ar x "$(basename "${package}")" 52 | 53 | tar xJf data.tar.xz 54 | 55 | cp usr/bin/qemu-aarch64-static . 56 | cp usr/bin/qemu-arm-static . 57 | 58 | # cleanup 59 | rm control.tar.xz 60 | rm data.tar.xz 61 | rm debian-binary 62 | rm Packages 63 | rm "$(basename "${package}")" 64 | rm -r usr 65 | } 66 | 67 | # Checks if the specified Toolset component is partially installed, and if so, 68 | # cleans up its directory and initializes it for the installation, creating the 69 | # .partial file there. 70 | # Globals: 71 | # None 72 | # Arguments: 73 | # Target directory 74 | # Returns: 75 | # 0 if the specified component directory was initialized 76 | # 1 if there was no need to initialize the specified component directory 77 | init_installation_if_needed() { 78 | local dir=$1 79 | 80 | create_dir "${dir}" 81 | if [ -z "$(ls -A "${dir}")" ] || [ -f "${dir}"/.partial ]; then 82 | rm -rf "${dir:?}"/* 83 | 84 | touch "${dir}"/.partial 85 | 86 | return 0 87 | fi 88 | 89 | return 1 90 | } 91 | 92 | # Figures out the number of CPU cores which are available on the current 93 | # machine. 94 | # Globals: 95 | # None 96 | # Arguments: 97 | # None 98 | # Returns: 99 | # Number of available cores 100 | number_of_cores() { 101 | grep -c ^processor /proc/cpuinfo 102 | } 103 | -------------------------------------------------------------------------------- /pieman/pieman/util.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | """Miscellaneous utility functions. """ 17 | 18 | import logging 19 | import os 20 | import sys 21 | from urllib.request import urlretrieve 22 | 23 | import redis 24 | 25 | LOGGING_FORMATTER = '%(asctime)s %(levelname)-5.5s %(message)s' 26 | 27 | 28 | def _reporthook(chunk_number, buffer_size, total_size): 29 | """It must accept three numeric parameters: 30 | - a chunk number; 31 | - the maximum size chunks are read in; 32 | - the total size of the download (-1 if unknown). 33 | """ 34 | 35 | readsofar = chunk_number * buffer_size 36 | readsofar = total_size if readsofar > total_size else readsofar 37 | if total_size: 38 | percent = readsofar * 100 / total_size 39 | status = '\r{:>5.1f}% {:>{n}} / {}'.format( 40 | percent, readsofar, total_size, n=len(str(total_size))) 41 | sys.stderr.write(status) 42 | else: # total size is unknown 43 | sys.stderr.write('\rread {}'.format(readsofar)) 44 | 45 | 46 | def connect_to_redis(host, port): 47 | """Connects to the specified Redis server. The function raises on of the 48 | exceptions derived from redis.exceptions.RedisError in case of a problem. 49 | """ 50 | conn = redis.StrictRedis(host=host, port=port) 51 | conn.ping() 52 | 53 | return conn 54 | 55 | 56 | def download(url, dst, quiet=False): 57 | """Downloads the specified document from the Web, 58 | (optionally) displaying a progress bar. 59 | """ 60 | _, msg = urlretrieve(url, dst + '.part', 61 | _reporthook if not quiet else None) 62 | 63 | os.rename(dst + '.part', dst) 64 | 65 | size = os.stat(dst).st_size 66 | if not quiet: 67 | sys.stderr.write('\n') 68 | if int(msg['Content-Length']) == size: 69 | filename = os.path.basename(dst) 70 | sys.stderr.write('{} was downloaded successfully\n' 71 | .format(filename)) 72 | 73 | 74 | def init_logger(logger, log_level, log_file_prefix='', 75 | logging_formatter=LOGGING_FORMATTER): 76 | """Initializes the logger. """ 77 | 78 | formatter = logging.Formatter(logging_formatter) 79 | logger.setLevel(log_level) 80 | 81 | streaming_handler = logging.StreamHandler() 82 | streaming_handler.setLevel(log_level) 83 | streaming_handler.setFormatter(formatter) 84 | logger.addHandler(streaming_handler) 85 | 86 | if log_file_prefix: 87 | file_handler = logging.FileHandler(log_file_prefix) 88 | file_handler.setFormatter(formatter) 89 | file_handler.setFormatter(formatter) 90 | logger.addHandler(file_handler) 91 | -------------------------------------------------------------------------------- /helpers/others.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Checks if Pieman is run in the docker container based on its official Docker 17 | # image cusdeb/pieman. 18 | # Globals: 19 | # None 20 | # Arguments: 21 | # None 22 | # Returns: 23 | # Boolean 24 | check_if_run_in_docker() { 25 | if [ -f /.dockerenv ]; then 26 | true 27 | else 28 | false 29 | fi 30 | } 31 | 32 | # Adds the specified package name to the BASE_PACKAGES environment variable 33 | # which is a comma-separated list. 34 | # Globals: 35 | # BASE_PACKAGES 36 | # Arguments: 37 | # Package name 38 | # Returns: 39 | # None 40 | add_package_to_base_packages() { 41 | if is_alpine; then 42 | add_item_to_list "${1}" BASE_PACKAGES " " 43 | else 44 | add_item_to_list "${1}" BASE_PACKAGES "," 45 | fi 46 | } 47 | 48 | # Adds the specified package name to the INCLUDES environment variable which is 49 | # a comma-separated list. 50 | # Globals: 51 | # INCLUDES 52 | # Arguments: 53 | # Package name 54 | # Returns: 55 | # None 56 | add_package_to_includes() { 57 | add_item_to_list "${1}" INCLUDES "," 58 | } 59 | 60 | # Adds the specified options to the PM_OPTIONS environment variable which is 61 | # a space-separated list. 62 | # Globals: 63 | # PM_OPTIONS 64 | # Arguments: 65 | # option 66 | # Returns: 67 | # None 68 | add_option_to_pm_options() { 69 | add_item_to_list "${1}" PM_OPTIONS " " 70 | } 71 | 72 | # Creates a keyring from the public keys related to the operating system which 73 | # is going to be used as a base for the target image. Then, the keyring is 74 | # passed to debootstrap. The keyring name is stored in the KEYRING environment 75 | # variable. 76 | # Globals: 77 | # PIECES 78 | # KEYRING 79 | # Arguments: 80 | # None 81 | # Returns: 82 | # None 83 | create_keyring() { 84 | for key in keys/"${PIECES[0]}"/*; do 85 | gpg --no-default-keyring --keyring="${KEYRING}" --import "${key}" 86 | done 87 | } 88 | 89 | # Adds the public keys, related to the operating system which is used as a base 90 | # for the target image, to the list of trusted keys. 91 | # Globals: 92 | # PIECES 93 | # R 94 | # Arguments: 95 | # None 96 | # Returns: 97 | # None 98 | mark_keys_as_trusted() { 99 | for key in keys/"${PIECES[0]}"/*; do 100 | local key_name="" 101 | 102 | key_name=$(basename "${key}") 103 | 104 | cp "${key}" "${R}" 105 | 106 | info "adding ${key} to the list of trusted keys" 107 | chroot_exec apt-key add "${key_name}" 108 | 109 | chroot_exec rm "${key_name}" 110 | done 111 | } 112 | -------------------------------------------------------------------------------- /helpers/deb.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018-2021 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Declares the DEBOOTSTRAP_EXEC environment variable which then can be used to 17 | # execute debootstrap. 18 | # Globals: 19 | # DEBOOTSTRAP_DIR 20 | # DEBOOTSTRAP_EXEC 21 | # TOOLSET_FULL_PATH 22 | # Arguments: 23 | # None 24 | # Returns: 25 | # None 26 | init_debootstrap() { 27 | local path_to_debootstrap="${TOOLSET_FULL_PATH}/debootstrap" 28 | local ver="" 29 | 30 | DEBOOTSTRAP_EXEC="env DEBOOTSTRAP_DIR=${path_to_debootstrap} ${path_to_debootstrap}/debootstrap" 31 | 32 | info "using ${DEBOOTSTRAP_EXEC}" 33 | } 34 | 35 | # Checks if debootstrap is equal to or higher than the version specified in the 36 | # DEBOOTSTRAP_VER environment variable. 37 | # Globals: 38 | # DEBOOTSTRAP_VER 39 | # TOOLSET_FULL_PATH 40 | # Arguments: 41 | # None 42 | # Returns: 43 | # Boolean 44 | is_debootstrap_uptodate() { 45 | local path_to_debootstrap="${TOOLSET_FULL_PATH}/debootstrap" 46 | 47 | # After cloning the debootstrap git repo the program is a fully 48 | # functional, but does not have a correct version number. However, the 49 | # version can be found in the source package changelog. 50 | ver=$(sed 's/.*(\(.*\)).*/\1/; q' "${path_to_debootstrap}"/debian/changelog) 51 | 52 | if [ -z "${ver}" ]; then 53 | fatal "your debootstrap seems to be broken. Could not get its version." 54 | exit 1 55 | fi 56 | 57 | if dpkg --compare-versions "${ver}" lt "${DEBOOTSTRAP_VER}"; then 58 | false 59 | else 60 | true 61 | fi 62 | } 63 | 64 | # Runs the first stage of building a chroot environment based on a Debian-based 65 | # distribution. Then it installs a user mode emulation binary to the chroot. 66 | # Globals: 67 | # BASE_PACKAGES 68 | # DEBOOTSTRAP_EXEC 69 | # KEYRING 70 | # OS 71 | # PIECES 72 | # R 73 | # Arguments: 74 | # None 75 | # Returns: 76 | # None 77 | run_first_stage() { 78 | local additional_opts="" 79 | 80 | if [ -n "${BASE_PACKAGES}" ]; then 81 | additional_opts="--include=${BASE_PACKAGES}" 82 | fi 83 | 84 | arch=${PIECES[2]} 85 | codename=${PIECES[1]} 86 | primary_repo=$(get_attr repos | head -n1) 87 | # shellcheck disable=SC2086 88 | ${DEBOOTSTRAP_EXEC} --arch="${arch}" --foreign --variant=minbase --keyring="${KEYRING}" ${additional_opts} ${codename} "${R}" "${primary_repo}" 1>&2 89 | 90 | install_user_mode_emulation_binary 91 | } 92 | 93 | # Runs the second (i.e. final) stage of building a chroot environment based on 94 | # a Debian-based distribution. 95 | # Globals: 96 | # None 97 | # Arguments: 98 | # None 99 | # Returns: 100 | # None 101 | run_second_stage() { 102 | chroot_exec debootstrap/debootstrap --second-stage 103 | } 104 | -------------------------------------------------------------------------------- /helpers/pm.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Clears out the local repository of retrieved package files and removes 17 | # indexes. 18 | # Globals: 19 | # R 20 | # Arguments: 21 | # None 22 | # Returns: 23 | # None 24 | clean() { 25 | if is_alpine; then 26 | rm -rf "${R}"/var/cache/apk/* 27 | elif is_debian_based; then 28 | chroot_exec apt-get clean 29 | rm -rf "${R}"/var/lib/apt/lists/* 30 | fi 31 | } 32 | 33 | # Updates the indexes in the chroot environment. 34 | # Globals: 35 | # None 36 | # Arguments: 37 | # None 38 | # Returns: 39 | # None 40 | update_indexes() { 41 | if is_alpine; then 42 | chroot_exec apk update 43 | elif is_debian_based; then 44 | chroot_exec apt-get update 45 | fi 46 | } 47 | 48 | # Upgrades the chroot environment. 49 | # Globals: 50 | # PM_OPTIONS 51 | # Arguments: 52 | # None 53 | # Returns: 54 | # None 55 | upgrade() { 56 | if is_alpine; then 57 | # shellcheck disable=SC2086 58 | chroot_exec apk upgrade ${PM_OPTIONS} 59 | elif is_debian_based; then 60 | # shellcheck disable=SC2086 61 | chroot_exec apt-get -y ${PM_OPTIONS} dist-upgrade 62 | fi 63 | } 64 | 65 | # Installs the specified packages in the chroot environment. 66 | # Globals: 67 | # DEBIAN_FRONTEND 68 | # ENABLE_UNATTENDED_INSTALLATION 69 | # PM_OPTIONS 70 | # Arguments: 71 | # Packages names, separated by spaces 72 | # Returns: 73 | # None 74 | install_packages() { 75 | if is_alpine; then 76 | # shellcheck disable=SC2086 77 | chroot_exec apk add ${PM_OPTIONS} "$@" 78 | elif is_debian_based; then 79 | if ${ENABLE_UNATTENDED_INSTALLATION}; then 80 | # shellcheck disable=SC2086 81 | DEBIAN_FRONTEND=noninteractive chroot_exec apt-get -y -q -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" ${PM_OPTIONS} install "$@" 82 | else 83 | # shellcheck disable=SC2086 84 | chroot_exec apt-get -y ${PM_OPTIONS} install "$@" 85 | fi 86 | fi 87 | } 88 | 89 | # Configures the keyboard-configuration package. 90 | # Globals: 91 | # None 92 | # Arguments: 93 | # None 94 | # Returns: 95 | # None 96 | configure_keyboard_configuration() { 97 | if is_debian_based; then 98 | echo "keyboard-configuration keyboard-configuration/layout select English" | chroot_exec debconf-set-selections 99 | fi 100 | } 101 | 102 | # Removes the specified packages with their configuration files from the chroot 103 | # environment. 104 | # Globals: 105 | # None 106 | # Arguments: 107 | # Packages names, separated by spaces 108 | # Returns: 109 | # None 110 | purge_packages() { 111 | if is_alpine; then 112 | chroot_exec apk del "$@" 113 | elif is_debian_based; then 114 | chroot_exec apt-get -y purge "$@" 115 | fi 116 | } 117 | -------------------------------------------------------------------------------- /pieman/bin/du.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Copyright (C) 2018 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | """Utility intended to calculate the size of the chroot environments. 18 | The main motivation to create a substitution for du from GNU Coreutils is that 19 | it can sometimes provide inaccurate result. For example, directory size may 20 | vary depending on when du is called -- before or after transferring the 21 | directory to an image. 22 | """ 23 | 24 | import math 25 | import os 26 | import sys 27 | from argparse import ArgumentParser 28 | 29 | 30 | def get_tree_size(path, block_size=4096): 31 | """Returns total size of files and number of files in the specified 32 | directory. 33 | """ 34 | total_size = items_number = 0 35 | 36 | # os.walk skips the symbolic links that resolve to directories, not 37 | # counting them at all. It has a great impact on the end result, so we need 38 | # a different way to solve the task. 39 | for dir_entry in fault_tolerant_scandir(path): 40 | items_number += 1 41 | 42 | if os.path.islink(dir_entry.path): 43 | total_size += block_size 44 | elif os.path.isdir(dir_entry.path): 45 | ret = get_tree_size(dir_entry.path) 46 | total_size += ret[0] + block_size 47 | items_number += ret[1] 48 | elif os.path.isfile(dir_entry.path): 49 | file_size = os.path.getsize(dir_entry.path) 50 | if file_size > block_size: 51 | total_size += file_size 52 | else: 53 | total_size += block_size 54 | 55 | return total_size, items_number 56 | 57 | 58 | def fault_tolerant_scandir(path): 59 | """Wrapper for ``os.scandir`` which is supposed to write to stderr if there 60 | is some problems instead of throwing exceptions. 61 | """ 62 | 63 | try: 64 | return os.scandir(path) 65 | except PermissionError: 66 | sys.stderr.write('Permission denied when trying to figure out ' 67 | 'the size of {}\n'.format(path)) 68 | 69 | return [] 70 | 71 | 72 | def main(): 73 | """The main entry point. """ 74 | 75 | parser = ArgumentParser() 76 | parser.add_argument("-b", "--block-size", default=4096, type=int, 77 | help="block size", metavar="SIZE") 78 | parser.add_argument("-m", "--size-in-megabytes", action="store_true", 79 | help="return total size in megabytes", dest="megabytes") 80 | parser.add_argument('directory') 81 | args = parser.parse_args() 82 | 83 | if not os.path.isdir(args.directory): 84 | sys.stderr.write('The {} directory does not exist\n'.format(args.directory)) 85 | sys.exit(1) 86 | 87 | total_size, items_number = get_tree_size(args.directory, args.block_size) 88 | 89 | if args.megabytes: 90 | total_size = math.ceil(total_size / 1024 / 1024) 91 | 92 | print('Items number: {}'.format(items_number)) 93 | print('Total size: {}'.format(total_size)) 94 | 95 | 96 | if __name__ == '__main__': 97 | main() 98 | -------------------------------------------------------------------------------- /bootstrap/15-networking.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | check_if_variable_is_set \ 17 | ENABLE_CUSTOM_DNS \ 18 | ENABLE_BASIC_YANDEX_DNS \ 19 | ENABLE_FAMILY_YANDEX_DNS \ 20 | ENABLE_GOOGLE_DNS \ 21 | ETC 22 | 23 | dns_addr1="" 24 | dns_addr2="" 25 | dns_is_set=false 26 | 27 | if ${ENABLE_GOOGLE_DNS}; then 28 | dns_addr1="8.8.8.8" 29 | dns_addr2="8.8.4.4" 30 | dns_is_set=true 31 | elif ${ENABLE_BASIC_YANDEX_DNS}; then 32 | dns_addr1="77.88.8.8" 33 | dns_addr2="77.88.8.1" 34 | dns_is_set=true 35 | elif ${ENABLE_FAMILY_YANDEX_DNS}; then 36 | dns_addr1="77.88.8.7" 37 | dns_addr2="77.88.8.3" 38 | dns_is_set=true 39 | elif [[ -n ${ENABLE_CUSTOM_DNS} ]]; then 40 | dns_addr1="${ENABLE_CUSTOM_DNS}" 41 | dns_is_set=true 42 | fi 43 | 44 | if is_alpine; then 45 | mkdir "${ETC}/udhcpc" 46 | addrs=$(echo "${dns_addr1} ${dns_addr2}" | xargs) 47 | echo -e "dns=\"${addrs}\"" > "${ETC}/udhcpc/udhcpc.conf" 48 | elif is_debian_based; then 49 | for i in ${dns_addr1} ${dns_addr2}; do 50 | echo "nameserver ${i}" >> "${ETC}"/resolvconf/resolv.conf.d/base 51 | done 52 | 53 | if ${dns_is_set}; then 54 | chroot_exec resolvconf -u 55 | fi 56 | fi 57 | 58 | install_readonly files/etc/hostname.template "${ETC}"/hostname 59 | sed -i "s/{HOSTNAME}/${HOST_NAME}/" "${ETC}/hostname" 60 | 61 | install_readonly files/etc/hosts.template "${ETC}"/hosts 62 | sed -i "s/{HOSTNAME}/${HOST_NAME}/" "${ETC}/hosts" 63 | 64 | render "${PIEMAN_DIR}"/files/network/interfaces.j2 "${ETC}"/network/interfaces 65 | 66 | if ${ENABLE_WIRELESS}; then 67 | if is_debian_based; then 68 | echo brcmfmac > "${ETC}"/modules-load.d/networking.conf 69 | 70 | mkdir -p "${R}"/lib/firmware/brcm 71 | 72 | wget https://raw.githubusercontent.com/RPi-Distro/firmware-nonfree/86e88fbf0345da49555d0ec34c80b4fbae7d0cd3/brcm/brcmfmac43430-sdio.bin -O "${R}"/lib/firmware/brcm/brcmfmac43430-sdio.bin 73 | wget https://raw.githubusercontent.com/RPi-Distro/firmware-nonfree/86e88fbf0345da49555d0ec34c80b4fbae7d0cd3/brcm/brcmfmac43430-sdio.txt -O "${R}"/lib/firmware/brcm/brcmfmac43430-sdio.txt 74 | 75 | install_readonly files/network/wpa_supplicant.conf "${ETC}"/wpa_supplicant/wpa_supplicant.conf 76 | 77 | if [[ -n ${WPA_SSID} ]]; then 78 | do_wpa_passphrase >> "${ETC}"/wpa_supplicant/wpa_supplicant.conf 79 | fi 80 | fi 81 | fi 82 | 83 | if is_alpine; then 84 | info "Adding the hostname service to the default runlevel" 85 | chroot_exec rc-update add hostname default 86 | 87 | info "Adding the networking service to the default runlevel" 88 | chroot_exec rc-update add networking default 89 | 90 | install_exec files/etc/local.d/11-up_eth0.start "${ETC}"/local.d/11-up_eth0.start 91 | 92 | # The networking service should depend on the local service since one of 93 | # the scripts from /etc/local.d raises the network interface. 94 | sed -i '/^\tneed/ s/$/ local/' "${ETC}/init.d/networking" 95 | fi 96 | 97 | send_request_to_bsc_server DONE_WITH_NETWORKING_CODE 98 | -------------------------------------------------------------------------------- /test/test_essentials.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (C) 2018-2021 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | # 18 | # Mock the variables which are required by functions.sh 19 | # 20 | 21 | setUp() { 22 | PIEMAN_DIR="${PIEMAN_DIR:=$(pwd)}" 23 | 24 | # shellcheck source=/dev/null 25 | . "${PIEMAN_DIR}"/essentials.sh 26 | 27 | # referenced but not assigned 28 | # shellcheck disable=SC2154 29 | FATAL="${text_in_red_color}Fatal${reset}" 30 | } 31 | 32 | # 33 | # Let the test begin 34 | # 35 | 36 | test_defining_private_variables() { 37 | priv="test" 38 | 39 | def_private_var priv "default" 40 | assertEquals "default" "${priv}" 41 | 42 | def_private_var priv2 "default" 43 | # referenced but not assigned 44 | # shellcheck disable=SC2154 45 | assertEquals "default" "${priv2}" 46 | 47 | def_private_var EMPTY "" 48 | assertNull "${EMPTY}" 49 | } 50 | 51 | test_defining_variables() { 52 | S1="test" 53 | def_var S1 "value by default" 54 | assertEquals "test" "${S1}" 55 | 56 | def_var S2 "value by default" 57 | assertEquals "value by default" "${S2}" 58 | 59 | def_var S3 "default" 60 | assertEquals "default" "${S3}" 61 | 62 | def_var BOOLEAN true 63 | assertTrue "${BOOLEAN}" 64 | 65 | def_var EMPTY "" 66 | assertNull "${EMPTY}" 67 | } 68 | 69 | test_defining_bool_variables() { 70 | local result="" 71 | local output="+ V1=test" 72 | local len=$((${#output} + 1)) # plus a new line character 73 | 74 | result=$( (def_bool_var V1 "test") 2>&1 ) 75 | assertEquals "${FATAL}: V1 must be a boolean" "${result:len}" 76 | 77 | result=$( (def_bool_var V2 "") 2>&1 ) 78 | output="+ V2=" 79 | len=$((${#output} + 1)) 80 | assertEquals "${FATAL}: V2 must be a boolean" "${result:len}" 81 | 82 | def_bool_var V3 "true" 83 | assertTrue "${V3}" 84 | 85 | def_bool_var V4 "false" 86 | assertFalse "${V4}" 87 | } 88 | 89 | test_defining_int_variables() { 90 | local result="" 91 | local output="+ N1=hello" 92 | local len=$((${#output} + 1)) # plus a new line character 93 | 94 | result=$( (def_int_var N1 hello) 2>&1 ) 95 | assertEquals "${FATAL}: N1 must be an integer" "${result:len}" 96 | 97 | def_int_var N2 1337 98 | assertEquals 1337 "${N2}" 99 | } 100 | 101 | test_defining_protected_variables() { 102 | S1="test" 103 | def_protected_var S1 "value by default" 104 | assertEquals "test" "${S1}" 105 | 106 | def_protected_var S2 "value by default" 107 | assertEquals "value by default" "${S2}" 108 | 109 | def_protected_var S3 "default" 110 | assertEquals "default" "${S3}" 111 | 112 | def_protected_var B true 113 | assertTrue "${B}" 114 | 115 | DASH="-" 116 | def_protected_var DASH "value by default" << EOF 117 | different value 118 | EOF 119 | assertEquals "different value" "${DASH}" 120 | 121 | def_protected_var EMPTY "" 122 | assertNull "${EMPTY}" 123 | } 124 | 125 | # shellcheck source=/dev/null 126 | . "$(command -v shunit2)" 127 | -------------------------------------------------------------------------------- /keys/ubuntu/ubuntu-archive-automatic-signing.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | mQINBE+tgXgBEADfiL1KNFHT4H4Dw0OR9LemR8ebsFl+b9E44IpGhgWYDufj0gaM 4 | /UJ1Ti3bHfRT39VVZ6cv1P4mQy0bnAKFbYz/wo+GhzjBWtn6dThYv7n+KL8bptSC 5 | Xgg1a6en8dCCIA/pwtS2Ut/g4Eu6Z467dvYNlMgCqvg+prKIrXf5ibio48j3AFvd 6 | 1dDJl2cHfyuON35/83vXKXz0FPohQ7N7kPfI+qrlGBYGWFzC/QEGje360Q2Yo+rf 7 | MoyDEXmPsoZVqf7EE8gjfnXiRqmz/Bg5YQb5bgnGbLGiHWtjS+ACIdLUq/h+jlSp 8 | 57jw8oQktMh2xVMX4utDM0UENeZnPllVJSlR0b+ZmZz7paeSar8Yxn4wsNlL7GZb 9 | pW5A/WmcmWfuMYoPhBo5Fq1V2/siKNU3UKuf1KH+X0p1oZ4oOcZ2bS0Zh3YEG8IQ 10 | ce9Bferq4QMKsekcG9IKS6WBIU7BwaElI2ILD0gSwu8KzvNSEeIJhYSsBIEzrWxI 11 | BXoN2AC9PCqqXkWlI5Xr/86RWllB3CsoPwEfO8CLJW2LlXTen/Fkq4wT+apdhHei 12 | WiSsq/J5OEff0rKHBQ3fK7fyVuVNrJFb2CopaBLyCxTupvxs162jjUNopt0c7OqN 13 | BoPoUoVFAxUSpeEwAw6xrM5vROyLMSeh/YnTuRy8WviRapZCYo6naTCY5wARAQAB 14 | tEJVYnVudHUgQXJjaGl2ZSBBdXRvbWF0aWMgU2lnbmluZyBLZXkgKDIwMTIpIDxm 15 | dHBtYXN0ZXJAdWJ1bnR1LmNvbT6JAjgEEwECACIFAk+tgXgCGwMGCwkIBwMCBhUI 16 | AgkKCwQWAgMBAh4BAheAAAoJEDtP5qzAsh8yXX4QAJHUdK6eYMyJcrFP3yKXtUYQ 17 | MpaHRM/floqZtOFhlmcLVMgBNOr0eLvBU0JcZyZpHMvZciTDBMWX8ItCYVjRejf0 18 | K0lPvHHRGaE7t6JHVUCeznNbDMnOPYVwlVJdZLOa6PmE5WXVXpk8uTA8vm6RO2rS 19 | 23vE7U0pQlV+1GVXMWH4ZLjaQs/Tm7wdvRxeqTbtfOEeHGLjmsoh0erHfzMV4wA/ 20 | 9Zq86WzuJS1HxXR6OYDC3/aQX7CxYT1MQxEw/PObnHtkl3PRMWdTW7fSQtulEXzp 21 | r2/JCev6Mfc8Uy0aD3jng9byVk9GpdNFEjGgaUqjqyZosvwAZ4/dmRjmMEibXeNU 22 | GC8HeWC3WOVV8L/DiA+miJlwPvwPiA1ZuKBI5A8VF0rNHW7QVsG8kQ+PDHgRdsmh 23 | pzSRgykN1PgK6UxScKX8LqNKCtKpuEPApka7FQ1u4BoZKjjpBhY1R4TpfFkMIe7q 24 | W8XfqoaP99pED3xXch2zFRNHitNJr+yQJH4z/o+2UvnTA2niUTHlFSCBoU1MvSq1 25 | N2J3qU6oR2cOYJ4ZxqWyCoeQR1x8aPnLlcn4le6HU7TocYbHaImcIt7qnG4Ni0OW 26 | P4giEhjOpgxtrWgl36mdufvriwya+EHXzn36EvQ9O+bm3fyarsnhPe01rlsRxqBi 27 | K1JOw/g4GnpX8iLGEX1ViQIcBBABCAAGBQJPrYpcAAoJEDk1h9l9hlALtdMP/19l 28 | ZWneOCFEFdsK6I1fiUSrrsi+RRefxGT5VwUWTQYIr7UwTJLGPj+GkLQe2deEj1v+ 29 | mmaZNsb83IQJKocQbo21OZAr3Uv4G6K3fAwj7zE3V+2k1iZKDH/3MfHpZ9x+1sUQ 30 | PcC+Y0Oh0jWw2GGPClYjLwP7WGegayCfPdejlAOReulKi2ge+mkoNM2Zm1ApA1q1 31 | 5rHST5QvIp1WqarK003QPABreDY37zffKiQwTo/jUzncTlTFlThLWqvh2H7g+r6r 32 | jrDhy/ytB+lOOAKp0qMHG1eovqQ6lpaRx+N0UR+bH4+WMBAg756ter/3h/Z9wApI 33 | PgpdA/BkxFQu932JbheZq+8WXQ3XwvXj/PVkqRr3zNAMYKVcSIFQ0hAhd2SK8Xrz 34 | KUMPPDqDF6lUA4hv3aU0kmLiWJibFWGxlE5LLpSPwy3Ed/bSvxYxE+OE+skdB3iP 35 | qHN7GHLilTHXsRTEXPLMN9QfKGKXiLFGXnLLc7hMLFbtoX5UdbaaEK7+rEkIc1zZ 36 | zw9orgefH2oXQSehuhwzmQpfmGM/zEwUSmbeZwXW82txeaGRn/Q5MfAIeqxBKLST 37 | 6Lv8SNfpI+f1vWNDZeRUTw3F8yWLrll8a5RKHDvnK3jXzeT8dLZPIjGULMyFm8r3 38 | U2djKhIrUJjjd89QM7qQnNFdU7LR3YG0ezT5pJu+iQIcBBABAgAGBQJPrYliAAoJ 39 | EAv7hH8/Jy9bZ2oQAKT+lN7RHIhwpz+TuTrBJSGFYhLur5T9Fg11mIKbQ9hdVMAS 40 | 9XO9fV/H4Odoiz6+ncbWIu8znPsqaziPoSEugj4CrBfVzDncDzOOeivJI66yuiek 41 | s53P48ougGgM3G2aTFAns8hXCgSVBZd4DxMQwR9w9PmuXgGnsVIShsn9TrNz+UOS 42 | pTX2F7PGwT+vOW8hM6W0GpaUhFuNVvi4HAGcW3HgcDy/KuKU5JzLKdUbnGey5N+H 43 | tcTYq+KbRBHCpfG6pPNjRIVdl/X6QcIFDaUO24L1tYTnvgehQnkz3GyLkeqiqmwu 44 | b7sTXYmhUStzdPM2NXGbPVQGNXu5tyvuvLAc+JTrn4ADIjDD35oY/4ti+LcCkuyD 45 | uzU8EWcMbG/QqF3VH2bUI0pP4TFIkeLWkMO7idOCOf6+ntvQaGa3BrnRs9CemDKa 46 | VyWwjNJEXboS8+LwBpWmNw/idWgLzf9N7XF1+GfrF61FeYccltcB1X8M4ElI/Cch 47 | vk52+OG8j6USemCOL1OSirbYqvj8UroQabVUwe90TZrboOL06Q2dPeX0fBIk837U 48 | XRDJpzKYexZvWg9kg7Ibf9MYuodt5bkG+6slwmbN7W1I4UAgrIj4EhlE9wsmdsMc 49 | 2eNXk6DOClN8sseXPx490nL623SQSx4tbYpukzaEXREXOQT2uY5GHvDVMv7biQIc 50 | BBABAgAGBQJPrYqXAAoJENfD8TGrKpH1rJAQAJr+AfdLW5oB95I68tZIYVwvqZ41 51 | wU8pkf8iXuNmT4C26wdj204jQl86iSJlf8EiuqswzD0eBrY/QNPOL6ABcKvhO4Kl 52 | uaRiULruaXI7odkmIDAty5gYe04nD7E3wv55lQOTrT7u7QZnfy//yY+3Qw4Ea6Me 53 | SeGW+s3REpmAPSl+iaWkqYiox/tmCQOQJK0jzxTcYyHcLzoNaJ+IqANZUM8URCrb 54 | RapRbm3XxA9FeD0Zlg77NGCZyT1pw6XkG7kLlE4BvUmzS/dIQkx8qnpJhchLQ20l 55 | xqcBaT1buRTxktvflWPeVhPy0MLl72l/Bdhly21YcQbmbClkbWMGgLctbqN25HwH 56 | 8Lo6guUk9oWlqvtuXOEI31lZgSestpsCz/JvlfYuyevBa33srUoRTFNnZshGNzkT 57 | 20GXjnx7WDb6mHxwcpAZFCCC2ktfDwd+/U0mU6+02zYHby6OIjRHnAvbCGhz51Ed 58 | PfE362W3CY021ktEgu9xYpIGOfREncrjo0AoOwqoWQhEoLG3ihF8LMUryVNac0ew 59 | srGY7gxFCnP+aHtXzaa8mMW8dkWgNwi6RfJfphrgHkdgKVjKukkIqRrZrDoD5O7A 60 | 18oTb3iMrBKHdSVZp0icpmAHb0ddBNlY9zun7akuBrVzM5aKuo21l/Qs9z3UK5k4 61 | DjfegedFClqpn37b 62 | =rDTH 63 | -----END PGP PUBLIC KEY BLOCK----- 64 | -------------------------------------------------------------------------------- /pieman/pieman/attrs.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | """Module intended to simplify working with pieman.yml files. """ 17 | 18 | import yaml 19 | 20 | 21 | TYPES_SCHEME = { 22 | 'repos': (list, ), 23 | 'codename': (str, ), 24 | 'base': (list, str), 25 | 'includes': (list, str), 26 | 'boot': (list, str), 27 | 'spl_bin': (str, ), 28 | 'params': (list, ), 29 | 'kernel': { 30 | 'package': (str, ), 31 | 'rebuild': (bool, ), 32 | 'patches': (str, ), 33 | }, 34 | } 35 | 36 | 37 | class AttributeDoesNotExist(Exception): 38 | """Exception raised when attempting to get an attribute which does not 39 | exist. """ 40 | def __init__(self, par_name, cur_name): 41 | message = ('{} does not have attribute {}'.format(par_name, cur_name)) 42 | Exception.__init__(self, message) 43 | 44 | 45 | class RootDoesNotExist(Exception): 46 | """Exception raised when attempting to get the root which does not 47 | exist. """ 48 | 49 | 50 | class UnknownAttribute(Exception): 51 | """Exception raised when attempting to get an attribute which may exist 52 | but is not mentioned in the specification. """ 53 | 54 | 55 | class UnprintableType(Exception): 56 | """Exception raised when attempting to print an attribute the type of which 57 | is neither str nor list. """ 58 | 59 | 60 | class Attribute: # pylint: disable=too-few-public-methods 61 | """Class representing a single attribute. """ 62 | 63 | def __init__(self, attribute, attribute_type): 64 | self.attribute, self._attribute_type = attribute, attribute_type 65 | 66 | def echo(self): 67 | """Writes the value of the attribute to stdout or raises 68 | `UnprintableType` if the attribute type is neither str nor list. 69 | """ 70 | if list in self._attribute_type or str in self._attribute_type: 71 | if isinstance(self.attribute, str): 72 | self.attribute = [self.attribute] 73 | 74 | for line in self.attribute: 75 | print(line) 76 | else: 77 | raise UnprintableType 78 | 79 | 80 | class AttributesList: # pylint: disable=too-few-public-methods 81 | """Class implementing the interface for working with pieman.yml files. """ 82 | 83 | def __init__(self, infile): 84 | self._attributes = yaml.load(infile, Loader=yaml.FullLoader) 85 | 86 | def get_attribute(self, attributes_chain): 87 | """Gets the value of the attribute. To get the value the full path to 88 | the attribute must be specified starting with the root. 89 | """ 90 | 91 | if attributes_chain: 92 | par_name = attributes_chain[0] 93 | try: 94 | cur_attribute = self._attributes[par_name] 95 | except KeyError as exc: 96 | raise RootDoesNotExist from exc 97 | 98 | cur_type = TYPES_SCHEME 99 | 100 | for attribute_name in attributes_chain[1:]: 101 | try: 102 | cur_attribute = cur_attribute[attribute_name] 103 | except KeyError as exc: 104 | raise AttributeDoesNotExist(par_name, attribute_name) from exc 105 | 106 | try: 107 | cur_type = cur_type[attribute_name] 108 | except KeyError as exc: 109 | raise UnknownAttribute from exc 110 | 111 | par_name = attribute_name 112 | 113 | if isinstance(cur_type, dict): 114 | cur_type = (dict, ) 115 | 116 | return Attribute(cur_attribute, cur_type) 117 | 118 | return None 119 | -------------------------------------------------------------------------------- /pieman/bin/apk_tools_version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Copyright (C) 2018 Evgeny Golyshev 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | """Utility intended to fetch the latest version of the apk-tools-static package 18 | in the specified version of Alpine Linux. The point is that the 19 | apk-tools-static version is not frozen in the stable release of Alpine Linux 20 | and may vary. 21 | """ 22 | 23 | import os 24 | import sys 25 | import time 26 | from argparse import ArgumentParser 27 | from html.parser import HTMLParser 28 | from urllib.error import URLError, HTTPError 29 | from urllib.parse import urljoin 30 | from urllib.request import urlopen 31 | 32 | 33 | ARCH = 'armhf' 34 | 35 | ALPINE_VERSION = '3.12' 36 | 37 | MIRROR = 'http://dl-cdn.alpinelinux.org' 38 | 39 | NAP = 1 40 | 41 | RETRIES_NUMBER = 5 42 | 43 | 44 | class CustomHTMLParser(HTMLParser): # pylint: disable=abstract-method 45 | """Simplified HTML parser to find the apk-tools-static version on the 46 | specified page. 47 | """ 48 | 49 | def __init__(self, content): 50 | HTMLParser.__init__(self, convert_charrefs=True) 51 | 52 | self._apk_tools_version = None 53 | self._content = content 54 | 55 | def get_apk_tools_version(self): 56 | """Returns the apk-tools-static version. """ 57 | self.feed(self._content) 58 | return self._apk_tools_version 59 | 60 | def handle_starttag(self, tag, attrs): 61 | if tag == 'a': 62 | for name, value in attrs: 63 | package_name = 'apk-tools-static' 64 | if name == 'href' and value.startswith(package_name): 65 | prefix = len(package_name) + 1 66 | suffix = len('.apk') 67 | self._apk_tools_version = value[prefix:-suffix] 68 | break 69 | 70 | 71 | def main(): 72 | """The main entry point. """ 73 | 74 | parser = ArgumentParser() 75 | parser.add_argument('--alpine-version', default=ALPINE_VERSION, 76 | help='alpine version', metavar='ALPINE_VERSION') 77 | parser.add_argument('--arch', default=ARCH, 78 | help='target architecture', metavar='ARCH') 79 | parser.add_argument('--mirror', default=MIRROR, 80 | help='mirror', metavar='MIRROR') 81 | args = parser.parse_args() 82 | 83 | address = urljoin(args.mirror, 84 | os.path.join('alpine', 'v' + args.alpine_version, 85 | 'main', args.arch)) 86 | 87 | content = b'' 88 | for attempt in range(1, RETRIES_NUMBER + 1): 89 | try: 90 | content = urlopen(address).read() 91 | break 92 | except HTTPError as exc: 93 | sys.stderr.write('{}: request failed (error code {})\n'. 94 | format(sys.argv[0], exc.code)) 95 | except URLError as exc: 96 | sys.stderr.write('{}: {}\n'.format(sys.argv[0], exc.reason)) 97 | 98 | if attempt != RETRIES_NUMBER: 99 | sys.stderr.write('Retrying in {} seconds...\n'.format(NAP)) 100 | time.sleep(NAP) 101 | 102 | if content == b'' and attempt == RETRIES_NUMBER: 103 | sys.stderr.write('Could not request {} after {} attempts\n'. 104 | format(address, RETRIES_NUMBER)) 105 | sys.exit(1) 106 | 107 | parser = CustomHTMLParser(content.decode('utf8')) 108 | apk_tools_version = parser.get_apk_tools_version() 109 | if not apk_tools_version: 110 | sys.stderr.write('Could not get apk tools version\n') 111 | sys.exit(1) 112 | 113 | print(apk_tools_version) 114 | 115 | 116 | if __name__ == '__main__': 117 | main() 118 | -------------------------------------------------------------------------------- /logo/pieman.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 30 | 34 | 38 | 42 | 46 | 50 | 54 | 55 | 58 | 59 | -------------------------------------------------------------------------------- /pieman/pieman/preprocessor.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | """A module that provides an implementation of the preprocessor of YAML files. The main function 17 | of the preprocessor is variable substitution, i.e. referencing (retrieving) variables values. The 18 | preprocessor supports the ${VAR} syntax to reference variables values. There are three types of 19 | variables: 20 | * environment variables (for example, ${USER} or ${HOME}); 21 | * the ${parent_node_name} builtin which contains parent nodes names, as it's seen from the name of 22 | the variable; 23 | * every string type node. 24 | """ 25 | 26 | import os 27 | import re 28 | import yaml 29 | 30 | 31 | class RootNameCouldNotBeFound(Exception): 32 | """Raised when the specified root name could not be found in the target YAML file. """ 33 | 34 | def __init__(self, root_name): 35 | super().__init__(f"The root name '{root_name}' could not be found") 36 | 37 | 38 | class UndefinedVariable(Exception): 39 | """Raised when the target YAML file references to an undefined variable. """ 40 | 41 | def __init__(self, var_name): 42 | super().__init__(f"The variable '{var_name}' is undefined") 43 | 44 | 45 | class Preprocessor: # pylint: disable=too-few-public-methods 46 | """A class that provides an implementation of the preprocessor of YAML files. """ 47 | 48 | def __init__(self, file_name, outfile, root_name): 49 | with open(file_name, 'r') as infile: 50 | self._toolset = yaml.load(infile, Loader=yaml.FullLoader) 51 | 52 | self._root_name = root_name 53 | self._tree = None 54 | 55 | self._get_tree() 56 | 57 | self._var_re = re.compile(r'\${([\w\d]+)}') 58 | 59 | self._go_through_all_yml(self._tree, self._toolset) 60 | 61 | new_tree = {self._root_name: self._tree} 62 | yaml.dump(new_tree, outfile, default_flow_style=False) 63 | 64 | # 65 | # Private methods 66 | # 67 | 68 | def _get_tree(self): 69 | try: 70 | self._tree = self._toolset[self._root_name] 71 | except KeyError as exc: 72 | raise RootNameCouldNotBeFound(self._root_name) from exc 73 | 74 | def _go_through_all_yml(self, parent_node, node, table_names=None, parent_node_name=None): 75 | table_names = table_names if table_names else {} 76 | 77 | if isinstance(node, dict): 78 | for key, val in node.items(): 79 | table_names['parent_node_name'] = parent_node_name 80 | if not isinstance(val, (dict, list, )): 81 | table_names[key] = val 82 | 83 | self._go_through_all_yml(node, val, table_names, key) 84 | elif isinstance(node, list): 85 | for i, val in enumerate(node): 86 | table_names['parent_node_name'] = parent_node_name 87 | self._go_through_all_yml(node, val, table_names, i) 88 | else: 89 | node_value = parent_node[parent_node_name] 90 | while True: # find all variables and substitute them for their values in the loop 91 | if not isinstance(node_value, str): 92 | break 93 | 94 | match = self._var_re.search(node_value) 95 | if match is None: 96 | break 97 | 98 | var_name = match[1] 99 | try: 100 | value = table_names[var_name] 101 | except KeyError: 102 | try: 103 | value = os.environ[var_name] 104 | except KeyError as exc: 105 | raise UndefinedVariable(var_name) from exc 106 | 107 | node_value = node_value.replace(match[0], value) 108 | 109 | parent_node[parent_node_name] = node_value 110 | -------------------------------------------------------------------------------- /helpers/mender.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Checks if the Mender dependencies are satisfied. 17 | # Globals: 18 | # None 19 | # Arguments: 20 | # None 21 | # Returns: 22 | # 0 or 1 depending on the result. 23 | are_mender_dependencies_satisfied() { 24 | local ret=0 25 | 26 | >&2 echo -n "checking /usr/include/sys/types.h... " 27 | yes_or_no "[ -f /usr/include/sys/types.h ]" || ret=1 28 | 29 | >&2 echo -n "checking bc... " 30 | yes_or_no "[ ! -z $(command -v bc) ]" || ret=1 31 | 32 | >&2 echo -n "checking cc... " 33 | yes_or_no "[ ! -z $(command -v cc) ]" || ret=1 34 | 35 | >&2 echo -n "checking dtc... " 36 | yes_or_no "[ ! -z $(command -v dtc) ]" || ret=1 37 | 38 | >&2 echo -n "checking go... " 39 | yes_or_no "[ ! -z $(command -v go) ]" || ret=1 40 | 41 | >&2 echo -n "checking make... " 42 | yes_or_no "[ ! -z $(command -v make) ]" || ret=1 43 | 44 | return "${ret}" 45 | } 46 | 47 | # Installs the Mender client. 48 | # Globals: 49 | # BOOT 50 | # MENDER_SERVER_URL 51 | # MENDER_TENANT_TOKEN 52 | # MOUNT_POINT 53 | # PIEMAN_DIR 54 | # TOOLSET_FULL_PATH 55 | # Arguments: 56 | # None 57 | # Returns: 58 | # None 59 | install_mender() { 60 | local etc_mender_dir="${MOUNT_POINT}"/etc/mender 61 | local mender_identity_dir="usr/share/mender/identity" 62 | local mender_inventory_dir="usr/share/mender/inventory" 63 | 64 | # The kernel and dtb files are supposed to be placed in /boot 65 | cp "${BOOT}"/kernel7.img "${MOUNT_POINT}"/boot/zImage 66 | cp "${BOOT}"/*.dtb "${MOUNT_POINT}"/boot 67 | 68 | # 69 | # Install Mender client 70 | # 71 | 72 | # Install the daemon executable and its configuration files 73 | install -m 0755 "${TOOLSET_FULL_PATH}/mender/mender" "${MOUNT_POINT}"/usr/bin/mender 74 | install -d "${etc_mender_dir}" 75 | install -m 0644 "${PIEMAN_DIR}"/files/mender/mender.conf.template "${etc_mender_dir}"/mender.conf 76 | sed -i -e "s#{MENDER_INVENTORY_POLL_INTERVAL}#${MENDER_INVENTORY_POLL_INTERVAL}#" "${etc_mender_dir}"/mender.conf 77 | sed -i -e "s#{MENDER_RETRY_POLL_INTERVAL}#${MENDER_RETRY_POLL_INTERVAL}#" "${etc_mender_dir}"/mender.conf 78 | sed -i -e "s#{MENDER_SERVER_URL}#${MENDER_SERVER_URL}#" "${etc_mender_dir}"/mender.conf 79 | sed -i -e "s#{MENDER_TENANT_TOKEN}#${MENDER_TENANT_TOKEN}#" "${etc_mender_dir}"/mender.conf 80 | sed -i -e "s#{MENDER_UPDATE_POLL_INTERVAL}#${MENDER_UPDATE_POLL_INTERVAL}#" "${etc_mender_dir}"/mender.conf 81 | install -m 0644 "${PIEMAN_DIR}"/files/mender/artifact_info "${etc_mender_dir}" 82 | sed -i -e "s#{MENDER_ARTIFACT_NAME}#${MENDER_ARTIFACT_NAME}#" "${etc_mender_dir}"/artifact_info 83 | 84 | # Make the daemon start on boot 85 | install -m 0644 "${PIEMAN_DIR}"/files/mender/mender.service "${MOUNT_POINT}"/lib/systemd/system 86 | ln -s "${MOUNT_POINT}"/lib/systemd/system/mender.service "${MOUNT_POINT}"/etc/systemd/system/multi-user.target.wants/mender.service 87 | 88 | # Install fw_printenv and fw_setenv 89 | install -m 0755 "${TOOLSET_FULL_PATH}"/mender/fw_printenv "${MOUNT_POINT}"/sbin/fw_printenv 90 | ln -fs /sbin/fw_printenv "${MOUNT_POINT}"/usr/bin/fw_printenv 91 | ln -fs /sbin/fw_printenv "${MOUNT_POINT}"/sbin/fw_setenv 92 | ln -sf /data/u-boot/fw_env.config "${MOUNT_POINT}"/etc/fw_env.config 93 | 94 | # Mender generates keys (mender-agent.pem) and places them in 95 | # /var/lib/mender. The keys must be physically located on the data 96 | # partition because the keys must present on both A and B partitions. 97 | ln -sf /data/mender "${MOUNT_POINT}/var/lib/mender" 98 | 99 | install -m 0644 "${PIEMAN_DIR}"/files/mender/fstab "${MOUNT_POINT}"/etc/fstab 100 | 101 | install -d "${MOUNT_POINT}/${mender_identity_dir}" 102 | install -d "${MOUNT_POINT}/${mender_inventory_dir}" 103 | 104 | install -t "${MOUNT_POINT}/${mender_identity_dir}" -m 0755 "${TOOLSET_FULL_PATH}"/mender/mender-device-identity 105 | install -t "${MOUNT_POINT}/${mender_inventory_dir}" -m 0755 "${TOOLSET_FULL_PATH}"/mender/mender-inventory-* 106 | } 107 | -------------------------------------------------------------------------------- /helpers/bsc.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2020 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | # Checks if it's possible to connect to the Redis server, specified via the 17 | # Pieman parameters. 18 | # Globals: 19 | # ENABLE_BSC_CHANNEL 20 | # REDIS_HOST 21 | # REDIS_IS_AVAILABLE 22 | # REDIS_PORT 23 | # Arguments: 24 | # None 25 | # Returns: 26 | # None 27 | check_redis() { 28 | if ${ENABLE_BSC_CHANNEL}; then 29 | info "checking if it is possible to connect to the Redis server" \ 30 | "${REDIS_HOST}:${REDIS_PORT}" 31 | 32 | if ! check_redis.py -H "${REDIS_HOST}" -P "${REDIS_PORT}"; then 33 | fatal "could not connect to Redis" 34 | 35 | REDIS_IS_AVAILABLE=false 36 | 37 | # Don't exit with non-zero code since the problem related to Redis 38 | # mustn't affect the success of the current build. 39 | else 40 | info "Redis is available" 41 | fi 42 | fi 43 | } 44 | 45 | # Sends a request to Build Status Codes server. 46 | # Globals: 47 | # ENABLE_BSC_CHANNEL 48 | # PROJECT_NAME 49 | # REDIS_IS_AVAILABLE 50 | # Arguments: 51 | # None 52 | # Returns: 53 | # None 54 | send_request_to_bsc_server() { 55 | if ${REDIS_IS_AVAILABLE} && ${ENABLE_BSC_CHANNEL}; then 56 | local request=$1 57 | local unix_socket_path="/var/run/bscd-${PROJECT_NAME}.sock" 58 | 59 | bsc.py --unix-socket-name "${unix_socket_path}" "${!request}" > /dev/null 2>&1 60 | fi 61 | } 62 | 63 | # Starts the Build Status Codes server. 64 | # Globals: 65 | # ENABLE_BSC_CHANNEL 66 | # PROJECT_NAME 67 | # REDIS_HOST 68 | # REDIS_IS_AVAILABLE 69 | # REDIS_PORT 70 | # Arguments: 71 | # None 72 | # Returns: 73 | # None 74 | start_bscd() { 75 | if ${REDIS_IS_AVAILABLE} && ${ENABLE_BSC_CHANNEL}; then 76 | local daemon_started=false 77 | local pid_file="/var/run/bscd-${PROJECT_NAME}.pid" 78 | local log_file="${PIEMAN_DIR}/build/bscd-${PROJECT_NAME}.log" 79 | local unix_socket_path="/var/run/bscd-${PROJECT_NAME}.sock" 80 | 81 | info "starting the Build Status Codes server" 82 | bscd.py \ 83 | --channel-name "bscd-${PROJECT_NAME}" \ 84 | --daemonize \ 85 | --log-file-prefix "${log_file}" \ 86 | --pid "${pid_file}" \ 87 | --redis-host "${REDIS_HOST}" \ 88 | --redis-port "${REDIS_PORT}" \ 89 | --unix-socket-name "${unix_socket_path}" 90 | 91 | local max_retries=10 92 | for i in $(eval echo "{1..${max_retries}}"); do 93 | if [[ ! -f "${pid_file}" ]]; then 94 | info "waiting when bscd is up" 95 | sleep 1 96 | else 97 | daemon_started=true 98 | break 99 | fi 100 | done 101 | 102 | if ${daemon_started}; then 103 | info "bscd -- channel name is bscd-${PROJECT_NAME}" 104 | info "bscd -- log file is ${log_file}" 105 | info "bscd -- pid file is ${pid_file}" 106 | info "bscd -- Unix socket path is ${unix_socket_path}" 107 | else 108 | fatal "could not start bscd" 109 | 110 | # Don't exit with non-zero code since the problem related to bscd 111 | # mustn't affect the success of the current build. 112 | fi 113 | fi 114 | } 115 | 116 | # Stops the Build Status Codes server. 117 | # Globals: 118 | # PROJECT_NAME 119 | # Arguments: 120 | # None 121 | # Returns: 122 | # None 123 | stop_bscd() { 124 | local pid_file="/var/run/bscd-${PROJECT_NAME}.pid" 125 | 126 | if [[ -f "${pid_file}" ]]; then 127 | local daemon_stopped=false 128 | local max_retries=10 129 | 130 | info "shutting down bscd" 131 | send_request_to_bsc_server EXIT_REQUEST 132 | 133 | for i in $(eval echo "{1..${max_retries}}"); do 134 | if [[ -f "${pid_file}" ]]; then 135 | info "waiting when bscd is down ($((max_retries - i)) attempts left)" 136 | sleep 1 137 | else 138 | daemon_stopped=true 139 | break 140 | fi 141 | done 142 | 143 | if ! ${daemon_stopped}; then 144 | fatal "could not stop bscd" 145 | fi 146 | fi 147 | } 148 | -------------------------------------------------------------------------------- /keys/devuan/primary-devuan-signing.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | 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 79 | =TkR6 80 | -----END PGP PUBLIC KEY BLOCK----- 81 | -------------------------------------------------------------------------------- /bootstrap/12-pm.sh: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017-2021 Evgeny Golyshev 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | for var in CREATE_ONLY_CHROOT ENABLE_NONFREE ENABLE_UNIVERSE ETC PIECES; do 17 | check_if_variable_is_set ${var} 18 | done 19 | 20 | if ${ALLOW_UNAUTHENTICATED}; then 21 | if is_alpine; then 22 | add_option_to_pm_options --allow-untrusted 23 | elif is_debian_based; then 24 | add_option_to_pm_options --allow-unauthenticated 25 | fi 26 | fi 27 | 28 | if ${ENABLE_MENDER} || ${CREATE_ONLY_MENDER_ARTIFACT}; then 29 | add_package_to_includes ca-certificates 30 | # Need to have the reboot executable file in $PATH 31 | # Solved by adding systemd-sysv to pieman.yml 32 | fi 33 | 34 | if ${ENABLE_SUDO}; then 35 | add_package_to_includes sudo 36 | fi 37 | 38 | # /etc/rc.firstboot dependencies 39 | add_package_to_includes parted 40 | add_package_to_includes ifupdown 41 | 42 | if is_alpine; then 43 | add_package_to_includes e2fsprogs-extra 44 | add_package_to_includes util-linux 45 | elif is_debian_based; then 46 | # Networking 47 | add_package_to_includes netbase 48 | add_package_to_includes net-tools 49 | add_package_to_includes isc-dhcp-client 50 | add_package_to_includes inetutils-ping 51 | fi 52 | 53 | if ${ENABLE_WIRELESS}; then 54 | if is_debian_based; then 55 | add_package_to_includes wpasupplicant 56 | fi 57 | fi 58 | 59 | if is_alpine; then 60 | if ${ENABLE_COMMUNITY}; then 61 | additional_sections="community" 62 | fi 63 | 64 | # By default /etc/apt/sources.list uses only the main section of the archive. 65 | # However, the ENABLE_NONFREE and ENABLE_UNIVERSE environment variables can 66 | # change the situation. 67 | elif is_kali || is_raspberrypios || is_devuan; then 68 | if ${ENABLE_NONFREE}; then 69 | additional_sections=" contrib non-free" 70 | fi 71 | elif is_ubuntu; then 72 | if ${ENABLE_UNIVERSE}; then 73 | additional_sections=" universe" 74 | fi 75 | fi 76 | 77 | if is_alpine; then 78 | primary_repo="$(get_attr repos | head -n1)" 79 | echo "${primary_repo}/v${PIECES[1]}/main" > "${ETC}"/apk/repositories 80 | 81 | if [[ -n ${additional_sections} ]]; then 82 | echo "${primary_repo}/v${PIECES[1]}/${additional_sections}" >> "${ETC}"/apk/repositories 83 | fi 84 | elif is_debian_based; then 85 | # If /etc/apt/sources.list exists, remove the content. 86 | echo "" > "${ETC}"/apt/sources.list 87 | 88 | # Form the content of /etc/apt/sources.list. 89 | for source in $(get_attr repos); do 90 | codename=${PIECES[1]} 91 | echo "deb ${source} ${codename} main${additional_sections}" >> "${ETC}"/apt/sources.list 92 | done 93 | 94 | # Add a channel that provides security updates. Debian and Ubuntu have 95 | # different approaches of adding the channel to /etc/apt/sources.list. 96 | 97 | if is_debian; then 98 | echo "deb ${source}-security ${codename}/updates main${additional_sections}" >> "${ETC}"/apt/sources.list 99 | fi 100 | 101 | if is_ubuntu; then 102 | echo "deb ${source} ${codename}-security main${additional_sections}" >> "${ETC}"/apt/sources.list 103 | fi 104 | fi 105 | 106 | run_scripts "${SOURCE_DIR}"/pre-update-indexes 107 | 108 | info "updating indexes" 109 | update_indexes 110 | 111 | run_scripts "${SOURCE_DIR}"/post-update-indexes 112 | 113 | send_request_to_bsc_server UPDATED_CODE 114 | 115 | dns_params=( 116 | ENABLE_GOOGLE_DNS 117 | ENABLE_BASIC_YANDEX_DNS 118 | ENABLE_FAMILY_YANDEX_DNS 119 | ENABLE_CUSTOM_DNS 120 | ) 121 | for param in "${dns_params[@]}"; do 122 | if ${!param} && [[ -n ${!param} ]]; then 123 | if is_debian_based; then 124 | add_package_to_includes resolvconf 125 | fi 126 | fi 127 | done 128 | 129 | # Install the packages recommended by the maintainer of the image, specified by 130 | # the user and required by some parameters. 131 | 132 | includes="$(get_attr_or_nothing includes)" 133 | if [[ -n ${includes} ]]; then 134 | for i in ${includes}; do 135 | add_package_to_includes "${i}" 136 | done 137 | fi 138 | 139 | if ${XFCE4}; then 140 | add_package_to_includes xfce4 141 | add_package_to_includes lxdm 142 | add_package_to_includes xfce4-goodies 143 | configure_keyboard_configuration 144 | fi 145 | 146 | if [[ -n ${INCLUDES} ]]; then 147 | packages_list=$(echo "${INCLUDES}" | sed -r 's/,/ /g') 148 | 149 | run_scripts "${SOURCE_DIR}"/pre-install 150 | 151 | info "installing ${packages_list}" 152 | 153 | # ${packages_list} mustn't be quoted. 154 | # For example, ${packages_list} stores "nginx mariadb-server-10.3". If you 155 | # invoke install_packages "${packages_list}", the package manager will try 156 | # to find and install the package named "nginx mariadb-server-10.3" but not 157 | # nginx and mariadb-server-10.3 separately. However, shellcheck doesn't 158 | # like when variables are unquoted, so 159 | # shellcheck disable=SC2086 160 | install_packages ${packages_list} 161 | 162 | run_scripts "${SOURCE_DIR}"/post-install 163 | 164 | send_request_to_bsc_server INSTALLED_PACKAGES_CODE 165 | fi 166 | 167 | run_scripts "${SOURCE_DIR}"/pre-upgrade 168 | 169 | info "upgrading chroot environment" 170 | upgrade 171 | 172 | run_scripts "${SOURCE_DIR}"/post-upgrade 173 | 174 | send_request_to_bsc_server UPGRADED_CODE 175 | 176 | if ${CREATE_ONLY_CHROOT}; then 177 | clean 178 | 179 | info "exiting since CREATE_ONLY_CHROOT is set to true" 180 | 181 | cleanup 182 | 183 | success "Chroot environment ${R} is done. Now you can speed up next builds by passing it to Pieman via the BASE_DIR parameter." 184 | 185 | exit 0 186 | fi 187 | --------------------------------------------------------------------------------