SYSUSERS.D(5)
okay bestie, sit down, hydrate, because sysusers.d(5) is the page where systemd just declares which system users and groups get to exist on your machine ๐ it's giving "spreadsheet, but it's a directory" and honestly? iconic. no cap.
๐ธ NAME ๐ธ
sysusers.d โ declarative allocation of system users and groups ๐
โจ SYNOPSIS โจ
these are the directories it goes looking in, in case you were wondering ๐ง
/etc/sysusers.d/*.conf
/run/sysusers.d/*.conf
/usr/local/lib/sysusers.d/*.conf
/usr/lib/sysusers.d/*.conf
and here's the โจshapeโจ of a line โ one line, one user or group, periodt:
#Type Name ID GECOS Home directory Shell
u user_name uid "User Description" /home/dir /path/to/shell
u user_name uid:gid "User Description" /home/dir /path/to/shell
u user_name /file/owned/by/user "User Description" /home/dir /path/to/shell
g group_name gid
g group_name /file/owned/by/group
m user_name group_name
r - lowest-highest
๐ DESCRIPTION ๐
so systemd-sysusers takes the files chillin' in the sysusers.d directory and uses them to create system users and groups, and to add users to groups โ either when a package gets installed, or at boot time. main character energy fr fr.
but okay, important vibe check: this tool is for allocating system users and groups only. it is not useful for creating non-system users and groups (you know, the regular, "human" ones ๐), because it goes straight at /etc/passwd and /etc/group directly, bypassing any more complex user databases โ for example any database involving NIS or LDAP. so if your users live in one of those, this is not the tool for you, bestie ๐ญ
๐๏ธ CONFIGURATION DIRECTORIES AND PRECEDENCE ๐๏ธ
every config file has to be named in the style of package.conf or package-part.conf ๐ the second variant is the one you want when it'd be cute and convenient to override just that one part of the configuration, no biggie.
here's the tea on who wins, in order of drama:
- files in
/etc/sysusers.doverride files with the same name in/usr/lib/sysusers.dand/run/sysusers.d - files in
/run/sysusers.doverride files with the same name in/usr/lib/sysusers.d - packages should install their configuration files in
/usr/lib/sysusers.d - files in
/etc/sysusers.dare reserved for the local administrator ๐ who may use this logic to override the configuration files installed by vendor packages
all configuration files get sorted by their filename in lexicographic order, regardless of which of the directories they live in. and if multiple files specify the same path? the entry in the file with the lexicographically earliest name gets applied. everything after that for the same user and group names gets logged as warnings โ so like, the algorithm is not subtle about it, it will tell on you ๐ธ
if the administrator wants to disable a configuration file supplied by the vendor, the recommended way is to place a symlink to /dev/null in /etc/sysusers.d/ bearing the same filename. yes, really. that's the move ๐
๐ CONFIGURATION FILE FORMAT ๐
the file format is one line per user or group, and each line carries: name, ID, GECOS field description, home directory, and login shell. that's it, that's the whole vibe:
#Type Name ID GECOS Home directory Shell
u! httpd 404 "HTTP User"
u! _authd /usr/bin/authd "Authorization user"
u! postgres - "Postgresql Database" /var/lib/pgsql /usr/libexec/postgresdb
g input - -
m _authd input
u root 0 "Superuser" /root /bin/zsh
r - 500-900
empty lines and lines beginning with the # character are ignored, and may be used for commenting ๐ (yes, comment away, it's your file)
๐ค Type ๐ค
the type is literally just a single letter. here's the whole lineup, bestie:
u
create a system user and group of the specified name, should they not exist yet โจ the user's primary group will be set to the group bearing the same name โ unless the ID field specifies it. the account gets created disabled, so that logins are not allowed. no sneaking in ๐
added in version 215.
type u may be suffixed with an exclamation mark ("u!") to create a fully locked account ๐ฅ this is recommended, since logins should typically not be allowed for system users. with or without the exclamation mark, an invalid password is set. for "u!", the account is also locked โ and that makes a difference for non-password forms of authentication, such as SSH or similar. so like, not the same thing, don't @ me ๐
added in version 257.
g
create a system group of the specified name, should it not exist yet. note that u implicitly creates a matching group, so you might not even need this one ๐ the group will be created with no password set.
added in version 215.
m
add a user to a group. if the user or group do not exist yet, they will be implicitly created โ the system is just going to handle it for you, slay ๐ซถ
added in version 215.
r
add a range of numeric UIDs/GIDs to the pool, so new UIDs and GIDs can be allocated from it. if no line of this type is specified, the range of UIDs/GIDs is set to some compiled-in default ๐ note that both UIDs and GIDs are allocated from the same pool, in order to ensure that users and groups of the same name are likely to carry the same numeric UID and GID. cute, right? that's the whole point.
added in version 216.
๐ท๏ธ Name ๐ท๏ธ
the name field specifies the user or group name. the rules are strict and they are not playing around:
- it must consist only of the characters
a-z,A-Z,0-9,"_"and"-" - the first character must be one of
a-z,A-Zor"_"(i.e. numbers and"-"are not permitted as the first character) - the user/group name must have at least one character, and at most 31
for further details about the syntax of user/group names, see User/Group Name Syntax[1].
it is strongly recommended to pick user and group names that are unlikely to clash with normal users created by the administrator. a good scheme to guarantee this is by prefixing all system and group names with the underscore, and avoiding too generic names. do that. trust ๐
for m lines, this field should contain the user name to add to a group.
for lines of type r, this field should be set to "-".
๐ข ID ๐ข
for u and g: the numeric 32-bit UID or GID of the user/group. do not use IDs 65535 or 4294967295, as they have special placeholder meanings ๐ญ
- specify
"-"for automatic UID/GID allocation for the user or group โ this is strongly recommended unless it is strictly necessary to use a specific UID or GID - alternatively, specify an absolute path in the file system. in this case, the UID/GID is read from the path's owner/group. this is useful to create users whose UID/GID match the owners of pre-existing files (such as SUID or SGID binaries) ๐ฆ
- the syntaxes
"uid:gid"and"uid:groupname"are supported, to allow creating users with specific primary groups. the given group must be created explicitly, or it must already exist. specifying"-"for the UID in these syntaxes is also supported โจ
for m lines, this field should contain the group name to add to a user to.
for lines of type r, this field should be set to a UID/GID range in the format "FROM-TO", where both values are formatted as decimal ASCII numbers. alternatively, a single UID/GID may be specified formatted as decimal ASCII numbers.
๐ฃ๏ธ GECOS ๐ฃ๏ธ
a short, descriptive string for users to be created, enclosed in quotation marks. note that this field may not contain colons ๐ โโ๏ธ
only applies to lines of type u and should otherwise be left unset (or "-").
๐ Home Directory ๐
the home directory for a new system user. if omitted, it defaults to the root directory.
only applies to lines of type u and should otherwise be left unset (or "-"). it is recommended to omit this, unless software strictly requires a home directory to be set. like, don't set it for funsies.
heads up bestie:systemd-sysusersonly sets the home directory record in the user database. to actually create the directory, consider adding a correspondingtmpfiles.d(5)fragment ๐ธ
๐ Shell ๐
the login shell of the user. if not specified, this will be set to /usr/sbin/nologin โ except if the UID of the user is 0, in which case /bin/sh will be used ๐
only applies to lines of type u and should otherwise be left unset (or "-"). it is recommended to omit this, unless a shell different from /usr/sbin/nologin must be used.
๐ SPECIFIERS ๐
specifiers can be used in the "Name", "ID", "GECOS", "Home directory", and "Shell" fields โจ an unknown or unresolvable specifier is treated as invalid configuration โ so no improvising, bestie, it will simply say no ๐
the following expansions are understood:
โจ Table 1. Specifiers available โจ
okay bestie, here's the whole specifier menu, no skips, no cuts, every single one ๐
"%a"โ Architecture</p>: a short string identifying the architecture of the local system. Likex86,x86-64orarm64. Wanna see the whole list? Check the architectures defined forConditionArchitecture=insystemd.unit(5). ๐"%A"โ Operating system image version</p>: the operating system image version identifier of the running system, read straight from theIMAGE_VERSION=field of/etc/os-release. If it's not set, it resolves to an empty string.os-release(5)has the tea. ๐ซถ"%b"โ Boot ID</p>: the boot ID of the running system, formatted as a string. Seerandom(4)for more. ๐ฅ"%B"โ Operating system build ID</p>: the operating system build identifier of the running system, read from theBUILD_ID=field of/etc/os-release. Not set? Empty string, bestie.os-release(5)for more. โจ"%H"โ Host name</p>: the hostname of the running system. that's it, that's the whole vibe ๐"%l"โ Short host name</p>: the hostname of the running system, truncated at the first dot to remove any domain component. bye domain ๐"%m"โ Machine ID</p>: the machine ID of the running system, formatted as a string.machine-id(5)has more info. ๐"%M"โ Operating system image identifier</p>: the operating system image identifier of the running system, read from theIMAGE_ID=field of/etc/os-release. If not set, resolves to an empty string. Seeos-release(5). ๐ธ"%o"โ Operating system ID</p>: the operating system identifier of the running system, read from theID=field of/etc/os-release.os-release(5)for more. โญ"%q"โ Pretty host name</p>: the pretty hostname of the running system, read from thePRETTY_HOSTNAME=field of/etc/machine-info. If it's not set, it resolves to the short hostname. Seemachine-info(5)for more information. ๐"%T"โ Directory for temporary files</p>: this is either/tmpor whatever path"$TMPDIR","$TEMP"or"$TMP"are set to. (heads up: the directory may be specified without a trailing slash.) ๐ฆ"%v"โ Kernel release</p>: identical touname -routput. literally the same thing, no cap. ๐ฅ"%V"โ Directory for larger and persistent temporary files</p>: this is either/var/tmpor the path"$TMPDIR","$TEMP"or"$TMP"are set to. (again: the directory may be specified without a trailing slash.) ๐"%w"โ Operating system version ID</p>: the operating system version identifier of the running system, read from theVERSION_ID=field of/etc/os-release. If not set, resolves to an empty string. Seeos-release(5)for more. ๐"%W"โ Operating system variant ID</p>: the operating system variant identifier of the running system, read from theVARIANT_ID=field of/etc/os-release. If not set, it resolves to an empty string.os-release(5)for more information. โจ
"%%"โ a single percent sign</p>, bestie ๐ just write"%%"anywhere you want one literal"%"to show up. that's it. that's the whole trick.
๐ซถ IDEMPOTENCE
okay so real talk, this is the part that makes systemd-sysusers so chill to run: it will literally do nothing if the users or groups you asked for already exist, or if those users are already members of the groups you listed. ๐
which means โ and this is the slay part โ normally there is no reason to override sysusers.d vendor configuration, except to block certain users or groups from being created. like, that's the only vibe-check-passing reason to go stomping on the vendor files. no cap. โจ
๐ SEE ALSO
go read those, bestie, they're the main characters here ๐
๐ NOTES
- User/Group Name Syntax โ
https://systemd.io/USER_NAMES
that link is where the whole "what even counts as a valid user or group name" lore lives. check it if you're naming something cursed and need to know if the system will accept it ๐ฆ
and that's a wrap on the whole page, my love ๐ it's systemd 262.1 energy, it's SYSUSERS.D(5) in the section 5 lineup, and this edition is dated right there in the footer. go make some users. you're gonna eat. ๐โจ
๐ฆ where this page comes from
- arch rolling: systemd 262.1-1 ยท LGPL-2.1-or-later AND CC0-1.0 AND GPL-2.0-or-later AND MIT-0
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms