You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Getting Started: Creating a Custom Linux Image with Builder
15
+
# Create a custom Feature and build an image with the Builder
15
16
16
-
This tutorial will walk you through the process of creating a custom Linux image using the Builder tool.
17
-
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.
17
+
This How-To will walk you through the process of creating a custom Linux image using the Builder tool.
18
+
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.
18
19
19
20
Let's begin by creating a new GitHub repository based on the Builder example repository using this link:
20
21
@@ -53,9 +54,9 @@ mkdir features/nginx
53
54
```
54
55
55
56
> This is where our nginx feature will live.
56
-
Features are a concept of the builder that allows us to build variants of images.
57
-
For example, if we wanted to add an alternative HTTP server later, we could add an `apacheHttpd` feature.
58
-
At image build time, we could pick if we want the `nginx` or the `apacheHttpd` feature.
57
+
> Features are a concept of the builder that allows us to build variants of images.
58
+
> For example, if we wanted to add an alternative HTTP server later, we could add an `apacheHttpd` feature.
59
+
> At image build time, we could pick if we want the `nginx` or the `apacheHttpd` feature.
59
60
60
61
2. Create a file named `info.yaml` inside `features/nginx` and edit it with the content below:
61
62
@@ -68,17 +69,16 @@ features:
68
69
```
69
70
70
71
> The `info.yaml` file is required for each feature by the builder.
71
-
We'll specify that our `nginx` feature includes the `base` feature.
72
-
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`.
73
-
See [features documentation](../reference/features.md) for detailed information on the structure of features.
72
+
> We'll specify that our `nginx` feature includes the `base` feature.
73
+
> 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`.
74
+
> See [features documentation](../reference/features.md) for detailed information on the structure of features.
74
75
75
76
1. Create a file named `pkg.include` inside `features/nginx` with the following content:
76
77
77
78
```
78
79
nginx
79
80
```
80
81
81
-
82
82
> `pkg.include` is a list of packages this feature needs, each feature on a new line.
83
83
84
84
4. Create a file named `exec.config` inside `features/nginx` with the following content:
@@ -91,9 +91,8 @@ set -eufo pipefail
91
91
systemctl enable nginx
92
92
```
93
93
94
-
95
94
> `exec.config` is a shell script we can use to customize our image.
96
-
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.
95
+
> 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.
The Builder is a powerful tool for effortlessly building Linux system images based on config directories. It serves as the primary build tooling for the [gardenlinux](https://github.com/gardenlinux/gardenlinux) project.
20
+
21
+
By default, the Builder runs inside rootless Podman, enabling building without requiring elevated permissions.
22
+
23
+
## Requirements
24
+
25
+
The Builder has minimal dependencies and only requires a working container engine. We recommend using rootless Podman. Please refer to the [Podman rootless setup guide](https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md) for instructions on setting it up.
26
+
27
+
## Usage
28
+
29
+
To utilize the Builder, follow these steps:
30
+
31
+
1. Download the latest version of the [build script](https://github.com/gardenlinux/builder/releases/download/latest/build).
32
+
2. Run the build script within a config directory.
By default, the Builder uses `podman` as the container engine. If you prefer using a different container engine, you can specify it using the `--container-engine` option.
40
+
41
+
If you decide to use `docker` on a system restricting unprivileged user namespaces with apparmor (e.g. Ubuntu 23.10 or newer) an apparmor profile allowing `userns` is required. This can be automatically created and selected by the Builder by opting in to the permanent system change. You can avoid this by:
42
+
43
+
- Using `podman`
44
+
- Passing a custom profile using the `--apparmor-profile` option
45
+
- Using a system not restricting unprivileged user namespaces
46
+
47
+
## Config Directory
48
+
49
+
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:
50
+
51
+
-**`features` directory**: Contains sub-directories for each feature. You can create your own features by referring to [features.md](docs/features.md).
52
+
53
+
-**`cert` directory** (optional): If you plan to use secure boot, include a `cert` directory.
54
+
55
+
In addition to the above components, your configuration directory must include the following configuration scripts:
56
+
57
+
-`get_commit`: This script should output the Git commit used to tag the build artifacts.
58
+
-`get_repo`: This script should output the apt package repository to use.
59
+
-`get_timestamp`: This script should output the timestamp to be used instead of the real system time, ensuring reproducibility of builds.
60
+
-`get_version`: This script should output the version of the package repository to use. For example, use `forky` for Debian or `today` for Garden Linux.
61
+
-`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/forky/debian-archive-keyring) package.
62
+
63
+
For a quick start guide on setting up your own config directory with your own features checkout [getting_started.md](docs/getting_started.md).
64
+
65
+
### Example Config Directory
66
+
67
+
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.
68
+
69
+
Feel free to explore these examples to gain a better understanding of how to effectively structure your own config directory.
70
+
71
+
## Local Development
72
+
73
+
To test changes made to the builder locally you can simply create a symlink to the build script inside the builder directory inside a config directory. This will automatically be detected by the build script and the builder re-build iff necessary.
74
+
75
+
e.g.: if you have the gardenlinux and builder repos both inside the same parent directory and you want to work on the builder you would do the following:
76
+
77
+
```
78
+
cd gardenlinux
79
+
ln -f -s ../builder/build build
80
+
```
81
+
82
+
Now you can make your modifications inside the builder directory and running `./build ${target}` inside the gardenlinux repo will use the local builder, rebuilding the build container if necessary.
83
+
84
+
## Next Steps
85
+
86
+
-[Features Reference](/reference/features.md)
87
+
-[Building a custom Feature](/how-to/custom-features.md)
@@ -17,15 +18,15 @@ Each feature must contain an `info.yaml` file that adheres to the following stru
17
18
18
19
## `info.yaml` file structure:
19
20
20
-
-`description`: (*optional*) A string explaining the purpose or functionality of the feature.
21
+
-`description`: (_optional_) A string explaining the purpose or functionality of the feature.
21
22
-`type`: Can be one of the following:
22
23
-`platform`
23
24
-`element`
24
25
-`flag`
25
26
- 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.
26
-
-`features`: (*optional*) A sub-structure that contains related features.
27
-
- `include`: (*optional*) A list of features that will automatically be included if this feature is selected.
28
-
- `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.
27
+
-`features`: (_optional_) A sub-structure that contains related features.
28
+
-`include`: (_optional_) A list of features that will automatically be included if this feature is selected.
29
+
-`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.
29
30
30
31
Here's an example of an `info.yaml` file:
31
32
@@ -128,3 +129,8 @@ They take the image artifact created by an image script and output a different f
128
129
Scripts of the form `convert.<ext>` get the raw image as input and produce a `.<ext>` output.
129
130
Scripts of the form `convert.<extA>~<extB>` get `.<extB>` as input and produces `.<extA>` as output.
130
131
The second form is only useful for advanced use cases, if you are not aware of one, you'll probably never need it!
0 commit comments