BTW, it would be interesting to see your reinstall script.
So it's actually a bit more than just a reinstall script, but making no apologies for the lack of comments, lack of decent checking, etc., here you go
This lives in /etc (I roll my own kernel+world and insert a few items that are part of
my base).
So this part is the common script that lives on all machines. It mounts a directory over NFS based on the short hostname, which contains all the per-host specific files (see below). One of those is the
update.local.sh script, which in this particular case is my workstation.
Code:
$ cat /etc/update.sh
#!/bin/sh
logger () {
${LOGGER} -t AI $1
}
RCConf_set () {
$AWK ${RCP} operation=set key=$1 value=$2 < /etc/rc.conf > /tmp/stage/etc/rc.conf && \
cp /tmp/stage/etc/rc.conf /etc && logger "rc.conf/$1"
}
INetConf_set () {
${AWK} -f ${aLIB} -f ${SCRIPT}/e_inetd_conf.awk -f ${aEXEC} operation=set key=$1 value="$2" \
< /etc/inetd.conf > /tmp/stage/etc/inetd.conf && cp /tmp/stage/etc/inetd.conf /etc && logger "inetd.conf $1"
}
Pkg_AddIfMissing () {
${PKG} query -e '%a=0' %o | ${AWK} -f ${aLIB} -f ${SCRIPT}/e_Pkg.awk -f ${aEXEC} operation=addifmissing pkg=$1
if [ $? == 0 ]; then
PKG_INSTALLED=${PKG_INSTALLED},$2
fi
}
Pkg_RemoveIfInstalled () {
${PKG} query -e '%a=0' %o | ${AWK} -f ${aLIB} -f ${SCRIPT}/e_Pkg.awk -f ${aEXEC} operation=delifpresent pkg=$1
if [ $? == 0 ]; then
PKG_INSTALLED=${PKG_INSTALLED},$2
fi
}
Pkg_Upgrade () {
env ASSUME_ALWAYS_YES=YES ${PKG} upgrade
}
if [ `id -u` != 0 ]; then
echo "ONLY ROOT CAN EXECUTE THIS SCRIPT";
exit 1
fi
if [ $# == 1 ]; then
MODE=$2
else
MODE=UPDATE
fi
echo "****************"
echo "* Mode: ${MODE}"
echo "****************"
H=`/bin/hostname -s`
CP=/bin/cp
CPIO=/usr/bin/cpio
FIND=/usr/bin/find
RM=/bin/rm
TM=/tmp/mnt
TS=/tmp/stage
AWK=/usr/bin/awk
PKG=/usr/sbin/pkg
KILL=/bin/kill
LOGGER=/usr/bin/logger
REBOOT=/sbin/reboot
SERVICE=/usr/sbin/service
SCRIPT=/tmp/mnt/common/scripts
aEXEC=${SCRIPT}/exec.awk
aLIB=${SCRIPT}/lib.awk
/bin/mkdir ${TM} ${TS}
/sbin/mount -t nfs,ro 10.1.1.1:/var/lib/tftpboot/FreeBSD/SystemConfig/Hostname ${TM}
${CP} -a ${TM}/common/root/* ${TS}
${CP} -a ${TM}/$H/root/* ${TS}
MyScriptDateBefore=`ls -lD%s /etc/update.sh | awk '{print $6}'`
${CP} -a ${TS}/etc/update.sh /etc
MyScriptDateAfter=`ls -lD%s /etc/update.sh | awk '{print $6}'`
#${CP} -av ${TS}/* /
PWD=`pwd`
cd ${TS}
${FIND} etc | ${CPIO} -p -dmv /etc
#cd ${PWD}
#${RM} -rf ${TS}
if [ "${MyScriptDateBefore}" == "${MyScriptDateAfter}" ]; then
if [ -f ${TM}/common/scripts/standard.sh ]; then
. ${TM}/common/scripts/standard.sh ${MODE}
fi
if [ -f /etc/update.local.sh ]; then
. /etc/update.local.sh ${MODE}
fi
#--------
#PWD=`pwd`
#cd ${TS}
${FIND} . | ${CPIO} -p -dmv /
cd ${PWD}
${RM} -rf ${TS}
/sbin/umount ${TM}
${RM} -rf ${TM}
else
echo "***"
echo "*** Update script changed, finishing early..."
echo "***"
/sbin/umount ${TM}
${RM} -rf ${TM}
exit 10
fi
if [ "${SYS_REBOOT}" == "TRUE" ]; then
logger Rebooting...
echo "SYSTEM ABOUT TO REBOOT."
sleep 1
echo "SYSTEM ABOUT TO REBOOT.."
sleep 2
echo "SYSTEM ABOUT TO REBOOT..."
sleep 3
echo "SYSTEM ABOUT TO REBOOT...."
sleep 4
${REBOOT}
else
if [ "${SERVICE_CUPSD_RESTART}" == "TRUE" ]; then
$SERVICE cupsd stop
$SERVICE cupsd start
fi
if [ "${SERVICE_SAMBA_RESTART}" == "TRUE" ]; then
$SERVICE samba_server stop
$SERVICE samba_server start
fi
if [ "${INIT_REBOOT}" == "TRUE" ]; then
${KILL} -HUP 1
fi
fi
$
So the directory layout looks like this:
Code:
[root@RLServices /]# cd /var/lib/tftpboot/FreeBSD/SystemConfig/Hostname/ws-leeb
[root@RLServices ws-leeb]# find .
.
./Disk2
./root
./root/etc
./root/etc/update.local.sh
./root/etc/ssl
./root/etc/ssl/certs
./root/etc/ssl/certs/Server-AD-ldap-proxy.crt
./root/etc/ssl/certs/4e6ecc8f.0
./root/etc/ssl/certs/TNMC-RootCA.crt
./root/etc/ssl/certs/Server-AD-dc-root.crt
./root/etc/ssl/certs/db302771.0
./root/etc/ssl/certs/01e214fd.0
./root/etc/ssl/certs/CANI-RootCSA.crt
./root/etc/ssl/certs/b74c0feb.0
./root/etc/ssl/certs/TNMC-RootCSA.crt
./root/etc/ssl/certs/8f8016b4.0
./root/etc/ssl/certs/Server-LDAP1.crt
./root/etc/ssl/certs/a78a50b2.0
./root/etc/ssl/certs/Server-AD-dc-lodge.crt
./root/etc/ssl/certs/3bc4d629.0
./root/etc/nsswitch.conf
./root/etc/ssh
./root/etc/ssh/ssh_host_ecdsa_key
./root/etc/ssh/id_dsa
./root/etc/ssh/ssh_host_dsa_key.pub
./root/etc/ssh/ssh_host_dsa_key
./root/etc/ssh/ssh_host_rsa_key
./root/etc/ssh/id_dsa.pub
./root/etc/ssh/ssh_host_ecdsa_key.pub
./root/etc/ssh/ssh_host_rsa_key.pub
./root/etc/pam.d
./root/etc/pam.d/system
./root/etc/pam.d/sshd
./root/etc/rc.conf.local
./root/usr
./root/usr/local
./root/usr/local/etc
./root/usr/local/etc/nss_ldap.conf
./root/usr/local/etc/pkg
./root/usr/local/etc/pkg/repos
./root/usr/local/etc/pkg/repos/NyingmaCentral.conf
./root/usr/local/etc/ldap.conf
./root/usr/local/etc/squid
./root/usr/local/etc/squid/squid.conf
./root/usr/local/etc/openldap
./root/usr/local/etc/openldap/ldap.conf
./root/usr/local/etc/security
./root/usr/local/etc/security/pam_mount.conf.xml
./root/usr/local/etc/smb4.conf
./root/usr/local/etc/X11
./root/usr/local/etc/X11/xorg.conf.d
./root/usr/local/etc/X11/xorg.conf.d/xorg.conf
The important parts being
/root/etc/update.local.sh and
/root/usr/local/etc/pkg/ports/NyingmaCentral.conf
Then finally it's going to run the
update.local.sh containing
Code:
$ cat /etc/update.local.sh
${AWK} </boot/loader.conf -f ${aLIB} -f ${SCRIPT}/e_loader_conf.awk -f ${aEXEC} key=nvidia_load value=\"YES\" > /tmp/stage/boot/loader.conf && SYS_REBOOT=TRUE && \
${CP} /boot/loader.conf /boot/loader.conf.local.bak && \
${CP} /tmp/stage/boot/loader.conf /boot && \
logger "Local processed /boot/loader.conf"
Pkg_AddIfMissing net/samba42
Pkg_AddIfMissing net/nss_ldap
#Pkg_AddIfMissing security/pam_ldap
Pkg_AddIfMissing security/pam_mkhomedir
Pkg_AddIfMissing sysutils/pam_mount
Pkg_AddIfMissing editors/nano EDITORS
Pkg_AddIfMissing x11-servers/xorg-server
Pkg_AddIfMissing x11-drivers/xf86-input-keyboard
Pkg_AddIfMissing x11-drivers/xf86-input-mouse
Pkg_AddIfMissing x11/xinit
Pkg_AddIfMissing x11/nvidia-driver-304
Pkg_AddIfMissing x11-wm/xfce4
#Pkg_AddIfMissing www/chromium
Pkg_AddIfMissing x11/nvidia-settings
Pkg_AddIfMissing www/squid
Pkg_AddIfMissing net/rdesktop
#Pkg_AddIfMissing editors/libreoffice
#Pkg_AddIfMissing ftp/filezilla
Pkg_AddIfMissing graphics/evince
Pkg_AddIfMissing graphics/gimp
Pkg_AddIfMissing graphics/inkscape
#Pkg_AddIfMissing multimedia/vlc
Pkg_AddIfMissing net/sqtop
Pkg_AddIfMissing net/wireshark
Pkg_AddIfMissing net/x11vnc
#Pkg_AddIfMissing print/cups-client
Pkg_AddIfMissing sysutils/kdirstat
Pkg_AddIfMissing sysutils/smartmontools
Pkg_AddIfMissing sysutils/xfce4-cpugraph-plugin
Pkg_AddIfMissing sysutils/xfce4-fsguard-plugin
Pkg_AddIfMissing sysutils/xfce4-genmon-plugin
Pkg_AddIfMissing sysutils/xfce4-mount-plugin
Pkg_AddIfMissing sysutils/xfce4-netload-plugin
Pkg_AddIfMissing textproc/antiword
Pkg_AddIfMissing textproc/meld
#Pkg_AddIfMissing www/opera
Pkg_Upgrade
${AWK} </etc/sysctl.conf -f ${aLIB} -f ${SCRIPT}/e_sysctl_conf.awk -f ${aEXEC} key=kern.ipc.shm_allow_removed value=1 > /tmp/stage/etc/sysctl.conf && \
${CP} /etc/sysctl.conf /etc/sysctl.conf.local.bak && \
${CP} /tmp/stage/etc/ttys /etc && \
logger "/etc/sysctl.conf modified"
For added fun, if you are still with me,that
Disk2 file contains
Code:
SCRUB ada0
SCRUB ada1
SCRUB ada2
part ada0
destroy -F
create -s GPT
bootcode -b /boot/pmbr
add -t freebsd-boot -a 4K -s 128K -l boot0
bootcode -p /boot/gptboot -i 1
add -t freebsd-swap -a 4K -s 4G -l swap0
add -t freebsd-ufs -a 4K -s 10G -l root0
add -t freebsd-ufs -a 4K -s 10G -l var0
add -t freebsd-ufs -a 4K -s 20G -l squid0
add -t freebsd-ufs -a 4K -s 100G -l usr0
part ada1
destroy -F
create -s GPT
bootcode -b /boot/pmbr
add -t freebsd-boot -a 4K -s 128K -l boot1
bootcode -p /boot/gptboot -i 1
add -t freebsd-swap -a 4K -s 4G -l swap1
add -t freebsd-ufs -a 4K -s 10G -l root1
add -t freebsd-ufs -a 4K -s 10G -l var1
add -t freebsd-ufs -a 4K -s 20G -l squid1
add -t freebsd-ufs -a 4K -s 100G -l usr1
part ada2
destroy -F
create -s GPT
bootcode -b /boot/pmbr
add -t freebsd-boot -a 4K -s 128K -l boot2
bootcode -p /boot/gptboot -i 1
add -t freebsd-swap -a 4K -s 4G -l swap2
add -t freebsd-ufs -a 4K -s 10G -l root2
add -t freebsd-ufs -a 4K -s 20G -l var2
add -t freebsd-ufs -a 4K -s 20G -l squid2
add -t freebsd-ufs -a 4K -s 200G -l usr2
stripe
label Svar /dev/gpt/var0 /dev/gpt/var1
label Ssquid /dev/gpt/squid0 /dev/gpt/squid1 /dev/gpt/squid2
label Susr /dev/gpt/usr0 /dev/gpt/usr1
mirror
label Mboot /dev/gpt/boot0 /dev/gpt/boot1 /dev/gpt/boot2
label Mroot /dev/gpt/root0 /dev/gpt/root1 /dev/gpt/root2
label Mvar /dev/stripe/Svar /dev/gpt/var2
label Musr /dev/stripe/Susr /dev/gpt/usr2
newfs
/dev/mirror/Mroot
/dev/mirror/Mvar
/dev/mirror/Musr
/dev/stripe/Ssquid
fstab
/dev/mirror/Mroot / ufs rw 0 1
/dev/gpt/swap0 none swap sw 0 0
/dev/gpt/swap1 none swap sw 0 0
/dev/gpt/swap2 none swap sw 0 0
/dev/mirror/Musr /usr ufs rw 0 2
/dev/mirror/Mvar /var ufs rw 0 2
/dev/stripe/Ssquid /SquidCache ufs rw,async,noatime 0 2
bootloader.conf
geom_stripe_load="YES"
geom_mirror_load="YES"
tmpfs_load="YES"
vm.pmap.pcid_enabled="0"
os
Workstation
distribute
kernel
base
end
which is used by my install script.
So for a bare-metal rebuild, I PXE boot the machine into my install version of FreeBSD (basically just a GENERIC amd64 kernel with
/etc/INSTALL.SH in there and run the install script. That uses the MAC address, which is linked to the hostname
00:1e:c9:44:dc:b4 -> ../Hostname/ws-leeb/, parses the above, which formats the disks, sets up the GEOM structures, fstab, grabs the OS
kernel.txz base.txz files, extracts them and runs the same update script mentioned above. Finally it reboots into a usable system.
This can take around 20 minutes to run on my workstation, but it's all hands off after I hit enter. A server typically is far less, as the packages are much smaller.
I wrote this because the nice new
bsdinstall(8) didn't agree with me (it was very new and I was very impatient).
<soapbox on>
I'm
trying to move migrating my severs from CentOS to FreeBSD and wanted a reproducible way to bring up a system, easy to move to different hardware and (eventually) self healing/auditing. By that I mean if a file is modified on the system directly, rather than just overwriting them by running the update script periodically, I'd like to diff what's on the machine vs. the staging server, mail me the offending file, then overwrite it with the staging version. While Linux has some nice newer stuff (I've been deep into IP and QoS mostly), it's too much of a wild bronco for this aging admin. I don't want to have to re-learn what I already know, what already works very well (besides which using both GNU and BSD utilities gets darned confusing).
FreeBSD is, IMHO, a very well engineered OS and I'd rather the slower pace.
<soapbox off>