Users and groups

Creating users and groups is governed by GLEP 81. It is implemented via acct-user and acct-group eclasses. New users and groups are created as packages respectively in acct-user and acct-group categories.

First, check the UID/GID assignment list and choose a free UID/GID in the range between 101 and 749. If you are adding a user and a group with the same name, use the same number for their UID and GID, respectively. When in doubt, take the next free number from 101 upwards. The helper script ./bin/used_free_uidgids.sh available in the data/api.git repository can be used to find the next available UID or GID.

Add your new user(s) and group(s) to the uid-gid.txt file located in the data/api.git repository and push them before adding the actual packages. This counts as reserving the identifiers and will prevent collisions. Afterwards, you can push the new ebuilds.

The historical way of using user.eclass directly is now deprecated and must not be used for new packages.

Group ebuilds

Group ebuilds are placed in acct-group category, with the package name matching the group name. The following ebuild for acct-group/suricata can be used as a template for writing group ebuilds:

# Copyright 2019-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=7

inherit acct-group

DESCRIPTION="Group for Suricata IDS"
ACCT_GROUP_ID=477

ACCT_GROUP_ID must be set to the requested GID.

User ebuilds

User ebuilds are placed in acct-user category, with the package name matching the user name. The following ebuild for acct-user/suricata can be used as a template for writing user ebuilds:

# Copyright 2019-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=7

inherit acct-user

DESCRIPTION="User for Suricata IDS"
ACCT_USER_ID=477
ACCT_USER_GROUPS=( ${PN} )

acct-user_add_deps

ACCT_USER_ID must be set to the requested GID. ACCT_USER_GROUPS should list all the groups user belongs to, the primary group first. All the other keys are optional.

ACCT_USER_SHELL can be used to set the shell for the user. If unset, the best system equivalent of nologin is used. ACCT_USER_HOME specifies the home directory, with /dev/null being the default. ACCT_USER_HOME_OWNER can be used to override the ownership of the home directory, and ACCT_USER_HOME_PERMS to override the default permissions. The defaults are the user and primary group for the owner, and 0755 for the permissions.

You should embark upon a GLEP81 migration like an EAPI update. Rather than simply copy your user's settings into an acct-user package, you should take the opportunity to re-evaluate your user's name, shell, home directory, and its permissions. Our GLEP 81 implementation will reveal many user management issues that were allowed to fester in the past.

Choosing a shell

In most cases, the default shell (that is, no shell) should be used. Services can still be started as a user who has no shell, and daemons are able to drop privileges to a user who has no shell. If necessary, the administrator can override a user's default shell with su -s <shell> <username>. This is sufficient for testing, management of SSH credentials, and for initial configuration in an ebuild's pkg_config phase.

An obvious exception to this rule is if a human being will need to log into the account interactively, as is the case with the root user. Other exceptions certainly exist, but should be evaluated case-by-case. In other words, if you haven't checked, don't set your user's shell to /bin/bash because you think he might need it.

The goal here is twofold. First, the principle of least privilege says that if a user doesn't need a real shell, he shouldn't have one. And along those same lines, not having a shell gives the system administrator some peace of mind: he doesn't have to be as concerned with whether or not that user has a password (and how strong it is), or whether or not its filesystem permissions are all set correctly, or whether or not it can log in via SSH, et cetera.

Choosing a home directory

In most cases, the default home directory (that is, no home directory) should be used. GLEP81 changed two aspects of user management with respect to home directories:

  1. Creating a user can now modify the permissions on an existing directory. Should the need arise, this is necessary for a new version of an acct-user package to be able to fix the ownership and permissions of its home directory.
  2. All user data aside from the username became non-local to ebuilds that depend on that user. This is merely a side-effect of moving the user creation out of the client package, and into a separate acct-user package.

The first item means that you should be conservative when choosing a home directory. If at all possible, avoid choosing a home directory that is used by another package. In particular, no two acct-user packages should use the same home directory. At best, the ownership and permissions on a shared home directory would need to be kept synchronized between all packages that share it. At worst, one package goes out-of-sync and introduces a security hole for the others who no longer have the expected permissions.

The second item means that if your package requires a user, you can no longer be sure of that user's home directory or its ownership and permissions. If your package requires a directory to be owned and writable by some user, then your package's ebuild should create that directory and ensure that it is writable by the user. In other words, you should not rely on the directory being created "transitively" by a dependency, even if that dependency is an acct-user package.

In summary,

  • Avoid using an ACCT_USER_HOME that belongs to another package.
  • No two acct-user packages should define the same ACCT_USER_HOME.
  • If for example your package's configuration needs <username> to be able to write to /var/lib/<username>, then your package's ebuild should create that directory and set its ownership and permissions. Barring any other considerations, the corresponding acct-user package should leave ACCT_USER_HOME at its default (empty) value; setting ACCT_USER_HOME=/var/lib/<username> creates unnecessary duplication and risks desynchronizing the permissions.

Choosing home directory ownership

In most cases, the default home directory ownership is correct. If a non-default home directory is needed at all, then it should be writable by its user and giving ownership of it to someone else would prevent that. Being unwritable indicates that a shared and potentially sensitive location was chosen. Moreover, the fact that the home directory is not writable suggests that the default home directory (which is also not writable) would suffice instead; the home directory guidelines explain why the default is preferable in that case. For example, setting ACCT_USER_HOME_OWNER="root:root" is suspicious because it appears intended to "undo" the ownership changed by your user package, and that would only be necessary if the path in question is used by some other package.

Choosing home directory permissions

In many cases, the default home directory permissions (0755) will suffice. But, if your package will work with mode 0700 or 0750, then those are preferable. This is the principle of least privilege again. If your package works with a non-writable home directory, then you should probably be using the default of no home directory!

Epilogue

These suggestions are not rules and are not written in stone, except perhaps for the world-writable warning. There are packages in the tree that chroot() to $HOME, and require that directory to be owned by root:root for security reasons. In cases like that, it's impossible to avoid implicitly tying the user to the package that needs it via the home directory, and the best you can do is attempt to ensure that the users and paths are unique so that no conflicts arise.

Unless your package is exceptional, though, following these guidelines will minimize the potential for problems down the road.

Utilizing users and groups in packages

In order to make your package install specific users and groups, specify them as dependencies. Accounts needed at build time must be included in DEPEND, and accounts needed at runtime must be included in RDEPEND.

For example, an ebuild requiring the user and group foo at runtime would specify:

RDEPEND="
    acct-user/foo
    acct-group/foo"

This would also be sufficient if ownership of installed files were set in pkg_preinst. However, if the ebuild needs the user and group to be present at build-time already, it would specify:

RDEPEND="
    acct-user/foo
    acct-group/foo"
DEPEND="${RDEPEND}"