alpine-zdt-images/alpine-cloud-images/CONFIGURATION.md

11 KiB

Configuration

All the configuration for building image variants is defined by multiple config files; the base configs for official Alpine Linux cloud images are in the configs/ directory.

We use HOCON for configuration -- this primarily facilitates importing deeper configs from other files, but also allows the extension/concatenation of arrays and maps (which can be a useful feature for customization), and inline comments.


Resolving Work Environment Configs and Scripts

If work/configs/ and work/scripts/ don't exist, the build script will install the contents of the base configs/ and scripts/ directories, and overlay additional configs/ and scripts/ subdirectories from --custom directories (if any).

Files cannot be installed over existing files, with one exception -- the configs/images.conf same-directory symlink. Because the build script always loads work/configs/images.conf, this is the hook for "rolling your own" custom Alpine Linux cloud images.

The base configs/images.conf symlinks to alpine.conf, but this can be overridden using a --custom directory containing a new configs/images.conf same-directory symlink pointing to its custom top-level config.

For example, the configs and scripts in the overlays/testing/ directory can be resolved in a clean work environment with...

./build configs --custom overlays/testing

This results in the work/configs/images.conf symlink to point to work/configs/alpine-testing.conf instead of work/configs/alpine.conf.

If multiple directories are specified with --custom, they are applied in the order given.


Top-Level Config File

Examples of top-level config files are configs/alpine.conf and overlays/testing/configs/alpine-testing.conf.

There are three main blocks that need to exist (or be imported into) the top level HOCON configuration, and are merged in this exact order:

Default

All image variant configs start with this block's contents as a starting point. Arrays and maps can be appended by configs in Dimensions and Mandatory blocks.

Dimensions

The sub-blocks in Dimensions define the "dimensions" a variant config is comprised of, and the different config values possible for that dimension. The default alpine.conf defines the following dimensional configs:

  • version - Alpine Linux x.y (plus edge) versions
  • arch - machine architectures, x86_64 or aarch64
  • firmware - supports launching via legacy BIOS or UEFI
  • bootstrap - the system/scripts responsible for setting up an instance during its initial launch
  • cloud - for specific cloud platforms

The specific dimensional configs for an image variant are merged in the order that the dimensions are listed.

Mandatory

After a variant's dimensional configs have been applied, this is the last block that's merged to the image variant configuration. This block is the ultimate enforcer of any non-overrideable configuration across all variants, and can also provide the last element to array config items.


Dimensional Config Directives

Because a full cross-product across all dimensional configs may produce images variants that are not viable (i.e. aarch64 simply does not support legacy bios), or may require further adjustments (i.e. the aws aarch64 images require an additional kernel module from 3.15 forward, which aren't available in previous versions), we have two special directives which may appear in dimensional configs.

EXCLUDE array

This directive provides an array of dimensional config keys which are incompatible with the current dimensional config. For example, configs/arch/aarch64.conf specifies...

# aarch64 is UEFI only
EXCLUDE = [bios]

...which indicates that any image variant that includes both aarch64 (the current dimensional config) and bios configuration should be skipped.

WHEN block

This directive conditionally merges additional configuration IF the image variant also includes a specific dimensional config key (or keys). In order to handle more complex situations, WHEN blocks may be nested. For example, configs/cloud/aws.conf has...

WHEN {
  aarch64 {
    # new AWS aarch64 default...
    kernel_modules.gpio_pl061   = true
    initfs_features.gpio_pl061  = true
    WHEN {
      "3.14 3.13 3.12" {
        # ...but not supported for older versions
        kernel_modules.gpio_pl061   = false
        initfs_features.gpio_pl061  = false
      }
    }
  }

This configures AWS aarch64 images to use the gpio_pl061 kernel module in order to cleanly shutdown/reboot instances from the web console, CLI, or SDK. However, this module is unavailable on older Alpine versions.

Spaces in WHEN block keys serve as an "OR" operator; nested WHEN blocks function as "AND" operators.


Config Settings

Scalar values can be simply overridden in later configs.

Array and map settings in later configs are merged with the previous values, or entirely reset if it's first set to null, for example...

some_array = [ thing ]
# [...]
some_array = null
some_array = [ other_thing ]

Mostly in order of appearance, as we walk through configs/alpine.conf and the deeper configs it imports...

project string

This is a unique identifier for the whole collection of images being built. For the official Alpine Linux cloud images, this is set to https://alpinelinux.org/cloud.

When building custom images, you MUST override AT LEAST this setting to avoid image import and publishing collisions.

name array

The ultimate contents of this array contribute to the overall naming of the resultant image. Almost all dimensional configs will add to the name array, with two notable exceptions: version configs' contribution to this array is determined when work/images.yaml is resolved, and is set to the current Alpine Linux release (x.y.z or YYYYMMDD for edge); also because cloud images are isolated from each other, it's redundant to include that in the image name.

description array

Similar to the name array, the elements of this array contribute to the final image description. However, for the official Alpine configs, only the version dimension adds to this array, via the same mechanism that sets the revision for the name array.

motd map

This setting controls the contents of what ultimately gets written into the variant image's /etc/motd file. Later configs can add additional messages, replace existing contents, or remove them entirely (by setting the value to null).

The motd.version_notes and motd.release_notes settings have slightly different behavior:

  • if the Alpine release (x.y.z) ends with .0, release_notes is dropped to avoid redundancy
  • edge versions are technically not released, so both of these notes are dropped from /etc/motd
  • otherwise, version_notes and release_notes are concatenated together as release_notes to avoid a blank line between them

scripts array

These are the scripts that will be executed by Packer, in order, to do various setup tasks inside a variant's image. The work/scripts/ directory contains all scripts, including those that may have been added via build --custom.

script_dirs array

Directories (under work/scripts/) that contain additional data that the scripts will need. Packer will copy these to the VM responsible for setting up the variant image.

size string

The size of the image disk, by default we use 1G (1 GiB). This disk may (or may not) be further partitioned, based on other factors.

login string

The image's primary login user, set to alpine.

repos map

Defines the contents of the image's /etc/apk/repositories file. The map's key is the URL of the repo, and the value determines how that URL will be represented in the repositories file...

value result
null make no reference to this repo
false this repo is commented out (disabled)
true this repo is enabled for use
tag enable this repo with @tag

packages map

Defines what APK packages to add/delete. The map's key is the package name, and the value determines whether (or not) to install/uninstall the package...

value result
null don't add or delete
false explicitly delete
true add from default repos
tag add from @tag repo
--no-scripts add with --no-scripts option
--no-scripts tag add from @tag repo, with --no-scripts option

services map of maps

Defines what services are enabled/disabled at various runlevels. The first map's key is the runlevel, the second key is the service. The service value determines whether (or not) to enable/disable the service at that runlevel...

value result
null don't enable or disable
false explicitly disable
true explicitly enable

kernel_modules map

Defines what kernel modules are specified in the boot loader. The key is the kernel module, and the value determines whether or not it's in the final list...

value result
null skip
false skip
true include

kernel_options map

Defines what kernel options are specified on the kernel command line. The keys are the kernel options, the value determines whether or not it's in the final list...

value result
null skip
false skip
true include

initfs_features map

Defines what initfs features are included when making the image's initramfs file. The keys are the initfs features, and the values determine whether or not they're included in the final list...

value result
null skip
false skip
true include

qemu.machine_type string

The QEMU machine type to use when building local images. For x86_64, this is set to null, for aarch64, we use virt.

qemu.args list of lists

Additional QEMU arguments. For x86_64, this is set to null; but aarch64 requires several additional arguments to start an operational VM.

qemu.firmware string

The path to the QEMU firmware (installed in work/firmware/). This is only used when creating UEFI images.

bootloader string

The bootloader to use, currently extlinux or grub-efi.

access map

When images are published, this determines who has access to those images. The key is the cloud account (or PUBLIC), and the value is whether or not access is granted, true or false/null.

regions map

Determines where images should be published. The key is the region identifier (or ALL), and the value is whether or not to publish to that region, true or false/null.