<!-- Copyright (c) 2001 The FreeBSD Documentation Project

     Redistribution and use in source (SGML DocBook) and 'compiled' forms
     (SGML, HTML, PDF, PostScript, RTF and so forth) with or without
     modification, are permitted provided that the following conditions
     are met:

      1. Redistributions of source code (SGML DocBook) must retain the above
         copyright notice, this list of conditions and the following
         disclaimer as the first lines of this file unmodified.

      2. Redistributions in compiled form (transformed to other DTDs,
         converted to PDF, PostScript, RTF and other formats) must reproduce
         the above copyright notice, this list of conditions and the
         following disclaimer in the documentation and/or other materials
         provided with the distribution.

     THIS DOCUMENTATION IS PROVIDED BY THE FREEBSD DOCUMENTATION PROJECT "AS
     IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NIK CLAYTON BE LIABLE FOR ANY
     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE
     POSSIBILITY OF SUCH DAMAGE.

     $FreeBSD$
-->

<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook V4.1-Based Extension//EN" [
<!ENTITY % articles.ent PUBLIC "-//FreeBSD//ENTITIES DocBook FreeBSD Articles Entity Set//EN">
%articles.ent;
<!ENTITY legalnotice SYSTEM "../../share/sgml/legalnotice.sgml">
]>

<article>
  <articleinfo>
    <title>FreeBSD and Solid State Devices</title>

    <authorgroup>
      <author>
	<firstname>John</firstname>
	<surname>Kozubik</surname>

	<affiliation>
	  <address><email>john@kozubik.com</email></address>
	</affiliation>
      </author>
    </authorgroup>
    
    <pubdate>$FreeBSD$</pubdate>

    <copyright>
      <year>2001</year>
      <holder>The FreeBSD Documentation Project</holder>
    </copyright>

    <legalnotice id="trademarks" role="trademarks">
      &tm-attrib.freebsd;
      &tm-attrib.m-systems;
      &tm-attrib.general;
    </legalnotice>

    &legalnotice;
    
    <abstract>
      <para>This article covers the use of solid state disk devices in FreeBSD
	to create embedded systems.</para>
    
      <para>Embedded systems have the advantage of increased stability due to
	the lack of integral moving parts (hard drives).  Account must be
	taken, however, for the generally low disk space available in the
	system and the durability of the storage medium.</para>

      <para>Specific topics to be covered include the types and attributes of
	solid state media suitable for disk use in FreeBSD, kernel options
	that are of interest in such an environment, the
	<filename>rc.diskless</filename> mechanisms that automate the
	initialization of such systems and the need for read-only filesystems,
	and building filesystems from scratch.  The article will conclude
	with some general strategies for small and read-only FreeBSD
	environments.</para>
    </abstract>
  </articleinfo>

  <sect1 id="intro">
    <title>Solid State Disk Devices</title>

    <para>The scope of this article will be limited to solid state disk
      devices made from flash memory.  Flash memory is a solid state memory
      (no moving parts) that is non-volatile (the memory maintains data even
      after all power sources have been disconnected).  Flash memory can
      withstand tremendous physical shock and is reasonably fast (the flash
      memory solutions covered in this article are slightly slower than a EIDE
      hard disk for write operations, and much faster for read operations).
      One very important aspect of flash memory, the ramifications of which
      will be discussed later in this article, is that each sector has a
      limited rewrite capacity.  You can only write, erase, and write again to
      a sector of flash memory a certain number of times before the sector
      becomes permanently unusable.  Although many flash memory products
      automatically map bad blocks, and although some even distribute write
      operations evenly throughout the unit, the fact remains that there
      exists a limit to the amount of writing that can be done to the device.
      Competitive units have between 1,000,000 and 10,000,000 writes per
      sector in their specification.  This figure varies due to the
      temperature of the environment.</para>

    <para>Specifically, we will be discussing ATA compatible compact-flash
      units and the M-Systems &diskonchip; flash memory unit.  ATA compatible
      compact-flash cards are quite popular as storage media for digital
      cameras.  Of particular interest is the fact that they pin out directly
      to the IDE bus and are compatible with the ATA command set.  Therefore,
      with a very simple and low-cost adaptor, these devices can be attached
      directly to an IDE bus in a computer.  Once implemented in this manner,
      operating systems such as FreeBSD see the device as a normal hard disk
      (albeit small).  The M-Systems &diskonchip; product is based on the same
      underlying flash memory technology as ATA compatible compact-flash
      cards, but resides in a DIP form factor and is not ATA compatible.  To
      use such a device, not only must you install it on a motherboard that
      has a &diskonchip; socket, you must also build the `fla` driver into any
      FreeBSD kernel you wish to use it with.  Further, there is critical,
      manufacturer-specific data residing in the boot sector of this device,
      so you must take care not to install the FreeBSD (or any other) boot
      loader when using this.</para>

    <para>Other solid state disk solutions do exist, but their expense,
      obscurity, and relative unease of use places them beyond the scope of
      this article.</para>
  </sect1>

  <sect1 id="kernel">
      <title>Kernel Options</title>

    <para>A few kernel options are of specific interest to those creating
      an embedded FreeBSD system.</para>

    <para>First, all embedded FreeBSD systems that use flash memory as system
      disk will be interested in memory disks and memory filesystems.  Because
      of the limited number of writes that can be done to flash memory, the
      disk and the filesystems on the disk will most likely be mounted
      read-only.  In this environment, filesystems such as
      <filename>/tmp</filename> and <filename>/var</filename> are mounted as
      memory filesystems to allow the system to create logs and update
      counters and temporary files.  Memory filesystems are a critical
      component to a successful solid state FreeBSD implementation.</para>

    <para>You should make sure the following lines exist in your kernel
      configuration file:</para>

    <programlisting>options         MFS             # Memory Filesystem
options         MD_ROOT         # md device usable as a potential root device
pseudo-device   md              # memory disk</programlisting>

    <para>Second, if you will be using the M-Systems &diskonchip; product, you
      must also include this line:</para>

    <programlisting>device          fla0    at isa?</programlisting>
  </sect1>

  <sect1 id="ro-fs">
    <title><filename>rc.diskless</filename> and Read-Only Filesystems</title>

    <para>The post-boot initialization of an embedded FreeBSD system is
      controlled by <filename>/etc/rc.diskless2</filename>
      (<filename>/etc/rc.diskless1</filename> is for BOOTP diskless boot).
      This initialization script is invoked by placing a line in
      <filename>/etc/rc.conf</filename> as follows:</para>

    <programlisting>diskless_mount=/etc/rc.diskless2</programlisting>

    <para><filename>rc.diskless2</filename> mounts <filename>/var</filename>
      as a memory filesystem, makes a configurable list of directories in
      <filename>/var</filename> with the &man.mkdir.1; command, changes modes
      on some of those directories, and extracts a list of device entries to
      copy to a writable (again, a memory filesystem)
      <filename>/dev</filename> partition.  In the execution of
      <filename>/etc/rc.diskless2</filename>, one other
      <filename>rc.conf</filename> variable comes into play -
      <literal>varsize</literal>.  The <filename>/etc/rc.diskless2</filename>
      file creates a <filename>/var</filename> partition based on the value of
      this variable in <filename>rc.conf</filename>:</para>

    <programlisting>varsize=8192</programlisting>

    <para>Remember that this value is in sectors.  The creation of the
      <filename>/dev</filename> partition by
      <filename>/etc/rc.diskless2</filename>, however, is governed by a
      hard-coded value of 4096 sectors.  It is trivial to change this entry in
      the <filename>/etc/rc.diskless2</filename> file itself, although you
      should not need more space than that for
      <filename>/dev</filename>.</para>

    <para>It is important to remember that the
      <filename>/etc/rc.diskless2</filename> script assumes that you have
      already removed your conventional <filename>/tmp</filename> partition
      and replaced it with a symbolic link to <filename>/var/tmp</filename>.
      Because <filename>tmp</filename> is one of the directories created in
      <filename>/var</filename> by the <filename>/etc/rc.diskless2</filename>
      script, and because <filename>/var</filename> is a memory filesystem
      (which is mounted read-write), <filename>/tmp</filename> will now be a
      directory that is read-write as well.</para>

    <para>The fact that <filename>/var</filename> and
      <filename>/dev</filename> are read-write filesystems is an important
      distinction, as the <filename>/</filename> partition (and any other
      partitions you may have on your flash media) should be mounted
      read-only.  Remember that in <xref linkend="intro"> we detailed the
      limitations of flash memory - specifically the limited write capability.
      The importance of not mounting filesystems on flash media read-write,
      and the importance of not using a swap file, cannot be overstated.  A
      swap file on a busy system can burn through a piece of flash media in
      less than one year. Heavy logging or temporary file creation and
      destruction can do the same.  Therefore, in addition to removing the
      <literal>swap</literal> and <literal>/proc</literal> entries from your
      <filename>/etc/fstab</filename> file, you should also change the Options
      field for each filesystem to <literal>ro</literal> as follows:</para>

    <programlisting># Device                Mountpoint      FStype  Options         Dump    Pass#
/dev/ad0s1a             /               ufs     ro              1       1</programlisting>

    <para>A few applications in the average system will immediately begin to
      fail as a result of this change.  For instance, ports will not install
      from the ports tree because the
      <filename>/var/db/port.mkversion</filename> file does not exist.  cron
      will not run properly as a result of missing cron tabs in the
      <filename>/var</filename> created by
      <filename>/etc/rc.diskless2</filename>, and syslog and dhcp will
      encounter problems as well as a result of the read-only filesystem and
      missing items in the <filename>/var</filename> that
      <filename>/etc/rc.diskless2</filename> has created.  These are only
      temporary problems though, and are addressed, along with solutions to
      the execution of other common software packages in
      <xref linkend="strategies">.</para>

    <para>An important thing to remember is that a filesystem that was mounted
      read-only with <filename>/etc/fstab</filename> can be made read-write at
      any time by issuing the command:</para>

    <screen>&prompt.root; <userinput>/sbin/mount -uw <replaceable>partition</replaceable></userinput></screen>

    <para>and can be toggled back to read-only with the command:</para>

    <screen>&prompt.root; <userinput>/sbin/mount -ur <replaceable>partition</replaceable></userinput></screen>
  </sect1>

  <sect1>
    <title>Building a File System From Scratch</title>

    <para>Because ATA compatible compact-flash cards are seen by FreeBSD as
      normal IDE hard drives, as is a M-Systems &diskonchip; product (when you
      are running a kernel with the fla driver built in) you could
      theoretically install FreeBSD from the network using the kern and
      mfsroot floppies or from a CD.  Other than the fact that you should not
      write a boot-loader of any kind to the M-Systems device, no special
      instructions are needed.</para>

    <para>However, even a small installation of FreeBSD using normal
      installation procedures can produce a system in size of greater than 200
      megabytes.  Because most people will be using smaller flash memory
      devices (128 megabytes is considered fairly large - 32 or even 16
      megabytes is common) an installation using normal mechanisms is not
      possible&mdash;there is simply not enough disk space for even the
      smallest of conventional installations.</para>

    <para>The easiest way to overcome this space limitation is to install
      FreeBSD using conventional means to a normal hard disk.  After the
      installation is complete, pare down the operating system to a size that
      will fit onto your flash media, then tar the entire filesystem.  The
      following steps will guide you through the process of preparing a piece
      of flash memory for your tarred filesystem.  Remember, because a normal
      installation is not being performed, operations such as partitioning,
      labeling, file-system creation, etc. need to be performed by hand.  In
      addition to the kern and mfsroot floppy disks, you will also need to use
      the fixit floppy.  If you are using a M-Systems &diskonchip;, the kernel
      on your kern floppy must have the <literal>fla</literal> option detailed
      in <xref linkend="kernel"> compiled into it.  Please see
      <xref linkend="kern.flp"> for instructions on creating a new kernel for
      <filename>kern.flp</filename>.</para>

    <procedure>
      <step>
	<title>Partitioning your flash media device</title>

	<para>After booting with the kern and mfsroot floppies, choose
	  <literal>custom</literal> from the installation menu.  In the custom
	  installation menu, choose <literal>partition</literal>.  In the
	  partition menu, you should delete all existing partitions using the
	  <keycap>d</keycap> key.  After deleting all existing partitions,
	  create a partition using the <keycap>c</keycap> key and accept the
	  default value for the size of the partition.  When asked for the
	  type of the partition, make sure the value is set to
	  <literal>165</literal>.  Now write this partition table to the disk
	  by pressing the <keycap>w</keycap> key (this is a hidden option on
	  this screen).  When presented with a menu to choose a boot manager,
	  take care to select <literal>None</literal> if you are using an
	  M-Systems &diskonchip;.  If you are using an ATA compatible compact
	  flash card, you should choose the FreeBSD Boot Manager.  Now press
	  the <keycap>q</keycap> key to quit the partition menu.  You will be
	  shown the boot manager menu once more - repeat the choice you made
	  earlier.</para>
      </step>

      <step>
	<title>Creating filesystems on your flash memory device</title>

	<para>Exit the custom installation menu, and from the main
	  installation menu choose the <literal>fixit</literal> option.  After
	  entering the fixit environment, enter the following commands:</para>

	<informaltable frame="none" pgwide="1">
	  <tgroup cols="2">
	    <thead>
	      <row>
		<entry align="center">ATA compatible</entry>

		<entry align="center">&diskonchip;</entry>
	      </row>
	    </thead>
	    <tbody>
	      <row>
		<entry><para><screen>&prompt.root; <userinput>mknod /dev/ad0a c 116 0</userinput>
&prompt.root; <userinput>mknod /dev/ad0c c 116 2</userinput>		      
&prompt.root; <userinput>disklabel -e /dev/ad0c</userinput></screen></para></entry>

		<entry><para><screen>&prompt.root; <userinput>mknod /dev/fla0a c 102 0</userinput>
&prompt.root; <userinput>mknod /dev/fla0c c 102 2</userinput>
&prompt.root; <userinput>disklabel -e /dev/fla0c</userinput></screen></para></entry>
	      </row>
	    </tbody>
	  </tgroup>
	</informaltable>

	<para>At this point you will have entered the vi editor under the
	  auspices of the disklabel command.  If you are using &diskonchip;,
	  the first step will be to change the type value near the beginning
	  of the file from <literal>ESDI</literal> to
	  <literal>DOC2K</literal>.  Next, regardless of whether you are using
	  &diskonchip; or ATA compatible compact flash media, you need to add
	  an <literal>a:</literal> line at the end of the file.  This
	  <literal>a:</literal> line should look like:</para>

	<programlisting>a:      <replaceable>123456</replaceable>  0       4.2BSD  0       0</programlisting>

	<para>Where <replaceable>123456</replaceable> is a number that is
	  exactly the same as the number in the existing <literal>c:</literal>
	  entry for size. Basically you are duplicating the existing
	  <literal>c:</literal> line as an <literal>a:</literal> line, making
	  sure that fstype is <literal>4.2BSD</literal>.  Save the file and
	  exit.</para>

	<informaltable frame="none" pgwide="1">
	  <tgroup cols="2">
	    <thead>
	      <row>
		<entry align="center">ATA compatible</entry>

		<entry align="center">&diskonchip;</entry>
	      </row>
	    </thead>
	    <tbody>
	      <row>
		<entry><para><screen>&prompt.root; <userinput>disklabel -B -r /dev/ad0c</userinput>
&prompt.root; <userinput>newfs /dev/ad0a</userinput></screen></para></entry>

		<entry><para><screen>&prompt.root; <userinput>disklabel -B -r /dev/fla0c</userinput>
&prompt.root; <userinput>newfs /dev/fla0a</userinput></screen></para></entry>
	      </row>
	    </tbody>
	  </tgroup>
	</informaltable>
      </step>

      <step>
	<title>Placing your filesystem on the flash media</title>

	<para>Mount the newly prepared flash media:</para>

	<informaltable frame="none" pgwide="1">
	  <tgroup cols="2">
	    <thead>
	      <row>
		<entry align="center">ATA compatible</entry>

		<entry align="center">&diskonchip;</entry>
	      </row>
	    </thead>
	    <tbody>
	      <row>
		<entry><para><screen>&prompt.root; <userinput>mount /dev/ad0a /flash</userinput></screen></para></entry>

		<entry><para><screen>&prompt.root; <userinput>mount /dev/fla0a /flash</userinput></screen></para></entry>
	      </row>
	    </tbody>
	  </tgroup>
	</informaltable>
	
	<para>Bring this machine up on the network so we may transfer our tar
	  file and explode it onto our flash media filesystem.  One example of
	  how to do this is:</para>

	<screen>&prompt.root; <userinput>ifconfig xl0 192.168.0.10 netmask 255.255.255.0</userinput>
&prompt.root; <userinput>route add default 192.168.0.1</userinput></screen>

	<para>Now that the machine is on the network, transfer your tar file.
	  You may be faced with a bit of a dilemma at this point - if your
	  flash memory part is 128 megabytes, for instance, and your tar file
	  is larger than 64 megabytes, you cannot have your tar file on the
	  flash media at the same time as you explode it - you will run out of
	  space.  One solution to this problem, if you are using FTP, is to
	  untar the file while it is transferred over FTP.  If you perform
	  your transfer in this manner, you will never have the tar file and
	  the tar contents on your disk at the same time:</para>

	<screen><prompt>ftp></prompt> <userinput>get tarfile.tar "| tar xvf -"</userinput></screen>

	<para>If your tarfile is gzipped, you can accomplish this as
	  well:</para>

	<screen><prompt>ftp></prompt> <userinput>get tarfile.tar "| zcat | tar xvf -"</userinput></screen>

	<para>After the contents of your tarred filesystem are on your flash
	  memory filesystem, you can unmount the flash memory and
	  reboot:</para>

	<screen>&prompt.root; <userinput>cd /</userinput>
&prompt.root; <userinput>umount /flash</userinput>
&prompt.root; <userinput>exit</userinput></screen>

	<para>Assuming that you configured your filesystem correctly when it
	  was built on the normal hard disk (with your filesystems mounted
	  read-only, and with the necessary options compiled into the kernel)
	  you should now be successfully booting your FreeBSD embedded
	  system.</para>
      </step>
    </procedure>
  </sect1>

  <sect1 id="kern.flp">
    <title>Building a <filename>kern.flp</filename> Installation Floppy with
      the fla Driver</title>

    <note>
      <para>This section of the article is relevant only to those using
	M-Systems &diskonchip; flash media.</para>
    </note>

    <para>It is possible that your <filename>kern.flp</filename> boot floppy
      does not have a kernel with the <devicename>fla</devicename> driver
      compiled into it necessary for the system to recognize the &diskonchip;.
      If you have booted off of the installation floppies and are told that no
      disks are present, then you are probably lacking the
      <devicename>fla</devicename> driver in your kernel.</para>

    <para>After you have built a kernel with <devicename>fla</devicename>
      support that is smaller than 1.4 megabytes, you can create a custom
      <filename>kern.flp</filename> floppy image with it by following these
      instructions:</para>

    <procedure>
      <step>
	<para>Obtain an existing kern.flp image file</para>
      </step>

      <step>
	<para><screen>&prompt.root; <userinput>vnconfig vn0c kern.flp</userinput></screen></para>
      </step>

      <step>
	<para><screen>&prompt.root; <userinput>mount /dev/vn0c /mnt</userinput></screen></para>
      </step>
      
      <step>
	<para>Place your kernel file into <filename>/mnt</filename>, replacing
	  the existing one</para>
      </step>

      <step>
	<para><screen>&prompt.root; <userinput>vnconfig -d vn0c</userinput></screen></para>
      </step>
    </procedure>

    <para>Your <filename>kern.flp</filename> file now has your new kernel on it.</para>
  </sect1>

  <sect1 id="strategies">
    <title>System Strategies for Small and Read Only Environments</title>

    <para>In <xref linkend="ro-fs">, it was pointed out that the
      <filename>/var</filename> filesystem constructed by
      <filename>/etc/rc.diskless2</filename> and the presence of a read-only
      root filesystem causes problems with many common software packages used
      with FreeBSD.  In this article, suggestions for successfully running
      cron, syslog, ports installations, and the Apache web server will be
      provided.</para>

    <sect2>
      <title>cron</title>

      <para>In <filename>/etc/rc.diskless2</filename> there is a variable
	named <literal>var_dirs</literal>.  This variable consists of a
	space-delimited list of directories that will be created inside of
	<filename>/var</filename> after it is mounted as a memory filesystem.
	<filename>cron</filename> and <filename>cron/tabs</filename> are not
	in that list, and without those directories, cron will complain.  By
	inserting <literal>cron</literal>, <literal>cron/tabs</literal>, and
	perhaps even <literal>at</literal>, and <literal>at/jobs</literal> as
	elements of that variable, you will facilitate the running of the
	&man.cron.8; and &man.at.1; daemons.</para>

      <para>However, this still does not solve the problem of maintaining cron
	tabs across reboots.  When the system reboots, the
	<filename>/var</filename> filesystem that is in memory will disappear
	and any cron tabs you may have had in it will also disappear.
	Therefore, one solution would be to create cron tabs for the users
	that need them, mount your <filename>/</filename> filesystem as
	read-write and copy those cron tabs to somewhere safe, like
	<filename>/etc/tabs</filename>, then add a line to the end of
	<filename>/etc/rc.diskless2</filename> that copies those crontabs into
	<filename>/var/cron/tabs</filename> after that directory has been
	created during system initialization.  You may also need to add a line
	that changes modes and permissions on the directories you create and
	the files you copy with <filename>/etc/rc.diskless2</filename>.</para>
    </sect2>

    <sect2>
      <title>syslog</title>

      <para><filename>syslog.conf</filename> specifies the locations of
	certain log files that exist in <filename>/var/log</filename>.  These
	files are not created by <filename>/etc/rc.diskless2</filename> upon
	system initialization. Therefore, somewhere in
	<filename>/etc/rc.diskless2</filename>, after the section that creates
	the directories in <filename>/var</filename>, you will need to add
	something like this:</para>

      <screen>&prompt.root; <userinput>touch /var/log/security /var/log/maillog /var/log/cron /var/log/messages</userinput>
&prompt.root; <userinput>chmod 0644 /var/log/*</userinput></screen>

      <para>You will also need to add the log directory to the list of
	directories that <filename>/etc/rc.diskless2</filename>
	creates.</para>
    </sect2>

    <sect2>
      <title>ports installation</title>

      <para>Before discussing the changes necessary to successfully use the
	ports tree, a reminder is necessary regarding the read-only nature of
	your filesystems on the flash media.  Since they are read-only, you
	will need to temporarily mount them read-write using the mount syntax
	shown in <xref linkend="ro-fs">.  You should always remount those
	filesystems read-only when you are done with any maintenance -
	unnecessary writes to the flash media could considerably shorten its
	lifespan.</para>

      <para>To make it possible to enter a ports directory and successfully
	run <command>make install</command>, it is necessary for the file
	<filename>/var/db/port.mkversion</filename> to exist, and that it has
	a correct date in it.  Further, we must create a packages directory on
	a non-memory filesystem that will keep track of our packages across
	reboots. Because it is necessary to mount your filesystems as
	read-write for the installation of a package anyway, it is sensible to
	assume that an area on the flash media can also be used for package
	information to be written to.</para>

      <para>First, create a package database directory.  This is normally in
	<filename>/var/db/pkg</filename>, but we cannot place it there as it
	will disappear every time the system is booted.</para>

      <screen>&prompt.root; <userinput>mkdir /etc/pkg</userinput></screen>

      <para>Now, add a line to <filename>/etc/rc.diskless2</filename> that
	links the <filename>/etc/pkg</filename> directory to
	<filename>/var/db/pkg</filename>.  An example:</para>

      <screen>&prompt.root; <userinput>ln -s /etc/pkg /var/db/pkg</userinput></screen>
      
      <para>Add another line in <filename>/etc/rc.diskless2</filename> that
	creates and populates
	<filename>/var/db/port.mkversion</filename></para>

      <screen>&prompt.root; <userinput>touch /var/db/port.mkversion</userinput>
&prompt.root; <userinput>chmod 0644 /var/db/port.mkversion</userinput>
&prompt.root; <userinput>echo <replaceable>20010412</replaceable> >> /var/db/port.mkversion</userinput></screen>

      <para>where <replaceable>20010412</replaceable> is a date that is
	appropriate for your particular release of FreeBSD</para>

      <para>Now, any time that you mount your filesystems as read-write and
	install a package, the <command>make install</command> will work
	because it finds a suitable
	<filename>/var/db/port.mkversion</filename>, and package information
	will be written successfully to <filename>/etc/pkg</filename> (because
	the filesystem will, at that time, be mounted read-write) which will
	always be available to the operating system as
	<filename>/var/db/pkg</filename>.</para>
    </sect2>

    <sect2>
      <title>Apache Web Server</title>

      <para>Apache keeps pid files and logs in
	<filename><replaceable>apache_install</replaceable>/logs</filename>.
	Since this directory doubtless exists on a read-only filesystem, this
	will not work.  It is necessary to add a new directory to the
	<filename>/etc/rc.diskless2</filename> list of directories to create
	in <filename>/var</filename>, to link
	<filename><replaceable>apache_install</replaceable>/logs</filename> to
	<filename>/var/log/apache</filename>.  It is also necessary to set
	permissions and ownership on this new directory.</para>

      <para>First, add the directory <literal>log/apache</literal> to the list
	of directories to be created in
	<filename>/etc/rc.diskless2</filename>.</para>
      
      <para>Second, add these commands to
	<filename>/etc/rc.diskless2</filename> after the directory creation
	section:</para>

      <screen>&prompt.root; <userinput>chmod 0774 /var/log/apache</userinput>
&prompt.root; <userinput>chown nobody:nobody /var/log/apache</userinput></screen>

      <para>Finally, remove the existing
	<filename><replaceable>apache_install</replaceable>/logs</filename>
	directory, and replace it with a link:</para>

      <screen>&prompt.root; <userinput>rm -rf (apache_install)/logs</userinput>
&prompt.root; <userinput>ln -s /var/log/apache (apache_install)/logs</userinput></screen>
    </sect2>
  </sect1>
</article>

