NAME

Managing Users - managing users and groups on FreeBSD

SYNOPSIS

This document describes how to use FreeBSD's most commonly used tools for managing users, and explains some of the principles behind these tools.

The reader should be familiar with basic FreeBSD commands enough to be able to log into a FreeBSD server and get a shell prompt (either via telnet or ssh), change directories, list files, view files, and edit files.

Unless otherwise specified, all commands listed must be run as user root. If you do not have root access to your server, your options are limited to modifying your own account in certain, restricted ways (described in the appropriate sections below).

DESCRIPTION

This document will cover some of the basic commands that all FreeBSD system administrators should know about to manage users and groups.

Conventions

We use 'joe' as our example account on our system. We practice adding, modifying, and removing the 'joe' account in various ways.

Most of the time, the root user is executing commands to modify the 'joe' account. At these times, commands issued by root will appear with a hash (or pound sign: #) at the beginning of a line followed by a command:

# rmuser joe

This means that this command was issued by the root (super-user) user. This is a common convention in Unix documentation.

Likewise, a percent sign ('%') followed by a command is meant to indicate that the command was issued by a normal (unprivileged) user:

% passwd

This means that our example user 'joe' issued this command at his shell prompt.

Another convention we use in this document is manpage references. pw(8) means "the manpage named pw in section 8 of the manual". To read this manpage at your shell prompt, type:

# man 8 pw

Organization

This document is divided into the following sections:

CREATING NEW USERS

The most common aspect of managing users on a FreeBSD system is adding new users to your system (sometimes called "provisioning"). The following programs are but a few of the ways to do this:

adduser(8)

The simplest way to add a user to your system is with the adduser command (from the adduser(8) manpage):

Adduser is a simple program for adding new users.
Adduser checks the passwd, group and shell databases.
It creates passwd/group entries, HOME directory,
dotfiles and sends the new user a welcome message.

adduser works as a "wizard" (simple, step-by-step questions you answer). You can provide options to adduser to simplify the wizard interface even further. adduser is probably the most common way to add new users because of its simplicity. The -s and -q options removes some potentially confusing questions when adduser starts up:

# adduser -s -q
Use option ``-verbose'' if you want to see more warnings and questions 
or try to repair bugs.

Enter username [^[a-z0-9_][a-z0-9_-]*$]: joe
Enter full name []: Joe Schmoe, Jr.
Enter shell bash csh date ksh ksh93 no sh tcsh zsh [sh]: bash
Enter home directory (full path) [/home/joe]: 
Uid [1000]: 
Enter login class: default []: 
Login group joe [joe]: 
Login group is ``joe''. Invite joe into other groups: guest no 
[no]: 
Enter password []: 
Enter password again []: 

Name:     joe
Password: ****
Fullname: Joe Schmoe, Jr.
Uid:      1000
Gid:      1000 (joe)
Class:    
Groups:   joe 
HOME:     /home/joe
Shell:    /usr/local/bin/bash
OK? (y/n) [y]: 
Added user ``joe''
Add another user? (y/n) [y]: n

In this example, we enter a username 'joe', a full name 'Joe Schmoe, Jr.' and 'bash' for the shell. In all the rest of the questions, we simply hit Enter on our keyboard to specify that we want to accept the default value (found in square braces, e.g., [/home/joe]).

After entering the password (twice), adduser shows us a summary of what we are about to do and asks us to confirm this:

OK? (y/n) [y]:

at which prompt we hit Enter to confirm. We then see:

Add another user? (y/n) [y]:

at which prompt we reply n.

adduser has other configuration defaults you can specify in the /etc/adduser.conf file (adduser will even write this config file for you if you do not use the -q option). See the adduser(8) manpage for more details.

pw(8)

Not far behind adduser in terms of ease-of-use is pw. While the pw(8) manpage is a bit daunting, once you become familiar with its consistent and powerful interface (and learn what options to ignore in the manpages due to differences in your own setup) you will probably prefer pw over adduser.

As an example of what options to ignore, unless you're running YP/NIS (a system comprised of network equivalents of passwd, group, hosts, and other common services), you can completely ignore the -Y and -y command-line options. Further, until you begin customizing policy information and default startup files for new users (advanced techniques not covered in this tutorial), you can ignore the -C, -D, -k, and -L options.

And unless you plan on setting account expiration policies (i.e., an account will expire, or a user's password will expire, forcing them to reset it), you can ignore the -e, and -p options.

This leaves us with a much simplified usage for pw(8):

pw useradd [name|uid] [-q] [-n name] [-u uid] [-c comment] [-N]
   [-w method] [-g group] [-G grouplist] [-m] [-s shell] [-h fd] [-P]

These command-line options are likely the only ones you will use (unless you have more complex needs, of course, in which case the pw(8) manpage will be more useful to you).

Now we can look at a few examples of adding new accounts using pw.

vadduser(1) (for VPS v2 products)

For VPS v2 products (a "virtually" dedicated FreeBSD server), the vadduser(1) command is available. This command is simpler to use than either adduser or pw. A manpage is available, which lists all available options and gives many examples of simple usage.

Generally, the more you supply on the command-line, the less the vadduser program has to prompt you for information. You can create a complete account without any interaction with the program beyond the command-line arguments:

vadduser --login=joe --fullname="Joe Schmoe" --password=joeiscool \
--services="ftp,mail,shell" --shell=tcsh --quota=50 --home=/home/joe

Of course, you can always use the "wizard" interface, which will prompt you with questions and describe what answers you should supply.

vadduser

This will prompt you step by step like adduser does; vadduser, however, asks fewer questions and adds more description of what's happening, as well as allows you to set service options (email, ftp, etc.) and quotas for new accounts.

MODIFYING EXISTING USERS

Once a user account has been added to your system, you can use several programs to modify that user's settings. In fact, some of these programs are also available for users to run themselves (from a shell prompt), further reducing the need for your direct intervention as system administrator.

chpass(1)

chpass is a command useful for changing certain information in password files. If you run chpass as root, (e.g., chpass joe), an editor will open (e.g., pico, vi, emacs, ee, etc.) with the following information:

#Changing user database information for joe.
Login: joe
Password: $1$uAGNRKJP$4.JUH2Q.wftt9GiwBSsNL.
Uid [#]: 1002
Gid [# or name]: 1002
Change [month day year]:
Expire [month day year]:
Class:
Home directory: /home/joe
Shell: /usr/local/bin/bash
Full Name: Joseph Schmoe, Jr.
Office Location:
Office Phone:
Home Phone:
Other information:

The root user may change any of this information. If, on the other hand, you run chpass as the user (e.g., joe), you may only change a limited amount of information:

#Changing user database information for joe.
Shell: /usr/local/bin/bash
Full Name: Joseph Schmoe, Jr.
Office Location:
Office Phone:
Home Phone:
Other information:

That is, your shell and your "gecos" (full name, plus other info if desired) are the only things you may change when running chpass as the user.

chpass, despite its name, is usually not the program you want to run to change someone's password. For changing passwords, you should use passwd(1) instead.

passwd(1)

passwd is the program to use to change a user's password. If you run passwd as root, (e.g., passwd joe), you will be prompted twice for the new password for user joe:

# passwd joe
Changing local password for joe.
New password:
Retype new password:
passwd: updating the database...
passwd: done

If passwd is run as the user (e.g., joe), you will be prompted for your old password first, then your new password. This is a security feature to prevent unauthorized users from changing user passwords from an unattended terminal:

% passwd
Changing local password for joe.
Old password:
New password:
Retype new password:
passwd: updating the database...
passwd: done

Once run, the password for joe will be the new password. Email, FTP, and shell access will all be gained with this new password for the joe account.

pw(8)

Changing user account information interactively is best accomplished with either the chpass, or passwd commands. However, when you want a quick one-liner to fix an account, or if you need to automate account modification, pw is your program.

Note some of the interesting uses for pw:

vedituser (for VPS v2 products)

For VPS v2 products (a "virtually" dedicated FreeBSD server), the vedituser(1) command ins available. This command is simpler to use than pw, and safer to use than chpass. A manpage is available, which lists all available options and gives many examples of simple usage.

Like vadduser, the more you supply on the command-line, the less the vedituser program has to prompt you for information. By way of example:

vedituser --login=joe --services="ftp,mail"

will remove joe's shell access. You will be prompted for missing options, but the current account settings will be used as default values, so you can simply hit <Enter> to accept them.

DISABLING EXISTING USERS (BUT NOT REMOVING THEIR ACCOUNTS)

Disabling means many things to many people. Some people (including the author) would classify "disabling" as not only the inability to log in and do things, but also to shut off other existing services (such as cron, web, and other services that do not require the user to log in).

However, for the sake of space and time, we will define 'disabling' simply as the act of making a shell, ftp, and email (POP) account unavailable to the user. Disabling cron, web, and other services are beyond the scope of this tutorial, but are important considerations.

pw(8)

The simplest way to disable an account is via the pw command:

# pw lock joe

The joe account has now been disabled. To re-enable, simply:

# pw unlock joe

Now the joe account is available for login again.

chpass

Another effective, though slightly more error-prone method of disabling an account, is to insert an asterisk at the beginning of the user's password field. This is one of the few times you will use chpass as root to modify a password directly:

# chpass joe
#Changing user database information for joe.
Login: joe
Password: *$1$tmTYmsuQ$IHSy7urpdZwXEzA3iYsnF/

Note the asterisk ('*') at the beginning of the password hash. This guarantees that no password will match because the asterisk is outside the range of characters used by the password hashing algorithm.

When the time comes to re-enable the account, remove the asterisk using chpass.

Editing /etc/master.passwd directly

You may also disable the account by editing /etc/master.passwd directly. Like the chpass example above, insert an asterisk at the beginning of the password field. Be sure to run:

pwd_mkdb -p /etc/master.passwd

when you're done so your changes propagate to the other password databases.

Re-enabling the account is accomplished in an analogous way (and be sure to run pwd_mkdb again).

REMOVING EXISTING USERS

Removing users from your system is probably the simplest operation you will do. The command to run is called rmuser and it works like this:

# rmuser joe

This will prompt you with:

Matching password entry:

joe:$1$RzJXr6ka$xdE88TjW4vpwthy/.Vtho/:1004:1004::0:0:Joseph \
Carmichael Schmoe:/home/joe:/usr/local/bin/tcsh

Is this the entry you wish to remove? 

at which you simply type a 'y' and enter. You will also be prompted to remove their home directory:

Remove user's home directory (/home/joe)?

If you reply affirmatively, the home directory will be completely removed. Otherwise, the directory will continue to exist, and you may do with it as you please (e.g., tar it up as an archive and then remove it, etc.).

If you know you want to remove everything, you can use the -y option for rmuser, which will answer 'y' automatically at all questions:

# rmuser -y joe
Updating password file, updating databases, done.
Updating group file: (removing group joe -- personal group is empty) done.
Removing user's home directory (/home/joe): done.
Removing user's incoming mail file /var/mail/joe: done.
Removing files belonging to joe from /tmp: done.
Removing files belonging to joe from /var/tmp: done.
Removing files belonging to joe from /var/tmp/vi.recover: done.

Removing existing users by hand will not be covered in this tutorial, except to say that the password file entry, group entries, home directory, mail spools, cron jobs, and other miscellaneous files need to be considered when removing users. rmuser does all of this for you (and does it well).

Using pw

Of course, pw can also be used to remove user accounts:

# pw user del joe -r

The -r option is the inverse of -m. While -m instructs pw to create the home directory, -r tells pw to remove the home directory and its contents without prompting (much like rmuser with the -y option). pw is somewhat safer than rmuser; the pw(8) manpage tells us this about the -r option:

This tells pw to remove the user's home directory and all
of its contents.  Pw errs on the side of caution when
removing files from the system.  Firstly, it will not do so
if the uid of the account being removed is also used by
another account on the system, and the 'home' directory in
the password file is a valid path that commences with the
character `/'.  Secondly, it will only remove files and
directories that are actually owned by the user, or sym-
bolic links owned by anyone under the user's home direc-
tory.  Finally, after deleting all contents owned by the
user only empty directories will be removed.  If any addi-
tional cleanup work is required, this is left to the admin-
istrator.

If you notice that a home directory was not removed, it was for one of the reaons stated above. You should check it out to see why before completely removing the home directory.

MANAGING USERS EN-MASSE

Large-scale management of users requires you to write a little code to get things done. Which programming language or environment you use is usually not important. However, some programming languages have been tailored for system administration and make automating common tasks simple. Among these are Perl and the Bourne-shell languages, which we will use here for our examples (many shells are Bourne-compatible to some degree, among them: ash, bash, sh, (the original Bourne shell), and zsh in Bourne-compatibility mode).

In this section, our sample task will be to add several hundred users to our system (with an intentional mistake affecting all accounts). Once the accounts have been provisioned, we will fix our mistakes so that all of our account owners are happy.

Creating many accounts

We want to create 300 accounts at once. Our saving grace is that the usernames do not have to be very creative (in fact, they can be downright ugly). We can do this using Perl:

#!/usr/local/bin/perl -w
use strict;

## create accounts for user_1 .. user_300
for my $n ( 1..300 ) {
    system('pw', 'user', 'add', '-n', "user_$n");
}

We save this program in a file called create_users and type:

# perl create_users

After a few moments all of the accounts have been created. The account names are user_1, user_2, and so on. However, we just realized that we forgot to create the home directories for all these users! (We omitted the -m option after the username). Perl to the rescue again:

#!/usr/local/bin/perl -w
use strict;

## create home directories for user_1 .. user_300 
for my $n ( 1..300 ) {
    system('pw', 'user', 'mod', '-n', "user_$n", '-m');
}

We save this program in a file called modify_users and type:

# perl modify_users

After a few moments we check and, thankfully, all the home directories have now been created. You can see that our arguments to the pw program have changed in two places: we use mod instead of add, and we append the -m option after the username to create the home directory. We could change the shell in the same way, for example, by changing:

system('pw', 'user', 'mod', '-n', "user_$n", '-m');

to:

system('pw', 'user', 'mod', '-n', "user_$n", '-s', '/usr/local/bin/tcsh' );

Time passes. The need for these user accounts has disappeared. Is there a clean and sure-fire way to remove these accounts? Perl is our friend once again:

#!/usr/local/bin/perl -w
use strict;

## remove user_1 .. user_300 from our system
for my $n ( 1..300 ) {
    system('pw', 'user', 'del', '-n', "user_$n", '-r');
}

We save this program in a file called remove_users and type:

# perl remove_users

After a few moments we notice that the accounts (password entries, group entries, home directories--everything) are gone. Nice!

The Bourne shell can also be used to accomplish these feats. In order for these one-liners to work, you need to be running a Bourne-compatible shell. The author recommends bash because of its completeness, but many people prefer the original /bin/sh for shell programming, which is always in good taste because of portability reasons (one Bourne-shell script is much more likely to run with no or few modifications than a csh or "C-shell" script).

You can run a Bourne shell by typing:

# exec /bin/sh
Creating 300 users

This one-liner will add 300 users and create their home directories:

# i=300; while [ $i -gt 0 ]; do pw user add -n "user_$i" -m; \
i=`expr $i - 1`; done
Modifying 300 users

This one-liner will modify all 300 accounts, changing their shells to the Bourne shell:

# i=300; while [ $i -gt 0 ]; do pw user mod -n "user_$i" \
-s /bin/sh; i=`expr $i - 1`; done
Deleting 300 users

This one-liner uses rmuser to remove the users from the system:

# i=300; while [ $i -gt 0 ]; do rmuser -y "user_$i"; \
i=`expr $i - 1`; done

You will see a lot of output from rmuser, however. To silence it (including errors), do this:

# i=300; while [ $i -gt 0 ]; do rmuser -y "user_$i" \
> /dev/null 2>&1; i=`expr $i - 1`; done

or use the pw command instead.

QUOTAS

Quotas enable you, the system administrator, to control how much disk space users consume. This helps prevent abuse to your system (in general, bad things happen when a disk is full) as well as enable you, if you are using your system for profit, to allot resources as needed.

Enabling quotas

To enable quotas, open /etc/fstab in your favorite editor and make sure the mountpoint you want to enable quotas for has the userquota option set. For example, if your primary mountpoint (where your users' home directories reside) is /, you'll see:

# Device        Mountpoint      FStype  Options
/dev/da0e       /               ufs     rw

which becomes:

# Device        Mountpoint      FStype  Options
/dev/da0e       /               ufs     rw,userquota

Many systems use /usr or /home as mountpoints instead of /. In this case, you might see something like this:

# Device        Mountpoint      FStype  Options         Dump    Pass#
/dev/ad0s1f     /usr            ufs     rw              2       2

which becomes:

# Device        Mountpoint      FStype  Options         Dump    Pass#
/dev/ad0s1f     /usr            ufs     rw,userquota    2       2

Once you have added the userquota option (or if it is already present), save your file and return to your shell prompt.

Now you can type the following to enable quotas:

# quotaon -a

If you see a message like the following:

quotaon: using /usr/quota.user on
quotaon: /usr: Operation not supported

it means that your kernel has not been compiled to support quota operations. Compiling a new kernel is beyond the scope of this tutorial, but useful references may be found in the FreeBSD Handbook:

Once quotas have been enabled, you're read to "prime" your quota database:

# quotacheck -a

This will crawl the filesystem once to initialize the quota database. Once completed, this operation should not need to be repeated unless you disable quotas (e.g., with quotaoff -a), when it will need to be run again once quotas are re-enabled.

NOTE: If you are using a VPS v2 product (a "virtually" dedicated FreeBSD server), you may simply run vadduser, vedituser, or vquota to enable quotas on your system. All of these steps will be done for you.

Setting per-user quotas

Now that your system is configured to allow quotas, we want to impose quota limits on users. This is accomplished in two ways:

SUMMARY

FreeBSD supplies many useful commands to help system administrators manage user accounts. Chief among them are pw, adduser, passwd, and chpass. Knowing a shell or other programming language will also go a long way in automating routine and bulk tasks (including quota management).

The authoritative manual for FreeBSD system administration is The FreeBSD Handbook, found at:

http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/

SEE ALSO

The FreeBSD Handbook:

http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/

Managing users (from The FreeBSD Handbook):

  http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/users-modifying.html
 

Managing groups (from The FreeBSD Handbook):

http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/users-groups.html

AUTHOR

Scott Wiersdorf, <scott@perlcode.org>

VERSION

$SMEId: docs/sysadmin/managing_users.pod,v 1.4 2003/07/18 22:21:21 scottw Exp $