Skip to content

Commit

Permalink
Merge pull request #23 from gardenlinux/doc
Browse files Browse the repository at this point in the history
add docs
  • Loading branch information
nkraetzschmar authored Jul 18, 2023
2 parents ca6b3f7 + 231e162 commit a9846fc
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ By default, the Builder uses `podman` as the container engine. If you prefer usi

A config directory serves as the input for the Builder and is used to create a Linux system image. It consists of the following components:

- **`features` directory**: Contains sub-directories for each feature. You can create your own features by referring to the example in [gardenlinux/features/example](https://github.com/gardenlinux/gardenlinux/tree/main/features/example).
- **`features` directory**: Contains sub-directories for each feature. You can create your own features by referring to [features.md](docs/features.md).

- **`cert` directory** (optional): If you plan to use secure boot, include a `cert` directory.

Expand All @@ -38,6 +38,8 @@ In addition to the above components, your configuration directory must include t
- `get_version`: This script should output the version of the package repository to use. For example, use `bookworm` for Debian or `today` for Garden Linux.
- `keyring.gpg`: The PGP key used to validate the package repository. For Debian, you can obtain this key from the [debian-archive-keyring](https://packages.debian.org/bookworm/debian-archive-keyring) package.

For a quick start guide on setting up your own config directory with your own features checkout [getting_started.md](docs/getting_started.md).

### Example Config Directory

If you're new to configuring the Builder, you can find a minimal example config directory at [gardenlinux/builder_example](https://github.com/gardenlinux/builder_example). For a more comprehensive example, refer to the main [gardenlinux](https://github.com/gardenlinux/gardenlinux) repository.
Expand Down
77 changes: 77 additions & 0 deletions docs/features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Features

Each feature must at least contain an `info.yaml` file

The `info.yaml` file has the following structure fields:

- `description`: (*optional*) a string explaining what this feature does / what it is used for.
- `type`: can be any of `platform`, `element`, or `flag`. The builder does not make any technical distinction between each type of feature, however it is strongly encouraged that each image uses exactly one platform and flags should only perform minor changes and not include any other features.
- `features`: (*optional*) sub-structure containing related features
- `include`: (*optional*) list of features that will automatically be included as well if this feature gets included
- `exclude`: (*optional*) list of features that are incompatible with this feature. If any of these features were included implicitly from another they will be removed from the feature set. If they were explicitly provided as part of the target the build will fail.

An example `info.yaml` looks as follows:

```yaml
description: example platform feature
type: platform
features:
include:
- A
- B
exclude:
- C
```
Additionally a feature may contain any of the following:
## `pkg.include`

A list of packages to be installed into the image.

## `pkg.exclude`

A list of packages to be ignored if provided by another features `pkg.include`

## `file.include`

A directory containing files to copy into the target rootfs.
This directory is copied recursively into the root directory.
By default only the executable bit of the files permission will be preserved when copying.
The other permissions will be set to read write for owner and read for group and other.
The owner of all copied files will be root by default.

To overwrite these defaults see `file.stat` below

## `file.stat`

A file to assign owner and permissions to files copied by `file.include`.
Each line should contain an entry of the form:

```
user group permissions file
```

## `file.exclude`

A list of files / directories to remove from the rootfs at the end of the configure stage.
Wildcard in file paths are allowed.

## `exec.config` `exec.early` `exec.late` `exec.post`

Scripts to be executed to configure the image.
All scripts except `exec.post` are executed inside the rootfs of the system being build without any parameters.
`exec.post` is executed inside the builder container with the path of the rootfs provided as `argv[1]`.

The order of exectution is as follows:

- bootstrap (outside chroot)
- `exec.early`
- package install (from `pkg.include`)
- copy files from `file.include` and set permissions according to `file.stat`
- `exec.config`
- `exec.late`
- remove files according to `file.exclude`
- `exec.post` (outside chroot)

When building with multiple features the execution steps of each feature are interleaved; so for example the `exec.config` step will run for all features before any features `exec.late` runs.
86 changes: 86 additions & 0 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Getting started

These instructions will guide you through how to create a custom linux image using the builder.
We will start from the builder example repo, and build our own feature on top to add an `nginx` http server.

First clone the builder example repo:

```shell
git clone https://github.com/gardenlinux/builder_example
cd builder_example
```

At this point you can test, that your local podman install works by running `./build base`.
This should create a bootable debian bookworm disk image at `.build/base-amd64-bookworm-6f72b564.raw` (the commit may have changed since the time of writing).
You can test run the image with

```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-bookworm-6f72b564.raw
```

Now that we know all local tooling works, let's start building our own feature.

1. Create a feature directory called `nginx`.

```shell
mkdir features/nginx
```

2. create a file `features/nginx/info.yaml` and edit it using the editor of your choice to have the following content:

```yaml
description: http server using nginx
type: element
```
3. create a file `features/nginx/pkg.include` with the following content:

```
nginx
```
4. create a file `features/nginx/exec.config` with the following content:
```shell
#!/usr/bin/env bash
set -eufo pipefail
systemctl enable nginx
```

5. make this executable `chmod +x features/nginx/exec.config`

6. create a `/var/www/html` directory inside the nginx `file.include` directory

```shell
mkdir -p features/nginx/file.include/var/www/html
```

7. create a dummy `index.html` file inside `features/nginx/file.include/var/www/html` with content like the following or whatever you like:

```html
<!DOCTYPE html>
<html>
<body>
<p>Hello World!</p>
</body>
</html>
```

With this we have created our own first feature for the builder.
Test it by building with

```shell
./build base-nginx
```

and running with

```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-bookworm-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 and once booted opening http://localhost:8080 in a browser should display the hello world message.

Congrats, you have just successfully created a feature for the builder :tada:

0 comments on commit a9846fc

Please sign in to comment.