Merge branch 'master' into master

This commit is contained in:
Marcos Tischer Vallim 2024-09-07 23:42:59 -03:00 committed by GitHub
commit 84452eb575
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 745 additions and 404 deletions

View File

@ -9,7 +9,7 @@ on:
jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

View File

@ -9,7 +9,7 @@ on:
jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

View File

@ -9,7 +9,7 @@ on:
jobs:
build:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

29
.github/workflows/build-noble.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: build-noble
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: |
cd scripts
sed -i -E 's/TARGET_UBUNTU_VERSION=(.*)/TARGET_UBUNTU_VERSION="noble"/g' default_config.sh
./build.sh -
cd ..
- name: Archive artifacts
uses: actions/upload-artifact@v3
with:
name: ubuntu-from-scratch
path: |
scripts/ubuntu-from-scratch.iso
scripts/image/md5sum.txt

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
scripts/chroot
scripts/image
scripts/certificates
*.iso

View File

@ -1,4 +1,7 @@
Marcos Vallim <tischer@gmail.com>
Ken Gilmer <kgilmer@gmail.com>
Marcos Vallim <tischer@gmail.com> - mvallim
Ken Gilmer <kgilmer@gmail.com> - kgilmer
Anduin Xue <anduin@aiursoft.com> - Anduin2017
Andreas Blaesius <andi@unlegacy-android.org> - andi34
Andre Julius <> - NotNorom
sostela <>
monkey-jsun <>
Andreas Blaesius <andi@unlegacy-android.org>

672
README.md
View File

@ -21,6 +21,8 @@ See also the list of [contributors](CONTRIBUTORS.txt) who participated in this p
[![build-bionic](https://github.com/mvallim/live-custom-ubuntu-from-scratch/actions/workflows/build-bionic.yml/badge.svg)](https://github.com/mvallim/live-custom-ubuntu-from-scratch/actions/workflows/build-bionic.yml)
[![build-focal](https://github.com/mvallim/live-custom-ubuntu-from-scratch/actions/workflows/build-focal.yml/badge.svg)](https://github.com/mvallim/live-custom-ubuntu-from-scratch/actions/workflows/build-focal.yml)
[![build-jammy](https://github.com/mvallim/live-custom-ubuntu-from-scratch/actions/workflows/build-jammy.yml/badge.svg)](https://github.com/mvallim/live-custom-ubuntu-from-scratch/actions/workflows/build-jammy.yml)
[![build-noble](https://github.com/mvallim/live-custom-ubuntu-from-scratch/actions/workflows/build-noble.yml/badge.svg)](https://github.com/mvallim/live-custom-ubuntu-from-scratch/actions/workflows/build-noble.yml)
## Terms
@ -34,13 +36,9 @@ Install packages we need in the `build system` required by our scripts.
```shell
sudo apt-get install \
binutils \
debootstrap \
squashfs-tools \
xorriso \
grub-pc-bin \
grub-efi-amd64-bin \
mtools
debootstrap \
squashfs-tools \
xorriso
```
```shell
@ -57,7 +55,7 @@ mkdir $HOME/live-ubuntu-from-scratch
sudo debootstrap \
--arch=amd64 \
--variant=minbase \
focal \
noble \
$HOME/live-ubuntu-from-scratch/chroot \
http://us.archive.ubuntu.com/ubuntu/
```
@ -78,7 +76,7 @@ mkdir $HOME/live-ubuntu-from-scratch
*A chroot on Unix operating systems is an operation that changes the apparent root directory for the current running process and its children. A program that is run in such a modified environment cannot name (and therefore normally cannot access) files outside the designated directory tree. The term "chroot" may refer to the chroot system call or the chroot wrapper program. The modified environment is called a chroot jail.*
> Reference: https://en.wikipedia.org/wiki/Chroot
> Reference: <https://en.wikipedia.org/wiki/Chroot>
From this point we will be configuring the `live system`.
@ -114,14 +112,14 @@ From this point we will be configuring the `live system`.
```shell
cat <<EOF > /etc/apt/sources.list
deb http://us.archive.ubuntu.com/ubuntu/ focal main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ focal main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ noble main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ noble main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ noble-security main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ noble-security main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ focal-updates main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ noble-updates main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ noble-updates main restricted universe multiverse
EOF
```
@ -167,24 +165,27 @@ From this point we will be configuring the `live system`.
```shell
apt-get install -y \
sudo \
ubuntu-standard \
casper \
lupin-casper \
discover \
laptop-detect \
os-prober \
network-manager \
resolvconf \
net-tools \
wireless-tools \
wpagui \
locales \
grub-common \
grub-gfxpayload-lists \
grub-pc \
grub-pc-bin \
grub2-common
sudo \
ubuntu-standard \
casper \
discover \
laptop-detect \
os-prober \
network-manager \
net-tools \
wireless-tools \
wpagui \
locales \
grub-common \
grub-gfxpayload-lists \
grub-pc \
grub-pc-bin \
grub2-common \
grub-efi-amd64-signed \
shim-signed \
memtest86+ \
mtools \
binutils
```
```shell
@ -206,19 +207,19 @@ From this point we will be configuring the `live system`.
1. Configure keyboard
<p align="center">
<img src="images/keyboard-configure-01.png">
</p>
<p align="center">
<img src="images/keyboard-configure-01.png">
</p>
<p align="center">
<img src="images/keyboard-configure-02.png">
</p>
<p align="center">
<img src="images/keyboard-configure-02.png">
</p>
2. Console setup
<p align="center">
<img src="images/console-configure-01.png">
</p>
<p align="center">
<img src="images/console-configure-01.png">
</p>
11. **Install window manager**
@ -244,43 +245,43 @@ From this point we will be configuring the `live system`.
13. **Install Visual Studio Code (optional)**
1. Download and install the key
1. Download and install the key
```shell
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
```shell
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/
install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/
echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list
echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list
rm microsoft.gpg
```
rm microsoft.gpg
```
2. Then update the package cache and install the package using
2. Then update the package cache and install the package using
```shell
apt-get update
```shell
apt-get update
apt-get install -y code
```
apt-get install -y code
```
14. **Install Google Chrome (optional)**
1. Download and install the key
1. Download and install the key
```shell
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
```shell
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
echo "deb http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list
```
echo "deb http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list
```
2. Then update the package cache and install the package using
2. Then update the package cache and install the package using
```shell
apt-get update
```shell
apt-get update
apt-get install google-chrome-stable
```
apt-get install google-chrome-stable
```
15. **Install Java JDK 8 (optional)**
@ -311,134 +312,66 @@ From this point we will be configuring the `live system`.
18. **Reconfigure packages**
1. Generate locales
1. Generate locales
```shell
dpkg-reconfigure locales
```
```shell
dpkg-reconfigure locales
```
1. *Select locales*
<p align="center">
<img src="images/locales-select.png">
</p>
1. *Select locales*
<p align="center">
<img src="images/locales-select.png">
</p>
2. *Select default locale*
<p align="center">
<img src="images/locales-default.png">
</p>
2. *Select default locale*
<p align="center">
<img src="images/locales-default.png">
</p>
2. Reconfigure resolvconf
2. Configure network-manager
```shell
dpkg-reconfigure resolvconf
```
```shell
cat <<EOF > /etc/NetworkManager/NetworkManager.conf
[main]
rc-manager=none
plugins=ifupdown,keyfile
dns=systemd-resolved
1. *Confirm changes*
<p align="center">
<img src="images/resolvconf-confirm-01.png">
</p>
[ifupdown]
managed=false
```
<p align="center">
<img src="images/resolvconf-confirm-02.png">
</p>
3. Reconfigure network-manager
<p align="center">
<img src="images/resolvconf-confirm-03.png">
</p>
3. Configure network-manager
```shell
cat <<EOF > /etc/NetworkManager/NetworkManager.conf
[main]
rc-manager=resolvconf
plugins=ifupdown,keyfile
dns=dnsmasq
[ifupdown]
managed=false
EOF
```
4. Reconfigure network-manager
```shell
dpkg-reconfigure network-manager
```
19. **Cleanup the chroot environment**
1. If you installed software, be sure to run
```shell
truncate -s 0 /etc/machine-id
```
2. Remove the diversion
```shell
rm /sbin/initctl
dpkg-divert --rename --remove /sbin/initctl
```
3. Clean up
```shell
apt-get clean
rm -rf /tmp/* ~/.bash_history
umount /proc
umount /sys
umount /dev/pts
export HISTSIZE=0
exit
```
## Unbind mount points
```shell
sudo umount $HOME/live-ubuntu-from-scratch/chroot/dev
sudo umount $HOME/live-ubuntu-from-scratch/chroot/run
```
```shell
dpkg-reconfigure network-manager
```
## Create the CD image directory and populate it
We are now back in our `build environment` after setting up our `live system` and will continue creating files necessary to generate the ISO.
1. Access build directory
1. Create directories
```shell
cd $HOME/live-ubuntu-from-scratch
mkdir -p /image/{casper,isolinux,install}
```
2. Create directories
2. Copy kernel images
```shell
mkdir -p image/{casper,isolinux,install}
cp /boot/vmlinuz-**-**-generic image/casper/vmlinuz
cp /boot/initrd.img-**-**-generic image/casper/initrd
```
3. Copy kernel images
3. Copy memtest86+ binary (BIOS)
```shell
sudo cp chroot/boot/vmlinuz-**-**-generic image/casper/vmlinuz
sudo cp chroot/boot/initrd.img-**-**-generic image/casper/initrd
cp /boot/memtest86+.bin image/install/memtest86+
```
4. Copy memtest86+ binary (BIOS)
```shell
sudo cp chroot/boot/memtest86+.bin image/install/memtest86+
```
5. Download and extract memtest86 binary (UEFI)
4. Download and extract memtest86 binary (UEFI)
```shell
wget --progress=dot https://www.memtest86.com/downloads/memtest86-usb.zip -O image/install/memtest86-usb.zip
@ -450,19 +383,13 @@ We are now back in our `build environment` after setting up our `live system` an
## GRUB menu configuration
1. Access build directory
```shell
cd $HOME/live-ubuntu-from-scratch
```
2. Create base point access file for grub
1. Create base point access file for grub
```shell
touch image/ubuntu
```
3. Create image/isolinux/grub.cfg
2. Create image/isolinux/grub.cfg
```shell
cat <<EOF > image/isolinux/grub.cfg
@ -508,69 +435,32 @@ We are now back in our `build environment` after setting up our `live system` an
Next we create a file `filesystem.manifest` to specify each package and it's version that is installed on the `live system`. We create another file `filesystem.manifest-desktop` which specifies which files will be installed on the `target system`. Once the Ubiquity installer completes, it will
remove packages specified in `filesystem.manifest` that are *not* listed in `filesystem.manifest-desktop`.
1. Access build directory
1. Generate manifest
```shell
cd $HOME/live-ubuntu-from-scratch
```
dpkg-query -W --showformat='${Package} ${Version}\n' | sudo tee /image/casper/filesystem.manifest
2. Generate manifest
cp -v /image/casper/filesystem.manifest image/casper/filesystem.manifest-desktop
```shell
sudo chroot chroot dpkg-query -W --showformat='${Package} ${Version}\n' | sudo tee image/casper/filesystem.manifest
sed -i '/ubiquity/d' /image/casper/filesystem.manifest-desktop
sudo cp -v image/casper/filesystem.manifest image/casper/filesystem.manifest-desktop
sed -i '/casper/d' /image/casper/filesystem.manifest-desktop
sudo sed -i '/ubiquity/d' image/casper/filesystem.manifest-desktop
sed -i '/discover/d' /image/casper/filesystem.manifest-desktop
sudo sed -i '/casper/d' image/casper/filesystem.manifest-desktop
sed -i '/laptop-detect/d' /image/casper/filesystem.manifest-desktop
sudo sed -i '/discover/d' image/casper/filesystem.manifest-desktop
sudo sed -i '/laptop-detect/d' image/casper/filesystem.manifest-desktop
sudo sed -i '/os-prober/d' image/casper/filesystem.manifest-desktop
```
## Compress the chroot
After everything has been installed and preconfigured in the **chrooted** environment, we need to generate an image of everything that was done by following the next steps in the `build environment`.
1. Access build directory
```shell
cd $HOME/live-ubuntu-from-scratch
```
2. Create squashfs
```shell
sudo mksquashfs chroot image/casper/filesystem.squashfs
```
> **Squashfs** is a highly compressed read-only filesystem for Linux. It uses zlib compression to compress both files, inodes and directories. Inodes in the system are very small and all blocks are packed to minimize data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
> **Squashfs** is intended for general read-only filesystem use, for archival use (i.e. in cases where a .tar.gz file may be used), and in constrained block device/memory systems (e.g. **embedded systems**) where low overhead is needed.
3. Write the filesystem.size
```shell
printf $(sudo du -sx --block-size=1 chroot | cut -f1) > image/casper/filesystem.size
sed -i '/os-prober/d' /image/casper/filesystem.manifest-desktop
```
## Create diskdefines
**README** file often found on Linux LiveCD installer discs, such as an Ubuntu Linux installation CD; typically named “**README.diskdefines**” and may be referenced during installation.
1. Access build directory
1. Create file /image/README.diskdefines
```shell
cd $HOME/live-ubuntu-from-scratch
```
2. Create file image/README.diskdefines
```shell
cat <<EOF > image/README.diskdefines
cat <<EOF > /image/README.diskdefines
#define DISKNAME Ubuntu from scratch
#define TYPE binary
#define TYPEbinary 1
@ -583,32 +473,201 @@ After everything has been installed and preconfigured in the **chrooted** enviro
EOF
```
## Create ISO Image for a LiveCD (BIOS + UEFI)
### Creating the certificates to Secure Boot
1. Create the certificate template
```shell
mkdir /certificates
```
```shell
cd /certificates
```
```shell
cat <<EOF > config.conf
[ req ]
default_bits = 2048
default_md = sha256
distinguished_name = dn
prompt = no
[ dn ]
C = BR
ST = SP
L = Campinas
O = Scratch, Labs
OU = Labs
CN = \${ENV::CN}
[ root ]
basicConstraints = critical,CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
keyUsage = critical,digitalSignature,keyEncipherment,keyCertSign,cRLSign
[ ca ]
basicConstraints = critical,CA:TRUE,pathlen:0
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = critical,digitalSignature,keyEncipherment,keyCertSign,cRLSign
[ db ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:FALSE
keyUsage = critical,keyEncipherment,dataEncipherment
authorityKeyIdentifier = keyid,issuer:always
EOF
```
2. Create the Root CA certificate
```shell
CN="Root, CA" \
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout root.key \
-days 3650 \
-config config.conf \
-extensions root \
-out root.pem
```
3. Create the intermediate CA certificate
```shell
CN="Ubuntu live from scratch, CA" \
openssl req -newkey rsa:2048 -nodes \
-keyout ca.key \
-config config.conf \
-out ca.pem
```
4. Create Database (DB) request certificate
```shell
CN="Ubuntu live from scratch, Database" \
openssl req -newkey rsa:2048 -nodes \
-keyout db.key \
-config config.conf \
-out db.pem
```
5. Sign the intermediate CA certificate with the Root CA certificate
```shell
CN="Ubuntu live from scratch, CA" \
openssl x509 -req \
-extfile config.conf \
-extensions ca \
-in ca.pem \
-CA root.pem \
-CAkey root.key \
-CAcreateserial \
-out ca.pem \
-days 3650 -sha256
```
6. Sign Database (DB) certificate using your own CA
```shell
CN="Ubuntu live from scratch, Database" \
openssl x509 -req \
-extfile config.conf \
-extensions db \
-in db.pem \
-CA ca.pem \
-CAkey ca.key \
-CAcreateserial \
-out db.pem \
-days 3650 -sha256
```
7. Create the intermediate CA certificate chain
```shell
cat ca.pem root.pem > ca-chain.pem
```
8. Verify the signatures
```shell
openssl verify -CAfile ca-chain.pem db.pem
```
9. Create DER version of our public key (CA)
```shell
openssl x509 -outform DER -in ca.pem -out ca.cer
```
### Creating image
1. Access image directory
```shell
cd $HOME/live-ubuntu-from-scratch/image
cd /image
```
2. Create a FAT16 UEFI boot disk image containing the EFI bootloader
2. Create [SBAT](https://github.com/rhboot/shim/blob/main/SBAT.md) file
```shell
GRUB_VERSION=`grub-mkstandalone -V | tr -s ' ' | cut -d' ' -f3 | cut -d'-' -f1`
GRUB_RELEASE=`grub-mkstandalone -V | tr -s ' ' | cut -d' ' -f3`
# create SBAT file
cat <<EOF > isolinux/sbat.csv
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
grub,1,Free Software Foundation,grub,$GRUB_VERSION,https://www.gnu.org/software/grub/
grub.ubuntu,1,Ubuntu,grub2,$GRUB_RELEASE,https://www.ubuntu.com/
EOF
```
3. Create a grub UEFI image
```shell
grub-mkstandalone \
--format=x86_64-efi \
--output=isolinux/grubx64.efi \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=isolinux/grub.cfg"
```
* Fix Secure Boot Grub
```shell
sed -i 's/SecureBoot/SecureB00t/' isolinux/grubx64.efi
```
4. Add .sbat sections
```shell
objcopy --add-section .sbat=isolinux/sbat.csv isolinux/grubx64.efi --change-section-address .sbat=10000000
```
5. UEFI secure boot signing
```shell
sbsign --key /certificates/db.key --cert /certificates/db.pem --output isolinux/grubx64.efi isolinux/grubx64.efi
```
6. Create a FAT16 UEFI boot disk image containing the EFI bootloader
```shell
(
cd isolinux && \
sudo dd if=/dev/zero of=efiboot.img bs=1M count=10 && \
LOOP_DEVICE=`sudo losetup --find --show $PWD/efiboot.img` && \
sudo mkfs.vfat -F 16 $LOOP_DEVICE && \
sudo mkdir efi && \
sudo mount $LOOP_DEVICE efi && \
sudo grub-install --target=x86_64-efi --efi-directory=efi --uefi-secure-boot --removable --no-nvram $LOOP_DEVICE && \
sudo umount $LOOP_DEVICE && \
sudo losetup --detach $LOOP_DEVICE && \
sudo rm -rf efi
cd isolinux && \
dd if=/dev/zero of=efiboot.img bs=1M count=10 && \
mkfs.vfat -F 16 efiboot.img && \
LC_CTYPE=C mmd -i efiboot.img certificates efi efi/boot && \
LC_CTYPE=C mcopy -i efiboot.img /usr/lib/shim/shimx64.efi.signed.previous ::efi/boot/bootx64.efi && \
LC_CTYPE=C mcopy -i efiboot.img /usr/lib/shim/mmx64.efi ::efi/boot/mmx64.efi && \
LC_CTYPE=C mcopy -i efiboot.img /image/isolinux/grubx64.efi ::efi/boot/grubx64.efi && \
LC_CTYPE=C mcopy -i efiboot.img /certificates/ca.cer ::certificates/
)
```
3. Create a grub BIOS image
7. Create a grub BIOS image
```shell
grub-mkstandalone \
@ -621,45 +680,135 @@ After everything has been installed and preconfigured in the **chrooted** enviro
"boot/grub/grub.cfg=isolinux/grub.cfg"
```
4. Combine a bootable Grub cdboot.img
8. Combine a bootable Grub cdboot.img
```shell
cat /usr/lib/grub/i386-pc/cdboot.img isolinux/core.img > isolinux/bios.img
```
5. Generate md5sum.txt
9. Generate md5sum.txt
```shell
sudo /bin/bash -c "(find . -type f -print0 | xargs -0 md5sum | grep -v -e 'md5sum.txt' -e 'bios.img' -e 'efiboot.img' > md5sum.txt)"
/bin/bash -c "(find . -type f -print0 | xargs -0 md5sum | grep -v -e 'md5sum.txt' -e 'bios.img' -e 'efiboot.img' > md5sum.txt)"
```
6. Create iso from the image directory using the command-line
## Cleanup the chroot environment
1. If you installed software, be sure to run
```shell
truncate -s 0 /etc/machine-id
```
2. Remove the diversion
```shell
rm /sbin/initctl
dpkg-divert --rename --remove /sbin/initctl
```
3. Clean up
```shell
apt-get clean
rm -rf /tmp/* ~/.bash_history
umount /proc
umount /sys
umount /dev/pts
export HISTSIZE=0
exit
```
## Unbind mount points
```shell
sudo umount $HOME/live-ubuntu-from-scratch/chroot/dev
sudo umount $HOME/live-ubuntu-from-scratch/chroot/run
```
## Compress the chroot
After everything has been installed and preconfigured in the **chrooted** environment, we need to generate an image of everything that was done by following the next steps in the `build environment`.
1. Access build directory
```shell
cd $HOME/live-ubuntu-from-scratch
```
2. Move image artifacts
```shell
sudo mv chroot/{image,certificates} .
```
3. Create squashfs
```shell
sudo mksquashfs chroot image/casper/filesystem.squashfs \
-noappend -no-duplicates -no-recovery \
-wildcards \
-comp xz -b 1M -Xdict-size 100% \
-e "var/cache/apt/archives/*" \
-e "root/*" \
-e "root/.*" \
-e "tmp/*" \
-e "tmp/.*" \
-e "swapfile"
```
> **Squashfs** is a highly compressed read-only filesystem for Linux. It uses zlib compression to compress both files, inodes and directories. Inodes in the system are very small and all blocks are packed to minimize data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
> **Squashfs** is intended for general read-only filesystem use, for archival use (i.e. in cases where a .tar.gz file may be used), and in constrained block device/memory systems (e.g. **embedded systems**) where low overhead is needed.
4. Write the filesystem.size
```shell
printf $(sudo du -sx --block-size=1 chroot | cut -f1) | sudo tee image/casper/filesystem.size
```
## Create ISO Image for a LiveCD (BIOS + UEFI + Secure Boot)
1. Access build directory
```shell
cd $HOME/live-ubuntu-from-scratch/image
```
2. Create iso from the image directory using the command-line
```shell
sudo xorriso \
-as mkisofs \
-iso-level 3 \
-full-iso9660-filenames \
-J -J -joliet-long \
-volid "Ubuntu from scratch" \
-output "../ubuntu-from-scratch.iso" \
-eltorito-boot boot/grub/bios.img \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
--eltorito-catalog boot/grub/boot.cat \
--grub2-boot-info \
--grub2-mbr /usr/lib/grub/i386-pc/boot_hybrid.img \
-eltorito-alt-boot \
-e EFI/efiboot.img \
-no-emul-boot \
-eltorito-boot boot/grub/bios.img \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
--eltorito-catalog boot/grub/boot.cat \
--grub2-boot-info \
--grub2-mbr ../chroot/usr/lib/grub/i386-pc/boot_hybrid.img \
-eltorito-alt-boot \
-e EFI/efiboot.img \
-no-emul-boot \
-append_partition 2 0xef isolinux/efiboot.img \
-m "isolinux/efiboot.img" \
-m "isolinux/bios.img" \
-graft-points \
"/EFI/efiboot.img=isolinux/efiboot.img" \
"/boot/grub/grub.cfg=isolinux/grub.cfg" \
"/boot/grub/bios.img=isolinux/bios.img" \
"."
-graft-points \
"/EFI/efiboot.img=isolinux/efiboot.img" \
"/boot/grub/bios.img=isolinux/bios.img" \
"."
```
## Alternative way, if previous one fails, create an Hybrid ISO
@ -702,17 +851,24 @@ After everything has been installed and preconfigured in the **chrooted** enviro
```shell
apt install -y syslinux-common && \
cp /usr/lib/ISOLINUX/isolinux.bin isolinux/ && \
cp /usr/lib/syslinux/modules/bios/* isolinux/
cp /usr/lib/ISOLINUX/isolinux.bin image/isolinux/ && \
cp /usr/lib/syslinux/modules/bios/* image/isolinux/
```
3. Create iso from the image directory
3. Access build directory
```shell
cd $HOME/live-ubuntu-from-scratch/image
```
4. Create iso from the image directory
```shell
sudo xorriso \
-as mkisofs \
-iso-level 3 \
-full-iso9660-filenames \
-J -J -joliet-long \
-volid "Ubuntu from scratch" \
-output "../ubuntu-from-scratch.iso" \
-isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin \

View File

@ -3,7 +3,6 @@
set -e # exit on error
set -o pipefail # exit on pipeline error
set -u # treat unset variable as error
#set -x
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
@ -99,13 +98,13 @@ function check_config() {
function setup_host() {
echo "=====> running setup_host ..."
sudo apt update
sudo apt install -y binutils debootstrap squashfs-tools xorriso grub-pc-bin grub-efi-amd64-bin mtools dosfstools unzip grub2-common
sudo apt install -y debootstrap squashfs-tools xorriso
sudo mkdir -p chroot
}
function debootstrap() {
echo "=====> running debootstrap ... will take a couple of minutes ..."
sudo debootstrap --arch=amd64 --variant=minbase $TARGET_UBUNTU_VERSION chroot $TARGET_UBUNTU_MIRROR
sudo debootstrap --arch=amd64 --variant=minbase $TARGET_UBUNTU_VERSION chroot $TARGET_UBUNTU_MIRROR
}
function run_chroot() {
@ -136,143 +135,50 @@ function run_chroot() {
function build_iso() {
echo "=====> running build_iso ..."
rm -rf image
mkdir -p image/{casper,isolinux,install}
# copy kernel files
sudo cp chroot/boot/vmlinuz-**-**-generic image/casper/vmlinuz
sudo cp chroot/boot/initrd.img-**-**-generic image/casper/initrd
# memtest86
sudo cp chroot/boot/memtest86+.bin image/install/memtest86+
wget --progress=dot https://www.memtest86.com/downloads/memtest86-usb.zip -O image/install/memtest86-usb.zip
unzip -p image/install/memtest86-usb.zip memtest86-usb.img > image/install/memtest86
rm -f image/install/memtest86-usb.zip
# grub
touch image/ubuntu
cat <<EOF > image/isolinux/grub.cfg
search --set=root --file /ubuntu
insmod all_video
set default="0"
set timeout=30
menuentry "${GRUB_LIVEBOOT_LABEL}" {
linux /casper/vmlinuz boot=casper nopersistent toram quiet splash ---
initrd /casper/initrd
}
menuentry "${GRUB_INSTALL_LABEL}" {
linux /casper/vmlinuz boot=casper only-ubiquity quiet splash ---
initrd /casper/initrd
}
menuentry "Check disc for defects" {
linux /casper/vmlinuz boot=casper integrity-check quiet splash ---
initrd /casper/initrd
}
menuentry "Test memory Memtest86+ (BIOS)" {
linux16 /install/memtest86+
}
menuentry "Test memory Memtest86 (UEFI, long load time)" {
insmod part_gpt
insmod search_fs_uuid
insmod chain
loopback loop /install/memtest86
chainloader (loop,gpt1)/efi/boot/BOOTX64.efi
}
EOF
# generate manifest
sudo chroot chroot dpkg-query -W --showformat='${Package} ${Version}\n' | sudo tee image/casper/filesystem.manifest
sudo cp -v image/casper/filesystem.manifest image/casper/filesystem.manifest-desktop
for pkg in $TARGET_PACKAGE_REMOVE; do
sudo sed -i "/$pkg/d" image/casper/filesystem.manifest-desktop
done
# move image artifacts
sudo mv chroot/{image,certificates} .
# compress rootfs
sudo mksquashfs chroot image/casper/filesystem.squashfs \
-noappend -no-duplicates -no-recovery \
-wildcards \
-comp xz -b 1M -Xdict-size 100% \
-e "var/cache/apt/archives/*" \
-e "root/*" \
-e "root/.*" \
-e "tmp/*" \
-e "tmp/.*" \
-e "swapfile"
printf $(sudo du -sx --block-size=1 chroot | cut -f1) > image/casper/filesystem.size
# create diskdefines
cat <<EOF > image/README.diskdefines
#define DISKNAME ${GRUB_LIVEBOOT_LABEL}
#define TYPE binary
#define TYPEbinary 1
#define ARCH amd64
#define ARCHamd64 1
#define DISKNUM 1
#define DISKNUM1 1
#define TOTALNUM 0
#define TOTALNUM0 1
EOF
# write the filesystem.size
printf $(sudo du -sx --block-size=1 chroot | cut -f1) | sudo tee image/casper/filesystem.size
# create iso image
pushd $SCRIPT_DIR/image
(
cd isolinux && \
sudo dd if=/dev/zero of=efiboot.img bs=1M count=10 && \
LOOP_DEVICE=`sudo losetup --find --show $PWD/efiboot.img` && \
sudo mkfs.vfat -F 16 $LOOP_DEVICE && \
sudo mkdir efi && \
sudo mount $LOOP_DEVICE efi && \
sudo grub-install --target=x86_64-efi --efi-directory=efi --uefi-secure-boot --removable --no-nvram $LOOP_DEVICE && \
sudo umount $LOOP_DEVICE && \
sudo losetup --detach $LOOP_DEVICE && \
sudo rm -rf efi
)
grub-mkstandalone \
--format=i386-pc \
--output=isolinux/core.img \
--install-modules="linux16 linux normal iso9660 biosdisk memdisk search tar ls" \
--modules="linux16 linux normal iso9660 biosdisk search" \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=isolinux/grub.cfg"
cat /usr/lib/grub/i386-pc/cdboot.img isolinux/core.img > isolinux/bios.img
sudo /bin/bash -c "(find . -type f -print0 | xargs -0 md5sum | grep -v -e 'md5sum.txt' -e 'bios.img' -e 'efiboot.img' > md5sum.txt)"
sudo xorriso \
-as mkisofs \
-iso-level 3 \
-full-iso9660-filenames \
-J -J -joliet-long \
-volid "$TARGET_NAME" \
-eltorito-boot boot/grub/bios.img \
-output "$SCRIPT_DIR/$TARGET_NAME.iso" \
-eltorito-boot boot/grub/bios.img \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
--eltorito-catalog boot/grub/boot.cat \
--grub2-boot-info \
--grub2-mbr /usr/lib/grub/i386-pc/boot_hybrid.img \
-eltorito-alt-boot \
--grub2-mbr ../chroot/usr/lib/grub/i386-pc/boot_hybrid.img \
-eltorito-alt-boot \
-e EFI/efiboot.img \
-no-emul-boot \
-append_partition 2 0xef isolinux/efiboot.img \
-output "$SCRIPT_DIR/$TARGET_NAME.iso" \
-m "isolinux/efiboot.img" \
-m "isolinux/bios.img" \
-graft-points \
"/EFI/efiboot.img=isolinux/efiboot.img" \
"/boot/grub/grub.cfg=isolinux/grub.cfg" \
"/boot/grub/bios.img=isolinux/bios.img" \
"."
-graft-points \
"/EFI/efiboot.img=isolinux/efiboot.img" \
"/boot/grub/bios.img=isolinux/bios.img" \
"."
popd
}

View File

@ -3,11 +3,10 @@
set -e # exit on error
set -o pipefail # exit on pipeline error
set -u # treat unset variable as error
#set -x
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
CMD=(setup_host install_pkg finish_up)
CMD=(setup_host install_pkg build_image finish_up)
function help() {
# if $1 is set, use $1 as headline message in help()
@ -100,23 +99,27 @@ function install_pkg() {
# install live packages
apt-get install -y \
sudo \
ubuntu-standard \
casper \
discover \
laptop-detect \
os-prober \
network-manager \
resolvconf \
net-tools \
wireless-tools \
wpagui \
grub-common \
grub-gfxpayload-lists \
grub-pc \
grub-pc-bin \
grub2-common \
locales
sudo \
ubuntu-standard \
casper \
discover \
laptop-detect \
os-prober \
network-manager \
net-tools \
wireless-tools \
wpagui \
locales \
grub-common \
grub-gfxpayload-lists \
grub-pc \
grub-pc-bin \
grub2-common \
grub-efi-amd64-signed \
shim-signed \
memtest86+ \
mtools \
binutils
case $TARGET_UBUNTU_VERSION in
"focal" | "bionic")
@ -132,11 +135,11 @@ function install_pkg() {
# graphic installer - ubiquity
apt-get install -y \
ubiquity \
ubiquity-casper \
ubiquity-frontend-gtk \
ubiquity-slideshow-ubuntu \
ubiquity-ubuntu-artwork
ubiquity \
ubiquity-casper \
ubiquity-frontend-gtk \
ubiquity-slideshow-ubuntu \
ubiquity-ubuntu-artwork
# Call into config function
customize_image
@ -146,14 +149,13 @@ function install_pkg() {
# final touch
dpkg-reconfigure locales
dpkg-reconfigure resolvconf
# network manager
cat <<EOF > /etc/NetworkManager/NetworkManager.conf
[main]
rc-manager=resolvconf
rc-manager=none
plugins=ifupdown,keyfile
dns=dnsmasq
dns=systemd-resolved
[ifupdown]
managed=false
@ -164,6 +166,250 @@ EOF
apt-get clean -y
}
function build_image() {
echo "=====> running build_image ..."
rm -rf /image
mkdir -p /image/{casper,isolinux,install}
pushd /image
# copy kernel files
cp /boot/vmlinuz-**-**-generic casper/vmlinuz
cp /boot/initrd.img-**-**-generic casper/initrd
# memtest86
if [ -f "/boot/memtest86+x64.bin" ]; then
cp /boot/memtest86+x64.bin install/memtest86+
else
cp /boot/memtest86+.bin install/memtest86+
fi
# memtest86++
wget --progress=dot https://www.memtest86.com/downloads/memtest86-usb.zip -O install/memtest86-usb.zip
unzip -p install/memtest86-usb.zip memtest86-usb.img > install/memtest86
rm -f install/memtest86-usb.zip
# grub
touch ubuntu
cat <<EOF > isolinux/grub.cfg
search --set=root --file /ubuntu
insmod all_video
set default="0"
set timeout=30
menuentry "Try Ubuntu FS without installing" {
linux /casper/vmlinuz boot=casper nopersistent toram quiet splash ---
initrd /casper/initrd
}
menuentry "Install Ubuntu FS" {
linux /casper/vmlinuz boot=casper only-ubiquity quiet splash ---
initrd /casper/initrd
}
menuentry "Check disc for defects" {
linux /casper/vmlinuz boot=casper integrity-check quiet splash ---
initrd /casper/initrd
}
menuentry "Test memory Memtest86+ (BIOS)" {
linux16 /install/memtest86+
}
menuentry "Test memory Memtest86 (UEFI, long load time)" {
insmod part_gpt
insmod search_fs_uuid
insmod chain
loopback loop /install/memtest86
chainloader (loop,gpt1)/efi/boot/BOOTX64.efi
}
EOF
# generate manifest
dpkg-query -W --showformat='${Package} ${Version}\n' | sudo tee casper/filesystem.manifest
cp -v casper/filesystem.manifest casper/filesystem.manifest-desktop
for pkg in $TARGET_PACKAGE_REMOVE; do
sudo sed -i "/$pkg/d" casper/filesystem.manifest-desktop
done
# create diskdefines
cat <<EOF > README.diskdefines
#define DISKNAME ${GRUB_LIVEBOOT_LABEL}
#define TYPE binary
#define TYPEbinary 1
#define ARCH amd64
#define ARCHamd64 1
#define DISKNUM 1
#define DISKNUM1 1
#define TOTALNUM 0
#define TOTALNUM0 1
EOF
# create certificates
rm -rf /certificates
mkdir /certificates
pushd /certificates
# create the certificate template
cat <<EOF > config.conf
[ req ]
default_bits = 2048
default_md = sha256
distinguished_name = dn
prompt = no
[ dn ]
C = BR
ST = SP
L = Campinas
O = Scratch, Labs
OU = Labs
CN = \${ENV::CN}
[ root ]
basicConstraints = critical,CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
keyUsage = critical,digitalSignature,keyEncipherment,keyCertSign,cRLSign
[ ca ]
basicConstraints = critical,CA:TRUE,pathlen:0
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = critical,digitalSignature,keyEncipherment,keyCertSign,cRLSign
[ db ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:FALSE
keyUsage = critical,keyEncipherment,dataEncipherment
authorityKeyIdentifier = keyid,issuer:always
EOF
# create the Root CA certificate
CN="Root, CA" \
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout root.key \
-days 3650 \
-config config.conf \
-extensions root \
-out root.pem
# create the intermediate CA certificate
CN="Ubuntu live from scratch, CA" \
openssl req -newkey rsa:2048 -nodes \
-keyout ca.key \
-config config.conf \
-out ca.pem
# create Database (DB) request certificate
CN="Ubuntu live from scratch, Database" \
openssl req -newkey rsa:2048 -nodes \
-keyout db.key \
-config config.conf \
-out db.pem
# sign the intermediate CA certificate with the Root CA certificate
CN="Ubuntu live from scratch, CA" \
openssl x509 -req \
-extfile config.conf \
-extensions ca \
-in ca.pem \
-CA root.pem \
-CAkey root.key \
-CAcreateserial \
-out ca.pem \
-days 3650 -sha256
# sign Database (DB) certificate using your own CA
CN="Ubuntu live from scratch, Database" \
openssl x509 -req \
-extfile config.conf \
-extensions db \
-in db.pem \
-CA ca.pem \
-CAkey ca.key \
-CAcreateserial \
-out db.pem \
-days 3650 -sha256
# create the intermediate CA certificate chain
cat ca.pem root.pem > ca-chain.pem
# verify the signatures
openssl verify -CAfile ca-chain.pem db.pem
# create DER version of our public key (CA)
openssl x509 -outform DER -in ca.pem -out ca.cer
popd # return to image directory
# grub version/release
GRUB_VERSION=`grub-mkstandalone -V | tr -s ' ' | cut -d' ' -f3 | cut -d'-' -f1`
GRUB_RELEASE=`grub-mkstandalone -V | tr -s ' ' | cut -d' ' -f3`
# create SBAT file
cat <<EOF > isolinux/sbat.csv
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
grub,1,Free Software Foundation,grub,$GRUB_VERSION,https://www.gnu.org/software/grub/
grub.ubuntu,1,Ubuntu,grub2,$GRUB_RELEASE,https://www.ubuntu.com/
EOF
# create a grub UEFI image
grub-mkstandalone \
--format=x86_64-efi \
--output=isolinux/grubx64.efi \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=isolinux/grub.cfg"
# fix secure boot grub
sed -i 's/SecureBoot/SecureB00t/' isolinux/grubx64.efi
# add .sbat sections
objcopy --add-section .sbat=isolinux/sbat.csv isolinux/grubx64.efi --change-section-address .sbat=10000000
# UEFI secure boot signing
sbsign --key /certificates/db.key --cert /certificates/db.pem --output isolinux/grubx64.efi isolinux/grubx64.efi
# create a FAT16 UEFI boot disk image containing the EFI bootloader
(
cd isolinux && \
dd if=/dev/zero of=efiboot.img bs=1M count=10 && \
mkfs.vfat -F 16 efiboot.img && \
LC_CTYPE=C mmd -i efiboot.img certificates efi efi/boot && \
LC_CTYPE=C mcopy -i efiboot.img /usr/lib/shim/shimx64.efi.signed.previous ::efi/boot/bootx64.efi && \
LC_CTYPE=C mcopy -i efiboot.img /usr/lib/shim/mmx64.efi ::efi/boot/mmx64.efi && \
LC_CTYPE=C mcopy -i efiboot.img ./grubx64.efi ::efi/boot/grubx64.efi && \
LC_CTYPE=C mcopy -i efiboot.img /certificates/ca.cer ::certificates/
)
# create a grub BIOS image
grub-mkstandalone \
--format=i386-pc \
--output=isolinux/core.img \
--install-modules="linux16 linux normal iso9660 biosdisk memdisk search tar ls" \
--modules="linux16 linux normal iso9660 biosdisk search" \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=isolinux/grub.cfg"
# combine a bootable Grub cdboot.img
cat /usr/lib/grub/i386-pc/cdboot.img isolinux/core.img > isolinux/bios.img
# generate md5sum.txt
/bin/bash -c "(find . -type f -print0 | xargs -0 md5sum | grep -v -e 'md5sum.txt' -e 'bios.img' -e 'efiboot.img' > md5sum.txt)"
popd # return initial directory
}
function finish_up() {
echo "=====> finish_up"

View File

@ -5,9 +5,9 @@
# Usage: Copy this file to config.sh and make changes there. Keep this file (default_config.sh) as-is
# so that subsequent changes can be easily merged from upstream. Keep all customiations in config.sh
# The version of Ubuntu to generate. Successfully tested: bionic, cosmic, disco, eoan, focal, groovy, jammy
# The version of Ubuntu to generate. Successfully tested LTS: bionic, focal, jammy, noble
# See https://wiki.ubuntu.com/DevelopmentCodeNames for details
export TARGET_UBUNTU_VERSION="jammy"
export TARGET_UBUNTU_VERSION="noble"
# The Ubuntu Mirror URL. It's better to change for faster download.
# More mirrors see: https://launchpad.net/ubuntu/+archivemirrors
@ -41,7 +41,7 @@ export TARGET_PACKAGE_REMOVE="
function customize_image() {
# install graphics and desktop
apt-get install -y \
plymouth-theme-ubuntu-logo \
plymouth-themes \
ubuntu-gnome-desktop \
ubuntu-gnome-wallpapers