Kickstart Support in Photon OS

Photon OS works with kickstart for unattended, automated installations. The kickstart configuration file can either reside in the CD-ROM attached to the host or be served through an HTTP server.

Kickstart Capabilities

Photon OS supports the following configurations with kickstart:

  • Setting the hostname
  • Setting the password
  • Setting the disk to install
  • Selecting whether to install the full or the minimal version of Photon OS
  • Applying a post-installation script
  • Adding public keys to allow the root account to log in through SSH

Permitted JSON Fields

The following is a list of allowed JSON fields and their descriptions:

FieldDescription
hostnameThe host name as string. You can also specify the name in printf format.

The hostname must not start with a number or "-" and must be less than 64 characters.

Example: "photon-$((RANDOM%4096))"

password:

crypted: true/false

text: password text

crypted: true: This indicates that the "text" field is already encrypted. In this case, the specified password is used as is for the root user.

crypted: false: This indicates that the "text" field is plain text. It is then encrypted and used to create the root user's password.

text: Plain text or encrypted password.

diskIndicates the install disk.

Example: /dev/sda

partitionsAn array of partition definitions.

To create GPT partitions

Example:

[

{"mountpoint": "/", "size": 0, "filesystem": "ext4"},

{"mountpoint": "/boot", "size": 128, "filesystem": "ext4"},

{"mountpoint": "/root", "size": 128, "filesystem": "ext4"},

{"size": 128, "filesystem": "swap"}

]

To create LVM partitions

Example:

[

{"mountpoint": "/", "size": 0, "filesystem": "ext4", "lvm":{"vg_name":"vg1", "lv_name":"rootfs"}},

{"mountpoint": "/boot", "size": 128, "filesystem": "ext4"},

            <p>{"mountpoint": "/root", "size": 128, "filesystem": "ext4","lvm":{"vg_name":"vg1", "lv_name":"root"}},

            <p>{"size": 128, "filesystem": "swap","lvm":{"vg_name":"vg2", "lv_name":"swap"}}

]

Note: Mounting '/boot' partition as lvm is not supported.

packagelist_fileIndicates the name of the file that contains the list of packages to install.

Example: { "packagelist_file": "packages_minimal.json" }

additional_packagesSpecify an array of additional packages.
install_linux_esxSpecify a boolean value to use linux esx instead of generic linux.
postinstallSpecify an array of bash commands to execute after install.

See the example for partitions.

Example: { "postinstall": [ "#!/bin/sh", "echo \"Hello World\" > /etc/postinstall" ] }

public_keyOptional.

The public key that you require to install for password-less logins.

This key is created in authorized_keys in the .ssh directory.

additional_filesOptional.

Contains a list of pairs {source file (or directory), destination file (or directory)} to copy to the target system. Source file (directory) will be looked up in "search_path" list.

Example: { "additional_files": [ {"resizefs.sh": "/usr/local/bin/resizefs.sh"}, {"resizefs.service": "/lib/systemd/system/resizefs.service"}]}

additional_rpms_pathOptional.

Provide a path containing additional RPMS that are to be bundled into the image.

archOptional.

Target system architecture. Should be set if target architecture is different from the host, for instance x86_64 machine building RPi image. Acceptable values are: "x86_64", "aarch64" Default value: autodetected host architecture

Example: { "arch": "aarch64" }

bootmodeOptional.

Sets the boot type to support: EFI, BIOS or both.

Acceptable values are: bios, efi, dualboot

bios

Adds special partition (very first) for first stage grub.

efi

Adds ESP (Efi Special Partition), format is as FAT and copy there EFI binaries including grub.efi

dualboot

Adds two extra partitions for "bios" and "efi" modes. This target will support both modes that can be switched in bios settings without extra actions in the OS.

Default value: "dualboot" for x86_64 and "efi" for aarch64

Example: { "bootmode": "bios" }

eject_cdromOptional.

Ejects cdrom after installation completed if set to true.

Boolean: true or false

Default value: true

Example: { "eject_cdrom": false }

liveOptional.

Should be set to flase if target system is not being run on host machine. When it set to false, installer will not add EFI boot entries, and will not generate unique machine-id.

Default value: false if "disk" is /dev/loop and true otherwise.

Example: { "live": false }

log_levelOptional.

Set installer logging level.

Acceptable values are: error, warning, info, debug

Default value: info

Example: { "log_level": "debug" }

ostreeOptional.

Atomic flavour of Photon OS.

default_repo

(required)

Define the type of repo data used for installing the OS There are two type:

1. Default Repo(comes with ISO)

2. Custom Repo (Remote server)

Boolean: true or false

where true : Default Repo is selected

false: Custom Repo is selected

Default value: true Example: { "ostree": {"default_repo": true}}

repo_url

(Required, Only If Custom Repo is selected) Supported Value: Valid "repo" URL of remote server where repo data exists

repo_ref

(Required, Only If Custom Repo is selected) Supported Value: Valid "ref" path which was mentioned for creation of Base Tree on remote server

Example: { "ostree": { "default_repo": false, "repo_url": "http://:/repo", "repo_ref": "photon/3.0/x86_64/minimal" } }

packagesOptional if packagelist_file set.

Contains list of packages to install.

Example: { "packages": ["minimal", "linux", "initramfs"] }

partition_typeOptional.

Set partition table type. Supported values are: gpt, msdos.

Default value: gpt

Example: { "partition_type": "msdos" }

networkOptional.

Used to configure network on a live/installed system.

type

required

String; must be one of dhcp/static/vlan. Indicates how the network is being configured.

hostname

optional; when type == dhcp

String; DHCP client hostname

ip_addr

required; when type == static

IP String; IP address to be configured

netmask

required; when type == static

IP String; Netmask to be configured

gateway

required; when type == static

IP String; Gateway IP address to be configured

nameserver

required; when type == static

IP String; Name server IP address to be configured

vlan_id

required; when type == vlan

ID String. (1-4094); VLAN ID number expressed as string

postinstallscriptsOptional.

Contains list of scripts to run on the target after installation. Scripts will be looked up in "search_path" list.

Example: { "postinstallscripts": ["rpi3-custom-patch.sh"] }

search_pathOptional.

List of directories to search for additional files and scripts.

Example: { "search_path": ["/home/user", "/tmp"] }

shadow_passwordOptional.

Contains encrypted root password. Short form of: { "password": { "crypted": true, "text": "encrypted password here"} }

uiOptional.

Installer will show progress status in the UI, if it set to true. Or logging output will be printed to console - default behavior.

Boolean: true or false

Default value: false

Example: { "ui": true }

Sample Configuration File

Here is a sample kickstart configuration file:

{
    "hostname": "photon-machine",
    "password":
        {
            "crypted": false,
            "text": "changeme"
        },
    "disk": "/dev/sda",
    "partitions": [
                        {"mountpoint": "/", "size": 0, "filesystem": "ext4"},
                        {"mountpoint": "/boot", "size": 128, "filesystem": "ext4"},
                        {"mountpoint": "/root", "size": 128, "filesystem": "ext4"},
                        {"size": 128, "filesystem": "swap"}
                    ],
    "packagelist_file": "packages_minimal.json",
    "additional_packages": ["vim"],
    "postinstall": [
                		"#!/bin/sh",
                    	"echo \"Hello World\" > /etc/postinstall"
                   ],
    "public_key": "<ssh-key-here>",
    "install_linux_esx": false,
    "network": {
        "type": "dhcp"
    }    
}

Installing Root Partition as LVM

In the kickstart file modify the partitions field to mount root partition as LVM.

For example:

"disk": "/dev/sda"
"partitions":[
                {"mountpoint": "/", "size": 0, "filesystem": "ext4", "lvm":{"vg_name":"vg1", "lv_name":"rootfs"}},
                {"mountpoint": "/boot", "size": 128, "filesystem": "ext4"},

                {"mountpoint": "/root", "size": 128, "filesystem": "ext4","lvm":{"vg_name":"vg1", "lv_name":"root"}},

                {"size": 128, "filesystem": "swap","lvm":{"vg_name":"vg2", "lv_name":"swap"}}
]

Note:

  • vg_name : Volume Group Name
  • lv_name : Logical Volume Name

In above example rootfs, root are logical volumes in the volume group vg1 and swap is logical volume in volume group vg2, physical volumes are part of disk /dev/sda.

Multiple disks are also supported. For example:

"disk": "/dev/sda"
"partitions":[
                {"mountpoint": "/", "size": 0, "filesystem": "ext4", "lvm":{"vg_name":"vg1", "lv_name":"rootfs"}},
                {"mountpoint": "/boot", "size": 128, "filesystem": "ext4"},

                {"disk": "/dev/sdb", "mountpoint": "/root", "size": 128, "filesystem": "ext4","lvm":{"vg_name":"vg1", "lv_name":"root"}},

                {"size": 128, "filesystem": "swap","lvm":{"vg_name":"vg1", "lv_name":"swap"}}
]

If disk name is not specified, the physical volumes will be part of the default disk: dev/sda. In above example rootfs,root and swap are logical volumes in volume group vg1, physical volumes are in the disk /dev/sdb and partitions are present in /dev/sda.

Note: Mounting /boot partition as LVM is not supported.

Unattended Installation Through Kickstart

For an unattended installation, you pass the ks=<config_file> parameter to the kernel command. To pass the config file, there are two options: by providing it on the ISO or by serving it from an HTTP server.

The syntax to pass the config-file to the kernel through the ISO takes the following form:

ks=cdrom:/<config_file_path>

Here is an example:

ks=cdrom:/isolinux/my_ks.cfg

The syntax to serve the config-file to the kernel from a HTTPS server takes the following form:

ks=https://<server>/<config_file_path>

To use HTTP path or self-signed HTTPS path, you have to enable insecure_installation by using insecure_installation=1 along with defining the ks path. The kernel command line argument, insecure_installation, acts as a flag that user can set to 1 to allow some operations that are not normally allowed due to security concerns. This is disabled by default and it is up to the user to the ensure security when this options is enabled.

  • For HTTP: ks=http://<server>/<config_file_path> insecure_installation=1

  • For HTTPS (self-signed): ks=https://<server>/<config_file_path> insecure_installation=1

Building an ISO with a Kickstart Config File

Here’s an example of how to add a kickstart config file to the Photon OS ISO by mounting the ISO on an Ubuntu machine and then rebuilding the ISO. The following example assumes you can adapt the sample kickstart configuration file that comes with the Photon OS ISO to your needs. You can obtain the Photon OS ISO for free from VMware at the following URL:

https://packages.vmware.com/photon

Once you have the ISO, mount it.

mkdir /tmp/photon-iso
sudo mount photon.iso /tmp/photon-iso

Then copy the content of the ISO to a writable directory and push it into the directory stack:

mkdir /tmp/photon-ks-iso
cp -r /tmp/photon-iso/* /tmp/photon-ks-iso/
pushd /tmp/photon-ks-iso/

Next, copy the sample kickstart configuration file that comes with the Photon OS ISO and modify it to suit your needs. In the ISO, the sample kickstart config file appears in the isolinux directory and is named sample_ks.cfg. The name of the directory and the name of the file might be in all uppercase letters.

cp isolinux/sample_ks.cfg isolinux/my_ks.cfg
nano isolinux/my_ks.cfg

With a copy of the sample kickstart config file open in nano, make the changes that you want.

Now add a new item to the installation menu by modifying isolinux/menu.cfg:

cat >> isolinux/menu.cfg << EOF
label my_unattended
	menu label ^My Unattended Install
	menu default
	kernel vmlinuz
	append initrd=initrd.img root=/dev/ram0 loglevel=3 photon.media=cdrom
EOF

Finally, rebuild the ISO so that it includes your kickstart config file:

mkisofs -R -l -L -D -b isolinux/isolinux.bin -c isolinux/boot.cat \
		-no-emul-boot -boot-load-size 4 -boot-info-table -V "PHOTON_$(date +%Y%m%d)" \
		. > <new_iso_path>.iso

popd
Last modified March 24, 2021: big docs v4 cleanup (80869a1a7)