Solved Can FreeBSD 9 installation ISO be modified?

I'd like to modify the bsdinstall scripts used during the install process in order to automate and customize future FreeBSD 9 installations. Mainly, I want to setup root on ZFS without having to enter the Shell environment at the Partitioning step and enter a series of commands. I don't even want to enter the Shell environment to download and run a script for this (as seen here). I've created a modified copy of the auto bsdinstall script and several other scripts that will be run by auto.

My first attempt was to mount the installation ISO, copy its contents to a writable file system, modify the contents of the copy (as described above), and create an ISO of the copy. I ran [cmd=]mkisofs -R -no-emul-boot -b boot/cdboot -o <ISO-target-path> <modified-copy>[/cmd] to create an ISO of the copy. The ISO would be created, but it could not be used to boot a system.

My next attempt was to use /usr/src/release/generate-release.sh, which I modified to copy my custom scripts to <scratch-dir>/usr/src/usr.sbin/bsdinstall/scripts after the source is checked out from svn.freebsd.org into <scratch-dir>. After the release was built, I mounted the yielded ISO only to see that my scripts were not on the ISO.

Can I modify the FreeBSD 9 installation ISO to fulfill my goal of automating the root-on-ZFS process? If not, what do you suggest as an alternative?
 
kkaos said:
Can I modify the FreeBSD 9 installation ISO
It may not be the prettiest way, but have you tried mounting the ISO image and then editing it?
Code:
[cmd=#]mdconfig -f /path/to/iso/image[/cmd]
md[i]X[/i] ([i]X[/i] will probably be 0)
[cmd=#]mount -t cd9660 /dev/md[i]X[/i] /mnt/some/mount/point[/cmd]
[cmd=#]cd /mnt/some/mount/point[/cmd]
(do your thing with it and make sure to [CMD=]cd[/CMD] out of it when you're done)
[cmd=#]mdconfig -d -u [i]X[/i][/cmd]
And then burn the image file to a CD/DVD.

I use this to add custom files to USB install images, but I think it should also work with ISO images.
 
Hi @fonz.

I can't write to the ISO after mounting it, as you suggested. That's why I copied it to a writable file system.
 
Last edited by a moderator:
Ok, I've figured out how to use the existing ISO to create a modified copy. You mount the ISO, copy its contents to a writable file system, modify the copy as you see fit, and then, you run # sh /usr/src/release/<CPU-arch>/mkisoimages.sh -b <ISO-label> <new-ISO> <path-to-copy> to generate a bootable installation ISO.

For example:

Code:
mdconfig -a -t vnode -f FreeBSD-9.1-x64.iso -u 0
mount_cd9660 /dev/md0 my-freebsd-9.1-x64-iso
cp myauto my-freebsd-9.1-x64-iso/usr/libexec/bsdinstall/auto
sh /usr/src/release/amd64/mkisoimages.sh -b MYFREEBSD9 MyFreeBSD-9.1-x64.iso my-freebsd-9.1-x64-iso
<Your new ISO is MyFreeBSD-9.1-x64.iso!>

My ISO booted and got just past the partitioning step when the installation failed. The ZFS root environment didn't get created so I'll have to modify my scripts.

If anyone has any advice on how to automate Root-on-ZFS partitioning, I'm all ears. :)
 
xy16644 said:
I'm also quite interested in automating a ZFS on root install however I want to include Geli encryption in my script too as well as putting /boot onto a separate USB drive.

I came across this guide/script which may be helpful for you:

FreeBSD ZFS Root Install Script

Yes, that was helpful. I couldn't find a feasible way to use bsdinstall auto to do this automatically, but entering a Shell at the beginning of installation and executing a zfs.sh script similar to the one provided at FreeBSD ZFS Root Install Script is quick and easy enough.

Here's my zfs.sh:

Code:
#!/bin/sh

# Find disk device to partition
DISK=
if [ -e /dev/mfid0 ] # It's a RAID drive
then
   DISK=mfid0
elif [ -e /dev/da0 ] # It's a VM disk
then
   DISK=da0
else
   DISK=ada0 # It's a non-RAID disk
fi

echo "# Initialize disk"
index=1
while [ 1 ] ; do
   partition=$DISK'p'$index
   [ ! -e /dev/$partition ] && break
   gpart delete -i $index $DISK
   index=`expr $index + 1`
done
gpart destroy -F $DISK

echo ""
echo "# Create and partition GPT table on disk"
gpart create -s gpt $DISK
gpart add -s 122 -t freebsd-boot -l boot $DISK
gpart add -s 1G -t freebsd-swap -l swap0 $DISK
gpart add -t freebsd-zfs -l root $DISK
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 $DISK

# Load necessary modules
kldload opensolaris
kldload zfs

echo ""
echo "# Create ZFS root environment"
zpool create -o altroot=/mnt zroot /dev/gpt/root
zfs set checksum=fletcher4 zroot
zfs create -o compression=on -o exec=off -o setuid=off zroot/tmp ; chmod 1777 /mnt/tmp
zfs create zroot/usr
zfs create -o setuid=off -o exec=off zroot/usr/home ; cd /mnt ; ln -s usr/home home ; cd -
zfs create -o compression=lzjb -o setuid=off zroot/usr/ports
zfs create -o compression=off -o exec=off -o setuid=off zroot/usr/ports/distfiles
zfs create -o compression=off -o exec=off -o setuid=off zroot/usr/ports/packages
zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/usr/src
zfs create zroot/var
zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/var/crash
zfs create -o exec=off -o setuid=off zroot/var/db
zfs create -o compression=lzjb -o exec=on -o setuid=off zroot/var/db/pkg
zfs create -o exec=off -o setuid=off zroot/var/empty
zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/var/log
zfs create -o compression=gzip -o exec=off -o setuid=off zroot/var/mail
zfs create -o exec=off -o setuid=off zroot/var/run
zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/var/tmp ; chmod 1777 /mnt/var/tmp

echo ""
echo "# Install FreeBSD OS (base.txz kernel.txz ports.txz)"
echo "# This will take a few minutes."
cd /usr/freebsd-dist
export DESTDIR=/mnt
for file in base.txz kernel.txz ports.txz;
do (cat $file | tar --unlink -xpJf - -C ${DESTDIR:-/}); done

echo ""
echo "# Enable ZFS in the startup configuration."
echo 'dumpdev="NO"' >> /mnt/etc/rc.conf
echo 'zfs_enable="YES"' >> /mnt/etc/rc.conf
echo 'zfs_load="YES"' >> /mnt/boot/loader.conf
echo 'vfs.root.mountfrom="zfs:zroot"' >> /mnt/boot/loader.conf

echo ""
echo "# Enable swap at boot."
cat > /mnt/etc/fstab << __EOF__
# Device        Mountpoint      FStype  Options         Dump    Pass#
/dev/gpt/swap0  none            swap    sw              0       0
__EOF__

echo ""
echo "# Enable IPv4 networking."
for IF in `ifconfig -l`; do
        test "$IF" = "lo0" && continue
        test "$IF" = "plip0" && continue
        (ifconfig -g wlan | egrep -wq $IF) && continue
        INTERFACES="$INTERFACES $IF"
done
IF=`echo $INTERFACES | cut -d' ' -f1`
echo 'hostname="freebsd"' >> /mnt/etc/rc.conf
echo 'ifconfig_'$IF'="DHCP"' >> /mnt/etc/rc.conf

echo ""
echo "# Setup resolv.conf."
echo 'search domain.com' >> /mnt/etc/resolv.conf
<Nameserver entries go here>

echo ""
echo "# Setup make rules for installing ports."
echo 'WITHOUT_X11=yes' >> /mnt/etc/make.conf
echo 'CPUTYPE=nocona' >> /mnt/etc/make.conf
echo 'CFLAGS= -O2 -pipe -funroll-loops' >> /mnt/etc/make.conf
echo 'COPTFLAGS= -O2 -pipe -funroll-loops' >> /mnt/etc/make.conf
chown root:wheel /mnt/etc/make.conf
chmod 644 /mnt/etc/make.conf

echo ""
echo "# Setup pf firewall"
touch /mnt/etc/pf.conf
chown root:wheel /mnt/etc/pf.conf
echo 'pf_enable="YES"' >> /mnt/etc/rc.conf
echo 'pf_rules="/etc/pf.conf"' >> /mnt/etc/rc.conf
echo 'pflog_enable="YES"' >> /mnt/etc/rc.conf
echo 'pflog_logfile="/var/log/pflog"' >> /mnt/etc/rc.conf
cat > /mnt/etc/pf.conf << __EOF__
<Firewall rules go here>
__EOF__
chmod 400 /mnt/etc/pf.conf

echo ""
echo "# Setup sysctl.conf."
echo 'net.inet.icmp.drop_redirect=1' >> /mnt/etc/sysctl.conf
echo 'net.inet.icmp.icmplim=50' >> /mnt/etc/sysctl.conf
echo 'net.inet.icmp.maskrepl=0' >> /mnt/etc/sysctl.conf
echo 'net.inet.icmp.bmcastecho=0' >> /mnt/etc/sysctl.conf
echo 'net.inet.ip.redirect=0' >> /mnt/etc/sysctl.conf
echo 'net.inet.ip.rtexpire=2' >> /mnt/etc/sysctl.conf
echo 'net.inet.ip.rtminexpire=2' >> /mnt/etc/sysctl.conf
echo 'net.inet.ip.rtmaxcache=256' >> /mnt/etc/sysctl.conf
echo 'net.inet.ip.accept_sourceroute=0' >> /mnt/etc/sysctl.conf
echo 'net.inet.ip.sourceroute=0' >> /mnt/etc/sysctl.conf
echo 'net.inet.tcp.msl=7500' >> /mnt/etc/sysctl.conf
echo 'net.inet.tcp.blackhole=2' >> /mnt/etc/sysctl.conf
echo 'net.inet.tcp.drop_synfin=1' >> /mnt/etc/sysctl.conf
echo 'net.inet.tcp.icmp_may_rst=0' >> /mnt/etc/sysctl.conf
echo 'net.inet.udp.blackhole=1' >> /mnt/etc/sysctl.conf
echo >> /mnt/etc/sysctl.conf
echo 'kern.ipc.somaxconn=32768' >> /mnt/etc/sysctl.conf

echo ""
echo "# Enable sshd at boot."
echo 'sshd_enable="YES"' >> /mnt/etc/rc.conf
echo ""
echo "#Enable ntpd at boot."
echo 'ntpd_enable="YES"' >> /mnt/etc/rc.conf
echo ""
echo "# Don't allow syslogd to listen on TCP/IP."
echo 'syslogd_flags="-s -s"' >> /mnt/etc/rc.conf

echo ""
echo "# Set sticky bit on all world-writeable directories"
/usr/bin/find /mnt -type d -perm -0002 -exec chmod a+t {} \; 2> /dev/null > /dev/null

echo ""
echo "# Fix zpool cachefile to be able to boot from the new pool."
zfs unmount -a
zpool export zroot
zpool import -o cachefile=/tmp/zpool.cache -o altroot=/mnt zroot

echo ""
echo "# Set mountpoints."
zfs set mountpoint=/ zroot
cp /tmp/zpool.cache /mnt/boot/zfs/
zfs unmount -a
zpool set bootfs=zroot zroot
zpool set cachefile='' zroot
zfs set mountpoint=legacy zroot
zfs set mountpoint=/tmp zroot/tmp
zfs set mountpoint=/var zroot/var
zfs set mountpoint=/usr zroot/usr
zfs set readonly=on zroot/var/empty

sync
echo ""
echo "# Install Done. Syncing file system. You can reboot now."
sync

It's not perfect, but it works for me. I would like to add a functionality to this script to set up a predetermined root password using a SHA512 hash.
 
Back
Top