Provisioning and Configuration

This guide introduces the in-depth configuration specification for human-friendly FCOS Configuration (FCC) YAML files.

Rather than read these detailed instructions, advanced users may want to reference the configuration specification for an abbreviated list of options.

Ignition overview

Ignition is a provisioning utility that reads a configuration file (in JSON format) and provisions an FCOS system based on that configuration. Configurable components include storage and filesystems, systemd units, and users.

Ignition runs only once during the first boot of the system (in initramfs). Because Ignition runs so early in the boot process, it can re-partition disks, format filesystems, create users, and write files before the userspace begins to boot. As a result, systemd services are already written to disk when systemd starts, speeding the time to boot.

Configuration process

Ignition configurations are formatted as JSON, which is quick and easy for a machine to read. However, these files are not easy for humans to read or write. The solution is a two-step configuration process that is friendly for both humans and machines:

  1. Produce a YAML-formatted Fedora CoreOS Configuration (FCC) file.

  2. Run the Fedora CoreOS Configuration Transpiler (fcct) to convert the YAML file into a JSON Ignition file.

During the transpilation process, fcct verifies the syntax of the YAML file, which can catch errors before you use it to launch the FCOS system.

Once you have an Ignition (.ign) file, you can use it to boot an FCOS system in a VM or install it on bare metal.

FCC file structure

The FCC file follows YAML syntax and contains the following top-level nodes:

  • variant: specifies fcos as the operating system

  • version: specifies the version of fcct

  • ignition: specifies a remote configuration (for convenience or for platforms that do not allow for the ingestion of large configuration files)

  • storage: provisions storage and configures the filesystem

  • systemd: controls systemd units

  • passwd: configures users

YAML files must have consistent indentation. See the YAML Specification for further details.

FCC file metadata (variant and version)

The first two lines of an FCC file define fcos as the operating system and the semantic version of the document specification (e.g. 1.1.0). Both lines are required.

Example of the FCC file metadata
variant: fcos
version: 1.1.0

Ignition metadata (ignition)

The optional ignition block defines the metadata for the Ignition configuration. It allows you to specify a remote configuration file for platforms that do not allow the direct ingestion of large configuration files. It tells Ignition to start the first boot of FCOS, at which time, Ignition will fetch the specified Ignition file from a remote server.

Nodes

The ignition node contains the following nodes:

  • config - provides the location of the remote Ignition file and specifies whether to merge it with the current file or replace it.

  • timeouts - specifies how to handle http responses.

  • security - specifies a tls certificate authority, if necessary.

Remote configuration file (config)

The first line of the config node specifies whether you want to merge or replace the remote configuration. Regardless of this choice, the following lines are the same:

  • source defines the remote location as a URL. The supported schemes are http, https, s3, tftp, and data.

  • verification is optional but recommended when using the http scheme. It contains a hash of the configuration

    • hash provides the hash string in the form <type>-<value> where type is sha512.

Handling HTTP responses (timeouts)

This node is optional but recommended when fetching Ignition files via http or https.

  • http_response_headers is an integer for the time to wait (in seconds) for the server’s response headers (but not the body) after making the request. The default is 10. To specify no timeout, set the value to 0.

  • http_total is an integer for the time limit (in seconds) for the entire operation (connection, request, and response), including any retries. The default is 0 for no timeout.

Network security (security)

This optional node provides options related to TLS when fetching an Ignition file via https. It contains the tls object, which contains the certificate_authorities, a list of certificate authorities (in addition to system authorities) to be used for TLS verification. All certificate authorities must have a unique source:

  • source is a string that specifies the URL of the certificate in PEM format. The supported schemes are http, https, s3, tftp, and data.

  • verification is optional but recommended when using the http scheme. It contains a hash of the certificate.

    • hash provides the hash string in the form <type>-<value> where type is sha512.

Note that certificate authorities listed here are not automatically added to the host filesystem. They are solely used by Ignition itself when fetching over https. If you’d like to also install them on the host filesystem, include them as usual under the storage.files array.

Examples

The following examples show how to retrieve an Ignition file from a remote source. They are both set to replace the current configuration with a remote Ignition file.

Retrieving a remote Ignition file via http
variant: fcos
version: 1.1.0
ignition:
  config:
    replace:
      source: http://example.com/sample.ign
      verification:
        hash: sha512-e2bb19fdbc3604f511b13d66f4c675f011a63dd967b97e2fe4f5d50bf6cb224e902182221ba0f9dd87c0bb4abcbd2ab428eb7965aa7f177eb5630e7a1793e2e6
Retrieving a remote Ignition file via https
variant: fcos
version: 1.1.0
ignition:
  config:
    replace:
      source: https://example.com/sample.ign
  security:
    tls:
      certificate_authorities:
        - source: https://example.com/source1
          verification:
            hash: sha512-e2bb19fdbc3604f511b13d66f4c675f011a63dd967b97e2fe4f5d50bf6cb224e902182221ba0f9dd87c0bb4abcbd2ab428eb7965aa7f177eb5630e7a1793e2e6

Storage specification

This section describes the FCOS Configuration (FCC) YAML format for defining the desired state of storage associated with a FCOS instance.

The storage block contains a list of objects, which can be of the following type:

  • disks: List of disks

  • raid: List of RAID arrays

  • filesystems: List of filesystems

  • files: List of files to be written

  • directories: List of directories to be created

  • links: List of links to be created

Disks

Every entry under the disks node must correspond to a unique device. For each device, specify a list of GPT partitions. Unless specified as optional, all nodes are mandatory. The contents of disks is as follows:

  • device (string): Absolute path of the disk device. Disks are typically referenced by the /dev/disk/by-* symlinks. Avoid specifying the disk device /dev/sdx directly: when new disks are inserted, the system might re-enumerate devices at boot. This could change the order of the /dev/sdx devices. The /dev/disk/by-* symlinks always point to the right devices.

  • wipe_table (boolean, optional): When true, Ignition erases the partition table before proceeding. Otherwise, the table’s existing partition entries are left alone.

  • partitions (object list, optional): List of partitions to be written to the partition table of the device. Each partition occupies a slot in the table. You can either specify the slot directly with the number node, or specify number: 0 and supply a unique label.

    • label (string, optional): GPT PARTLABEL for the partition.

    • number (integer, optional): Slot number occupied by the partition, starting at 1. To use the next available slot, specify 0. In this case, you should also specify a unique label.

    • size_mib (integer, optional): Size of the partition in mebibytes. If 0, the partition is sized as large as possible. Note: 1 mebibytes = 1024 * 1024 bytes.

    • start_mib (integer, optional): Start position of the partition from the beginning of the disk, in mebibytes. If 0, the partition will be placed at the start of the largest block available.

    • type_guid (string, optional): Partition type GUID. If omitted, it defaults to 0FC63DAF-8483-4772-8E79-3D69D8477DE4, the Linux native file system GUID. The ultimate reference list for the type GUIDs is currently the parttypes.cc file in the GPT fdisk source code. A more readable list can be found in the GUID Partition Table article on Wikipedia.

    • guid (string, optional, must be unique): GUID of the partition. You can omit this when creating new partitions.

    • wipe_partition_entry (boolean, optional)

      • true: Ignition erases any existing partition that does not match this entry.

      • false: Ignition leaves the partition unchanged, which will fail.

    • should_exist (boolean, optional). Defaults to true.

      • true: If true and if it does not already exist, the partition with the specified number is created. If the partition exists, and wipe_partition_entry is false, then number must be specified as a non-zero integer, and label, start_mib, size_mib, guid and type_guid must all be omitted.

      • false: If false and the partition exists, Ignition looks at the wipe_partition_entry value and deletes the partition if true, or fails if false.

Example for defining a disk containing some partitions
variant: fcos
version: 1.1.0
storage:
  disks:
    -
      # Mandatory. We use the World-Wide Number ID of the drive to ensure
      # uniqueness.
      device: /dev/disk/by-id/wwn-0x50014e2eb507fcdf
      # This ensures that the partition table is re-created, along with all
      # the partitions.
      wipe_table: true
      partitions:
        # The first partition (slot number 1) is 32 GiB and starts at the
        # beginning of the device. Its type_guid identifies it as a Linux
        # swap partition.
        - label: part1
          number: 1
          size_mib: 32768
          start_mib: 0
          type_guid: 0657fd6d-a4ab-43c4-84e5-0933c84b4f4f
        # The second partition (implicit slot number 2) will be placed after
        # partition 1 and will occupy the rest of the available space.
        # Since type_guid is not specified, it will be a Linux native
        # partition.
        - label: part2
          number: 0

Raid

Every entry under the raid node must correspond to a unique RAID array. The resulting configuration is implemented as an mdadm "software" RAID. The contents of raid is as follows. Unless specified as optional, all nodes are mandatory.

  • name (string): Name of the resulting md device.

  • level (string): Redundancy level of the array. See the supported levels in the Fedora mdadm man page. Examples: linear, raid0, raid.

  • devices (list of strings): List of devices that should be part of the array, referenced by absolute path.

  • spares (optional, integer): Number of spares in the array, if applicable.

  • options (optional, list of strings): Additional options to be passed to mdadm.

File systems

Entries under the filesystems node list the file systems to be created and mounted. Each file system must have a unique device. The contents of filesystems is as follows. Unless specified as optional, all nodes are mandatory.

  • path (string): Mount point of of the filesystem while Ignition is running, relative to where the root filesystem will be mounted. This is not necessarily the same as where it should be mounted in the real root, but you should set it as such.

  • device (string): Absolute path of the device.

  • format (string): File system "format" (ie - file system type). Accepted values: ext4, btrfs, xfs, vfat, or swap.

  • wipe_filesystem (boolean, optional): If true, the device is wiped before the file system is created.

  • label (string, optional): Label of the file system.

  • uuid (string, optional): UUID of the file system.

  • options (list of strings, optional): Additional options to be passed to mkfs.

Example for defining a file system on a RAID storage device
variant: fcos
version: 1.1.0
storage:
  disks:
  # This defines two partitions, each on its own disk. The disks are
  # identified by their WWN.
  - device: /dev/disk/by-id/wwn-0x50014ee261e524e4
    wipe_table: true
    partitions:
    -
      # Each partition gets a human-readable label.
      label: "raid.1.1"
      # Each partition is placed at the beginning of the disk and is 64 GiB
      # long.
      number: 1
      size_mib: 65536
      start_mib: 0
  - device: /dev/disk/by-id/wwn-0x50014ee0b8442cd3
    wipe_table: true
    partitions:
    - label: "raid.1.2"
      number: 1
      size_mib: 65536
      start_mib: 0
  # We use the previously defined partitions as devices in a RAID1 md array.
  raid:
    - name: publicdata
      level: raid1
      devices:
      - /dev/disk/by-partlabel/raid.1.1
      - /dev/disk/by-partlabel/raid.1.2
  # The resulting md array is used to create an EXT4 file system.
  filesystems:
    - path: /var/publicdata
      device: /dev/md/publicdata
      format: ext4
      label: PUB
Example for adding a /var partition to the primary disk
variant: fcos
version: 1.1.0
storage:
  disks:
  -
    # The name of the primary block device. In virtio-based setups, this is
    # likely `/dev/vda`. Elsewhere, it's likely `/dev/sda`.
    device: /dev/vda
    # We do not want to wipe the partition table since this is the primary
    # device.
    wipe_table: false
    partitions:
    - size_mib: 0
      start_mib: 0
      # We assign a descriptive label to the partition. This is important
      # for referring to it in a device-agnostic way in other parts of the
      # configuration.
      label: var
  filesystems:
    - path: /var
      device: /dev/disk/by-partlabel/var
      format: xfs
systemd:
  units:
    -
      # We need to create a systemd mount unit so that /var actually gets
      # mounted on /var.
      name: var.mount
      enabled: true
      contents: |
        [Unit]
        Before=local-fs.target
        [Mount]
        Where=/var
        What=/dev/disk/by-partlabel/var
        [Install]
        WantedBy=local-fs.target

Files

The files node lets you define a list of files, identified by a unique path, that Ignition will create with the required contents and attributes as needed.

An empty file would not be very useful, so the files can be defined with a contents option to specify either a source from which the file will be copied, or inline data.

The contents of files is as follows. Unless specified as optional, all nodes are mandatory.

  • path (string, must be unique): Absolute path of the file to be created.

  • overwrite (boolean, optional): Defaults to false. If true, source must be specified, and any preexisting file of the specified path will be overwritten with the contents of source.

  • contents (object, optional): Specifies the contents of the file.

    • compression (string, optional): Type of compression of the source. Possible values are null or gzip. Defaults to null. Compression cannot be specified if source uses an s3 scheme.

    • source (string, optional): Mandatory if overwrite is true. Mutually exclusive with option inline. Specifies the URL of the source to be copied to the path. Supported schemes are http, https, tftp, s3, and data. If you use the http scheme, you should specify a verification option to ensure the remote contents have not changed. If source is omitted, Ignition checks if the file already exists:

      • File exists: Ignition does nothing.

      • File does not exist: Ignition creates an empty file.

    • inline (string, optional): Mutually exclusive with option source. Specifies a string to be written to the file.

    • verification (object, optional): Tells Ignition to verify the contents of the file. Currently, only one verification option has been implemented: hash.

      • hash (string, mandatory if verification is specified): Hash of the file contents, in the form <type>-<value>. The only supported type is sha512.

  • append (object list, optional): This node has the same options as source. It specifies contents to be appended to the (presumably existing) file.

    • compression: See contents.

    • source: See contents.

    • inline: See contents.

    • verification: See contents.

      • hash: See contents.

  • mode (integer, optional): Specifies the file’s permission or mode. If mode is not specified, Ignition checks to see if the file already exists:

    • File exists: Keep the existing file mode if overwrite is false and source is not specified. Otherwise, set mode to octal 0644.

    • File does not exist: mode defaults to octal 0644.

  • user (object, optional): Specifies the user ID of the file owner. Either an ID or name must be specified.

    • id (integer, optional): User ID of the owner.

    • name (string, optional): User name of the owner.

  • group (object, optional): Specifies the group of the file owner. Either an ID or name must be specified.

    • id (integer, optional): Group ID of the owner.

    • name (string, optional): Group name of the owner.

Directories

The directories node specifies a list of directories, identified by a unique path, that Ignition creates as needed.

The directories structure is similar to the files structure. Unless specified as optional, all nodes are mandatory.

  • path (string): See Files.

  • overwrite (boolean, optional): Defaults to false. If true, preexisting files or directories at the specified path are removed. If overwrite is false and a file system object already exists at the specified path, Ignition checks the type of the existing file system object:

    • Existing path is a directory: Ignition does nothing

    • Existing path is not a directory: Ignition fails.

  • mode (integer, optional): Specifies the directory’s permission or mode. If mode is not specified, Ignition checks to see if the directory already exists:

    • Directory exists: if overwrite is false, Ignition does nothing, otherwise the mode is set to octal 0755.

    • Directory does not exist: The mode is set to 0755.

  • user: Specifies the directory owner. See Files.

    • id: See Files

    • name: See Files

  • group: Specifies the directory group. See Files.

    • id: See Files

    • name: See Files

The links node lets you specify links (hard or symbolic) to be created by Ignition as needed.

The contents of links is as follows. Unless specified as optional, all nodes are mandatory.

  • path (string, must be unique): Absolute path of the link to be created.

  • overwrite (boolean, optional): Defaults to false. If false and a link already exists at the specified path, Ignition sets only the owner and group.

  • user: Specifies the link owner. See Files.

    • id: See Files.

    • name: See Files.

  • group: Specifies the link group. See Files.

    • id: See Files.

    • name: See Files.

  • target (string): Target path of the link.

  • hard (boolean, optional): Defaults to false. If true, Ignition creates a hard link. If false, it creates a symbolic link

Example for defining files, directories and links
variant: fcos
version: 1.1.0
storage:
  # This creates a directory. Its mode is set to 0755 by default, that
  # is, readable and executable by all, and writable by the owner.
  directories:
  - path: /opt/tools
    overwrite: true
  files:
    -
      # Creates a file /var/helloworld containing a string defined in-line.
      path: /var/helloworld
      overwrite: true
      contents:
        inline: Hello, world!
      # Sets the file mode to 0644 (readable by all, also writable by the
      # owner).
      mode: 0644
      user:
        # The owner uid and group are defined by their numerical IDs.
        id: 500
      group:
        id: 500
    -
      # We need the nifty (and alas imaginary) transmogrifier tool.
      path: /opt/tools/transmogrifier
      overwrite: true
      # Deploys this tool by copying an executable from an https link. The
      # file is compressed with gzip.
      contents:
        source: https://mytools.example.com/path/to/archive.gzip
        compression: gzip
        verification:
          # The hash is sha512- followed by the 128 hex characters given by
          # the sha512sum command.
          hash: sha512-5c84785eb10c9efdea1f...
      # Makes the tool file readable and executable by all.
      mode: 0555
  links:
    -
      # Creates a symlink to the tool location from /usr/local/bin. This is
      # useful to let local processes invoke this tool without altering
      # their PATH environment variable.
      path: /usr/local/bin/transmogrifier
      overwrite: true
      target: /opt/tools/transmogrifier
      hard: false

Configuring systemd Units (systemd)

The systemd node of an FCC file allows you to add and configure systemd units on the FCOS machine.

Nodes

The systemd node contains one top-level node: a list of units. For each unit, the following options are available:

  • name (string, required, must be unique): the full name of the unit in the form of thing.service.

  • enabled (boolean): When set to true, the unit is enabled. By default, the service is unmodified. For a unit to run, it must have an [Install] section.

  • mask (boolean): determines whether the unit is masked. When set to true, the service is masked by a symlink to /dev/null.

  • contents (string): the contents of the unit.

  • dropins (list of objects): a list of drop-ins for the unit.

    • name (string, required, must be unique): the name of the drop-in, which must have a suffix of .conf.

    • contents (string): the contents of the drop-in.

Examples

Running Containers shows some examples of adding systemd units to an FCC file.

Configuring Users (passwd)

The passwd node allows you to create, modify, and configure FCOS users.

FCOS has a default privileged user named core. You can use this user for system administration tasks. Use the passwd node to modify this user’s attributes, as shown below.

Nodes

The top-level nodes for passwd include users and groups. These are both lists of objects.

  • users (list of objects): the lists of accounts to create on FCOS.

    • name (string, required, must be unique): the username

    • password_hash (string): the hashed password for the account.

    • ssh_authorized_keys (list of strings, each must be unique): a list of SSH keys to be added as an SSH key fragment in the user’s home directory (.ssh/authorized_keys.d/ignition).

    • uid (integer): the user ID of the account

    • gecos (string): the GECOS field of the account

    • home_dir (string): the home directory of the account

    • no_create_home (boolean): when set to true, no home directory is created for the user. This does not have any effect on any existing home directory.

    • primary_group (string): the name of the primary group of the account

    • groups (list of strings): the list of supplementary groups of the account

    • no_user_group (boolean): when true, does not create a user group for the account. This has no effect on any existing groups.

    • no_log_init (boolean): when set to true, does not add the user to the lastlog and faillog databases. This has no effect on any existing accounts.

    • shell (string): the login shell of the new account

    • system (boolean): when set to true, creates the account as a system account. Has no effect on an existing account.

  • groups (list of objects): a list of groups to be added

    • name (string, required, must be unique): the name of the group

    • gid (integer): the group ID of the group

    • password_hash (string): the hashed password for the group

    • system (boolean): when set to true, the group is created as a system group. Has no effect on existing groups.

Examples

Producing an Ignition File is a tutorial for how to provide an SSH key for login of the existing core user.

You can also add a password hash to this user, specify the user’s groups, and add more users as shown below:

Example for modifying and adding users:
  passwd:
  users:
    - name: core
      ssh_authorized_keys:
        - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGdByTgSVHq......."
    - name: elroy
      password_hash: "$6$5s2u6/jR$un0AvWnqilcgaNB3Mkxd5yYv6mTlWfOoCYHZmfi3LDKVltj.E8XNKEcwWm..."
      ssh_authorized_keys:
        - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGdByTgSVHq......."
      groups: [ sudo, docker ]

As you can see from this snippet, the core user is modified with a private SSH key, and a new user named elroy is added. The elroy user can log in with a private SSH key or with a password and is added to the sudo and docker groups.