Changes RSS

====== Differences ====== This shows you the differences between two versions of the page.

Link to this comparison view

testing:readonly-lenny [2009/03/17 19:10]
fishy oops
testing:readonly-lenny [2009/03/18 14:29] (current)
fishy New section...
Line 16: Line 16:
   * Partitioning: Manual, one partition, no swap   * Partitioning: Manual, one partition, no swap
   * Tasksel Install: Base system only.   * Tasksel Install: Base system only.
 +  * Non-root user: kitteh
  
 Post install:  Post install: 
Line 89: Line 90:
 ln -s /proc/mounts /etc/mtab ln -s /proc/mounts /etc/mtab
 </code> </code>
 +
 +Setting up /etc/fstab so that all locations where we will write data is a tempfs, in other words a memory filesystem. If the directories that are set up as tempfs here need to contain data after boot, those data will either be copied across by /etc/rcS.d/S36rosystem-fix or /etc/rc.local
  
 <code> <code>
-mkdir /var/local/data    +# <file system> <mount point>    <type>  <options>          <dump>  <pass> 
-mv resolv.conf /var/local/data/ +/dev/hdc1       /                ext3    defaults,noatime   0       0 
-ln -s /var/local/data/resolv.conf .+proc            /proc            proc    defaults 0 0 
 +tmpfs           /var/run         tmpfs   defaults 0 0 
 +tmpfs           /var/lock        tmpfs   defaults 0 0 
 +tmpfs           /var/local/data  tmpfs   defaults 0 0 
 +tmpfs           /var/log         tmpfs   defaults 0 0 
 +tmpfs           /tmp             tmpfs   defaults 0 0 
 +tmpfs           /var/lib/urandom tmpfs   defaults 0 0 
 +tmpfs           /var/lib/dhcp3   tmpfs   defaults 0 0 
 +tmpfs           /home            tmpfs   defaults 0 0
 </code> </code>
  
-/etc/fstab+Now, we need resolv.conf to be writable for dhclient, so it needs to be located somewhere outside of /etc 
 <code> <code>
-# <file system> <mount point>   <type>  <options>          <dump>  <pass> +mkdir /var/local/data    
-/dev/hdc1                     ext3    defaults,noatime   0       0 +mv resolv.conf /var/local/data
-proc            /proc           proc    defaults 0 0 +ln -s /var/local/data/resolv.conf /etc/resolv.conf
-tmpfs           /var/run        tmpfs   defaults 0 0 +
-tmpfs           /var/lock       tmpfs   defaults 0 0 +
-tmpfs           /var/log        tmpfs   defaults 0 0 +
-tmpfs           /tmp            tmpfs   defaults 0 0 +
-tmpfs           /var/lib/dhcp3/ tmpfs   defaults 0 0+
 </code> </code>
 +
 +Now, we need to have the dhclient-script (runs while/after dhclient is run) update the writable resolv.conf, instead of trying to replace our link on the read-only part of the system. This is sed-magic, to really see what this does, make a copy of /sbin/dhclient-script, and diff it afterwards...
  
 <code> <code>
Line 112: Line 121:
     -e '/local new_/s/=.*/=\/tmp\/resolv.conf.dhclient-new/' \     -e '/local new_/s/=.*/=\/tmp\/resolv.conf.dhclient-new/' \
     -e '/mv -f/s/mv -f.*/cat $new_resolv_conf > \/etc\/resolv.conf/' \     -e '/mv -f/s/mv -f.*/cat $new_resolv_conf > \/etc\/resolv.conf/' \
-    -i dhclient-script+    -i /sbin/dhclient-script
 </code> </code>
  
-For clarity, this is the result of the above command....+Just verify that network settings are appropriate for our/your/the networkI am using DHCP to configure, so i end up with:
 <code> <code>
-diff dhclient-script* +cat /etc/network/interfaces 
-17c17 +
-<         local new_resolv_conf=/etc/resolv.conf.dhclient-new +
---- +
->         local new_resolv_conf=/tmp/resolv.conf.dhclient-new +
-48c48 +
-<         mv -f $new_resolv_conf /etc/resolv.conf +
---- +
->         cat $new_resolv_conf > /etc/resolv.conf+
 </code> </code>
- 
 <code> <code>
-cat /etc/network/interfaces  
 auto lo auto lo
 iface lo inet loopback iface lo inet loopback
Line 135: Line 134:
 iface eth0 inet dhcp iface eth0 inet dhcp
 </code> </code>
 +
 +ifupdown insists on writing a status file to /etc/network/run, so that location needs to be redirected to a tmpfs location. Note that the directory /var/local/data/network_run is created on boot by /etc/rcS.d/S36rosystem-fix, which
 +will be created later on..
  
 <code> <code>
-apt-get install syslogd+rm /etc/network/run 
 +mkdir /var/local/data/network_run 
 +ln -s /var/local/data/network_run /etc/network/run 
 +rmdir /var/local/data/network_run
 </code> </code>
 +
 +Debian uses udev and hotplug since, well, a long time now. It is set up to assign each ethernet adaper a separate device name, based on the MAC-address and/or the kernel-driver used. We do not want to save any persistent ethernet device data, and we want to use eth0 as the networking device. So, we have to remove the udev-definitions of “persistent devicenames”. The definition for persistent net device names are located in /etc/udev/rules.d/70-persistent-net.rules. Edit this file by hand, or use the following sed line:
  
 <code> <code>
 + sed -e '/^SUBSYSTEM=="net".*eth/D' -e '/^$/D' \
 +     -e '/^# PCI device/D' \
 +     -e '/^$/D' \
 +     -i /etc/udev/rules.d/70-persistent-net.rules
 +</code>
 +
 +We install syslogd for logging, and remove all references to xconsole from the configuration. At a later stage, it will be configured to send its log data to a central logging server, and not buffer any logging locally.
 +<code>
 +apt-get install syslogd
 sed -e '/xconsole/s/^/#/' -i /etc/syslog.conf  sed -e '/xconsole/s/^/#/' -i /etc/syslog.conf 
 </code> </code>
 +
 +In the fstab listed above, the root filesystem is mounted with "defaults,noatime". That normally implies that the file system is mounted read-write. But we want read-only. This is fixed by changing the default "rootmode" in /etc/init.d/checkroot.sh from "rw" to "ro". It _could_ also be done by setting "ro" on the kernel boot lines in /boot/grub/menu.lst, but previous experience shows that this may sometimes not be honored. So, forcing it is perhaps not the best way, but still the most "stable" way((Most stable as long as we do not upgrade to a new release of Debian, that is...)). 
  
 <code> <code>
 sed -e 's/rootmode=rw/rootmode=ro/' -i /etc/init.d/checkroot.sh  sed -e 's/rootmode=rw/rootmode=ro/' -i /etc/init.d/checkroot.sh 
 </code> </code>
 +
 +I have referenced the file /etc/rcS.d/S36rosystem-fix a few times now. This file is a init-script-hack that sets up a few locations and files that are needed right after the mount of local filesystems. I'm not listing the entire file here, to examine the content, and what it does, check out the current version at http://dilbert.hig.no/jonl/rosystem-fix.txt 
 +
 +The file is placed in /etc/init.d as normal, set executable, and symlinked into /etc/rcS.d. The number is chosen so that it is run right after mountlocal-bootmisc.sh.
  
 <code> <code>
-sed -e '/\.clean$/s/$/\n\ttouch \/var\/log\/dmesg/-/etc/init.d/bootmisc.sh +wget http://dilbert.hig.no/jonl/rosystem-fix.txt -O /etc/init.d/rosystem-fix 
 +chmod 755 /etc/init.d/rosystem-fix 
 +ln -s /etc/init.d/rosystem-fix /etc/rcS.d/S36rosystem-fix
 </code> </code>
 +
 +The final changes done to the prototype image, is to set up a pair of handy aliases to remount the root filesystem in
 +read-write and read-only setups, respectively.
  
 <code> <code>
Line 158: Line 185:
  
  
 +===== Transferring back =====
 +
 +Transferring the image back is simply a task of unmounting the loopmount, and dumping the resulting image back onto the CF card.
 +
 +Unmounting first...
 +<code>
 +exit
 +cd ~
 +sudo umount -l /mnt/proc
 +sudo umount -l /mnt/dev/
 +sudo umount /mnt/
 +</code>
 +
 +And dumping the image back. Yes, I am using 'cat'. I should have used 'dd'. But both tools do the same job, so, why bother with complexity when you can have simplicity...
 +
 +<code>
 +sudo cat lenny_testimg1.img > /dev/sdb
 +</code>
 +
 +
 +===== Booting up, verifying =====
 +
 +After tanking up the CF image, the card is moved back to the eBOX, and the eBOX is booted up. While the system is booting, check closely for stuff that fails, and verify that all essential systems start up OK.
 +
 +In the first iteration, I had a whole lot of errors. I went though them and corrected all the critical ones, and updated this document to reflect the corrections. The corrections that I was not able to fix by cleanly modifying existing startup scripts, or doing bind-mounts or tempfs mounts, are fixed in the rosystem-fix startup script. So, if you follow this walkthrough, and have errors, the likely places to put your fixes will be in /etc/fstab and /etc/init.d/rosystem-fix.
 +
 +After booting up, the next task is to make this a kind of Kiosk; i.e. starting a web browser in full screen...
 +
 +===== X Server installation =====
 +
 +I decided to try to keep the X Server installation small, but not super-small ;) By using apt, a bunch of dependencies that are not really needed are pulled in, but at least it is not as bloated as it would be, had I pulled in a complete desktop meta-package.
 +
 +First: set the filesystem writable....
 +
 +<code>
 +rw
 +</code>
 +
 +<code>
 +apt-get install pci-utils dbus dbus-x11 defoma x11-apps x11-session-utils x11-utils  \
 +                x11-xserver-utils xfonts-base  xserver-xorg-input-kbd \
 +                xserver-xorg-input-mouse xserver-xorg-video-dummy xserver-xorg-video-openchrome \
 +                xserver-xorg-video-vesa xserver-xorg-video-vga xinit cpp cpp-4.3 xserver-xorg \
 +                xserver-xorg-core xfs xfonts-100dpi xfonts-75dpi xfonts-scalable ttf-dejavu \
 +                ttf-freefont gtk2-engines xterm blackbox iceweasel unclutter
 +</code>
 +
 +We need some additional fonts for our setup. Note that we add the "contrib" package of Microsoft Core fonts. No religious views here, we allow non-free stuff in... Klavika is a font that is used extensively in the GUC visual profile.
 +
 +<code>
 +echo "deb http://ftp.no.debian.org/debian/ lenny contrib" >> /etc/apt/sources.list
 +echo "deb http://ftp.no.debian.org/debian/ lenny non-free" >> /etc/apt/sources.list
 +apt-get update
 +apt-get install msttcorefonts
 +cd /tmp
 +wget http://dilbert.hig.no/jonl/klavika.tar.bz2
 +cd /usr/share/fonts
 +tar jxvf /tmp/klavika.tar.bz2
 +fc-cache -f -v
 +fc-list | grep Kl # to confirm the install
 +</code>
 +
 +The Xorg configuration will need to be tweaked to the display the Kiosk is to run with.
 +
 +Finally, the filesystem is set read-only again.
 +<code>
 +ro
 +</code>
 +
 +===== Setting up the Kiosk function... =====
 +
 +With X up and running, and the filesystem back in read-only mode, make sure the non-root user crated during install is available for use, by setting up the home directory:
 +
 +<code>
 +mkdir /home/kitteh
 +chown kitteh.kittteh /home/kitteh
 +</code>
 +
 +Now, either switch to a different VT, or log out root. Log in as the non-root user created during install, create a simple ~/.xinitrc:
 +
 +<code>
 +# File: /home/kitteh/.xinitrc
 +xterm &
 +blackbox
 +</code>
 +
 +Start up X:
 +
 +<code>
 +startx
 +</code>
 +
 +Now, start up iceweasel (yeah, firefox is not called firefox, but iceweasel on Debian, due to licensing issues). Install the Autohide extension from http://www.krickelkrackel.de/autohide/, and configure it for the local user. By enabling this extension, and exiting iceweasel while it is displayed fullscreen, iceweasel will "always" start in full-screen mode.
 +
 +After setting iceweasel up, update the .xinitrc:
 +
 +<code>
 +# File: /home/kitteh/.xinitrc
 +xsetroot -solid white &
 +xset -dpms s off &
 +unclutter &
 +xterm -iconic &
 +iceweasel http://the.url.of.the.kiosk.example.com &
 +blackbox
 +</code>
 +
 +After this, exit X11, test that it works OK, and exit the non-root login completely.
 +
 +Now, we need to retain the settings made from boot to boot. /home is mounted as a tmpfs, so we need to clone the kitteh
 +home directory somewhere else on the file system, and push it back in place on boot. Log in as root..
 +
 +<code>
 +rw
 +cp -pRv /home/kitteh /usr/local/kitteh
 +</code>
 +
 +Add  the following to /etc/rc.local to clone the saved homedir content on boot:
 +<code>
 +cp -R /usr/local/kitteh /home/kitteh
 +chown -R kitteh.kitteh /home/kitteh
 +</code>
 +
 +I have opted to force X to start on boot by running it from /etc/rc.local as well, by adding this line
 +just above "exit 0":
 +
 +<code>
 +su -c "startx" kitteh
 +</code>
 +
 +Now, X will normally not start unless the user starting it is also controlling the console. As I am starting X from an rc-script, that is not the case. So, to allow rc.local starting X as the user "kitteh", put the following content in 
 +/etc/X11/Xwrapper.config
 +
 +<code>
 +# Keeping the old setting as a comment, for clarity...
 +# allowed_users=console
 +#
 +# This is not really seen as "safe", but in our case, it is needed..
 +allowed_users=anybody
 +#
 +# Niceness value? Nah....
 +nice_value=0
 +</code>
 +
 +That should really be enough for starters. Close everything up, set the file system as read only again, and reboot.
 +
 +<code>
 +ro
 +reboot
 +</code>