Relax tmpfs ram limits while building stuff
[dpa-image-builder.git] / README.md
1 # DPA image builder
2
3 I've written my own image builder to create my own, custom, devuan based images.
4 Originally, I did this to run devuan & some other stuff of mine on the librem5,
5 but it can now also make images for other devices (the pinephone-pro), and
6 can also make images for other debian & debootstrap based distributions.
7
8 While this image builder can bootstrap images based on the repositories of various linux distros,
9 and can thus create images based on devuan, debian, ubuntu, etc. Please note that this
10 aren't official images and that they do contain some files and packages not (yet?) available upstream.
11
12 I'm building these images every day at 0 UTC on my build server: https://repo.dpa.li/apt/dpa-image-builder/images/ (Please note that the base images don't contain a desktop environment)
13
14 This project is still a work in progress, it's not ready for regular usage yet.
15
16 # Required packages & programs
17
18 You need the following packages for this to work:
19  * `make`
20  * `gcc`
21  * `gcc-aarch64-linux-gnu`
22  * `libc6-dev-arm64-cross`
23  * `gcc-arm-none-eabi`
24  * `libnewlib-arm-none-eabi`
25  * `libstdc++-arm-none-eabi-newlib`
26  * `libext2fs-dev`
27  * `util-linux`
28  * `libtar-dev`
29  * `bison`
30  * `flex`
31  * `libfuse-dev`
32  * `pkg-config`
33  * `device-tree-compiler`
34  * `comerr-dev`
35  * `jq`
36  * `equivs`
37  * `binfmt-support` `qemu-user-static` (for /usr/bin/qemu-aarch64-static, needed on non-aarch64 hosts only)
38  * `uidmap`
39  * `fuse-overlayfs`
40
41 ## Other requirements & things to check first
42
43 These build scripts take advantage of the linux kernels unprivileged user namespace
44 feature, subuids and subgids to to run commands in the chroot environment it bootstraps
45 as if they where run as root or some other user, while they actually run as the current
46 user or one of it's subuids. For this to work, please first check the following.
47
48 Verify that unprivileged user namespaces are enabled: `sysctl kernel.unprivileged_userns_clone`.
49 If they aren't, they can either be enable temporarely: `sysctl kernel.unprivileged_userns_clone=1`,
50 or permanently by adding the line `kernel.unprivileged_userns_clone = 1` to
51 `/etc/sysctl.conf` and reloading it using `sysctl -p`.
52
53 The user the build script runs as should have at least 65536 subuids and subgids
54 (because 65536:65536 is always nobody:nogroup). The files `/etc/subuid` and
55 `/etc/subgid` contain all subuids and subgids and are an easy way to check if a
56 user has any. To add new subuids and subgids, you can use the `usermod` program.
57 The subuids shouldn't overlap with any existing uids or subuids, because a user
58 can switch to it's subuids. Usually, just using the uids after the biggest/last
59 used subuid is a good idea.
60
61 ## Usage
62
63 Everithing in this repo is designed to work without root. I haven't tested if it even works when run as root.
64
65 Creating an image in `bin/$(DISTRO)-$(RELEASE)-$(BOARD)-$(VARIANT).img`
66 ```
67 make
68 ```
69
70 | Variable | Default | Description |
71 | -------- | ------- | ----------- |
72 | BOARD |  | For which board the image is to be built. For example "librem5-devkit", "librem5-phone" or "pinephone-pro". |
73 | IMGSIZE | 3GiB | The size of the image. Can be specified in GB, GiB, MB, MiB, etc. |
74 | DISTRO | devuan | The distribution the image is based on |
75 | RELEASE | daedalus | The release of the disribution to debootstrap |
76 | VARIANT | base | A variation of the image to build, used to create image versions with some additional packages, repos, etc. |
77 | REPO | http://pkgmaster.devuan.org/merged/ | The repository to use for debootstraping |
78 | CHROOT_REPO | $REPO | The repository to use in the /etc/apt/sources.list |
79 | IMAGE_NAME | $(DISTRO)-$(RELEASE)-$(BOARD)-$(VARIANT).img | The name of the image |
80 | BUILD_PACKAGES | no | Wheter or not to build packages using chroot-build-helper at all |
81 | DONT_BUILD_IF_IN_REPO | yes | If the package to be built is already in the repo, don't rebuild it |
82 | USE_IMAGE_BUILDER_REPO | yes | Wheter or not to use and add a sources.list for $IMAGE_BUILDER_REPO. If you don't want to use another repo and instead build all package yourself, set this to "no" and also set $BUILD_PACKAGES to "yes". |
83 | IMAGE_BUILDER_REPO | `deb https://repo.dpa.li/apt/dpa-image-builder/ $(DISTRO)/$(RELEASE) $(BUILDER_PLATFORM)` | If $USE_IMAGE_BUILDER_REPO is set to yes, this repos is used & added. |
84 | IMAGE_BUILDER_REPO_KEY | https://repo.dpa.li/apt/dpa-image-builder/key.gpg | If $USE_IMAGE_BUILDER_REPO is set to "yes", this repo key is added. |
85
86 You can use the `config-set//%` and the `config-unset//%` targets to change these variables or the urls or branches of any of the repos. See the next section on how to use that feature.
87
88 You can also specify them in the make command directly instead, but if you do it that way, you need to take care of the following yourself:
89
90  * To change the IMGSIZE, you need to delete the image in bin/.
91  * To change REPO and CHROOT_REPO, remove the build/filesystem directory, or the rootfs and bootfs tar archives in it.
92
93 There are also make targets for that.
94
95 Packages can be built even if BUILD_PACKAGES is set to "no". For this, just enter
96 the `chroot-build-helper` subdirectory. In there, you can use `make` as normal,
97 including the `repo`, `reset*` and `clean*` make targets. You can also build an individual
98 package that way, using the `make build//%` make target (just replace `%` with the repo name).
99
100 ## Platform specific things
101
102  * [Librem 5](platform/librem5/README.md)
103  * [Pinephone Pro](platform/pinephone-pro/README.md)
104
105 ## Other useful make targets
106
107 | Name | Purpose |
108 | ---- | ------- |
109 | all  | Build the image |
110 | config-list | List all config variables, this includes the repo urls and branches |
111 | [CONF=path/to/config] config-set//variable-name TO=new-value | Set variable-name to new-value in file conf/$CONF, which defaults to userdefined. This will also clean up or reset images and repos as needed. |
112 | [CONF=path/to/config] config-unset//variable-name | Remove variable from file conf/$CONF. This will also clean up or reset images and repos as needed. |
113 | bootloader | builds the uboot bootloader at uboot/bin/uboot_firmware_and_dtb.bin |
114 | enter-buildenv | Setup environment & PATH most scripts of this repo use & execute $SHELL (unfortunately, make sets thet to sh...) |
115 | linux | builds the kernel packages |
116 | clean-fs | Removes the tar archives which contain the bootstrapped rootfs and bootfs of the current release |
117 | clean-fs-all | Removes the whole build/filesystem folder. This is enough for most purposes. |
118 | clean-image | Removes the image for the current release. |
119 | clean-image-all | Removes all images in the bin/ folder |
120 | repo | Clones all repositories into repo/* |
121 | repo//reponame | Clones the specified repository to repo/remote |
122 | clean-build   | remove all build files. (the files in build/, bin/ etc.) |
123 | clean-repo | Completely removes all repositories |
124 | clean-repo//reponame | Completly removes repo |
125 | update-repo | Update mirror all repos |
126 | update-repo//reponame | same as the above, but for a speciffic repo |
127 | clean-all | short for clean-repo and clean-build, removes pretty much everithing. |
128 | reset | Short for reset-repo and clean-build, mostly the same as clean-all, but doesn't require downloading all repos again |
129 | chroot//path/to/env/ | Chroot to a directory. Useful to look into a build environment in chroot-build-helper/build-env/*/ and similar stuff. |
130
131 The urls and reponame of all used repositories as well as the defaults of most variables can be found in the config/ directory, with the exception of the imx firmware from nxp, which is still in src/repositories.mk.
132
133
134 ## Modifying the image
135
136 All config settings, lists of packages to be installed, the packages to be built,
137 and additional files to be included in the image can be found in the `config/`
138 directory. The build script will combine the contents of the following subdirectories:
139  * `default`
140  * `default/v-$(VARIANT)`
141  * `$(DISTRO)`
142  * `$(DISTRO)/v-$(VARIANT)`
143  * `$(DISTRO)/r-$(RELEASE)`
144  * `$(DISTRO)/r-$(RELEASE)/v-$(VARIANT)`
145  * `default/b-$(BOARD)`
146  * `default/v-$(VARIANT)/b-$(BOARD)`
147  * `$(DISTRO)/b-$(BOARD)`
148  * `$(DISTRO)/v-$(VARIANT)/b-$(BOARD)`
149  * `$(DISTRO)/r-$(RELEASE)/b-$(BOARD)`
150  * `$(DISTRO)/r-$(RELEASE)/v-$(VARIANT)/b-$(BOARD)`
151
152 The list of directories to be searched is defined by the `CONFIG_PATH` variable,
153 which is set in the config file `config/default/conf`.
154
155 These subdirectories contain the following files:
156  * `config`: Config settings
157  * `install_debootstrap`: Packages to be installed by debootstrap.
158  * `install_early`: Packages to be installed using apt after the bootstrapping.
159  * `install_target`: Packages to be installed after the first boot.
160  * `download`: Packages which are only downloaded (including the dependencies), but not installed.
161  * `build`: Packages which have to be built from source. This must be a repo specified in the config which can be built using `debootstrap -us -uc -b`.
162  * `defer_installation_of_problemetic_package`: Some packages may not be installable in a crossdev chroot. Packages in this file are temporarely replaced with a dummy package.
163
164 All config and package lists in the search path are combined. Config settings
165 in config files later in the path override earlier ones. The special config file
166 `config/user_config_override`, which is the default for the `config-set//%` and
167 `config-unset//%` makefile targets, can override the settings from all other config
168 files and will be ignored in the git repo. It is useful for changing local
169 settings & preferences, such as the repos to use for bootstrapping, the image
170 files size, or using a different branch or remote for a repo, or generally
171 just to thest things without having to worry about these settings being overritten
172 by later git pulls.
173
174 The directories in the `$CONFIG_PATH` can also contain a `rootfs` folder. This
175 folder contains additional files to be added to the image. If the same file
176 exists in multiple rootfs folders, the last one in the config path is chowsen.
177 These files can also have an extension with a special meaning:
178  * `.in`: Uses envsubst to replace variables in the file. Use $$ to escape $.
179  * `.rm`: If a file with that name & path exists after bootstrapping, remove it.
180  * `.ignore`: If there was a file with the same name earlier in the config path, ignore it.
181
182 The recommended way of creating an image with your own additional packages & files
183 in it is to create a new image variant. Use `make config-set//VARIANT TO=your-new-variant`
184 to change the default variant. After that, you can check in which directories
185 the build script will now search the configs: `make config-list | grep '^CONFIG_PATH'`.
186 You can then add & make changes to the configs related to your new image variant.
187
188 Most of the scripts in this repo expect to be run with the environment provided
189 by the makefile. You can get a shell `make enter-buildenv` with this environment.
190 All scripts and binaries are then automatically in the PATH. You can also check
191 your config settings this way. For example, to check which packages it picked up,
192 you can use the command `env | grep '^PACKAGES'`. To see the config search path
193 with one path per line, you can use `printf '%s\n' $CONFIG_PATH`, and so on.
194 It's recommended to exit this shell before building the images though.
195
196 ## Automatically creating & adding built packages to a repo
197
198 Just install reprepro and set the following variables:
199
200 | Variable | Purpose |
201 | -------- | ------- |
202 | ADD_TO_EXTERNAL_REPO | Set this to "yes" to automatically add packages to a repo |
203 | REPO_DIR | The directory in which the files for the repo shall be stored. The actual repo will be in a subdirectory called "repo/". Use an absolute path here. |
204 | NEW_PKG_ORIGIN | Set the origin for the repo |
205 | NEW_PKG_COMPONENT | Set the component of the repo |
206 | NEW_PKG_KEY | Set the GPG key to use for signing |
207
208 You may also want to change: BUILD_PACKAGES, USE_IMAGE_BUILDER_REPO,
209 IMAGE_BUILDER_REPO and IMAGE_BUILDER_REPO_KEY. See section [Usage](#usage) for details.
210
211 You can build the packages even if BUILD_PACKAGES is set to no
212
213 ## Other important stuff
214
215 The license in this repository only applies to the files in this repository.
216 Other repositories loaded by these scripts often use different licenses,
217 and the parts of the files generated using these sources in turn have the license restrictions
218 that come with the corresponding sources applied to them.
219
220 Things unpacked after the debootstrapping currently don't have acls applied to them.
221 I don't know if any package unpacked at that stage would have them otherwise, but it's something I should
222 fix eventually and which should be kept in mind when adding packages to that phase of debootstrapping.
223
224 If you get an error message like "mount: something/proc: permission denied.", it means something is fishy with the proc mount of the host system.
225 Usually, this means something is mounted inside proc. Container engines / hypervisors like to do this for "security" resons.
226 But mounting proc in an unprivileged container would not have those mounts, thus revealing the files mounted over to the container, which kernel people considered a security issue.
227 Anyway, to fix this, just don't mount stuff in proc, except what's there by default anyway.
228 In my libvirt-lxc containers, I work around this by simply unmounting and mounting proc again in an init wrapper script:
229 ```
230 #!/bin/sh
231 umount /proc
232 mount -t proc -o nodev,nosuid,noexec /proc /proc
233 exec /sbin/init
234 ```