Monday, December 15, 2008

Preparing small miniroot with zfs and ssh

This is instructions for building smallest OpenSolaris miniroot (standalone RAM) with ssh and zfs.
I use the receptions familiar to funs of minimization according to Jim Connors's framework. But now we will use IPS for installation of packages and we should delete files of some packages manually ("--install" or "--uninstall --without-deps" not yet implemented in pkg).
Well, I'm running Solaris Express and will use "/opt/test" as working dir. Here are the packages for small miniroot (/opt/pkg.list):
SUNWcsd
SUNWcs
SUNWcakr
SUNWcar
SUNWckr
SUNWcnetr
SUNWcsl
SUNWesu
SUNWgss
SUNWgssc
SUNWkey
SUNWkvm
SUNWlibms
SUNWlibsasl
SUNWloc
SUNWlxml
SUNWnfsc
SUNWnfsckr
SUNWopenssl
SUNWos86r
SUNWpr
SUNWpsdcr
SUNWpsdir
SUNWrmodr
SUNWbip
SUNWsmapi
SUNWssh
SUNWsshcu
SUNWsshd
SUNWtecla
SUNWtls
SUNWtoo
SUNWusb
SUNWusbs
SUNWzfs
SUNWzfskr
SUNWzlib
SUNWzone
SUNWbash
SUNWrtls

As you can see, I have Realteck network adapter (SUNWrtls). Let's go:
# working dir
export ROOTDIR=/opt/test

# create the packaging db (pkg already installed on Nevada)
/usr/bin/pkg image-create -F -a opensolaris.org=http://pkg.opensolaris.org ${ROOTDIR}

cd ${ROOTDIR}
for pkg in `cat ../pkg.list`; do
/usr/bin/pkg install ${pkg}
done

But after that we have some additional packages because of dependences. Now we need to remove these unneeded packages (/opt/rm.txt) :
SUNWaudd
SUNWgccruntime
SUNWinstall-libs
SUNWmd
SUNWpicl
SUNWpool
SUNWwbsup

I cannot delete some packages and will use "pkg contents" command:
for pkg in `cat ../rm.txt`; do
pkg contents -m $pkg|grep file|sed -e 's/.*path=//; s/pkg.csize.*//'|\
awk '{print "./"$1}';
pkg contents -m $pkg|grep link|sed -e 's/.*path=//; s/target.*//'|\
awk '{print "./"$1}';
done > files.tmp

We need "libmeta.so" library for devfsadm:
cat files.tmp|sed 's/.*libmeta.*//g' > files.list

Now I delete packages files:
for file in `cat ../files.list `; do rm -rf $file; done

Basic miniroot configuration:
cd ${ROOTDIR}

# Copy usr/sfw/lib/libwrap.so.1 to usr/lib
cp ${ROOTDIR}/lib/svc/seed/global.db ${ROOTDIR}/etc/svc/repository.db

rm ${ROOTDIR}/usr/lib/libcrypto.so*
cp ${ROOTDIR}/usr/sfw/lib/libcrypto.so.0.9.8 ${ROOTDIR}/usr/lib


# Fix etc/vfstab
echo "/devices/ramdisk:a - / ufs - no nologging" >> ${ROOTDIR}/etc/vfstab

# Set the timezone
echo "TZ=US/Eastern" > ${ROOTDIR}/etc/TIMEZONE

# Set hostname
echo "small" > ${ROOTDIR}/etc/nodename

# Create /etc/inet/hosts and /etc/inet/ipnodes file
echo "127.0.0.1 localhost loghost" > ${ROOTDIR}/etc/inet/hosts
echo "192.168.1.1 small" >> ${ROOTDIR}/etc/inet/hosts
echo "::1 localhost loghost" > ${ROOTDIR}/etc/inet/ipnodes
echo "127.0.0.1 localhost loghost" >> ${ROOTDIR}/etc/inet/ipnodes
echo "192.168.1.1 small" >> ${ROOTDIR}/etc/inet/ipnodes

# Set nsswitch.conf
cp ${ROOTDIR}/etc/nsswitch.files ${ROOTDIR}/etc/nsswitch.conf

# Set IP Address
echo "small" > ${ROOTDIR}/etc/hostname.rtls0

# Set up default route
echo "192.168.1.200" > ${ROOTDIR}/etc/defaultrouter

# Set the environment variables for svccfg.
SVCCFG_DTD=${ROOTDIR}/usr/share/lib/xml/dtd/service_bundle.dtd.1
SVCCFG_REPOSITORY=${ROOTDIR}/etc/svc/repository.db
SVCCFG=/usr/sbin/svccfg

export SVCCFG_DTD SVCCFG_REPOSITORY SVCCFG

${SVCCFG} import ${ROOTDIR}/var/svc/manifest/milestone/sysconfig.xml

# turnoff boot-archive, manifest-import
${SVCCFG} -s system/boot-archive setprop start/exec=:true
${SVCCFG} -s system/manifest-import setprop start/exec=:true
${SVCCFG} -s network/rpc/bind delpg sysidtool
${SVCCFG} -s system/metainit:default setprop general/enabled=false

# Here's what needed to add ssh
${SVCCFG} import ${ROOTDIR}/var/svc/manifest/system/cryptosvc.xml
${SVCCFG} -s system/cryptosvc:default setprop general/enabled=true

${SVCCFG} import ${ROOTDIR}/var/svc/manifest/network/inetd.xml
${SVCCFG} -s network/inetd:default setprop general/enabled=true

${SVCCFG} import ${ROOTDIR}/var/svc/manifest/network/rpc/gss.xml
${SVCCFG} -s network/rpc/gss:default setprop general/enabled=true

${SVCCFG} import ${ROOTDIR}/var/svc/manifest/network/ssh.xml
${SVCCFG} -s network/ssh:default setprop general/enabled=true

# Creating RSA/DSA keys for ssh
/usr/bin/ssh-keygen -q -f ${ROOTDIR}/etc/ssh/ssh_host_rsa_key -t rsa -N ''
/usr/bin/ssh-keygen -q -f ${ROOTDIR}/etc/ssh/ssh_host_dsa_key -t dsa -N ''

# Edit etc/ssh/sshd_config to allow ssh to root account
ex -s ${ROOTDIR}/etc/ssh/sshd_config > /dev/null <<> /dev/null

# Remove packaging, xpg4, sfw - you can remove more but be carefully
rm -rf var/sadm/* var/pkg/*
rm -rf usr/xpg4 usr/sfw

Now I prepare a miniroot image:
# we need freespace ~10mb
size=`/usr/bin/du -ks ${ROOTDIR}|/usr/bin/nawk '{print $1+10240}'`

/usr/sbin/mkfile ${size}k /opt/miniroot
lofidev=`/usr/sbin/lofiadm -a /opt/miniroot`

# get the miniroot raw device and create a filesystem on it
rlofidev=`echo $lofidev |sed s/lofi/rlofi/`
/usr/sbin/newfs -m 0 $rlofidev

# mount ufs filesystem
/usr/sbin/mount -o nologging $lofidev /mnt

/usr/bin/find .  /usr/bin/cpio -pdum /mnt
/usr/sbin/umount /mnt

/usr/sbin/lofiadm -d /opt/miniroot
/usr/bin/7za a -tgzip -mx=9 /opt/miniroot.gz /opt/miniroot

Done. Now I have a small OpenSolaris 2008.11 miniroot with ZFS and SSH (32601K gzipped - I've also removed a number of unnecessary binaries from SUNWcs). It's possible to make an image even less.

No comments:

How to determine PXE mac address when booting illumos via PXELinux/iPXE

In illumos, if you need to determine the interface which was used for booting via PXE then it's possible to use "boot-mac" pro...