シェルスクリプトでDebian wheezyのインストール自動化

みなさん、Debianのインストール作業はどうやっているだろうか。私は、OSのインストール作業なんてお金を貰わない限り手動でやりたくないので自動化している。OSの手動インストールをするだけでお金が発生するのであれば喜んでやらせていただく所存である。RedHat系の「Kickstart」と同じような仕組みの「preseed」というものがDebianにも存在するが、これを使わずに「pxeboot + debootstrap + シェルスクリプト」でインストールの自動化をしている。

pxeboot

# apt-get install debootstrap syslinux dnsmasq nfs-kernel-server

dnsmasq

DNSサーバ以外にもDHCP,TFTPサーバとしても使える便利なdnsmasq

# vi /etc/dnsmasq.d/pxe.conf
enable-tftp
tftp-root=/var/lib/tftpboot
dhcp-range=192.168.2.200,192.168.2.250,2h
dhcp-option=3,192.168.2.254
dhcp-boot=pxelinux.0

NFS

# vi /etc/exports
/var/lib/tftpboot/wheezy 192.168.2.0/24(rw,no_root_squash,no_subtree_check)

debootstrap

# mkdir -p /var/lib/tftpboot/wheezy
# debootstrap stable /var/lib/tftpboot/wheezy http://ftp.jp.debian.org/debian
# chroot /var/lib/tftpboot/wheezy passwd root
# chroot /var/lib/tftpboot/wheezy/ apt-get install linux-image-`uname -r` parted build-essential bzip2 grub2 debootstrap nfs-common

syslinux

# cp /boot/initrd* /var/lib/tftpboot
# cp /boot/vmlinuz* /var/lib/tftpboot

# cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot
# mkdir /var/lib/tftpboot/pxelinux.cfg

# vi /var/lib/tftpboot/pxelinux.cfg/default
default Debian
prompt 1
timeout 10
label Debian
kernel vmlinuz-3.2.0-4-amd64
append initrd=initrd.img-3.2.0-4-amd64 root=/dev/nfs ip=dhcp nfsroot=192.168.2.253:/var/lib/tftpboot/wheezy rw
# service dnsmasq start
# service nfs-kernel-server start

Debianインストールスクリプト

仕組みは「シェルスクリプトでFreeBSD 9.1のインストール自動化」と同じである。

debootstrapで取得した最小構成のWheezyをコピーするスクリプトを書いただけ。

パッケージインストール時にダイアログが表示され入力待ちにならないよう環境変数「DEBIAN_FRONTEND=noninteractive」を設定しておくのがポイントである。

この環境変数は解決方法はないかとdebconf(1)を眺めていたら

Debconf is a configuration system for Debian packages. For a debconf overview and documentation for sysadmins, see debconf(7) (in the debconf-doc package).

書かれており、説明に従いdebconf-docをインストールし、debconf(7)を眺めたところ見付けた。

os_install.shはconfファイルが1つだとうまく動いてくれないのでダミーのconfファイルを1つ作っておく。

# touch /var/scripts/dummy.conf
# mkdir -p /var/scripts/wheezy
# debootstrap stable /var/scripts/wheezy http://ftp.jp.debian.org/debian
# vi /var/scripts/os_install.sh
#!/bin/sh

get_conf() {
  if [ "$OS" = "FreeBSD" ]; then
    local MACADDR="`ifconfig | awk '/ether/ {print $NF}'`"
  elif [ "$OS" = "Linux" ]; then
    local MACADDR="`ifconfig | awk '/HWaddr/ {print $NF}'`"
  fi

  for a in $MACADDR; do
    grep -r $MACADDR ${CWD}/*.conf | awk -F: '{print $1}'
  done
}

CWD=`dirname $0`

OS=`uname`
CONFFILE=`get_conf`

if [ -z "$CONFFILE" ]; then
  printf 'Script Not Found\n'
  exit 1
fi

if [ "$OS" = "FreeBSD" ]; then
  IFACE=`netstat -nr | awk '{if($1 ~ /^default$/) print $6}'`
  MOUNTNAME=`sha256 -q $CONFFILE`
elif [ "$OS" = "Linux" ]; then
  IFACE=`netstat -nr | awk '{if($4 ~ /^UG$/) print $8}'`
  MOUNTNAME=`sha256sum $CONFFILE | awk '{print $1}'`
fi

$CONFFILE $IFACE $CWD $MOUNTNAME
# vi /var/scripts/debian_install.conf
#!/bin/bash -x

# 01:23:45:67:89:ab

DISK="/dev/vda"
IFACE=$1
CWD=$2
CHROOT_DEBIAN="/mnt/$3"

dd if=/dev/zero of=$DISK bs=1024 count=1

parted $DISK -s 'mklabel msdos'
parted $DISK -s 'mkpart primary 1 500'
parted $DISK -s 'mkpart primary 501 35000'
parted $DISK -s 'mkpart extended 35001 -0'
parted $DISK -s 'mkpart logical 35001 38000'
parted $DISK -s 'mkpart logical 38001 -0'
parted $DISK -s 'set 1 boot on'

mkswap ${DISK}5
swapon ${DISK}5
mkfs.ext2 ${DISK}1
mkfs.ext4 ${DISK}2
mkfs.ext4 ${DISK}6

mkdir $CHROOT_DEBIAN

mount ${DISK}2 ${CHROOT_DEBIAN}

cp -Rp ${CWD}/wheezy/* $CHROOT_DEBIAN

mount ${DISK}1 ${CHROOT_DEBIAN}/boot
mount ${DISK}6 ${CHROOT_DEBIAN}/home

mount --rbind /dev ${CHROOT_DEBIAN}/dev
mount -t proc none ${CHROOT_DEBIAN}/proc
mount --rbind /sys ${CHROOT_DEBIAN}/sys

cat << EOF > ${CHROOT_DEBIAN}/etc/hostname
install.localnet
EOF


cat << EOF > ${CHROOT_DEBIAN}/etc/resolv.conf
nameserver 8.8.8.8
EOF

cat << EOF > ${CHROOT_DEBIAN}/etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
address  192.168.2.100
netmask 255.255.255.0
gateway 192.168.2.254
EOF

cat << EOF > ${CHROOT_DEBIAN}/etc/fstab
${DISK}1               /boot           ext2            defaults        0 2
${DISK}2               /               ext4            defaults        0 1
${DISK}6               /home           ext4            defaults        0 2
${DISK}5               none            swap            sw              0 0
EOF

cat << EOF > ${CHROOT_DEBIAN}/tmp/debian_setup.sh
export DEBIAN_FRONTEND=noninteractive
cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
grep -v rootfs /proc/mounts > /etc/mtab

apt-get install -y linux-image-`uname -r` grub2 openssh-server

grub-mkconfig -o /boot/grub/grub.cfg
grub-install --no-floppy --root-directory=/ $DISK
EOF

cat << 'EOF' > ${CHROOT_DEBIAN}/tmp/user_acount.sh
useradd -m -G sudo nanashi
printf 'nanashi:$6$oHUVG9WPkdiCoxCP$XsnO5TmowzdGWNkZHv9pPUmFqgsEojkfzUa1OQj2zUOWAChL5cdGkm.dhseF0z5Tz30IEDrxNzOcsflPUgHDs.' | chpasswd -e
printf 'root:$6$wAeDl/exZFEDC0Sl$UdvTamL.94EcWFcGIAYJSgsvzaFxSd.ZLRMkD.KI27L6jxUGsWqOdEJs6if0rTG/XuEfQ9TNzHbjI99YfxPLD1' | chpasswd -e
EOF

chroot ${CHROOT_DEBIAN} /bin/bash /tmp/debian_setup.sh
chroot ${CHROOT_DEBIAN} /bin/bash /tmp/user_acount.sh

rm ${CHROOT_DEBIAN}/tmp/debian_setup.sh
rm ${CHROOT_DEBIAN}/tmp/user_acount.sh

cd /
umount -l ${CHROOT_DEBIAN}/{boot,home,proc,dev,sys}
umount -l $CHROOT_DEBIAN
sleep 2
rmdir $CHROOT_DEBIAN
reboot

pxeboot時にインストールスクリプトが実行されるようrc.localに書いておく。

# vi /var/lib/tftpboot/wheezy/etc/rc.local

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

/var/scripts/os_install.sh

exit 0