自作のVagrant Boxをかためるまでの手順(debian 系 Linux版)

Ubuntu 18.04 がリリースされたので、今まで書いてきた手順([これ](https://qiita.com/poad1010/items/98672357772350a470ec)とか[これ](https://qiita.com/poad1010/items/6d15bd8d46967c1fd031)とか、[これ](https://qiita.com/poad1010/items/061523e2d1911cb0d07d))を整理して、まとめ直してみようと思います。

# ゲスト側

## sudoers設定

```bash:
sudo sed -i -e '/Defaults\s\+env_reset/a Defaults\tenv_keep="SSH_AUTH_SOCK"' /etc/sudoers
sudo sed -i -e '/Defaults\s\+env_reset/a Defaults:vagrant !requiretty' /etc/sudoers
sudo sed -i -e '/Defaults\s\+env_reset/a Defaults\texempt_group=sudo' /etc/sudoers
sudo sed -i -e '/%sudo\s\ALL=(ALL:ALL) ALL/a %vagrant   ALL=(ALL) NOPASSWD: ALL' /etc/sudoers
```

## SSHの設定

```bash:
echo "UseDNS no" | sudo tee -a /etc/ssh/sshd_config
```

## SSHの公開鍵設定


```bash:
mkdir /home/vagrant/.ssh
wget --no-check-certificate 'https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub' -O /home/vagrant/.ssh/authorized_keys
chown -R vagrant /home/vagrant/.ssh
chmod -R go-rwsx /home/vagrant/.ssh
```

## ファイルサイズを小さくする


```bash:
# 共有するBoxの場合、Vagrant Boxの鍵をinsecureなmaster keyに置き換えておく
curl -sSL https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub > ~/.ssh/authorized_keys && \
chmod 740 .ssh && \
chmod 640 .ssh/authorized_keys

# sudoして作業するのが面倒なので、
sudo -s
# 最新化
apt update -qq && apt full-upgrade -qq -y && \
apt autoremove --purge -y && apt autoclean && \
rm -rf /var/lib/apt/lists/* && \
apt-get clean

## 共有フォルダーをアンマウントしておく
#umount /vagrant && \
#rm -rf /vagrant/*

# /var/log の中を簡単にお掃除
cd /var/log
rm *.gz *.1
for dir in $(find /var/log -maxdepth 1 -type d); do cd $dir; rm *.gz *.1; done

# デフラグする
cd
e4defrag /

# 0埋めする
dd if=/dev/zero of=/EMPTY bs=1M || :; rm /EMPTY

# swapも0埋めする
swap_device_uuid=`sudo /sbin/blkid -t TYPE=swap -o value -s UUID | uniq`
swap_device_label=`sudo /sbin/blkid -t TYPE=swap -o value -s LABEL | uniq`
if [ -n "$swap_device_uuid" ]; then
  swap_device=`readlink -f /dev/disk/by-uuid/"$swap_device_uuid"`
elif [ -n "$swap_device_label" ]; then
  swap_device=`readlink -f /dev/disk/by-label/"$swap_device_label"`
fi
/sbin/swapoff "$swap_device"
dd if=/dev/zero of="$swap_device" bs=1M || :
/sbin/mkswap ${swap_device_label:+-L "$swap_device_label"} ${swap_device_uuid:+-U "$swap_device_uuid"} "$swap_device"

# もっかい /var/log をお掃除
find /var/log -type f | while read f; do echo -ne '' > $f; done

# historyを削除
echo "" > ~/.bash_history ; history -c
exit
echo "" > ~/.bash_history ; history -c
```
# ホスト側

仮想マシンの仮想HDDをVDI形式に変換してから `vagrant package` すると、Box サイズが若干、小さくなります。
毎回手動で実施するのは手間なので、シェルスクリプト化しました。
MSYS2で動作確認していますが、VirtualBoxのインストールパスや、Box出力先ディレクトリを修正すれば、macOSやWSL、Linux上で動作するのではないかと思います。

```bash:package.sh
#!/bin/sh

export PATH=$PATH:"/c/Program Files/Oracle/VirtualBox"


# Box出力先ディレクトリ
OUTPUT_DIR=/d/boxs
ARCHIVE_DIR=/d/box_archives

VM=$(VBoxManage showvminfo "${1}" | grep "Config file")
VBOX=$(echo ${VM#"Config file: "}  | sed -e 's/^\s+//g' | sed -e 's/://g' | sed -e 's/\\/\//g')
BASE=${VBOX%%"${1}.vbox"}
VM_DIR=$(echo /${BASE,})
STORAGE_VM=$(VBoxManage showvminfo "${1}" | grep "SATA (0, 0): ")
DISK_=$(echo ${STORAGE_VM#"SATA (0, 0): "}  | sed -e 's/^\s+//g' | sed -e 's/://g' | sed -e 's/\\/\//g' | sed -e 's/ (UUID.*//')
DISK=$(echo /${DISK_,})
DISK_BASENAME=$(basename "${DISK}")
DISK_NAME=$(echo ${DISK_BASENAME} | sed 's/\.[^\.]*$//')
DISK_EXT=$(echo ${DISK_BASENAME##*.})

echo $VM_DIR


if [ -z "${1}" ]
then
	echo "Usage ${0} [base vm name] [output box file name without extention]"
	exit 0;
fi

if [ -z "${2}" ]
then
	echo "Usage ${0} [base vm name] [output box file name without extention]"
	exit 0;
fi

cd ${OUTPUT_DIR}

if [ -e ${OUTPUT_DIR}/"${2}.box" ]
then
	echo "[MV] mv ${OUTPUT_DIR}/\"${2}.box\" ${ARCHIVE_DIR}/\"${2}.box.bak\""
	mv ${OUTPUT_DIR}/"${2}.box" ${ARCHIVE_DIR}/"${2}.box.bak"
fi

if [ $(VBoxManage list runningvms | grep "${1}" | wc -l) -eq 1 ]
then
  echo "[Shutdown] Shutdown VM \"${1}\""
  #VBoxManage controlvm "${1}" acpipowerbutton;
  VBoxManage controlvm "${1}" poweroff
fi

cd "$VM_DIR"
if [ "$DISK_EXT" = "vmdk" ]
then
  VBoxManage storageattach "${1}" --storagectl SATA --medium none --port 0 && \
  echo "[Prepare] convert ${DISK_BASENAME} to ${DISK_NAME}.vdi" && \
  VBoxManage clonemedium disk ${DISK_BASENAME} ${DISK_NAME}.vdi --format vdi && \
  VBoxManage closemedium disk ${DISK_BASENAME} && \
  mv ${DISK_BASENAME} ${DISK_BASENAME}.bak
else
  DISK_BASENAME=${DISK_NAME}.vmdk
fi && \
echo "[Compact] VBoxManage modifyhd ${DISK_NAME}.vdi compact" && \
VBoxManage modifyhd ${DISK_NAME}.vdi compact && \
echo "[Cleanup] convert ${DISK_NAME}.vdi to ${DISK_BASENAME}" && \
VBoxManage clonemedium disk ${DISK_NAME}.vdi ${DISK_BASENAME} --format vmdk && \
if [ -e "${DISK_BASENAME}.bak" ]
then
  rm ${DISK_BASENAME}.bak
fi && \
VBoxManage closemedium ${DISK_NAME}.vdi && \
rm ${DISK_NAME}.vdi && \
VBoxManage storageattach "${1}" --storagectl SATA --medium "$VM_DIR"${DISK_BASENAME} --port 0 --type hdd && \
echo "[Package] vagrant package --base \"${1}\" --out ${OUTPUT_DIR}/\"${2}.box\"" && \
vagrant package --base "${1}" --out ${OUTPUT_DIR}/"${2}.box" && \
md5sum ${OUTPUT_DIR}/"${2}.box" > ${OUTPUT_DIR}/"${2}.box.md5sum"
```

## Box固め
`VM名` には、VirtualBox上の仮想マシン名を指定してください。

```:bash
./package.sh <VM名> <出力するVagrantBoxファイル名>
```