CreateHome
What is CreateHome? When a site has many user accounts, with users being added and removed constantly, there is always the associated procedure of creating and removing those user's home directories. And often, in such situations, the user account information is stored in a SQL database or an LDAP server. A proftpd daemon can be configured to authenticate against the SQL database or the LDAP server; this would still leave the task of creating the actual home directory for that user to be done.. What would help ease this particular burden on system administrators, though, is the ability to add the account information and have the new user's home directory created on demand. That is, to have a daemon such as proftpd create the home directory for the user, if that directory did not already exist.
proftpd
Now, proftpd already has some modules, such as mod_sql and mod_ldap that already support this home-on-demand creation capability. Each module implements it slightly differently, though. And other authentication modules, such as mod_radius, do not support it at all. It was decided then, rather than having authentication modules have largely duplicated code for this feature, to have home-on-demand creation in the core daemon itself. And so it is. As of 1.2.8rc2, proftpd has the CreateHome configuration directive.
mod_sql
mod_ldap
mod_radius
daemon
How to use CreateHome The description for this configuration directive shows its parameters to be:
CreateHome off|on [<mode>] [skel <path>] [dirmode <mode>] [uid <uid>] [gid <gid>] [homegid <gid>] [NoRootPrivs]
There is the first mode parameter, used to set the directory mode on the home directory being created. As described in the documentation, if this parameter is omitted the mode used will default to 0700. There is also the dirmode mode parameter, which is slightly different. The dirmode keyword informs the daemon that the following mode is to be used on directories that may need to be created in order to create the home directory. For example, let's assume that a new user, david, is logging in. User david has been given the home directory /home/users/d/da/david. Since this is a new user, the directory does not exist. In fact, /home/users/d does not exist. When this happens, proftpd will create the d, da, and david directories. A dirmode mode would be applied to the d and da directories, and the mode (no dirmode keyword) would be applied to the final david directory. To illustrate this, assume that the following CreateHome configuration is in use:
dirmode
/home/users/d/da/david
/home/users/d
d
da
david
CreateHome on 700 dirmode 711
/home/users
drwxr-xr-x 6 root root 4096 Jan 31 13:23 /home/users
drwxr-xr-x 6 root root 4096 Jan 31 13:23 /home/users drwx--x--x 6 root root 4096 Jan 31 13:23 /home/users/d drwx--x--x 6 root root 4096 Jan 31 13:23 /home/users/d/da drwx------ 6 david david 4096 Jan 31 13:23 /home/users/d/da/david
/home/users/d/da
rwx--x--x
rwx------
As an added feature, CreateHome also supports the ability to populate these newly created home directories. This is done by configuring a "skeleton" directory that will contain files (e.g. shell initialization files, documentation, notices, subdirectories, etc) that should be in every new user's home directory. This is done using the skel path parameter.
skel
Be sure to read the documentation for the CreateHome directive, for there are some restrictions and caveats to both the dirmode and skel parameters.
The uid and gid parameters can be used to set the ownership of the newly created parent directories, up to but not including the home directory. By default, those created parent directories are owned by root (UID 0 and GID 0).
uid
gid
The homegid parameter can be used to specify the group ownership of the target home directory itself. By default, this home directory will be owned by the user's primary GID.
homegid
The NoRootPrivs parameter can be used to prevent ProFTPD from using root privileges when creating the home directory and parents. This can be useful for e.g. the case where home directories are on NFS mounts which have root squashing enabled. When the NoRootPrivs option is used, the home directory in question will be created using the identity of the logging-in user.
NoRootPrivs
Here are some examples (from the documentation) to help illustrate how one might use the CreateHome configuration directive:
# Use the CreateHome default settings CreateHome on # Specify a mode of 711 for the created home directory CreateHome on 711 # Specify a mode of 711, and have the parent directories owned by a specific non-root UID/GID CreateHome on 711 uid 100 gid 100 # Specify a mode of 711, and have the parent directories owned by the UID/GID of the logging-in user CreateHome on 711 uid ~ gid ~ # Specify a skeleton directory CreateHome on skel /etc/ftpd/skel # No skeleton, but make sure that intermediate directories have 755 # permissions. CreateHome on dirmode 755 # Skeleton directory, with 700 intermediate directories CreateHome on skel /etc/ftpd/skel dirmode 700 # Explicitly configure everything, CreateHome-wise CreateHome on 711 skel /etc/ftpd/skel dirmode 700 # Explicitly configure everything, CreateHome-wise. And do NOT use root privileges when # creating the parent directories. CreateHome on 711 skel /etc/ftpd/skel dirmode 700 NoRootPrivs
When to use CreateHome "What about the prior configuration directives for mod_sql and mod_ldap?" one asks. The CreateHome configuration directive supersedes them. Those previous module-specific directives may well be deprecated in the future, in favor of CreateHome. Future authentication modules need not try to reinvent this particular wheel. CreateHome was designed for large sites in mind, but can be used any time home-on-demand creation is desired from the FTP daemon.
FAQ
Question: Is it possible to have different permissions for the CreateHome mode and dirmode based on the group of the connecting user? Answer: Yes, if you use the mod_ifsession module. For example:
mod_ifsession
<IfGroup special> CreateHome on 755 dirmode 755 </IfGroup> <IfGroup !special> CreateHome on 711 dirmode 711 </IfGroup>