Trustix Secure Linux Embedded

Trustix Linux embedded


Introduction

Much of this process was taken from

http://silent.gumph.org/content/4/1/011-linux-on-cf.html Thanks to the author of that article!

Trustix may not be the most well suited since it's size isn't extremely small, but it is small enough to start with and has many of the features that I'm after. I'm also toying with a busybox build, but I've had numerous problems building. I'll keep trying the busybox idea because it offers some amazing size freedom...a bootable system in under 5 MB!


Goal

Have a small linux distro with:

1. rpm
2. squid
3. iptables
4. dansguardian
5. caching-nameserver
6. uses CF card for storage; loads init image into RAM
7. heartbeat and extras
8. apache or other webserver
9. should have two entries for booting: 1. / is in ramdisk and 2. / is on CF card. this would allow a boot mode when updates need to be applied. Additionally needed is a scripted or otherwise means to get the updated, CF-base / into a new / ramdisk image
10. having xorg would be really nice, but not absolutely necessary; maybe webmin as alternative to graphical environment...

Requirements for performing this process

This process assumes you know how to install, configure and administer a standard installation of Trustix Linux 2.2 (tsl). In addition, it is also assumed you know how to use some of the more advanced tools in linux like, fdisk, dd, mkfs. There really are no extra hardware requirements for this process as compared to a standard install, but having more RAM certainly helps. Essentially, this process can be performed on a system using standard hard drives and memory, but it is aimed at systems with no moving parts.

Addon packages (heartbeat and it's dependencies and dansguardian were downloaded from their respective sites in source rpm form, and rebuilt on a Trustix 2.2 build host. If you need these packages, you have to download and build them yourself. My notes on building these can be found in the endnotes.

Design approach - Ramdisk /, CF-based /boot, /usr and /home, and tmpfs-based /tmp and /var

This process utilizes a VIA EPIA-M 6000 Fanless (Eden processor) board, casetronic travla c146 rackmount case, 512MB PC2100 RAM, IDE-CF Adapter, slimline teac 24X Cdrom drive, 1GB CF card. All this for under $500. Two Intel pro 1000 gigabit ethernet cards were added afterwards.

This method will be using Trustix 2.2, as version 3.0 has several problems that render it unusable in the process. A general overview of the process is 1) Install Trustix, 2) Run nw-prep-script, 3) Install additional software and update OS, 4) Configure system to your liking, 5) Run nw-update-ramdisk script, 6) Reboot and use.

As already noted, there are two separate post-install scripts: one to make system changes and one to update the ramdisk image. The script to make system changes, nw-prep-script, performs tasks that only need to be done once, whereas the second script, nw-update-ramdisk, performs tasks the need to be done every time the ramdisk image is to be updated i.e. after system configuration changes or updates.

Installing additional software must also be taken somewhat more specifically. The size of the ramdisk image and the entry in the grub.conf file is based upon the software outlined in this process. You must consider this size if using a different software set. If you need more space in your ramdisk, simply adjust the 65000 line in the nw-update-script and in /boot/grub/grub.conf accordingly. Here, 65 MB allows the listed packages to be installed, and more importantly, two kernels to be installed at the same time, which is important during OS upgrades. I personally like to have one old kernel version available in case the new one gives fits.

So, on with the show...

Install Trustix directly to the CF card, which should be detected as /dev/hda (if connected as master on primary ide bus).

1. Install Minimal+SSH of Trustix 2.2

1.1. During install, partition the CF card as follows:
/dev/hda1 * /boot 100 MB (forced to be primary partition)
/dev/hda2 / 60MB (forced to be primary partition)
/dev/hda3 /usr the rest (forced to be primary partition)
/dev/hda4 EXTENDED PARTITION
/dev/hda5 /home 10MB
/dev/hda6 /var 50MB
/dev/hda7 /tmp 50MB

1.2. Format partitions as ext2, since ext3 adds journaling and a whole lot more disk activity.

1.3. Do not use/create a swap partition.

2. After the install is complete, create the directory /usr/software and download the prep scripts tarball (nw-tsl-scripts.tar.gz) to /usr/software and unpack it.

3. run prep script first since it sets some things needed before software updates e.g. bootloader option. For those who perfer the manual process, here's a list of steps the nw-prep-script performs:

3.1. Modify the CF card's partition fsck options. Specifically, fsck options are set to run fsck after 50 mounts or 6 months elapsed time since the last check, whichever comes first. Thus, for each disk partition (e.g. /dev/hda1), run the following command:

 

# tune2fs -c 50 -i 6m /dev/hda1

Don't run for /dev/hda4 since this partition is of the type extended.

3.2. Clean up logrotate files and settings. My preferred settings under these conditions are to setup logrotation based on file size of 100K, don't keep any rotated copies, and check logfiles every 10 minutes. To do this manually, first edit /etc/logrotate.conf to look like (blue lines indicate changed lines):

############################################################
# see "man logrotate" for details
# rotate log files monthly
size=100k

# keep 12 months worth of backlogs
rotate 0

# create new (empty) log files after rotating old ones
create

# uncomment this if you want your log files compressed
#compress

# RPM packages drop log rotation information into this directory
include /etc/logrotate.d

# no packages own lastlog or wtmp -- we'll rotate them here
/var/log/wtmp {
size=100k
create 0664 root utmp
rotate 0
}

/var/log/lastlog {
size=100k
rotate 0
}

# system-specific logs may be configured here

################################################################

 

Next, move the logrotate cron script, /etc/cron.daily/logrotate to /etc/cron.d/logrotate (this file can be manually created, but be sure its executable). The /etc/cron.d/logrotate file should contain the following line:

*/10 * * * * root /etc/sysconfig/logrotate

3.3. Clean out cron dirs, since most cron jobs are unnecessary in this environment. Specifically, remove all cron scripts from /etc/cron.hourly, /etc/cron.daily except tmpwatch, /etc/cron.weekly, and /etc/cron.monthly.

3.4. Add the following alias to /etc/bashrc:
alias ll='ls -lh'

3.5. Add a default admin account, set its password and add it to the wheel group.
# useradd admin
# passwd admin # set password
# usermod -G wheel admin

3.6. Modify /etc/pam.d/su to allow members of the group wheel to use su to become root. The contents of /etc/pam.d/su should look like (change in blue):

#########################################
#%PAM-1.0" > /etc/pam.d/su
auth sufficient /lib/security/pam_rootok.so
auth required /lib/security/pam_wheel.so group=wheel
auth required /lib/security/pam_pwdb.so
account required /lib/security/pam_pwdb.so
session required /lib/security/pam_pwdb.so
#########################################

3.7. Update /etc/sysconfig/bootloader to enable autoactivation of kernels after install. Set AUTOACTIVATE=yes

3.8. Add boot entry to /boot/grub/grub.conf for booting from ramdisk. Below is an example grub.conf file with changes in blue:

#################################################
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/hda2
# initrd /initrd-version.img
#boot=/dev/hda
default=0
timeout=10
title Trustix_ramdisk
root (hd0,0)

kernel /vmlinuz ro ramdisk_size=65000 root=/dev/ramdisk
initrd /ramdisk.img.gz

title Trustix Linux
root (hd0,0)
kernel /vmlinuz ro root=/dev/hda2
initrd /initrd.img
title Trustix Linux-old
root (hd0,0)
kernel /vmlinuz.old ro root=/dev/hda2
initrd /initrd.img.old
#################################################

4. Next, upgrade OS software and add any additional packages and configure them accordingly. Also install the following from a mirror using swup:

Install using swup

(lines beginning with '--' are dependencies and do not need to be specified since swup will resolve and install these)

patch ( needed by the prep and update ramdisk scripts)
squid
iptables
ntp
--gdbm
--perl
--libpcap
telnet
libtool
libxml2
perl-libwww-perl
perl-html-parser
perl-net-dns
perl-io-socket-ssl
perl-uri
perl-xml-parser

Install addons - these were custom built for Trustix 2.2 - only install if needed
(lines beginning with '--' are dependancies. Use rpm -Uvh *.rpm to simply install all rpms with a directory)
dansguardian
webmin
heartbeat
heartbeat-pils
heartbeat-stonith
heartbeat-ldirectord
--perl-crypt-ssleay
--ipvsadm
--perl-mail-imapclient
--perl-parse-recdescent
--perl-ldap
--perl-convert-asn1
--perl-authen-sasl
--perl-xml-sax
--perl-xml-namespacesupport

Also, configure network interfaces, hostname (/etc/sysconfig/network: HOSTNAME variable; /etc/hosts), iptables rules, ip forwarding, etc.

5. The remainder of this process can be done by simply running the nw-update-ramdisk script, but to detail the process for those who want to do this manually (maybe for a different OS), steps will be outlined below.

5.1. Update local db for locate by running updatedb. This is to ensure an accurate db is added to the ramdisk image.
# updatedb

5.2. Flush the swup cache, since there isn't any reason to have the excess packages hanging around and copied to tmpfs when in embedded mode.
# swup --flush-cache

5.3. Clean out /var and /tmp. Specifically, empty all log files by echoing "" into each. A simple bash script to do this follows:

find /var/log -type f | while read line; do
echo "" > $line
done

Remove all content from /tmp using rm -rf /tmp/*

5.4. Create/update the ramdisk image. This is broken down into several steps.

5.4.1. create mount points for ramdisk and root partition:

# mkdir /mnt/local_root

# mkdir /mnt/ramdisk_root

5.4.2. Create a virgin ramdisk image in /boot of size 65 MB with block size of 1k. It's important to note that the formatting process requires about 3 MB, so a ramdisk of 65 MB will have a useable size of around 62 MB:

# dd if=/dev/zero of=/boot/ramdisk.img bs=1k count=65000

5.4.3. Format the newly created ramdisk image as ext2:

# mkfs -t ext2 -i 1024 -b 1024 -F /boot/ramdisk.img

5.4.4. Mount the new ramdisk image and also mount (again) /:
# mount -o loop /boot/ramdisk.img /mnt/ramdisk_root
# mount -bind / /mnt/local_root

5.4.5. Copy everything including permissions and ownership from /mnt/local_root to /mnt/ramdisk_root:
# cp -a /mnt/local_root/* /mnt/ramdisk_root/

5.4.6. Create a new mount point in ramdisk image for which to mount the partition containing /var contents:
# mkdir /mnt/ramdisk_root/var_p && chmod 755 /mnt/ramdisk_root/var_p

5.4.7. Unmount /mnt/local_root:
# umount /mnt/local_root

5.4.8. Update /mnt/ramdisk_root/etc/fstab to reflect embedded mode changes. Below is an example fstab:

##################################################
/dev/ramdisk / ext2 defaults 0 0
/dev/hda1 /boot ext2 defaults,ro 0 0
/dev/hda7 /home ext2 defaults,ro 0 0
/dev/hda3 /usr ext2 defaults,ro 0 0
/dev/hda5 /var_p ext2 defaults,ro 0 0
none /tmp tmpfs size=50M 0 0
none /var tmpfs size=50M 0 0
none /dev/pts devpts gid=5,mode=620 0 0
none /proc proc defaults 0 0
/dev/cdrom /mnt/cdrom udf,iso9660 noauto,owner,kudzu,ro 0 0
##################################################

5.4.9. Update /mnt/ramdisk_root/etc/rc.sysinit to optimize functions performed during boot in embedded mode. Essentially, this entails 3 steps:

5.4.9.1. Comment out all lines pertaining to using swap (3 lines)

5.4.9.2. Immediately after the section for "Mounting local filesystems", add a command to copy the contents of /var_p/* to /var/:

cp -a /var_p/* /var/

5.4.9.3. Fix a conditional statement that causes errors related to heartbeat to be spewed forth during the execution of rc.sysinit at boot time. Specifically, the case statement starting with "case "`basename $afile`" in" should also have a case for heartbeat. Below is what the case block should look like (changes are in blue):

 

##############################################
# Clean up /var. I'd use find, but /usr may not be mounted.
for afile in /var/lock/* /var/run/* ; do
if [ -d "$afile" ]; then
case "`basename $afile`" in
news|mon) ;;
sudo) rm -f $afile/*/* ;;
heartbeat) ;;
*) rm -f $afile/* ;;
esac
else
rm -f $afile
fi
done
##############################################

5.4.10. Unmount /mnt/ramdisk_root:
# umount /mnt/ramdisk_root

5.4.11. Compress ramdisk image using gzip:
# gzip -f -9 /boot/ramdisk.img


6. Reboot and give it a try!


FACTS:

1. size of a full trustix 2.2 install (selected all configurations and marked everything; this is before any addon packages and/or updates were added):

/boot 2.2 MB
/ 50 MB
/swap n/a
/usr 1017 MB
/var 19 MB
/tmp 28 KB
/home 16 MB

2. size of trustix 2.2 install with everything except development packages (this is before any addon packages and/or updates were added):

/boot 2.2 MB
/ 43 MB
/swap n/a
/usr 446 MB
/var 12 MB
/tmp 23 KB
/home 694 KB

3. size of trustix 2.2 install with minimal and SSH (before addons and/or updates):

/boot 2.2 MB
/ 39 MB
/swap n/a
/usr 84 MB
/var 3.5 MB
/tmp 17 KB
/home 14 KB

Same install but added addons: heartbeat* and dependancies, webmin, and dansguardian:
/boot 2.2 MB
/ 41 MB
/swap n/a
/usr 231 MB
/var 6.8 MB
/tmp 20 KB
/home 54 KB

4. When booted into modify mode and updating system with swup, before running nw-update-ramdisk script, be sure no cdrom is mounted AND no more than two kernels are installed. There isn't enough space for more than two kernels. Also, after installing a new kernel, be sure to reboot at least once into modify mode so that the kernel is activated and symlinks in /boot are updated...may not be necessary...need to determine when symlinks get updated during a kernel upgrade.

Building rpms of additional packages for Trustix 2.2

dansguardian

After trying to rebuild the source and rpm for dansguardian, I was getting an error about an rpm macro referring to the initrd directory. Trustix doesn't have a builtin rpm macro for _initrddir, so I supplied one in the spec file and set it to /etc/init.d. Now, dansguardian builds fine and should install fine. In fact, any rpm that has this problem can be rebuilt for Trustix 2.2. I also changed the release to reflect the rpm is for tsl. Here's my dansguardian.spec file.

webmin

Only modified release to reflect the rpm is for tsl. Source rpm built with no problems.

heartbeat

Heartbeat including heartbeat-ldirectord has a number of dependencies, which were all rebuilt on a tsl build host.

1. Heartbeat source rpms can be downloaded from http://www.linux-ha.org/downloads/index.html.

2. First, to build heartbeat from the source rpm, I had to create a symlink for uuid:
ln -s /lib/libuuid.so.1 /lib/libuuid.so

After creating this, heartbeat would then build. However, this link may need to be created on target before heartbeat will run correctly. This has not yet been tested.

In addition, there were some dependencies left out of the spec file that came with the heartbeat source rpm, so have a look at my heartbeat.spec file for an accurate dependency list.

3. Next, I downloaded the following dependencies from http://www.ultramonkey.org/download/heartbeat/2.0.2/rhel3 (the remaining dependencies can be installed from a tsl mirror using swup). Notice that here I have names all lower case. When rebuilding a source rpm, I edited each package's spec file and made lower case all dependencies, package names, and provides. Trustix appears to have a standard of all packages being named with lower case letters, so I wanted these to follow that convention.

perl-crypt-ssleay-0.51
perl-io-socket-ssl-0.96
perl-ldap-0.3202
perl-mail-imapclient-2.2.9
perl-parse-recdescent-1.94
perl-uri-1.34
libnet-1.1.2.1
perl-xml-namespacesupport-1.08
perl-authen-sasl-2.08
perl-xml-sax-0.12
perl-convert-asn1-0.18

???
ipvsadm-1.21

4. I built all dependencies except ipvsadm without problem. I simply made any references to packages in the spec file lower case, appended .tsl2 to the release, and rebuilt the rpm and srpm.

5. To build ipvsadm, I first downloaded ipvsadm-1.21.11.src.rpm from linuxvirtualserver.org. Next, installed kernel-source package with swup (I was using kernel 2.4.32-1tr) and created symlink (ln -s /usr/src/kernel-source-2.4.32-1tr /usr/src/linux).

Several changes need to be made to ipvsadm source to accommodate the trustix environment. Specifically, all references to /etc/rc.d/init.d need to be updated to /etc/init.d. This was accomplished using patches and manual editing of the spec file. The spec file needed the initrddir macro define and used, release number updated to reflect a build for trustix 2.2, and patches added. Patches are Makefile.patch, ipvsadm.sh.patch, and ipvsadm.spec.patch and should be placed in the sources directory before the build process. Finally, new rpm and src.rpm were built (cd /usr/src/trustix; rpmbuild -ba specs/ipvsadm.spec)