Шаблоны операционных систем (шаблоны ОС) — наборы образов диска и скриптов установки, состоящие из дистрибутива и других необходимых для установки операционной системы данных. Используются для удобства установки операционных систем на серверы.

В статье описаны принципы создания собственного шаблона ОС.

Шаблон ОС представляет из себя XML-файл metainfo.xml и набор файлов для установки. В metainfo.xml описаны механизмы, которые будут использованы при установке.

Подготовленные нами шаблоны доступны в репозитории.

Для создания шаблона необходимо создать директорию [NFS-хранилище]/<НАЗВАНИЕ_ШАБЛОНА>. Внутри должен обязательно содержаться файл metainfo.xml с XML-описанием шаблона. Также в этой директории должны находиться все файлы, которые указаны в параметрах шаблона.

В описании шаблона необходимо добавить:

<date>2013-04-14 15:37:21</date>
<install_result>ok</install_result>
BASH

Данные строки являются флагом, который сигнализирует, что шаблон уже установлен. В примерах эти поля не указаны, т.к. описание представлено в формате, который используется для шаблонов в репозитории.

После проделанных действий шаблон отобразится в меню добавления шаблонов ОС. Его можно добавить и использовать. Все изменения, которые осуществляются в файлах шаблона, применяются сразу.

Принципы создания собственного репозитория шаблонов ОС см. в статье Создание собственного репозитория шаблонов ОС.

Список параметров


Параметры

  • <kernel>Имя файла</kernel> — ядро Linux;

  • <initrd>Имя файла</initrd> — initrd;

  • <kernelcommand>Параметры</kernelcommand> — параметры загрузки ядра. Пример:

<kernelcommand>lang=en_US keymap=us ks=($OSINSTALLINFO_HTTP) method=http://mirror.yandex.ru/centos/6/os/x86_64/ initrd=initrd ip=($IP) netmask=($NETMASK) gateway=($GATEWAY) dns=($NAMESERVER)</kernelcommand>
BASH
  • <installcfg>Имя файла</installcfg> — файл, который будет отдан при запросе по URL (макрос $OSINSTALLINFO_HTTP). В файле можно использовать макросы. Подробнее см. в статье Макросы шаблонов ОС;
  • <image>Имя файла</image> — ISO-образ, который будет примонтирован как CD-ROM;
  • <tempipv4>yes</tempipv4> — опция, которая в значении "yes" определяет, что требуется временный IPv4-адрес. используется при установке ОС с основным IPv6-адресом;
    <sharedir>Имя директории</sharedir> — директория внутри шаблона, файлы из которой будут доступны по HTTP-протоколу. Узнать ссылку можно с помощью макросов;
  • <support><elem version='5.1.0'>vmmgr</elem><elem>dcimgr</elem></support> — краткое наименование панелей управления, которые поддерживают шаблон. version — минимальная версия панели управления;
  • <illegal_password_characters>Запрещённые символы</illegal_password_characters> — символы которые запрещено использовать в пароле;
  • <sshpublickey>yes</sshpublickey> — опция поддержки добавления публичных SSH-ключей;
  • <up_mem_on_install>512</up_mem_on_install> — оперативная память, которую может использовать сервер при установке ОС. После установки количество памяти возвращается к основному значению;
  • <chpasswd_method>mount.linux</chpasswd_method> — метод смены пароля. Реализован метод mount.linux для linux-шаблонов;
  • <loaderefi64>pxelinux.efi</loaderefi64> — поддержка загрузки через UEFI;
  • <ipxeconf>ipxe.conf</ipxeconf> — конфигурационный файл для загрузки через iPXE;
  • <ipxeconf type="tftp"> — опция загрузки конфигурационного файла ipxe.conf по протоколу tftp. В конфигурационный файл dhcpd.conf добавляется строка вида "tftp://<адрес_панели_управления>/.../ipxe.conf".
Все пути в параметрах указываются относительно директории с шаблоном.

Примеры шаблонов


kickstart (CentOS, Fedora, RedHat)

Рекомендуется использовать для шаблонов ОС CentOS, Fedora, RedHat. Подробнее о технологии kickstart см. в статье Википедии. Она позволяет гибко настраивать параметры установки. Для загрузки указывается kernel и initrd, а в команде ядра ссылка на файл ответов.

metainfo.xml

<?xml version="1.0"?>
<doc>
  <osname>CentOS-6-amd64</osname>
  <support>
    <elem>VMmgr</elem>
    <elem>IFXmgr</elem>
  </support>
  <rebootcount>1</rebootcount>
  <kernel>vmlinuz</kernel>
  <initrd>initrd.img</initrd>
  <type>ostemplate</type>
  <loader>pxelinux.0</loader>
  <pxelinuxcfg>pxelinux.conf</pxelinuxcfg>
  <tempipv4>yes</tempipv4>
  <kernelcommand>lang=en_US keymap=us ks=($OSINSTALLINFO_HTTPv4) ksdevice=link method=http://mirror.yandex.ru/centos/6/os/x86_64/ ip=($IPv4) netmask=($NETMASKv4) gateway=($GATEWAYv4) dns=($NAMESERVERv4) roxy=($HTTPPROXYv4) text</kernelcommand>
  <installcfg>install.cfg</installcfg>
  <limit>
    <elem name="ipv4">yes</elem>
    <elem name="ipv6">yes</elem>
    <elem name="mem">512</elem>
    <elem name="disk">2000</elem>
  </limit>
 </doc>
BASH

install.cfg

%pre

#!/bin/sh

for disk in `ls -la /dev/sd?`; do
    dd if=/dev/zero of=$disk bs=512 count=32
done

SWSIZE=$(grep MemTotal /proc/meminfo  | awk '{print int($2/1024)+1}')
if [ ${SWSIZE} -gt 2048 ]; then
    SWSIZE=2048
fi

if [ `cat /proc/scsi/scsi | grep -wc ATA` -eq 2 ]; then
     set $(fdisk -l 2>/dev/null | grep -vi mapper | grep Disk | grep dev |  sed 's/://' | awk '{print $2}' | tr '\n' ' ')
     HD1=$1
    HD2=$2
    if [ -b ${HD2} ]; then
        SIZE1=$(fdisk -l "${HD1}"  2>/dev/null  | grep Disk | grep dev |  sed 's/://'|awk '{print $5}')
        SIZE2=$(fdisk -l "${HD2}"  2>/dev/null  | grep Disk | grep dev |  sed 's/://'|awk '{print $5}')
        if [ -n "${SIZE1}" ] && [ -n "${SIZE2}" ] && [ "${SIZE1}" = "${SIZE2}" ]; then
            USE_MIRROR=yes
        fi
    fi
fi

if [ -n "${USE_MIRROR}" ]; then
cat > /tmp/part-include << EOF
part raid.11 --size=256 --asprimary --ondisk=sda
part raid.12 --size=${SWSIZE} --asprimary --ondisk=sda 
part raid.13 --size=1 --grow --asprimary --ondisk=sda 
part raid.21 --size=256 --asprimary --ondisk=sdb
part raid.22 --size=${SWSIZE} --asprimary --ondisk=sdb 
part raid.23 --size=1 --grow --asprimary --ondisk=sdb
raid /boot --fstype ext4 --device md0 --level=RAID1 raid.11 raid.21
raid swap --fstype swap --device md1 --level=RAID1 raid.12 raid.22
raid / --fstype ext4 --device md2 --level=RAID1 raid.13 raid.23
EOF
else
cat > /tmp/part-include << EOF
part /boot --fstype ext4 --size=256 --asprimary --ondisk=sda
part swap --size=${SWSIZE} --asprimary --ondisk=sda
part / --fstype ext4 --size=1 --grow --asprimary --ondisk=sda
EOF
fi

%end
auth --useshadow --enablemd5
# Crete partition map
bootloader --location=mbr
zerombr
clearpart --all --initlabel
firstboot --disable
# Disk partitioning information
%include /tmp/part-include
# System keyboard
keyboard us
# System language
lang en_US.UTF-8
# Installation logging level
logging --level=info
# Use NFS installation media
url --url http://mirror.yandex.ru/centos/6/os/x86_64/
#Root password
rootpw ($PASS)
# SELinux configuration
selinux --disabled
# Text installation
text
# System timezone
timezone --utc Europe/Moscow

# Network
network --bootproto=static --ip=($IPv4) --netmask=($NETMASK)  --gateway=($GATEWAYv4) --nameserver=($NAMESERVERv4) --hostname=($HOSTNAME) --device=link

# Install OS instead of upgrade
install
%packages
@core
%end

%post
# Настройка сети
#echo "NETWORKING=yes" > /etc/sysconfig/network
#echo "HOSTNAME=($HOSTNAME)"
ETHDEV=$(ip route show | grep default | grep -Eo 'dev\ .+\ ' | awk '{print $2}')
HWADDR=$(cat /etc/sysconfig/network-scripts/ifcfg-eth0 | awk -F= '/HWADDR/ {print $2}' | sed 's/"//g')
UUID=$(cat /etc/sysconfig/network-scripts/ifcfg-eth0 | awk -F= '/UUID/ {print $2}' | sed 's/"//g')

if [ -n "($IPv6)" ]; then
cat > /etc/sysconfig/network << EOF
NETWORKING=yes
NETWORKING_IPV6=yes
HOSTNAME=($HOSTNAME)
IPV6_DEFAULTGW=($GATEWAY)
EOF

cat > /etc/sysconfig/network-scripts/ifcfg-${ETHDEV} << EOF
DEVICE="${ETHDEV}"
BOOTPROTO="static"
DNS1="($NAMESERVER)"
HWADDR="${HWADDR}"
IPV6ADDR="($IPv6)/($NETMASKv6)"
IPV6INIT="yes"
IPV6_AUTOCONF="no"
IPV6_DEFAULTGW="($GATEWAY)"
NM_CONTROLLED="yes"
ONBOOT="yes"
TYPE="Ethernet"
UUID="${UUID}"
EOF

fi
%end

%post --nochroot
wget -O /dev/null --no-check-certificate "($FINISHv4)"
# Reboot after installation
%end

reboot
BASH

FreeBSD 9

Установка производится за счёт модифицированного образа установочного диска. В основе лежит образ bootonly.iso. Модифицируется файл /etc/rc.local который загружается после загрузки ОС с диска.

Чтобы изменить настройки установленной системы (пароль, сеть, пакеты и т.п.) и при этом пользователям не приходилось самостоятельно модифицировать образ используется следующий механизм: к серверу присоединяется дополнительный диск, который представляет из себя shell-скрипт, увеличенный до 1 мегабайта. После запуска ОС с диска запускается rc.local, который считывает все данные со второго жесткого диска и кладет их в файл /tmp/install.sh После чего запускает install.sh. В install.sh могут быть описаны любые действия.

Шаблон ОС включает в себя скрипт install.sh. В скрипте можно использовать макросы, вместо которых DCImanager подставит значения.

metainfo.xml

<?xml version="1.0"?>
<doc>
  <osname>FreeBSD-9-amd64</osname>
  <support>
    <elem>VMmgr</elem>
    <elem>DCImgr</elem>
  </support>
  <image>freebsd.iso</image>
  <rebootcount>1</rebootcount>
  <type>ostemplate</type>
  <installdrive>freebsdinstall.sh</installdrive>
  <loader>pxelinux.0</loader>
  <pxelinuxcfg>pxelinux.conf</pxelinuxcfg>
  <installcfg>freebsdinstall.sh</installcfg>
  <initrd>freebsd.iso</initrd>
  <kernel>memdisk</kernel>
  <kernelcommand>iso raw</kernelcommand>
  <limit>
    <elem name="ipv4">yes</elem>
    <elem name="ipv6">yes</elem>
    <elem name="mem">512</elem>
    <elem name="disk">1500</elem>
  </limit>
</doc>
BASH

freebsdinstall.sh

#!/bin/sh

WGET="fetch -o- -q "

if [ "$START_BSD_INSTALL" != "yes" ]; then
export START_BSD_INSTALL="yes"
bsdinstall ../../../$0

exit 0
fi

clear
echo "Begin Installation at $(date)" | tee -a $BSDINSTALL_LOG

2>>$BSDINSTALL_LOG

error() {
	${WGET} "($FAILURL)?error=$1"
	exit 1
} 

rm -rf $BSDINSTALL_TMPETC
mkdir $BSDINSTALL_TMPETC

echo "Setting hostname..."
HOSTNAME=($HOSTNAME)
echo "hostname=\"$HOSTNAME\"" > $BSDINSTALL_TMPETC/rc.conf.hostname
hostname -s "$HOSTNAME"

echo "Configuring interfaces"
echo "Detecting..."
INTERFACES="${IFACE}"
if [ -z "${INTERFACES}" ]; then
	for IF in `ifconfig -l`; do
       test "$IF" = "lo0" && continue
       INTERFACES="$IF"
	done
fi
if [ -z "$INTERFACES" ]; then
       dialog --backtitle 'FreeBSD Installer' \
           --title 'Network Configuration Error' \
           --msgbox 'No network interfaces present to configure.' 0 0
       exit 1
fi

if [ -n "($IPv6)" ]; then
	echo "Configuring IPv6"
	export http_proxy="($HTTPPROXYv6)"
	export HTTP_PROXY="($HTTPPROXYv6)"
	ifconfig $INTERFACES inet6 ($IPv6) prefixlen ($NETMASKv6)
	route add -inet6 default ($GATEWAYv6)
	echo "nameserver ($NAMESERVERv6)" >> /etc/resolv.conf

	cat >> $BSDINSTALL_TMPETC/rc.conf.network << EOF
ipv6_defaultrouter="($GATEWAYv6)"
ifconfig_${INTERFACES}_ipv6="inet6 ($IPv6) prefixlen ($NETMASKv6)" 
sshd_enable="YES"
ipv6_all_interfaces="YES"
EOF
	echo "nameserver ($NAMESERVERv6)" >> $BSDINSTALL_TMPETC/resolv.conf
elif [ -n "($IPv4)" ]; then
	echo "Configuring IPv4"
	export http_proxy="($HTTPPROXYv4)"
	export HTTP_PROXY="($HTTPPROXYv4)"
	ifconfig $INTERFACES inet ($IPv4) netmask ($NETMASKv4)
	route add default ($GATEWAYv4)
	echo "nameserver ($NAMESERVERv4)" >> /etc/resolv.conf
	echo "name_servers=($NAMESERVERv4)" >> /etc/resolvconf.conf

	cat >> $BSDINSTALL_TMPETC/rc.conf.network << EOF
defaultrouter="($GATEWAYv4)"
ifconfig_${INTERFACES}="inet ($IPv4) netmask ($NETMASKv4)" 
sshd_enable="YES"
EOF

	echo "nameserver ($NAMESERVERv4)" >> $BSDINSTALL_TMPETC/resolv.conf
fi
sleep 5

echo "Setting files for download"
if [ "#$(uname -m)" = "#amd64" ]; then
       export DISTRIBUTIONS="base.txz kernel.txz lib32.txz"
else
        export DISTRIBUTIONS="base.txz kernel.txz"
fi

FETCH_DISTRIBUTIONS=""
for dist in $DISTRIBUTIONS; do
       if [ ! -f $BSDINSTALL_DISTDIR/$dist ]; then
               FETCH_DISTRIBUTIONS="$FETCH_DISTRIBUTIONS $dist"
       fi
done
FETCH_DISTRIBUTIONS=`echo $FETCH_DISTRIBUTIONS` # Trim white space

MIRROR="http://mirror.yandex.ru/freebsd/snapshots"
BSDVER="9.1-STABLE"

BSDINSTALL_DISTSITE="$MIRROR/`uname -m`/`uname -p`/${BSDVER}"

export BSDINSTALL_DISTSITE


echo "Detecting disks"
rm $PATH_FSTAB
touch $PATH_FSTAB

DISKS=`/sbin/sysctl -n kern.disks`
if [ -n ${SKIP_HD} ]; then
	DISKS=$(echo ${DISKS} | sed "s/${SKIP_HD}[ ]\{0,\}//")
fi


HD=${HD:-empty}
if [ $HD = "empty" ]; then
 HD=`echo $DISKS | xargs -n1 echo | grep ar | sort -tr -k2 -n | head -1`
 if [ -z "$HD" ]; then
   HD=`echo $DISKS | xargs -n1 echo | grep ad | sort -td -k2 -n | head -1`
   if [ -z "$HD" ]; then
     HD=`echo $DISKS | xargs -n1 echo | grep da | sort -ta -k2 -n | head -1`
     if [ -z "$HD" ]; then
       HD=`echo $DISKS | /usr/bin/cut -d ' ' -f1`
       if [ -z "$HD" ]; then
         exit 1
       fi
     fi
   fi
 fi
else
 if [ ! -b /dev/$HD ]; then
   # Hard disk device with this name not found
   # Terminate install with error
   error "disknodetect"
 fi
fi

DISK_TYPE=$(echo ${HD} | sed -e 's/[0-9]\{1,\}.*$//g')
echo "Disk type: ${DISK_TYPE}"

if [ $(echo ${DISKS} | grep -Eo "${DISK_TYPE}[0-9]" | wc -l) -eq 2 ]; then
# Mirror
	HDDS=$(echo ${DISKS} | grep -Eo "${DISK_TYPE}[0-9]")
	echo "${HDDS}"
	set ${HDDS}
	HD1=$1
	HD2=$2
	echo "Disk1: ${HD1}"
	echo "Disk2: ${HD2}"
	SIZE1=$(grep -Eio "^${HD1}: [0-9]{1,}(mb|gb|tb|b) " /var/run/dmesg.boot | awk '{print $2}')
	SIZE2=$(grep -Eio "^${HD2}: [0-9]{1,}(mb|gb|tb|b) " /var/run/dmesg.boot | awk '{print $2}')

	grep -Eio "^${HD1}: [0-9]{1,}(mb|gb|tb|b) " /var/run/dmesg.boot
	echo "Disk1 size: ${SIZE1}"
	grep -Eio "^${HD2}: [0-9]{1,}(mb|gb|tb|b) " /var/run/dmesg.boot
	echo "Disk2 size: ${SIZE2}"

	if [ -n "${SIZE1}" ] && [ -n "${SIZE2}" ] && [ "${SIZE1}" = "${SIZE2}" ]; then
		echo "This is miroor system"
		GMIRROR=yes
	else
		echo "Disks size is differ"
		echo "This is single system"
		HDDS=${HD}
	fi
else
# single
	echo "This is single system"
	HDDS=${HD}
fi

#exec 1>&2
echo "Formatting disks"

clear_disks() {
	# $1 — disk
	# $2 — disk-label-ending
        gpart delete -i 2 $1
        gpart delete -i 3 $1
        gpart delete -i 4 $1
        gpart delete -i 5 $1
        gpart delete -i 6 $1
        echo "destroy" | tee -a $BSDINSTALL_LOG
        gpart destroy -F $1
        echo "create GPT" | tee -a $BSDINSTALL_LOG
        gpart create -s GPT $1
        echo "add boot" | tee -a $BSDINSTALL_LOG
        gpart add -t freebsd-boot -l gpboot$2 -s 256K $1
        echo "set bootcode" | tee -a $BSDINSTALL_LOG
        gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 $1
        echo "add swap" >> $BSDINSTALL_LOG
        SWSIZE=$(sysctl -n hw.realmem | awk '{print int($1/1024/1024)+1}')
		if [ ${SWSIZE} -gt 2048 ]; then
			SWSIZE=2048
		fi
        gpart add -t freebsd-swap -l swap$2 -s ${SWSIZE}M $1
        echo "add root" | tee -a $BSDINSTALL_LOG

        # calculating size (not neded now)
        #let "ROOT_PART = ($VOL_SIZE_M) — 1"
        #echo "$ROOT_PART"
        #gpart add -t freebsd-ufs -l rootfs -s "$ROOT_PART"M $HD
        gpart add -t freebsd-ufs -l rootfs$2 $1 

}

if [ -n "${GMIRROR}" ]; then
	clear_disks ${HD1} ${HD1}
	clear_disks ${HD2} ${HD2}
else
	clear_disks ${HD}
fi

if [ -n "${GMIRROR}" ]; then
	echo "Creating mirror"
	gmirror load
	gmirror label -v rootfs /dev/gpt/rootfs${HD1} /dev/gpt/rootfs${HD2}
	gmirror label -v swap /dev/gpt/swap${HD1} /dev/gpt/swap${HD2}

	echo "newfs root" | tee -a $BSDINSTALL_LOG
	newfs -U /dev/mirror/rootfs

	echo "mount" | tee -a $BSDINSTALL_LOG
	mount /dev/mirror/rootfs $BSDINSTALL_CHROOT

	echo "# Device Mountpoint FStype Options Dump Pass#" > $PATH_FSTAB
	echo "/dev/mirror/swap none swap sw 0 0"    >> $PATH_FSTAB
	echo "/dev/mirror/rootfs / ufs rw 1 1" >> $PATH_FSTAB
else

	echo "newfs root" | tee -a $BSDINSTALL_LOG
	newfs -U /dev/gpt/rootfs

	echo "mount" | tee -a $BSDINSTALL_LOG
	mount /dev/gpt/rootfs $BSDINSTALL_CHROOT

	echo "# Device Mountpoint FStype Options Dump Pass#" > $PATH_FSTAB
	echo "/dev/gpt/swap none swap sw 0 0"    >> $PATH_FSTAB
	echo "/dev/gpt/rootfs / ufs rw 1 1" >> $PATH_FSTAB
fi

if [ ! -z "$FETCH_DISTRIBUTIONS" ]; then
       ALL_DISTRIBUTIONS="$DISTRIBUTIONS"

       # Download to a directory in the new system as scratch space
       BSDINSTALL_FETCHDEST="$BSDINSTALL_CHROOT/usr/freebsd-dist"
       mkdir -p "$BSDINSTALL_FETCHDEST" || error

       export DISTRIBUTIONS="$FETCH_DISTRIBUTIONS"
       # Try to use any existing distfiles
       if [ -d $BSDINSTALL_DISTDIR ]; then
               DISTDIR_IS_UNIONFS=1
               mount_nullfs -o union "$BSDINSTALL_FETCHDEST" "$BSDINSTALL_DISTDIR"
       else
               export DISTRIBUTIONS="MANIFEST $ALL_DISTRIBUTIONS"
               export BSDINSTALL_DISTDIR="$BSDINSTALL_FETCHDEST"
       fi

       export FTP_PASSIVE_MODE=YES
       bsdinstall distfetch || error fetch
       export DISTRIBUTIONS="$ALL_DISTRIBUTIONS"
        clear
fi

bsdinstall checksum || error checksummincorrect
bsdinstall distextract || error distextractfail
clear

echo "Setting password"
PASSWORD="($PASS)"

echo $PASSWORD | pw -V "$BSDINSTALL_CHROOT/etc" usermod root -h0

echo "Configuring services"
echo "PermitRootLogin yes" >> "$BSDINSTALL_CHROOT/etc/ssh/sshd_config"

#echo sshd_enable=\"YES\" >> $BSDINSTALL_TMPETC/rc.conf.services
echo dumpdev=\"AUTO\" >> $BSDINSTALL_TMPETC/rc.conf.services

if [ -n "${GMIRROR}" ]; then
	echo geom_mirror_load="YES" >> $BSDINSTALL_CHROOT/boot/loader.conf
fi

echo "Installing configs"
bsdinstall config  || error

echo "Installing vim"
chroot $BSDINSTALL_CHROOT pkg_add -r vim-lite
sed -i "" -E 's/EDITOR(.*)vi/EDITOR\1vim/g' $BSDINSTALL_CHROOT/root/.cshrc
cat >> $BSDINSTALL_CHROOT/root/.vimrc << EOF
set nocompatible
set encoding=utf8mb4
syntax on
EOF

cp $BSDINSTALL_LOG $BSDINSTALL_CHROOT/root/
dmesg > $BSDINSTALL_CHROOT/root/dmesg
if [ ! -z "$BSDINSTALL_FETCHDEST" ]; then
       [ "$BSDINSTALL_FETCHDEST" != "$BSDINSTALL_DISTDIR" ] && \
           umount "$BSDINSTALL_DISTDIR"
       rm -rf "$BSDINSTALL_FETCHDEST"
fi

echo "Installation complete"
$WGET "($FINISH)"

echo "Installation Completed at $(date)" | tee -a $BSDINSTALL_LOG
cp $BSDINSTALL_LOG $BSDINSTALL_CHROOT/root

BASH


preseed (Debian, Ubuntu)

Рекомендуется использовать для шаблонов ОС Debian, Ubuntu.

<?xml version="1.0"?>
<doc>
  <osname>Debian-7-amd64</osname>
  <support>
    <elem>IFXmgr</elem>
    <elem>VMmgr</elem>
  </support>
  <rebootcount>1</rebootcount>
  <kernel>linux</kernel>
  <initrd>initrd.gz</initrd>
  <type>ostemplate</type>
  <loader>pxelinux.0</loader>
  <pxelinuxcfg>pxelinux.conf</pxelinuxcfg>
  <tempipv4>yes</tempipv4>
  <kernelcommand>url=($OSINSTALLINFO_HTTPv4) language=en debian-installer/country=RU locale=en_US keyboard-configuration/xkb-keymap=us console-keymaps-at/keymap=us interface=auto netcfg/disable_dhcp=true netcfg/get_ipaddress=($IPv4) netcfg/get_netmask=($NETMASKv4) netcfg/get_gateway=($GATEWAYv4) netcfg/get_nameservers=($NAMESERVERv4) hostname=($HOSTNAME) domain=($HOSTNAME)</kernelcommand>
  <installcfg>install.cfg</installcfg>
  <limit>
    <elem name="ipv4">yes</elem>
    <elem name="ipv6">yes</elem>
    <elem name="mem">512</elem>
    <elem name="disk">1000</elem>
  </limit>
</doc>

BASH


install.cfg

d-i keyboard-configuration/xkb-keymap select us

# Mirrors
#d-i mirror/protocol string ftp
#d-i mirror/country string manual
#d-i mirror/ftp/hostname string ftp.ru.debian.org
#d-i mirror/ftp/directory string /debian
#d-i mirror/ftp/proxy string
d-i mirror/country string manual
d-i mirror/http/hostname string mirror.yandex.ru
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string ($HTTPPROXYv4)

d-i passwd/make-user boolean false

d-i passwd/root-password password ($PASS)
d-i passwd/root-password-again password ($PASS)

d-i clock-setup/utc boolean true

d-i time/zone string Europe/Moscow

d-i preseed/early_command string \
	anna-install parted-udeb 

# Partitioning
d-i partman/early_command string \
for DISK in $(list-devices disk); do \
    dd if=/dev/zero of=${DISK} bs=512 count=1; \
    parted -s ${DISK} mklabel gpt; \
done; \
set $(list-devices disk); \
let numb=$#/2; \
DISKA=$1; \
DISKB=$2; \
if [ -b "${DISKB}" ]; then \
    SIZE1=$(fdisk -l "${DISKA}" 2>/dev/null|grep Disk|grep dev|cut -d' ' -f5); \
    SIZE2=$(fdisk -l "${DISKB}" 2>/dev/null|grep Disk|grep dev|cut -d' ' -f5); \
	if [ -n ${SIZE1} ] && [ -n ${SIZE2} ] && [ "${SIZE1}" = "${SIZE2}" ]; then \
	    USE_MIRROR=yes; \
	else \
	    USE_MIRROR=no; \
	fi; \
fi; \
if [ "#${USE_MIRROR}" = "#yes" ]; then \
	debconf-set partman-auto/disk "$DISKA $DISKB";\
	debconf-set partman-auto/method "raid";\
	debconf-set partman-auto/expert_recipe "multiraid :: \  100 50 100 raid $primary{ } method{ raid } . \  128 512 100% raid method{ raid } . \  1024 10000 1000000000 raid method{ raid } . ";\
	debconf-set partman-auto-raid/recipe "1 2 0 ext2 /boot ${DISKA}1#${DISKB}1 . \  1 2 0 swap — ${DISKA}5#${DISKB}5 . \  1 2 0 ext4 / ${DISKA}6#${DISKB}6 . ";\
	debconf-set grub-installer/bootdev "$DISKA $DISKB";\
else \
	debconf-set partman-auto/disk "$DISKA";\
	debconf-set partman-auto/method "regular";\
	debconf-set partman-auto/expert_recipe "boot-root :: \  100 50 100 ext2 $primary{ } $bootable{ } method{ format } format{ } use_filesystem{ } filesystem{ ext2 } mountpoint{ /boot } . \  128 512 100% linux-swap method{ swap } format{ } . \  1024 10000 1000000000 ext4 method{ format } format{ } use_filesystem{ } filesystem{ ext4 } mountpoint{ / } . ";\
	debconf-set grub-installer/bootdev "$DISKA";\
fi 


#d-i partman-auto/method string regular

#d-i partman-auto/expert_recipe string \
# boot-root :: \
# 40 50 100 ext2 \
# $primary{ } $bootable{ } \
# method{ format } format{ } \
# use_filesystem{ } filesystem{ ext2 } \
# mountpoint{ /boot } \
# . \
# 500 10000 1000000000 ext4 \
# method{ format } format{ } \
# use_filesystem{ } filesystem{ ext4 } \
# mountpoint{ / } \
# . \
# 64 512 300% linux-swap \
# method{ swap } format{ } \
# .

# Force overwrite partitions

d-i partman-partitioning/choose_label       select gpt
d-i partman-partitioning/confirm_new_label  boolean true
d-i partman-partitioning/unknown_label  boolean true
d-i partman/exception_handler   select  Yes
partman-partitioning    partman-partitioning/choose_label       select gpt
partman-partitioning    partman-partitioning/confirm_new_label  boolean true
partman-partitioning    partman-partitioning/unknown_label  boolean true
partman-base    partman/exception_handler   select  Yes

d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-lvm/device_remove_lvm boolean true 
d-i partman-md/device_remove_md boolean true
d-i partman-md/confirm boolean true
d-i partman-md/confirm_nooverwrite boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true

d-i partman/mount_style select traditional

# Apt

#d-i base-installer/install-recommends boolean true

#d-i base-installer/kernel/linux/initramfs-generators string initramfs-tools
#d-i base-installer/kernel/image string linux-image-amd64

d-i apt-setup/contrib boolean true
#d-i apt-setup/use_mirror boolean true

# Packages
d-i apt-setup/services-select multiselect security, volatile
tasksel tasksel/first multiselect standard
d-i pkgsel/include string openssh-server vim wget

popularity-contest popularity-contest/participate boolean false

# Grub
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true

d-i finish-install/keep-consoles boolean true

d-i preseed/late_command string \
	in-target rm -f /etc/apt/apt.conf ;\
	ETHDEV=$(ip route show | grep default | grep -Eo 'dev\ .+\ ' | cut -d' ' -f2) ;\
	if [ -n "($IPv6)" ]; then \
		echo "# The loopback network interface" > /target/etc/network/interfaces ;\
		echo "auto lo" >> /target/etc/network/interfaces ;\
		echo "iface lo inet loopback" >> /target/etc/network/interfaces ;\
		echo "" >> /target/etc/network/interfaces ;\
		echo "# The primary network interface" >> /target/etc/network/interfaces ;\
		echo "allow-hotplug ${ETHDEV}" >> /target/etc/network/interfaces ;\
		echo "iface ${ETHDEV} inet6 static" >> /target/etc/network/interfaces ;\
		echo -e "\taddress ($IPv6)" >> /target/etc/network/interfaces ;\
		echo -e "\tnetmask ($NETMASKv6)" >> /target/etc/network/interfaces ;\
		echo -e "\tgateway ($GATEWAYv6)" >> /target/etc/network/interfaces ;\
		echo -e "\tdns-nameservers ($NAMESERVERv6)" >> /target/etc/network/interfaces ;\
		echo "nameserver ($NAMESERVERv6)" > /target/etc/resolv.conf ;\
		sed -i "s/($IPv4)/($IPv6)/" /etc/hosts ;\
		sed -i "s/($IPv4)/($IPv6)/" /target/etc/hosts ;\
		echo "# The loopback network interface" > /etc/network/interfaces ;\
		echo "auto lo" >> /etc/network/interfaces ;\
		echo "iface lo inet loopback" >> /etc/network/interfaces ;\
		echo "" >> /etc/network/interfaces ;\
		echo "# The primary network interface" >> /etc/network/interfaces ;\
		echo "allow-hotplug ${ETHDEV}" >> /etc/network/interfaces ;\
		echo "iface ${ETHDEV} inet6 static" >> /etc/network/interfaces ;\
		echo -e "\taddress ($IPv6)" >> /etc/network/interfaces ;\
		echo -e "\tnetmask ($NETMASKv6)" >> /etc/network/interfaces ;\
		echo -e "\tgateway ($GATEWAYv6)" >> /etc/network/interfaces ;\
		echo -e "\tdns-nameservers ($NAMESERVERv6)" >> /etc/network/interfaces ;\
		echo "nameserver ($NAMESERVERv6)" > /etc/resolv.conf ;\
	fi ;\
	in-target wget --no-check-certificate "($FINISHv4)"

d-i finish-install/reboot_in_progress note
BASH