diff --git a/docs/features.md b/docs/features.md index 53186a9..006b42c 100644 --- a/docs/features.md +++ b/docs/features.md @@ -5,7 +5,11 @@ Each feature must contain an `info.yaml` file that adheres to the following stru ## `info.yaml` file structure: - `description`: (*optional*) A string explaining the purpose or functionality of the feature. -- `type`: Can be one of the following: `platform`, `element`, or `flag`. While the builder does not make any technical distinctions between these feature types, it is recommended that each image uses only one platform, and flags should be used for minor changes without including other features. +- `type`: Can be one of the following: + - `platform` + - `element` + - `flag` + - While the builder does not make any technical distinctions between these feature types, it is recommended that each image uses only one `platform`, and `flag` should be used for minor changes without including other features. - `features`: (*optional*) A sub-structure that contains related features. - `include`: (*optional*) A list of features that will automatically be included if this feature is selected. - `exclude`: (*optional*) A list of features that are incompatible with this feature. If any of these features were implicitly included from another feature, they will be removed from the feature set. If they were explicitly provided as part of the target, the build will fail. @@ -53,7 +57,7 @@ A list of files/directories to be removed from the rootfs at the end of the conf ## `exec.config`, `exec.early`, `exec.late`, `exec.post` -Scripts to be executed for image configuration. All scripts except `exec.post` are executed within the rootfs of the system being built without any parameters. `exec.post` is executed within the builder container, and the path of the rootfs is provided as `argv[1]`. +Scripts to be executed for image configuration. Script files need the executable bit set. All scripts except `exec.post` are executed within the rootfs of the system being built without any parameters. `exec.post` is executed within the builder container, and the path of the rootfs is provided as `argv[1]`. The order of execution is as follows: diff --git a/docs/getting_started.md b/docs/getting_started.md index f49a189..62335c5 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -1,6 +1,7 @@ # Getting Started: Creating a Custom Linux Image with Builder -This tutorial will walk you through the process of creating a custom Linux image using the Builder tool. We will start with the Builder example repository and build a feature to add an `nginx` HTTP server to our image. +This tutorial will walk you through the process of creating a custom Linux image using the Builder tool. +We will start with the Builder example repository and build a *feature* to add an [`nginx` HTTP server](https://nginx.org/en/) to our image. Let's begin by creating a new GitHub repository based on the Builder example repository using this link: @@ -21,7 +22,8 @@ To ensure that your local Podman installation is working correctly, you can test ./build base ``` -This command will create a bootable Debian Trixie disk image at `.build/base-amd64-trixie-6f72b564.raw` (note that the commit may have changed since the time of writing). You can test run the image using QEMU: +This command will create a bootable Debian Trixie disk image at `.build/base-amd64-trixie-6f72b564.raw` (note that the commit may have changed since the time of writing). +You can test run the image using [QEMU](https://www.qemu.org): ```shell qemu-system-x86_64 -m 2048 -nodefaults -display none -serial mon:stdio -drive if=pflash,unit=0,readonly=on,format=raw,file=/usr/share/OVMF/OVMF_CODE.fd -drive if=virtio,format=raw,file=.build/base-amd64-trixie-6f72b564.raw @@ -37,19 +39,35 @@ Now that we have verified that everything is working correctly, let's proceed to mkdir features/nginx ``` +> This is where our nginx feature will live. +Features are a concept of the builder that allows us to build variants of images. +For example, if we wanted to add an alternative HTTP server later, we could add an `apacheHttpd` feature. +At image build time, we could pick if we want the `nginx` or the `apacheHttpd` feature. + 2. Create a file named `info.yaml` inside `features/nginx` and edit it with the content below: ```yaml description: HTTP server using Nginx type: element +features: + include: + - base ``` -3. Create a file named `pkg.include` inside `features/nginx` with the following content: +> The `info.yaml` file is required for each feature by the builder. +We'll specify that our `nginx` feature includes the `base` feature. +This makes sense because the `nginx` feature on its own does not contain a full operating system, so to get a bootable image we include the debian system as it is defined in `base`. +See [features.md](./features.md) for detailed information on the structure of features. + +1. Create a file named `pkg.include` inside `features/nginx` with the following content: ``` nginx ``` + +> `pkg.include` is a list of packages this feature needs, each feature on a new line. + 4. Create a file named `exec.config` inside `features/nginx` with the following content: ```shell @@ -60,6 +78,10 @@ set -eufo pipefail systemctl enable nginx ``` + +> `exec.config` is a shell script we can use to customize our image. +In this case, we [enable the systemd unit for nginx](https://www.freedesktop.org/software/systemd/man/latest/systemctl.html#enable%20UNIT…) which makes nginx start on boot. + 5. Make the `exec.config` file executable: ```shell @@ -72,6 +94,9 @@ chmod +x features/nginx/exec.config mkdir -p features/nginx/file.include/var/www/html ``` + +> The `file.include` directory allows us to merge files and directories into the root filesystem of our image. + 7. Create a dummy `index.html` file inside `features/nginx/file.include/var/www/html` with content like the following (or customize it as desired): ```html @@ -86,13 +111,13 @@ mkdir -p features/nginx/file.include/var/www/html To test your feature, build the image using the following command: ```shell -./build base-nginx +./build nginx ``` You can then run the image with QEMU using the following command: ```shell -qemu-system-x86_64 -m 2048 -nodefaults -display none -serial mon:stdio -drive if=pflash,unit=0,readonly=on,format=raw,file=/usr/share/OVMF/OVMF_CODE.fd -drive if=virtio,format=raw,file=.build/base-nginx-amd64-trixie-local.raw -netdev user,id=net0,hostfwd=tcp::8080-:80 -device virtio-net-pci,netdev=net0 +qemu-system-x86_64 -m 2048 -nodefaults -display none -serial mon:stdio -drive if=pflash,unit=0,readonly=on,format=raw,file=/usr/share/OVMF/OVMF_CODE.fd -drive if=virtio,format=raw,file=.build/nginx-amd64-trixie-local.raw -netdev user,id=net0,hostfwd=tcp::8080-:80 -device virtio-net-pci,netdev=net0 ``` If everything worked as intended, you should see the system boot up. Once the system is booted, opening http://localhost:8080 in a browser should display the "Hello World!" message. @@ -111,8 +136,8 @@ index 181a646..9e4261e 100644 - uses: actions/checkout@v3 - name: Build the image - run: ./build base -+ run: ./build base-nginx -+ - uses: actions/upload-artifact@v3 ++ run: ./build nginx ++ - uses: actions/upload-artifact@v4 + with: + name: my-linux-image + path: .build/