USERDBCTL(1)
π USERDBCTL(1) π
okay bestie, welcome to userdbctl β the userdbctl manual page, part 1 of 3, and it's giving β¨main characterβ¨ system introspection energy. sit down, grab a strawberry π, and let's get into it.
πΈ NAME πΈ
userdbctl β go look at users, groups, and who's in which group, no cap
β¨ SYNOPSIS β¨
userdbctl [OPTIONS...] {COMMAND} [NAME...]
π¦ DESCRIPTION π¦
So like, userdbctl is your little bestie for inspecting the users and groups on the system (and also the group memberships, because yes those are a whole separate thing π
). This client utility goes and asks around β it queries user/group info from a bunch of different system services, both the ones operating on JSON user/group records (as defined by the JSON User Records and JSON Group Records definitions, iykyk) and the classic UNIX NSS/glibc user and group records.
Primarily this tool is a client to the User/Group Record Lookup API via Varlink, and it may also pick up drop-in JSON user and group records from /etc/userdb/, /run/userdb/, /run/host/userdb/, /usr/lib/userdb/ (go read nss-systemd(8) for the details about drop-in user records, fr fr).
π OPTIONS π
Here's everything this icon understands:
--output=MODEβ picks your output mode. Takes one of"classic","friendly","table"or"json". If it's"classic", you get output very close to the format of/etc/passwdor/etc/group. If it's"friendly", you get a more comprehensive, user-friendly, human-readable output. If it's"table", it's a minimal tabular situation. If it's"json", it's JSON formatted. Defaults to"friendly"if a user/group is specified on the command line, and"table"otherwise.
β οΈ heads up bestie: most output formats do not show all available information. In particular,"classic"and"table"show only the most important fields. Various modes also don't show password hashes. Use"json"if you want to view all fields, including any authentication fields. π
Added in version 245.
--json=FORMATβ selects JSON output mode (like--output=json) and also picks the precise display mode. Takes one of"pretty"or"short". If"pretty", human-friendly whitespace and newlines get inserted so the JSON data is actually readable. If"short", all superfluous whitespace is suppressed.
Added in version 250.
--service=SERVICE[:SERVICE...],-s SERVICE:SERVICE...β controls which services get queried for users/groups. Takes a list of one or more service names, separated by":". There's a list of well-known service names below. If you don't specify it, all available services get queried at once.
Added in version 245.
--with-nss=BOOLβ controls whether classic glibc/NSS user/group lookups are included in the output. If--with-nss=nois used, any attempts to resolve or enumerate users/groups provided only via glibc NSS are suppressed. If--with-nss=yesis specified, such users/groups are included in the output (and that's the default).
Added in version 245.
--with-varlink=BOOLβ controls whether Varlink user/group lookups are included in the output, i.e. those done via the User/Group Record Lookup API via Varlink. If--with-varlink=nois used, any attempts to resolve or enumerate users/groups provided only via Varlink are suppressed. If--with-varlink=yesis specified, such users/groups are included in the output (which is the default).
Added in version 249.
--with-dropin=BOOLβ controls whether user/group lookups defined using drop-in files in/etc/userdb/,/run/userdb/,/run/host/userdb/,/usr/lib/userdb/get included in the output. If--with-dropin=nois used, these records are suppressed. If--with-dropin=yesis specified, such users/groups are included in the output (which is the default).
Added in version 249.
--synthesize=BOOLβ controls whether to synthesize records for therootandnobodyusers/groups if they're not defined otherwise, plus the user/groups for the"foreign"UID range. By default (or with"yes"), such records are implicitly synthesized if otherwise missing, since they have special significance to the OS. When"no", this synthesizing is turned off.
Added in version 245.
-Nβ this option is short for--with-nss=no --synthesize=no. Use this when you want to show only records that are natively defined as JSON user or group records, with all NSS/glibc compatibility and all implicit synthesis turned off. clean. β¨
Added in version 245.
--multiplexer=BOOLβ controls whether to do lookups via the multiplexer service (if specified as true, the default) or do lookups in the client (if specified as false). Using the multiplexer service is typically preferable, since it runs in a locked down sandbox. π
Added in version 250.
--chainβ when used with thessh-authorized-keyscommand, this will allow passing an additional command line after the user name that is chain executed after the lookup completed. This allows chaining multiple tools that show SSH authorized keys.
Added in version 250.
--fuzzy,-zβ when used with theuserorgroupcommand, does a fuzzy string search. Any specified arguments get matched against the user name, the real name of the user record, the email address, and other descriptive strings of the user or group record. Moreover, instead of precise matching, a substring match or a match allowing slight deviations in spelling is applied. she's flexible like that π
Added in version 257.
--disposition=β when used with theuserorgroupcommand, filters by disposition of the record. Takes one of"intrinsic","system","regular","dynamic","container". May be used multiple times, in which case only users matching any of the specified dispositions are shown.
Added in version 257.
-I,-S,-Rβ shortcuts for--disposition=intrinsic,--disposition=system,--disposition=regular, respectively. π«Ά
Added in version 257.
--uid-min=,--uid-max=β when used with theuserorgroupcommand, filters the output by UID/GID ranges. Takes numeric minimum or maximum UID/GID values, respectively. Shows only records within the specified range. When applied to theusercommand, it matches against UIDs. When applied to thegroupcommand, it matches against GIDs (yes, despite the name of the switch, no we don't make the rules π). If unspecified, defaults to0(for the minimum) and4294967294(for the maximum), i.e. by default no filtering is applied, since the whole UID/GID range is covered.
Added in version 257.
--uuid=β when used with theuserorgroupcommand, filters the output to the record with the specified UUID. If unspecified, no UUID-based filtering is applied.
Added in version 259.
--boundaries=β when used with theuserorgroupcommand, controls whether to show relevant UID/GID range boundary information in the tabular output. Takes a boolean. Defaults to true.
Added in version 257.
-Bβ shortcut for--boundaries=no.
Added in version 257.
--from-file=PATH,-Fβ when used with theuserorgroupcommand, read the user definition in JSON format from the specified file, instead of querying it from the system. If the path is specified as"-", it reads the JSON data from standard input. This is useful to validate and introspect JSON user or group records quickly, and check how they would be interpreted on the local system. so handy fr fr π₯
Added in version 258.
--no-pagerβ do not pipe output into a pager.--no-legendβ do not print the legend, i.e. column headers and the footer with hints.-h,--helpβ print a short help text and exit.--versionβ print a short version string and exit.
π COMMANDS π
These are the commands you can actually run:
user [USER...]β list all known users records, or show details of one or more specified user records. Use--output=to tweak the output mode.
If used in conjunction with --from-file= the user record data is read in JSON format from the specified file instead of querying it from the system. For details see above. β¬οΈ
Added in version 245.
group [GROUP...]β list all known group records, or show details of one or more specified group records. Use--output=to tweak the output mode.
If used in conjunction with --from-file= the group record data is read in JSON format from the specified file instead of querying it from the system. For details see above. β¬οΈ
Added in version 245.
users-in-group [GROUP...]β list users that are members of the specified groups. If no groups are specified, list all user/group memberships defined. Use--output=to tweak the output mode.
Added in version 245.
groups-of-user [USER...]β lists groups that the specified users are members of. If no users are specified, it lists all user/group memberships defined (in this case,groups-of-userandusers-in-groupare equivalent). Use--output=to tweak the output mode.
Added in version 245.
servicesβ list all services currently providing user/group definitions to the system. See below for a list of well-known services providing user information.
Added in version 245.
ssh-authorized-keysβ show SSH authorized keys for this account. This command is intended to be used to allow the SSH daemon to pick up authorized keys from user records, see below.
Added in version 245.
load-credentialsβ when specified, the following credentials are used when passed in:userdb.user.*,userdb.group.*,userdb.transient.user.*,userdb.transient.group.*β these credentials should contain valid JSON User and JSON Group records. Foruserdb.user.*anduserdb.group.*credentials, records are placed in/etc/userdb/, while foruserdb.transient.user.*anduserdb.transient.group.*credentials they are placed in/run/userdb/. These records implement the interface described innss-systemd(8). Any passed user records must contain validUIDandGIDfields. Any passed group records must contain aGIDfield (i.e. automatic UID/GID allocation is not supported). For both user and group records, the credential suffix (for"userdb.user.foobar"the suffix is"foobar") must match the user or group name encoded in the record.
Added in version 258.
Added in version 258.
okay that's part 1 done bestie, and there's more coming so don't go anywhere π
π WELL-KNOWN SERVICES π
So the userdbctl services command is gonna spill the tea on every single service running right now that hands out user or group definitions to your system. And these are the iconic ones you'll see in that list, bestie:
io.systemd.DynamicUserβ okay so this one is served up by the system service manager itself (aka PID 1 π), and it makes all the users (and their groups) that get synthesized through theDynamicUser=setting in service unit files available system-wide. Wanna know more about that setting? Checksystemd.exec(5), she explains it all. β¨
Added in version 245.
io.systemd.Homeβ this service comes fromsystemd-homed.service(8)and it puts every user (and their group) that belongs to home directories managed by that service onto the system. π π
Added in version 245.
io.systemd.Machineβ brought to you bysystemd-machined.service(8), and it synthesizes records for all the users/groups used by a container that's doing user namespacing. lowkey magic tbh π¦
Added in version 246.
io.systemd.Multiplexerβ this one's fromsystemd-userdbd.service(8)and it multiplexes user/group look-ups out to all the other running lookup services. It's literally the main character entry point for user/group record clients, because it makes the client-side implementation sooooo much simpler β clients can just ask one service for lookups instead of asking every running service in parallel.userdbctlprefers this service too, ngl β unless you're using--with-nss=or--service=, in which case you need finer control over which services get talked to. π
Added in version 245.
io.systemd.NameServiceSwitchβ this one is (also) provided bysystemd-userdbd.service(8), and it converts classic NSS/glibc user and group records into JSON user/group records, giving you full backwards compatibility. Wanna turn that off? Use--with-nss=no, see above bestie. π And btw, the compatibility goes both ways:nss-systemd(8)will automatically synthesize classic NSS/glibc user/group records from all the JSON user/group records handed to the system, so using both APIs is mostly equivalent and gives you access to the same data β however, the NSS/glibc APIs necessarily only expose a more reduced set of fields. it's giving "same data, fewer fields" π
Added in version 245.
io.systemd.DropInβ also fromsystemd-userdbd.service(8), and it picks up JSON user/group records from/etc/userdb/,/run/userdb/,/run/host/userdb/,/usr/lib/userdb/. drop it like it's hot πβ¨
Added in version 249.
Heads up bestie:userdbctlhas internal support for NSS-based lookups too. Which means if neitherio.systemd.Multiplexernorio.systemd.NameServiceSwitchis running, look-ups into the basic user/group databases will still work. no cap. π«Ά
π INTEGRATION WITH SSH π
Okay so here's a glow-up moment: the userdbctl tool can be used to make the list of SSH authorized keys β the ones possibly chillin' inside a user record β available to the SSH daemon for authentication. ποΈβ¨ To do that, set this up in sshd_config(5):
...
AuthorizedKeysCommand /usr/bin/userdbctl ssh-authorized-keys %u
AuthorizedKeysCommandUser root
...
Sometimes it's useful to allow chain invocation of another program to list SSH authorized keys. By using the --chain option, such a tool may be chain-executed by userdbctl ssh-authorized-keys once a lookup completes β and it does this regardless of whether an SSH key was found or not. Example time, bestie:
...
AuthorizedKeysCommand /usr/bin/userdbctl ssh-authorized-keys %u --chain /usr/bin/othertool %u
AuthorizedKeysCommandUser root
...
So what the above does is: first it queries the userdb database for SSH keys, and then it chain-executes /usr/bin/othertool to get queried too. teamwork makes the dream work fr fr π€π
π¦ EXIT STATUS π¦
On success, 0 is returned, and a non-zero failure code otherwise. simple as that. periodt. π
πΈ ENVIRONMENT πΈ
okay bestie, here's where the vibes get configurable π these env vars are the ones this tool actually reads, and yes you need to know all of them:
$SYSTEMD_LOG_LEVELβ this one sets the max log level of emitted messages, aka anything more boring than the level you pick gets yeeted into the void. It takes a comma-separated list of values. Each value is either one of these (listed from most important to least important):emerg,alert,crit,err,warning,notice,info,debugβ or an integer in the range0...7. Checksyslog(3)for the lore. Each value can also be prefixed with one ofconsole,syslog,kmsgorjournalfollowed by a colon, which sets the max log level for that specific log target only β likeSYSTEMD_LOG_LEVEL=debug,console:infomeans log everything at debug level except when writing to the console, which stays at info. π And listen: the global max log level takes priority over any per-target max log levels. no cap.$SYSTEMD_LOG_COLORβ a boolean. If true, messages written to the tty get colored according to priority. π
ngl this one only matters when messages go straight to the terminal, because journalctl(1) and other log-displaying tools color messages based on the log level all on their own. they don't need your help bestie.
$SYSTEMD_LOG_TIMEβ a boolean. If true, console log messages get prefixed with a timestamp. β°
same deal as above: this is only useful when messages are written directly to the terminal or a file, because journalctl(1) and friends attach timestamps based on the entry metadata themselves. they got it, fr fr.
$SYSTEMD_LOG_LOCATIONβ a boolean. If true, messages get prefixed with a filename and line number pointing at where in the source code the message originates. π
heads up: the log location is often attached as metadata to journal entries anyway. but having it right there in the message text is still lowkey convenient when you're debugging programs.
$SYSTEMD_LOG_TIDβ a boolean. If true, messages get prefixed with the current numerical thread ID (TID). π§΅
heads up again (yes, the original says "the this", we're keeping it iconic): this info is attached as metadata to journal entries anyway. but again, having it in the message text can be convenient when debugging.
$SYSTEMD_LOG_TARGETβ where log messages go. one of:consoleβ log to the attached ttyconsole-prefixedβ log to the attached tty but with prefixes encoding the log level and "facility", seesyslog(3)kmsgβ log to the kernel circular log bufferjournalβ log to the journaljournal-or-kmsgβ log to the journal if available, and to kmsg otherwiseautoβ determine the appropriate log target automatically, the default β¨nullβ disable log output
$SYSTEMD_LOG_RATELIMIT_KMSGβ whether to ratelimit kmsg or not. takes a boolean, defaults to"true". if disabled, systemd will not ratelimit messages written to kmsg. π¦$SYSTEMD_PAGER,$PAGERβ which pager to use when--no-pagerisn't given.$SYSTEMD_PAGERwins if it's set; otherwise$PAGERis used. If neither is set, a whole lineup of well-known pager implementations gets tried in turn, includingless(1)andmore(1), until one is found. If no pager implementation is discovered at all, no pager is invoked, periodt. Setting these variables to an empty string or the value"cat"is equivalent to passing--no-pager.
β οΈ note: if$SYSTEMD_PAGERSECUREis not set,$SYSTEMD_PAGERand$PAGERcan only be used to disable the pager (with"cat"or"") β otherwise they're just ignored. π
$SYSTEMD_LESSβ override the options passed to less (by default"FRSXMK"). π
there are two options users especially love to mess with:
Kβ instructs the pager to exit immediately when Ctrl+C is pressed. To let less handle Ctrl+C itself and switch back to the pager command prompt, unset this option. If the value of$SYSTEMD_LESSdoes not include"K", and the pager invoked is less, Ctrl+C will be ignored by the executable and needs to be handled by the pager.Xβ instructs the pager to not send termcap initialization and deinitialization strings to the terminal. It's set by default so command output stays visible in the terminal even after the pager exits. That said, it prevents some pager functionality from working β in particular, paged output cannot be scrolled with the mouse. π±οΈ
note: setting the regular $LESS environment variable has no effect for less invocations by systemd tools.
see less(1) for more discussion.
$SYSTEMD_LESSCHARSETβ override the charset passed to less (by default"utf-8", if the invoking terminal is determined to be UTF-8 compatible). π
note: setting the regular $LESSCHARSET environment variable has no effect for less invocations by systemd tools.
$SYSTEMD_PAGERSECUREβ okay this one is the serious one, bestie, listen up. π
Common pager commands like less(1), on top of just "paging" (scrolling through output), also support opening or writing to other files and running arbitrary shell commands. When commands are invoked with elevated privileges β like under sudo(8) or pkexec(1) β the pager becomes a security boundary. Care must be taken that only programs with strictly limited functionality are used as pagers, and that unintended interactive features like opening or creating new files or starting subprocesses are not allowed. "Secure mode" for the pager may be enabled as described below, if the pager supports it (most pagers are not written in a way that takes this into consideration π). It is recommended to either explicitly enable "secure mode" or to completely disable the pager using --no-pager or PAGER=cat when allowing untrusted users to execute commands with elevated privileges.
This option takes a boolean argument. When set to true, the "secure mode" of the pager is enabled. In "secure mode", LESSSECURE=1 will be set when invoking the pager, which instructs the pager to disable commands that open or create new files or start new subprocesses. Currently only less(1) is known to understand this variable and implement "secure mode".
When set to false, no limitation is placed on the pager. Setting SYSTEMD_PAGERSECURE=0 or not removing it from the inherited environment may allow the user to invoke arbitrary commands. π
When $SYSTEMD_PAGERSECURE is not set, systemd tools attempt to automatically figure out if "secure mode" should be enabled and whether the pager supports it. "Secure mode" is enabled if the effective UID is not the same as the owner of the login session, see geteuid(2) and sd_pid_get_owner_uid(3), or when running under sudo(8) or similar tools ($SUDO_UID is set [4]). In those cases, SYSTEMD_PAGERSECURE=1 will be set and pagers which are not known to implement "secure mode" will not be used at all. Note that this autodetection only covers the most common mechanisms to elevate privileges and is intended as convenience. It is recommended to explicitly set $SYSTEMD_PAGERSECURE or disable the pager.
note: if the$SYSTEMD_PAGERor$PAGERvariables are to be honoured, other than to disable the pager,$SYSTEMD_PAGERSECUREmust be set too.
$SYSTEMD_COLORSβ takes a boolean argument, or a special value. By default (unset), systemd and related utilities will use colors in their output if possible. If$COLORTERMis set to"truecolor"or"24bit", 24-bit colors will be enabled, 256 colors otherwise, unless$NO_COLORor$TERMindicates colors are disabled. πβ¨trueβ same as unset, except that$NO_COLORis ignored.falseβ the output will be monochrome. π"16","256","24bit"β always use the base 16 ANSI colors, 256 colors, or 24 bit color, respectively."auto-16","auto-256","auto-24bit"β use the given quantity of colours, subject to$TERM, and what the console is connected to.
$SYSTEMD_URLIFYβ the value must be a boolean. Controls whether clickable links should be generated in the output for terminal emulators supporting this. This can be specified to override the decision that systemd makes based on$TERMand other conditions. π
π« SEE ALSO π«
systemd(1), systemd-userdbd.service(8), systemd-homed.service(8), nss-systemd(8), getent(1)
π NOTES π
- JSON User Records β
https://systemd.io/USER_RECORD - JSON Group Records β
https://systemd.io/GROUP_RECORD - User/Group Record Lookup API via Varlink β
https://systemd.io/USER_GROUP_API - It is recommended for other tools to set and check
$SUDO_UIDas appropriate, treating it as a common interface.
and that's the whole page, bestie!! ππ¦ this was systemd 262.1's USERDBCTL(1) β go forth, vibe check your users and groups, and stay hydrated. mwah πβ¨π
π¦ 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