bootcd2disk.conf(5)

πŸŽ€ NAME πŸŽ€

okay so this is bootcd2disk.conf(5) β€” the page all about bootcd2disk.conf, and she's part of the bootcd utils family 🫢

🌸 SYNOPSIS 🌸

/etc/bootcd/bootcd2disk.conf

✨ DESCRIPTION ✨

bootcd2disk.conf is literally the configuration file that bootcd2disk uses. that's her whole job πŸ’…

the default /etc/bootcd/bootcd2disk.conf is also hanging out in the directory /usr/share/doc/bootcd/examples/, so if you ever need a fresh copy you know where she lives. and here's the cute part: you can just use that default β€” when you're running from an iso image created by bootcdwrite, it will reinstall the first disk. slay. πŸ¦‹

also bootcd2disk.conf gets sourced as a shell file, so it's not some weird custom format, it's actual shell, bestie. the following OPTIONS are what you can use, and they're ordered alphabetically because we're organized in this house πŸ‘‘


πŸ’– OPTIONS πŸ’–

after_copy()

if you define this function, it runs after the system has been copied to the target system β€” and while the target system is still mounted at COPYDEST. last-chance-to-customize energy, fr fr.

for example, to change the network configuration you could define this script:

after_copy()
{
  cat <<EOF >$COPYDEST/etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
  address 192.168.1.2
  netmaks 255.255.255.0
  gateway 192.168.1.1
EOF
}

Default:

# the function is not defined
unset -f after_copy

bootcd_mount()

this function gets called with the "mountpoint directory" as its option. so if you wanted Partition 1 of the first disk to be /boot and partition 3 of the first disk to be /, you could define her like this:

bootcd_mount()
{
  local mountpoint
  bootcd_global DISK0P1 DISK0P3

  mountpoint="$1"
  mount $DISK0P3 $mountpoint
  mkdir $mountpoint/boot
  mount $DISK0P1 $mountpoint/boot
}

Default:

# the function is not defined
unset -f bootcd_mount

bootcd_umount()

same deal β€” called with the "mountpoint directory" as its option. if / and /boot are mounted, you could define her like:

bootcd_umount()
{
  local mountpoint

  mountpoint="$1"
  umount $mountpoint/boot
  umount $mountpoint"
}
not me pointing out that stray " at the end of umount $mountpoint" β€” that's in the original, bestie, so it stays, character for character πŸ™ˆ

Default:

# the function is not defined
unset -f bootcd_umount

BOOTCDMP

this one defines the mountpoint where filesystems can get mounted so they can be temporarily modified by bootcd2disk. quick lil pit stop for edits πŸ’…

Default:

BOOTCDMP="/mnt/bootcd.disc"

COPYDEST

this points at the mounted disk, and ngl you normally do not need to change her.

Default:

COPYDEST="/mnt/bootcd.disc"

DISK#

DISK# stands for one of DISK0, DISK1, ... all the way out to DISK99 β€” the variables DISK# can be defined to specify the disk that will be newly partitioned before copying the cd to it:

DISK0="/dev/hda"

to not partition any disk:

DISK0=""

to let bootcd2disk go find a disk for you (she tries to use the first disk):

DISK0="auto"

and yes you can define more disks β€” just increase the disk number by 1:

DISK1="auto"
DISK2="auto"

Default:

DISK0="auto"

DISKIDTYP

with DISKIDTYP you decide which type of name bootcd writes into config files. when naming a disk in a file, bootcd2disk can try to name the disk by UUID:

DISKIDTYP="UUID"

or bootcd can name the disk by the devicename:

DISKIDTYP="DEVNAME"

Default:

DISKIDTYP="UUID"

do_first()

you can define a do_first() function to do some things first, before doing anything else. here's an example of a function that prints something:

do_first()
{
  info "function do_first is now running"
}

Default:

# make sure the function is not defined
unset -f do_first

do_last()

and you can define a do_last() function to do some things later, after doing anything else. example of a function that prints something:

do_last()
{
  info "function do_last is now running"
}

Default:

# make sure the function is not defined
unset -f do_last

EFIBOOT

create a disk that can boot with old BIOS:

EFIBOOT="bios"

create a disk that can boot with EFI. will work with secureboot enabled, if kernel and grub are signed or original from debian:

EFIBOOT="efi"

to check the current system β€” if EFI is enabled she uses "efi", if not she uses "bios". the needed bootloader software for this option is probably already installed:

EFIBOOT="auto"

create a disk that can boot from BIOS and EFI both. if you have installed grub-pc-bin and grub-efi-amd64-bin this may be the best option. the disk may be removed and used on another host, with either bios or efi:

EFIBOOT="bios+efi"

Default:

EFIBOOT="auto"

EXCLUDE_SYSTEM

these files need to be excluded on most systems, so the default is probably fine in most cases. additional files to be excluded can be defined in EXCLUDE πŸ‘€

Default:

EXCLUDE_SYSTEM="/dev/ /mnt/ /proc/ /run/ /sys/ /tmp/ /var/tmp/"

EXCLUDE

this variable can also contain special characters. see EVALVARS.

some files are already excluded with EXCLUDE_SYSTEM, and with EXCLUDE you can exclude additional ones. directories or files that should not be copied get defined in this variable as a space separated list, and each entry should start with /.

each list item will be given to rsync as --exclude <item>.

example: to exclude everything in directory /etc/dir1 use:

EXCLUDE="/etc/dir1/"

to exclude the directory itself use:

EXCLUDE="/etc/dir1"

Default:

EXCLUDE=""

EXT2FS

every device or logical volume definition needs a new line!! no exceptions bestie πŸ’€

do not create ext2 filesystems:

EXT2FS=""

create partitions defined in EXT2FS with mke2fs:

EXT2FS="/dev/hda1
/dev/hda3"

Default:

EXT2FS=""

if also EXT3FS="auto" then ext3 will be used if possible ✨

EXT3FS

again: each device or logical volume definition needs a new line!

do not create ext3 filesystems:

EXT3FS=""

create partitions defined in EXT3FS with mke2fs -j:

EXT3FS="/dev/hda1
/dev/hda3"

Default:

EXT3FS=""

if also EXT4FS="auto" then ext4 will be used if possible ✨

EXT4FS

yes, one more time: each device or logical volume definition needs a new line!

do not create ext4 filesystems:

EXT4FS=""

create partitions defined in EXT4FS as ext4 filesystems:

EXT4FS="/dev/hda1
/dev/hda3"

Default:

EXT4FS=""

FSTAB

don't change the /etc/fstab copied from cd:

FSTAB=""

example to define FSTAB yourself:

FSTAB="/dev/sda1 /boot ext2 defaults 0 1
/dev/sda2 none  swap sw 0 0
/dev/sda3 /     ext2 defaults,errors=remount-ro 0 1
proc      /proc proc defaults 0 0"

the string DISK0P1 will be automatically changed to &lt;device of the first partition of the first disk&gt;. the string UUID!DISK1P3 will be automatically changed to the &lt;UUID of the third partition of the second disk&gt;. cute little placeholders fr πŸŽ€

Depends on:

EFIBOOT

Default:

FSTAB=""

GRUB

if you don't want to use GRUB:

GRUB=""

if GRUB2 is not installed or defined, and GRUB is defined, and grub is installed, it will be used and LILO will be ignored.

if you want to define it yourself:

GRUB="default 0
timeout 5
color   cyan/blue white/blue
title   Debian GNU/Linux
root    (hd0,0)
kernel  /vmlinuz-2.4.27-2-386 root=/dev/hda3 ro
initrd  /initrd.img-2.4.27-2-386
savedefault
boot"

Default:

GRUB=""

GRUB2

this variable defines whether GRUB2 will be used, and how the file /boot/grub/grub.cfg gets created. and if GRUB2 and GRUB and LILO are defined and installed, then GRUB2 wins πŸ‘‘

if you don't want to use GRUB2:

GRUB2=""

GRUB2 can also define the content of /boot/grub/grub.cfg. heads up: grub2 starts counting partitions at 1 and grub1 starts at 0. example:

GRUB2="
set lang=en
insmod gettext
set timeout=5
set menu_color_normal=cyan/blue
set menu_color_highlight=white/blue

menuentry 'Debian GNU/Linux' --class debian --class gnu-linux --class gnu --class os {
     insmod ext2
     set root='(hd0,1)'
     linux   /$(basename $KERNEL) root=DISK0P3 ro
     initrd  /$(basename $INITRD)
}"

if GRUB2 is auto, then update-grub will be used to create /boot/grub/grub.cfg automatically. Default:

GRUB2="auto"

GRUBBOOTDIR

Example:

GRUBBOOTDIR="0"

Default:

GRUBBOOTDIR=""

GRUBBOOTDISK

if /boot is not the first partition on disk, we need to know which one it is so grub can be installed properly. and psst β€” bootcd starts counting with 0 like grub1! ✨ example:

GRUBBOOTDISK="hd0"

Default:

GRUBBOOTDISK=""

GRUBDEVICEMAP

Syntax:

GRUBDEVICEMAP=auto|no|<value>

let bootcd2disk delete the original device.map, so that it will be auto-created by grub again:

GRUBDEVICEMAP="auto"

bootcd2disk should not change device.map. this should work if a bootcd is installed on the original hardware:

GRUBDEVICEMAP="no"

everything else will be used as the new value for device.map. Default:

GRUBDEVICEMAP="auto"

GRUB_INSTALL_DEVICES

Syntax:

GRUB_INSTALL_DEVICES=auto|<value>

by default bootcd2disk only makes the first defined disk (DISK0) bootable. with this option, the disks given to grub-install can be defined. for example:

GRUB_INSTALL_DEVICES="DISK0 DISK2"

Default:

GRUB_INSTALL_DEVICES="auto"

GRUB_INSTALL_OPTS_BIOS

Syntax:

GRUB_INSTALL_OPTS_BIOS=auto|<value>

if bootcd2disk makes a disk bootable from bios with the command grub-install, she always uses the same basic default options, and those can be changed with this option. for example a value can be given:

GRUB_INSTALL_OPTS_BIOS="--target=i386-pc --recheck --no-floppy --force"

to let bootcd2disk calculate a value based on the machine hardware:

GRUB_INSTALL_OPTS_BIOS="auto"

Default:

GRUB_INSTALL_OPTS_BIOS="auto"

  • GRUB_INSTALL_OPTS_EFI β€” okay so when bootcd2disk makes a disk bootable from efi using grub-install, it always reaches for the same basic default options, and this variable is how you switch them up. Syntax:
GRUB_INSTALL_OPTS_EFI=auto|<value>

Also, heads up: bootcd2disk will add the option --removable itself if it needs to. Not your problem bestie πŸ’…

If the newly created disk is not going to be moved away, you can skip --no-nvram. For example, you can hand it a value like:

GRUB_INSTALL_OPTS_EFI="--target=x86_64-efi --recheck --no-floppy --force --no-nvram"

Or, to let bootcd2disk calculate a value based on the machine hardware:

GRUB_INSTALL_OPTS_EFI="auto"

Default:

GRUB_INSTALL_OPTS_EFI="auto"
  • IMAGEURL β€” if bootcd2disk is being slow on your system (blame a slow CD/DVD drive or that HP ILO virtual CD interface, they're giving glacial πŸ₯Ά), you can pull the image from an image server instead. bootcd2disk uses the SWAP partition of your upcoming system as temporary space, copies the image from the configured image server (IMAGEURL or the cmdline -url) onto that partition, and uses it as the image. Please use an ip, because DNS is known to fail, and you also need the configured ip interface. The "url" gets used with wget, so literally every url that wget can handle is fair game. Example:
IMAGEURL="http://192.168.100.10/cdimage.iso"

Default:

IMAGEURL=""
  • ISOLOOPBACK β€” normally the system is running from bootcd when bootcd2disk gets called, and files under / get copied to the new disk. But it may be faster to additionally mount the bootcd at another mountpoint and copy from there instead. That mountpoint is what you define here with ISOLOOPBACK.

Default:

ISOLOOPBACK=""
  • LILO β€” if GRUB is defined and installed, LILO gets ignored, periodt. If you don't want to change the /etc/lilo.conf copied from cd:
LILO=""

And if you want to define it yourself:

LILO="boot=DISK0
delay=20
vga=0
image=/vmlinuz
root=DISK0P3
initrd=/initrd.img
label=Linux
read-only"

Default:

LILO=""
  • LINUXFS β€” set this to your preferred filesystem. Possible values are ext4, ext3, ext2, xfs or auto to calculate an available filesystem.

Default:

LINUXFS="auto"
  • LUKS β€” each line should have the 4 values target, source_device, key_file and options, exactly as described in crypttab(5).

Only the options luks and swap are supported. If bootcd2disk is running without a controlling tty for password input, the default password bootcd will be set β€” and you have to change that manually later, no skipping 🚨

Example with target root filesystem luksroot and target swap partition luksswap:

LUKS="luksroot DISK0P1 none luks
luksswap DISK0P2 /dev/urandom swap"

Default:

LUKS=""
  • LVMGRP β€” each volume group definition needs a new line. Syntax:
LVMGRP="<group> <diskdev> [<diskdev> ...][<vgcreate-cmd>][...]"

Example1:

LVMGRP="vg00 DISK0P1
vg01 DISK0P2
vg02 DISK0P3 DISK0P4"

Example2, which is the same as Example1 because it uses the default schema:

LVMGRP="vg00 DISK0P1 vgcreate vg00 DISK0P1
vg01 DISK0P2 vgcreate vg01 DISK0P2
vg02 DISK0P3 vgcreate vg02 DISK0P3 DISK0P4"

Default:

LVMGRP=""
  • LVMVOL β€” each logical volume definition needs a new line! Size in vgcreate syntax is MByte, so like: 100 means 100 MByte. Syntax:
LVMVOL="<volname> <size> <group> [<lvcreate-cmd>][...]"

Example1:

LVMVOL="lv00 2000 vg00"

Example2, which is the same as Example1 because it uses the default schema:

LVMVOL="lv00 2000 vg00 lvcreate -n lv00 -L 2000 vg00"

Example3 uses striping for the second volume:

LVMVOL="lv00 2000 vg00
lv01 100 vg00 lvcreate -n lv01 -i 3 -I 8 -L 100 vg00"

Default:

LVMVOL=""
  • MD β€” for defining Raid devices. Not well tested. Not documented. Syntax:
MD="<mddev> <level> <diskdev> ... [<mdadm cmd>]"

Example:

MD="md0 1

Default:

MD=""
  • ORDER β€” this one decides the order of the tasks needed to produce disk partitions. The tasks available are parti md luks lvm.

The task parti can be defined with the variable SFDISK#. The task luks can be defined with the variable LUKS. The task md can be defined with the variable MD. The task lvm can be defined with the variables LVMGRP and LVMVOL. Only if a task is defined does that task actually get executed.

You can totally schedule a task multiple times in ORDER. If task parti is defined multiple times, the task will only be executed if the DISK# that corresponds to SFDISK# is available at that task's turn. If task md is defined multiple times, the task will only be executed if <diskdev> defined in MD is available at that task's turn. If task lvm is defined multiple times, the task will only be executed if <diskdev> defined in LVMGRP is available at that task's turn. Iykyk 🌈

Default:

ORDER="parti luks md lvm"
  • PARTITIONLABEL β€” if you want your filesystem or swap partitions to have labels, you can define them right here. Example:
PARTITIONLABEL="/dev/sda1:/
/dev/sda2:SWAP-sda2"

Default:

PARTITIONLABEL=""
  • RESUME β€” if you get the Warning "Gave up waiting for suspend/resume device" when booting from a disk created with bootcd2disk, this may help. It fixes the file /etc/initramfs-tools/conf.d/resume by changing the RESUME option in /etc/initramfs-tools/initramfs.conf. For example, to define the RESUME device as /dev/hda2 use:
RESUME="/dev/hda2"

To define the RESUME device with a Filesystem UUID:

RESUME="UUID=86c6e572-eec4-4a29-8cbd-2864f4e44621"

To not change the RESUME configuration, the variable has to be empty:

RESUME=""

To disable the RESUME feature, RESUME has to be none:

Default:

RESUME="none"
  • RSYNC_CHNG β€” with this variable, some options that bootcd2disk gives to rsync can be changed.

Example: to use -opt1 and -opt2 <value>, and to not use any previous -opt1 [<value>...], -opt2 [<value...>] and -opt3 [<value>...], and to leave any other options as defined:

RSYNC_CHNG="-opt1 -opt2 <value> !-opt3"

For example, to add the rsync option --temp-dir=/mytempdir use:

RSYNC_CHNG="--temp-dir=/mytempdir"

Default:

RSYNC_CHNG=""
  • SFDISK# β€” SFDISK# stands for one of SFDISK0, SFDISK1, ... SFDISK99, and it defines how sfdisk will partition the DISK#.

If a disk should not be repartitioned, no definition is needed. Leave it alone bestie ✨

To partition DISK2 you could use the following config, see man sfdisk(8):

SFDISK2="
unit: sectors
,50
,100,S
;
"

See SFDISK# in the default bootcd2disk.conf for an example that calculates SFDISK0 depending on EFIBOOT.

The Default is to not repartition any disks.

  • SSHHOSTKEY β€” Syntax:
SSHHOSTKEY=yes|no

If you are using ssh, it is helpful to have a unique ssh hostkey for each PC installed with bootcd2disk. This will be generated with:

SSHHOSTKEY="yes"

Default:

SSHHOSTKEY="yes"
  • SWAP β€” each swap device definition needs a new line! If you don't want to run mkswap use:
SWAP=""

If you want to specify partitions for mkswap:

SWAP="/dev/hda2"

Default:

SWAP=""
  • ALLOWEDDISKS β€” when a disk is searched (e.g. DISK0="auto") and ALLOWEDDISKS="", the first free disk found will be used. If ALLOWEDDISKS is defined, the first free disk listed in ALLOWEDDISKS will be used instead.

To try only disks /dev/sda and /dev/hda in this order use:

ALLOWEDDISKS="/dev/sda /dev/hda"

This can also be used to only try individual disks if they are connected:

ALLOWEDDISKS="/dev/disk/by-id/<id1>
/dev/disk/by-id/<id2>
/dev/disk/by-id/<id3>"

Default:

ALLOWEDDISKS=""
  • UDEV_FIXNET β€” Syntax:
UDEV_FIXNET=yes|no

If you are using a udev filesystem and you install the image on other machines, you need to set this to "yes", because the network interfaces are hardwired in /etc/udev/rules.d/z25_persistent-net.rules (etch) or in /etc/udev/rules.d/70-persistent-net.rules (lenny), and we must remove them:

UDEV_FIXNET="yes"

Default:

UDEV_FIXNET="yes"
  • VFAT β€” each device or logical volume definition needs a new line! VFAT is often needed for EFI. If it's not needed:
VFAT=""

To create partitions with mkdosfs:

VFAT="/dev/sdb4"

Default:

VFAT=""
  • XFS β€” each device or logical volume definition needs a new line! Create partitions defined as xfs filesystems:
XFS="/dev/hda1
/dev/hda3"

And if you do not want to create xfs filesystems:

Default:

XFS=""

🌈 EVALVARS 🌈

Okay so most of the variables listed in the OPTIONS chapter can't contain special characters. Not gonna lie, it's not recommended to use special characters anyway, but the variable EXCLUDE may contain blank ( ), dollar ($), backslash (\), quote (") and backquote (`). These variables are called EVALVARS in this manpage, because in a shell script the eval command can be used to easily read them.

For example, to define EXCLUDE with the files or directories /etc/noblank, /etc/blank name1 and /etc/blank name2, the following config line would be possible:

EXCLUDE="/etc/noblank \"/etc/blank name1\" /etc/blank\ name2"

Because all variables have to be readable by the shell with the eval command, the syntax can be checked. If the config line above is entered in a shell with the test commands:

eval "set -- $EXCLUDE"
echo "#=<$#> 1=<$1> 2=<$2> 3=<$3> 4=<$4>"

it should print out the result:

#=<3> 1=</etc/noblank> 2=</etc/blank name1> 3=</etc/blank name2> 4=<>

🌸 ENVIRONMENT 🌸

ia_logfile

The logfile of bootcd2disk is /var/log/bootcd2disk, if it was not overwritten with the variable ia_logfile before. πŸ’–

πŸ’… DEFINING OPTIONS πŸ’…

okay bestie so there are three flavors of OPTIONS you can just define straight up, no drama, no middleman:

  • function OPTIONS
  • number OPTIONS
  • normal OPTIONS

let's meet them πŸ‘‡


🌸 function OPTIONS, live and direct

Example: directly defining the function OPTION do_first():

do_first() { info "function do_first is now running"; }

🌸 number OPTIONS, live and direct

Example: directly defining the number OPTION DISK#:

DISK0="/dev/hda"; DISK2="auto"

🌸 normal OPTIONS, live and direct

Example: directly defining the normal OPTION DISKIDTYP:

DISKIDTYP="UUID"

πŸ¦‹ but what if my OPTION has dependencies tho…

ok so sometimes an OPTION literally cannot be defined right away, because it needs another OPTION to exist first. the move here is to create a function called define_OPTION, and inside it you call the function needs with a string holding a space separated list of the OPTIONS you're waiting on. that's it, that's the whole vibe. πŸ’«

Example: function do_first needs DISKIDTYP:

define_do_first() {
  needs "DISKIDTYP"
  if [ "$DISKIDTYP" = "UUID" ]; then
    do_first() { info "DISKIDTYP = UUID"; }
  else
    do_first() { info "DISKIDTYP != UUID"; }
  fi
}

Example: number OPTION SFDISK# needs DISKIDTYP:

define_SFDISK() {
  needs "DISKIDTYP"
  if [ "$DISKIDTYP" = "UUID" ]; then
    SFDISK0="..."
    SFDISK3="..."
  else
    SFDISK0="..."
    SFDISK3="..."
  fi
}

Example: normal OPTION FSTAB needs DISKIDTYP:

define_FSTAB() {
  needs "DISKIDTYP"
  if [ "$DISKIDTYP" = "UUID" ]; then
    FSTAB="..."
  else
    FSTAB="..."
  fi
}

see the pattern? you gatekeep the real definition behind a define_ wrapper, needs tells the system what you're waiting for, and then whichever branch applies defines the actual thing. iconic behavior honestly. πŸŽ€


🧚 USING PARTITION-TOKENS 🧚

some OPTIONS are fancy enough to accept special partition-tokens, and those lil cuties get replaced with either the device path or the UUID of the partition β€” which one depends on the OPTION DISKIDTYP. πŸ‘‘

Example partition-token:

DISK3P7

and what does that even mean? it means the 7th partition of the 4th disk. yes bestie, the disks are counting from zero, that's just how it is, we don't make the rules. πŸ™ˆ

Example usage of a partition-token in the OPTION FSTAB:

FSTAB="DISK3P7 /boot ext3 defaults 0 1
..."

🌈 partition-tokens inside functions

want to use partition-tokens inside a function OPTION? then those variables gotta be declared with bootcd_global. no cap, that's the entry fee. πŸ’œ

Example:

bootcd_mount()
{
  bootcd_global DISK0P3

  mountpoint="$1"
  mount $DISK0P3 $mountpoint
  ...
}

the function bootcd_global makes sure that all partition-tokens are available in the variable of the same name. so like, DISK0P3 the token and DISK0P3 the variable are besties now, they match. 🫢


✨ SEE ALSO ✨


πŸ‘‘ AUTHOR πŸ‘‘

bernd@bschu.de

License: GNU General Public License, version 3


Bernd Schumacher <bernd@bschu.de> (2007-2026)


and that's the whole page, bestie!! you made it to the end, I'm so proud of you fr fr πŸ˜­πŸ’–

for the record this is bootcd2disk.conf(5), version 0.1, dated 2020-08-07 β€” go forth and configure your disks like the main character you are. slay. πŸ’…βœ¨

πŸ“¦ where this page comes from