Wednesday, May 12, 2010

Solaris : automatic creation of home dirs

When users in Solaris are externally authenticated (e.g. via LDAP, Active Directory, NIS, etc) you often find a need for users home directories to be created automatically when they login for the first time. In Linux people typically resort to pam_mkhomedir but in Solaris there is really no need as you've got something better: the automounter.

In this example I'll assume that users home directories are in /export/home/ldapusers/. What you want is that when user johndoe logs in you want to make sure he has a home directory, if not create one for him. Here is the trick: using the automounter you can do this.

First a few notes on what the automounter does. Essentially it automatically mounts 'something' when you access a certain mount point. By the latter a mean a local directory path, e.g. /export/home/ldapusers/johndoe. What you mount can be a network drive, a CD-ROM or simply another directory on the local file system. We'll do the latter in this example.

The Solaris automounter has a feature called 'executable maps'. This means that whenever a directory on the moint point is accessed a script will be executed. The script must return the destination on stdout but as it is a shell script it allows us any kind of customization before that such as creating directories, copying skell files, or whatever.

As said lets assume that /export/home/ldapusers/ is our mount point. As this is our mount point we cannot physically have the user's home directories in the same location; they must reside somewhere else, in our case in /export/home/.externalusers/.

Here we go:

1. Add the following lines to /etc/auto_master file :

# Automount (and create if not exist) home dirs for external users
/export/home/ldapusers /etc/auto_homedir


This essentially tells the automounter to execute script /etc/auto_homedir whenever someone accesses directories on /export/home/ldapusers. You can of course use any location and name for the script that you like.

2. Next create the /etc/auto_homedir script:

#!/bin/bash
#
# Automounter executable script.
# This script must be referenced in file /etc/auto_master in order
# to have any effect. Furthermore it must have the sticky bit set.
#
# This script receives as $1 the name of the object (file or directory)
# that is being accessed under the moint point. For example if the
# moint point is /home and someone is accessing /home/johndoe then
# $1 will be "johndoe".
# The script is expected to write the path of the physical location
# on stdout.


# ------------------------------------------------------------------------------
# Customizations


# Path of our mount point. This must be the same as the name
# in the first column in the file /etc/auto_master.
HOMEDIRPATH=/export/home/ldapusers

# Where the physical user home directories are
PHYSICALDIRPATH=/export/home/.extusers

# The group owner to give to a user's home directory
HOMEDIRGROUP="external users"


# ------------------------------------------------------------------------------

hdir=~$1


# Sanity check

if [[ $hdir != $HOMEDIRPATH/* ]]; then
# Someone is trying to access a directory under $HOMEDIRPATH
# which is not the name of a user. This we simply ignore, i.e. we exit
# without writing anything on stdout. This will make the automounter
# ignore the action and thus the user will get an error.
exit
fi


# Now we know that $1 is a valid user with a home directory
# under $HOMEDIRPATH

# Next see if the user's physical home dir exist. If not create it.

phdir="$PHYSICALDIRPATH/$1"

if [ -d "$phdir" ]; then
# Yes the user's physical home dir already exist.
# Return the path of the physical home dir to the automounter
# and exit.
echo "localhost:$phdir"
exit
fi


# Create the directory
mkdir -p $phdir

# Set owner and group
chown "$1":"$HOMEDIRGROUP" $phdir


# At this point we can copy setup files into the user's home directory
# e.g. files from /etc/skel. This step is optional.

# Example for Bash logins :
#cp /etc/skel/local.profile $phdir/.profile
#chown "$1":"$HOMEDIRGROUP" $phdir/.profile


# This was all we needed to do.
# Return the path of the physical home dir to the automounter
# and exit.

echo "localhost:$phdir"

exit


3. Set sticky bit and execute on the script

chmod +t+x /etc/auto_homedir

4. Restart the automounter

svcadm restart autofs


That's it.


Debugging and more info.

For more info see man automount. Also if you find that your script is not working as intended you can always put in a few debug lines such as

echo "Variable hdir is : $hdir " >> /tmp/mydebug

and then you can examine the contents of /tmp/mydebug file.

Why not on /home ?

Why don't I use /home in the above example? No good reason, really. Feel free to change. If you are from Linux and wonder about the difference between /home and /export/home then I recommend this blog posting. It also explains about the Solaris automounter although not the 'executable maps' feature we use above. Well worth the read.