<sect1 id="server">
<title>Setting Up an NFS Server</title>
<sect2 id="serverintro">
 <title>Introduction to the server setup</title>
 <para>
    It is assumed that you will be setting up both a server and a
    client.  If you are just setting up a client to work off of
    somebody else's server (say in your department), you can skip
    to <xref linkend="client">.  However, every client that is set up requires
    modifications on the server to authorize that client (unless 
    the server setup is done in a very insecure way), so even if you
    are not setting up a server you may wish to read this section to
    get an idea what kinds of authorization problems to look out for.
 </para>
 <para>
    Setting up the server will be done in two steps: Setting up the 
    configuration files for NFS, and then starting the NFS services.
 </para>
</sect2>
<sect2 id="config">
 <title>Setting up the Configuration Files</title>
 <para>
   There are three main configuration files you will need to edit to 
   set up an NFS server: <filename>/etc/exports</filename>,
   <filename>/etc/hosts.allow</filename>, and  <filename>/etc/hosts.deny</filename>. 
   Strictly speaking, you only need to edit <filename>/etc/exports</filename> to get 
   NFS to work, but you would be left with an extremely insecure setup. You may also need 
   to edit your startup scripts; see <xref linkend="daemons"> for more on that.
 </para>
<sect3 id="exports">
 <title>/etc/exports</title>
 <para>
   This file contains a list of entries; each entry indicates a volume
   that is shared and how it is shared.  Check the man pages (<command>man 
   exports</command>) for a complete description of all the setup options for 
   the file, although the description here will probably satistfy 
   most people's needs.
 </para>
 <para>
   An entry in <filename>/etc/exports</filename> will typically look like this:
 <programlisting>
 directory machine1(option11,option12) machine2(option21,option22)
</programlisting>
</para>
<para>
  where 
  <glosslist>
  <glossentry><glossterm>directory</glossterm>
  <glossdef>
   <para>
    the directory that you want to share.  It may be an 
    entire volume though it need not be.  If you share a directory, 
    then all directories under it within the same file system will 
    be shared as well.
   </para>
  </glossdef>
 </glossentry>
 <glossentry><glossterm>machine1 and machine2</glossterm>
  <glossdef>
   <para>
    client machines that will have access to the directory. The machines
    may be listed by their DNS address or their IP address 
    (e.g., <emphasis>machine.company.com</emphasis> or <emphasis>192.168.0.8</emphasis>).
    Using IP addresses is more reliable and more secure.  If you need to
    use DNS addresses, and they do not seem to be resolving to the right
    machine, see <xref linkend="symptom3">.
   </para>
  </glossdef>
 </glossentry>
 <glossentry><glossterm>optionxx</glossterm>
  <glossdef>
   <para>
    the option listing for each machine will describe what kind of 
    access that machine will have.  Important options are:
    <itemizedlist>
    <listitem>
      <para>
       <userinput>ro</userinput>:  The directory is shared read only; the client machine 
      will not be able to write to it.  This is the default.
    </para>
   </listitem>
   <listitem>
     <para>
       <userinput>rw</userinput>:  The client machine will have read and write access to the 
      directory.
     </para>
   </listitem>
   <listitem>
     <para>
       <userinput>no_root_squash</userinput>: By default,
       any file request made by user <computeroutput>root</computeroutput> 
       on the client machine is treated as if it is made by user 
       <computeroutput>nobody</computeroutput> on the 
       server.  (Excatly which UID the request is 
       mapped to depends on the UID of user "nobody" on the server,
       not the client.)  If <userinput>no_root_squash</userinput> 
       is selected, then 
       root on the client machine will have the same level of access 
       to the files on the system as root on the server.  This 
       can have serious security implications, although it may be 
       necessary if you want to perform any administrative work on 
       the client machine that involves the exported directories.
       You should not specify this option without a good reason.
     </para>
   </listitem>
   <listitem>
     <para>
       <userinput>no_subtree_check</userinput>: If only part of a volume is exported, a
       routine called subtree checking verifies that a file that is 
       requested from the client is in the appropriate part of the 
       volume.  If the entire volume is exported, disabling this check
       will speed up transfers.
     </para>
   </listitem>
   <listitem>
     <para>
       <userinput>sync</userinput>:
       By default, all but the most recent version (version 1.11)
       of the <command>exportfs</command> command will use 
       <userinput>async</userinput> behavior, telling a client 
       machine that a file write is complete - that is, has been written 
       to stable storage - when NFS has finished handing the write over to 
       the filesysytem.  This behavior may cause data corruption if the 
       server reboots, and the <userinput>sync</userinput> option prevents 
       this.  See <xref linkend="sync-async"> for a complete discussion of 
       <userinput>sync</userinput> and <userinput>async</userinput> behavior.
    </para>
   </listitem>
  </itemizedlist>
  </para>
 </glossdef>
</glossentry>
</glosslist>
</para>

<para>
  Suppose we have two client machines, <emphasis>slave1</emphasis> and <emphasis>slave2</emphasis>, that have IP
  addresses <emphasis>192.168.0.1</emphasis> and <emphasis>192.168.0.2</emphasis>, respectively.  We wish to share
  our software binaries and home directories with these machines.
  A typical setup for <filename>/etc/exports</filename> might look like this:
 <screen>
  /usr/local   192.168.0.1(ro) 192.168.0.2(ro)
  /home        192.168.0.1(rw) 192.168.0.2(rw)
 </screen>
</para>
<para>
  Here we are sharing <filename>/usr/local</filename> read-only to slave1 and slave2, 
  because it probably contains our software and there may not be 
  benefits to allowing slave1 and slave2 to write to it that outweigh 
  security concerns.  On the other hand, home directories need to be 
  exported read-write if users are to save work on them.
</para>
<para>
  If you have a large installation, you may find that you have a bunch 
  of computers all on the same local network that require access to 
  your server.  There are a few ways of simplifying references
  to large numbers of machines.  First, you can give access to a range 
  of machines at once by specifying a network and a netmask.  For 
  example, if you wanted to allow access to all the machines with IP 
  addresses between <emphasis>192.168.0.0</emphasis> and
<emphasis>192.168.0.255</emphasis> then you could have the entries:
 <screen>
  /usr/local 192.168.0.0/255.255.255.0(ro)
  /home      192.168.0.0/255.255.255.0(rw)
 </screen>
</para>
<para>
  See the <ulink url="http://www.linuxdoc.org/HOWTO/Networking-Overview-HOWTO.html">Networking-Overview HOWTO</ulink>
  for further information about how netmasks work, and you may also wish to 
  look at the man pages for <filename>init</filename> and <filename>hosts.allow</filename>.
</para>
<para>
  Second, you can use NIS netgroups in your entry. To specify a
  netgroup in your exports file, simply prepend the name of the
  netgroup with an "@".  See the <ulink url="http://www.linuxdoc.org/HOWTO/NIS-HOWTO.html">NIS HOWTO</ulink>
  for details on how netgroups work. 
</para>
<para>
  Third, you can use wildcards such as <emphasis>*.foo.com</emphasis> or
 <emphasis>192.168.</emphasis> instead of hostnames.  There were problems
  with wildcard implementation in the 2.2 kernel series that were fixed
  in kernel 2.2.19.
</para>
<para>
  However, you should keep in mind that any of these simplifications
  could cause a security risk if there are machines in your netgroup
  or local network that you do not trust completely.
</para>
<para>
  A few cautions are in order about what cannot (or should not) be
  exported.  First, if a directory is exported, its parent and child
  directories cannot be exported if they are in the same filesystem.
  However, exporting both should not be necessary because listing the
  parent directory in the <filename>/etc/exports</filename> file will cause all underlying
  directories within that file system to be exported.  
</para>
<para>
  Second, it is a poor idea to export a FAT or VFAT (i.e., MS-DOS or 
  Windows 95/98) filesystem with NFS.  FAT is not designed for use on a 
  multi-user machine, and as a result, operations that depend on 
  permissions will not work well.  Moreover, some of the underlying 
  filesystem design is reported to work poorly with NFS's expectations.  
</para>
<para>
  Third, device or other special files may not export correctly to non-Linux 
  clients.  See <xref linkend="interop"> for details on particular operating systems.
</para>
</sect3>
<sect3 id="hosts">
 <title>/etc/hosts.allow and /etc/hosts.deny</title>
 <para>
   These two files specify which computers on the network can use 
   services on your machine.  Each line of the file 
   contains a single entry listing 
   a service and a set of machines.  When the server gets a request 
   from a machine, it does the following:
  <itemizedlist>
  <listitem>
    <para>
     It first checks <filename>hosts.allow</filename> to see if the machine 
     matches a description listed in there. If it does, then the machine
     is allowed access.  
   </para>
  </listitem>
  <listitem>
   <para>
     If the machine does not match an entry in <filename>hosts.allow</filename>, the
     server then checks <filename>hosts.deny</filename> to see if the client matches a 
     listing in there.  If it does then the machine is denied  access.  
   </para>
  </listitem>
  <listitem>
   <para>
     If the client matches no listings in either file, then it
     is allowed access.
   </para>
  </listitem>
  </itemizedlist>
 </para>
 <para>
   In addition to controlling access to services 
   handled by <command>inetd</command> (such 
   as telnet and FTP), this file can also control access to NFS
   by restricting connections to the daemons that provide NFS services.
   Restrictions are done on a per-service basis.
 </para>
 <para>
   The first daemon to restrict access to is the portmapper.  This daemon
   essentially just tells requesting clients how to find all the NFS
   services on the system.  Restricting access to the portmapper is the
   best defense against someone breaking into your system through NFS
   because completely unauthorized clients won't know where to find the
   NFS daemons.  However, there are two things to watch out for.  First,
   restricting portmapper isn't enough if the intruder already knows
   for some reason how to find those daemons.  And second, if you are
   running NIS, restricting portmapper will also restrict requests to NIS.
   That should usually be harmless since you usually want
   to restrict NFS and NIS in a similar way, but just be cautioned.
   (Running NIS is generally a good idea if you are running NFS, because
   the client machines need a way of knowing who owns what files on the
   exported volumes.  Of course there are other ways of doing this such
   as syncing password files.  See the <ulink url="http://www.linuxdoc.org/HOWTO/NIS-HOWTO.html">NIS HOWTO</ulink> for information on
   setting up NIS.)
 </para>
 <para>
   In general it is a good idea with NFS (as with most internet services)
   to explicitly deny access to IP addresses that you don't need
   to allow access to.
 </para>
 <para>
   The first step in doing this is to add the followng entry to 
   <filename>/etc/hosts.deny</filename>:
 </para>
 <para>
  <screen>
   portmap:ALL
  </screen>
 </para>
 <para>
   Starting with <application>nfs-utils</application> 0.2.0, you can be a bit more careful by
   controlling access to individual daemons.  It's a good precaution
   since an intruder will often be able to weasel around the portmapper.
   If you have a newer version of <application>nfs-utils</application>, add entries for each of the
   NFS daemons (see the next section to find out what these daemons are;
   for now just put entries for them in hosts.deny):
 </para>
 <para>
  <screen>
    lockd:ALL
    mountd:ALL
    rquotad:ALL
    statd:ALL
  </screen>
 </para>
 <para> 
   Even if you have an older version of <application>nfs-utils</application>, adding these entries
   is at worst harmless (since they will just be ignored) and at best 
   will save you some trouble when you upgrade.  Some sys admins choose
   to put the entry <userinput>ALL:ALL</userinput> in the file <filename>/etc/hosts.deny</filename>, 
   which causes  any service that looks at these files to deny access to all 
   hosts unless it is explicitly allowed.  While this is more secure 
   behavior, it may also get you in trouble when you are installing new 
   services,  you forget you put it there, and you can't figure out for 
   the life of you why they won't work.
 </para>
 <para>
   Next, we need to add an entry to <filename>hosts.allow</filename> to give any hosts 
   access that we want to have access.  (If we just leave the above 
   lines in <filename>hosts.deny</filename> then nobody will have access to NFS.)  Entries 
   in <filename>hosts.allow</filename> follow the format
  <informalexample>
   <screen>
    service: host [or network/netmask] , host [or network/netmask]
   </screen>
  </informalexample>
 </para>
 <para>
   Here, host is IP address of a potential client; it may be possible 
   in some versions to use the DNS name of the host, but it is strongly 
   discouraged.
 </para>
 <para>
   Suppose we have the setup above and we just want to allow access
   to <emphasis>slave1.foo.com</emphasis> and <emphasis>slave2.foo.com</emphasis>, 
   and suppose that the IP addresses of these machines are <emphasis>192.168.0.1</emphasis>
   and <emphasis>192.168.0.2</emphasis>, respectively.  We could add the following entry to 
   <filename>/etc/hosts.allow</filename>:
  <informalexample>
   <screen>
   portmap: 192.168.0.1 , 192.168.0.2
   </screen>
  </informalexample>
 </para>
 <para>
   For recent nfs-utils versions, we would also add the following
   (again, these entries are harmless even if they are not supported):
  <informalexample>
   <screen>
    lockd: 192.168.0.1 , 192.168.0.2
    rquotad: 192.168.0.1 , 192.168.0.2
    mountd: 192.168.0.1 , 192.168.0.2
    statd: 192.168.0.1 , 192.168.0.2
   </screen>
  </informalexample>
 </para>
 <para>
   If you intend to run NFS on a large number of machines in a local
   network, <filename>/etc/hosts.allow</filename> also allows for network/netmask style 
   entries in the same manner as <filename>/etc/exports</filename> above.
 </para>
</sect3>
</sect2>
<sect2 id="servicestart">
 <title>Getting the services started</title>
 <sect3 id="prereq">
  <title>Pre-requisites</title>
  <para>
    The NFS server should now be configured and we can start it running.
    First, you will need to have the appropriate packages installed.  
    This consists mainly of a new enough kernel and a new enough version
    of the <application>nfs-utils</application> package.  
    See <xref linkend="swprereq"> if you are in doubt.
  </para>
  <para>
    Next, before you can start NFS, you will need to have TCP/IP 
    networking functioning correctly on your machine.  If you can use 
    telnet, FTP, and so on, then chances are your TCP networking is fine.
  </para>
  <para>
    That said, with most recent Linux distributions you may be able to 
    get NFS up and running simply by rebooting your machine, and the 
    startup scripts should detect that you have set up your <filename>/etc/exports</filename>
    file and will start up NFS correctly.  If you try this, see <xref linkend="verify">
    Verifying that NFS is running.  If this does not work, or if 
    you are not in a position to reboot your machine, then the following
    section will tell you which daemons need to be started in order to 
    run NFS services.  If for some reason <command>nfsd</command> 
    was already running when
    you edited your configuration files above, you will have to flush 
    your configuration; see <xref linkend="later"> for details.
  </para>
 </sect3>
 <sect3 id="portmapper">
  <title>Starting the Portmapper</title>
   <para>
     NFS depends on the portmapper daemon, either called <command>portmap</command> or 
     <command>rpc.portmap</command>.  It will need to be started first.  It should be 
     located in <filename>/sbin</filename> but is sometimes in <filename>/usr/sbin</filename>.  
     Most recent Linux distributions start this daemon in the boot scripts, but it is 
     worth making sure that it is running before you begin working with 
     NFS (just type <command>ps aux | grep portmap</command>).
   </para>
 </sect3>
 <sect3 id="daemons">
  <title>The Daemons</title>
   <para>
     NFS serving is taken care of by five daemons: <command>rpc.nfsd</command>, 
     which does most of the work; <command>rpc.lockd</command> and 
     <command>rpc.statd</command>, which handle file locking;
     <command>rpc.mountd</command>, which handles the initial mount requests, 
     and <command>rpc.rquotad</command>, which handles user file quotas on 
     exported volumes. Starting with 2.2.18, <command>lockd</command> 
     is called by <command>nfsd</command> upon demand, so you do
     not need to worry about starting it yourself. <command>statd</command> 
     will need to be started separately. Most recent Linux distributions will
     have startup scripts for these daemons.
   </para>
   <para>
     The daemons are all part of the nfs-utils package, and may be either
     in the <filename>/sbin</filename> directory or the <filename>/usr/sbin</filename> directory.
   </para>
   <para>
    If your distribution does not include them in the startup scripts, 
    then you should add them, configured to start in the following 
    order:
  <simplelist>
  <member><command>rpc.portmap</command></member>
  <member><command>rpc.mountd</command>, <command>rpc.nfsd</command></member>
  <member><command>rpc.statd</command>, <command>rpc.lockd</command> (if necessary), and <command>rpc.rquotad</command></member>
  </simplelist>
 </para>
 <para>
   The nfs-utils package has sample startup scripts for RedHat and
   Debian.  If you are using a different distribution, in general you
   can just copy the RedHat script, but you will probably have to take
   out the line that says:
   <screen>
    . ../init.d/functions
   </screen>
   to avoid getting error messages.
 </para>
</sect3>
</sect2>
<sect2 id="verify">
 <title>Verifying that NFS is running</title>
  <para>
    To do this, query the portmapper with the command <command>rpcinfo -p</command> to 
    find out what services it is providing.  You should get something 
    like this:
   <screen>
    program vers proto   port
    100000    2   tcp    111  portmapper
    100000    2   udp    111  portmapper
    100011    1   udp    749  rquotad
    100011    2   udp    749  rquotad
    100005    1   udp    759  mountd
    100005    1   tcp    761  mountd
    100005    2   udp    764  mountd
    100005    2   tcp    766  mountd
    100005    3   udp    769  mountd
    100005    3   tcp    771  mountd
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    300019    1   tcp    830  amd
    300019    1   udp    831  amd
    100024    1   udp    944  status
    100024    1   tcp    946  status
    100021    1   udp   1042  nlockmgr
    100021    3   udp   1042  nlockmgr
    100021    4   udp   1042  nlockmgr
    100021    1   tcp   1629  nlockmgr
    100021    3   tcp   1629  nlockmgr
    100021    4   tcp   1629  nlockmgr
  </screen>
 </para>
 <para>
   This says that we have NFS versions 2 and 3, rpc.statd version 1, 
   network lock manager (the service name for rpc.lockd) versions 1, 3, 
   and 4.  There are also different service listings depending on 
   whether NFS is travelling over TCP or UDP.  Linux systems use UDP
   by default unless TCP is explicitly requested; however other OSes 
   such as Solaris default to TCP.
 </para>
 <para>
   If you do not at least see a line that says 
   <computeroutput>portmapper</computeroutput>, a line that says 
   <computeroutput>nfs</computeroutput>, and a line that says 
   <computeroutput>mountd</computeroutput> then you will need 
   to backtrack and try again to start up the daemons 
   (see <xref linkend="troubleshooting">, 
   Troubleshooting, if this still doesn't work).
 </para>
 <para>
   If you do see these services listed, then you should be ready to 
   set up NFS clients to access files from your server.
 </para>
</sect2>
<sect2 id="later">
 <title>Making changes to /etc/exports later on</title>
 <para>
   If you come back and change your <filename>/etc/exports</filename> file, the changes you 
   make may not take effect immediately.  You should run the command 
   <command>exportfs -ra</command> to force <command>nfsd</command> to re-read the <filename>/etc/exports</filename>
   file.  If you can't find the <command>exportfs</command> command, then you can kill <command>nfsd</command> with the 
  <userinput> -HUP</userinput> flag (see the man pages for kill for details).
 </para>
 <para>
   If that still doesn't work, don't forget to check <filename>hosts.allow</filename> to 
   make sure you haven't forgotten to list any new client machines 
   there.  Also check the host listings on any firewalls you may have 
   set up (see <xref linkend="troubleshooting"> and 
   <xref linkend="security"> for more details on firewalls and NFS).
 </para>
</sect2>
</sect1>

