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

OSインストールをするだけでお金が貰えるならば喜んでやるが、趣味の時間をOSインストールに奪われるのはつらいので、自動化してみた。

PXE boot サーバ構築

# mdconfig -a -t vnode -f FreeBSD-9.1-RELEASE-amd64-disc1.iso
md0
# mount_cd9660 /dev/md0 /mnt
# mkdir /var/pxeboot
# cp -Rv /mnt/ /var/pxeboot
# umount /mnt
# mdconfig -d -u 0
# vi /var/pxeboot/etc/fstab
# /dev/iso9660/FREEBSD_INSTALL / cd9660 ro 0 0 <- コメントアウト
# vi /etc/inetd.conf
tftp    dgram   udp     wait    root    /usr/libexec/tftpd      tftpd -l -s /var/pxeboot/boot

# /etc/rc.d/inetd onestart
# cd /usr/ports/net/isc-dhcp42-server
# make install

# vi /usr/local/etc/dhcpd.conf
ddns-update-style none;
server-name "pxeboot";            # name of the tftp-server
server-identifier 192.168.0.253;  # address of the tftp-server
next-server 192.168.0.253;        # address of the NFS-server

subnet 192.168.0.0 netmask 255.255.255.0 {
    range 192.168.0.220 192.168.0.250;
    option routers 192.168.0.254;
    option root-path "/var/pxeboot"; # root-path for NFS
    filename "pxeboot";              # filename of NBP (network bootstrap program)
}

# /usr/local/etc/rc.d/isc-dhcpd onestart
# vi /etc/exports
/var/pxeboot -alldirs -maproot=root

# /etc/rc.d/nfsd onestart

再起動後もデーモンを起動させておきたければrc.confに書いておく。

# vi /etc/rc.conf
inetd_enable="YES"
dhcpd_enable="YES"
dhcpd_ifaces="em0"
nfs_server_enable="YES"

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

PXE BootしたマシンのMACアドレスが書かれたシェルスクリプトを探し、実行するようになっている。

# mkdir /var/scripts/freebsd91
# cd /usr/freebsd-dist
# cp *.txz /var/scripts/freebsd91
# vi /var/pxeboot/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/pxeboot/var/scripts/freebsd_install.conf
#!/bin/sh

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

DISK=ada0
IFACE=$1
CWD=$2
CHROOT_FREEBSD="/mnt/$3"
DIST_TXZ=`ls ${CWD}/freebsd91/*.txz`

gpart destroy -F $DISK
gpart create -s gpt $DISK
gpart add -s 64K -t freebsd-boot $DISK
gpart add -s 8G -t freebsd-swap -l swap0 $DISK
gpart add -t freebsd-ufs $DISK
gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 $DISK

newfs -U /dev/${DISK}p3

mkdir $CHROOT_FREEBSD

mount /dev/${DISK}p3 $CHROOT_FREEBSD

cd $CHROOT_FREEBSD

for FILE in $DIST_TXZ; do
  tar xfzp $FILE
done

cat << EOF > ${CHROOT_FREEBSD}/etc/rc.conf
hostname="freebsd.local"
keymap="us.iso.kbd"
ifconfig_${IFACE}=" inet 192.168.0.252 netmask 255.255.255.0"
defaultrouter="192.168.0.254"
sshd_enable="YES"
# Set dumpdev to "AUTO" to enable crash dumps, "NO" to disable
dumpdev="AUTO"
EOF

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

cat << EOF > ${CHROOT_FREEBSD}/etc/fstab
# Device        Mountpoint      FStype  Options Dump    Pass#
/dev/${DISK}p3     /               ufs     rw      1       1
/dev/${DISK}p2     none            swap    sw      0       0
EOF

cat << EOF > ${CHROOT_FREEBSD}/tmp/freebsd_setup.sh
newaliases
touch /etc/wall_cmos_clock
tzsetup Asia/Tokyo

dumpon /dev/${DISK}p2
ln -sf /dev/${DISK}p2 /dev/dumpdev
EOF

cat << 'EOF' > ${CHROOT_FREEBSD}/tmp/user_acount.sh
printf "$6$oHUVG9WPkdiCoxCP$XsnO5TmowzdGWNkZHv9pPUmFqgsEojkfzUa1OQj2zUOWAChL5cdGkm.dhseF0z5Tz30IEDrxNzOcsflPUgHDs." | pw usermod -n root -H 0

pw useradd -n nanashi -s /bin/tcsh -G wheel -m
printf "$6$wAeDl/exZFEDC0Sl$UdvTamL.94EcWFcGIAYJSgsvzaFxSd.ZLRMkD.KI27L6jxUGsWqOdEJs6if0rTG/XuEfQ9TNzHbjI99YfxPLD1" | pw usermod -n nanashi -H 0
EOF

mount -t devfs dev ${CHROOT_FREEBSD}/dev

chroot $CHROOT_FREEBSD /bin/sh /tmp/freebsd_setup.sh
chroot $CHROOT_FREEBSD /bin/sh /tmp/user_acount.sh

rm ${CHROOT_FREEBSD}/tmp/freebsd_setup.sh
rm ${CHROOT_FREEBSD}/tmp/user_acount.sh

cd /
umount ${CHROOT_FREEBSD}/dev
umount $CHROOT_FREEBSD

rmdir $CHROOT_FREEBSD
reboot

PXE boot時に指定のスクリプトを実行するようにrc.localに書いておく。

# vi /var/pxeboot/etc/rc.local

#!/bin/sh
# $FreeBSD: release/9.1.0/release/rc.local 232427 2012-03-03 02:13:53Z nwhitehorn $

/var/script/os_install.sh