SHELL-TIMEOUT.CON(5)

πŸ“¦ version 0.3.0, in epel 10, epel 9

πŸ’… shell-timeout.conf β€” hey bestie, let's talk timeouts πŸ’…

okay so this is the manual for shell-timeout.conf, the config file behind the shell-timeout inactivity scripts. it's genuinely not scary, i promise β€” it's just a bunch of KEY=VALUE lines and then your shell gets a nap timer. slay.


✨ SYNOPSIS ✨

/etc/default/shell-timeout

/etc/default/shell-timeout.d/*.conf

like yeah that's it, those are the two places it lives. one main file, one drop-in folder. iconic behavior honestly.


πŸŽ€ DESCRIPTION πŸŽ€

shell-timeout.conf is the configuration file for the shell-timeout.sh(7) script (that's the bash/zsh one) and the shell-timeout.csh(7) script (the csh/tcsh one). what these scripts do is: whenever the current user matches a configured UID, GID, username, or group name, they automatically set an inactivity timeout for interactive shells. so if you walk away from your terminal forever, it logs you out. self-care fr fr πŸ’–

the main configuration file is /etc/default/shell-timeout. you can also drop additional files into /etc/default/shell-timeout.d/*.conf. those drop-ins get processed in alphabetical order after the main file. and here's the cute part: values from later files extend the lists from earlier ones, they don't replace them. so a drop-in can add or remove entries without you having to rewrite the whole base config. no cap, that's the whole design goal.


🌸 FILE FORMAT 🌸

these config files use a shell-neutral KEY=VALUE format. rules go like this:

  • One key-value pair per line.
  • Keys and values are separated by a single = with no surrounding spaces.
  • Values may be optionally quoted with single or double quotes.
  • Multiple space-separated items may appear in a single value field.
  • Lines beginning with # are comments and are ignored.
  • Empty lines are ignored.

Example.

# Timeout all users who are members of the "staff" group
TMOUT_SECONDS=900
TMOUT_GROUPS=staff
TMOUT_READONLY=yes

see? adorable. tiny. does its job.


πŸ‘‘ CONFIGURATION VARIABLES πŸ‘‘

⏰ Timeout duration

  • TMOUT_SECONDS = integer β€” the inactivity timeout, in seconds. it has to be a positive integer greater than zero. non-integer, zero, negative, and empty values all cause the scripts to exit without setting any timeout (so like, nothing happens, no protection, just vibes). in csh and tcsh the value gets converted to minutes (rounded down, minimum 1 minute). don't ask, that's just how those shells live.

πŸ”’ Readonly enforcement

  • TMOUT_READONLY = yes | true | 1 | no | false | 0 β€” when it's set to yes, true, or 1, the timeout variable gets made read-only after being set, which stops users from disabling it. exactly the energy we want πŸ”₯. this option is silently ignored in csh and tcsh, because those shells don't support read-only shell variables at all. not their fault.

πŸ†” Matching by numeric UID or GID

  • TMOUT_UIDS = uid [uid ...] β€” space-separated list of numeric user IDs. any user whose effective UID shows up in this list gets the timeout set. values from multiple configuration files are merged together.
  • TMOUT_GIDS = gid [gid ...] β€” space-separated list of numeric group IDs. any user whose primary or supplementary GID shows up in this list gets the timeout set. values from multiple configuration files are merged together.

🧚 Matching by username or group name

  • TMOUT_USERNAMES = name [name ...] β€” space-separated list of usernames. each name gets resolved to a numeric UID at runtime via id(1). names that can't be resolved are silently ignored (no drama, no error). the resolved UIDs are merged into TMOUT_UIDS before matching.
  • TMOUT_GROUPS = name [name ...] β€” space-separated list of group names. each name gets resolved to a numeric GID at runtime via getent(1). names that can't be resolved are silently ignored. the resolved GIDs are merged into TMOUT_GIDS before matching.

πŸ™ˆ Removing entries from consideration (numeric)

  • TMOUT_UIDS_NOCHECK = uid [uid ...] β€” space-separated list of numeric UIDs to remove from TMOUT_UIDS. a user whose UID gets removed from the UID list won't match via the UID path anymore β€” but heads up, they might still match via the GID path if their group is configured. 😭
  • TMOUT_GIDS_NOCHECK = gid [gid ...] β€” space-separated list of numeric GIDs to remove from TMOUT_GIDS. a GID removed from the GID list won't cause a match via the GID path, but users whose UIDs are still in TMOUT_UIDS will keep matching. sneakyyyy.

🫢 Removing entries from consideration (by name)

  • TMOUT_USERNAMES_NOCHECK = name [name ...] β€” space-separated list of usernames to remove from consideration. each name gets resolved to a numeric UID at runtime and merged into TMOUT_UIDS_NOCHECK. numeric IDs and names can be freely mixed across files, so go off.
  • TMOUT_GROUPS_NOCHECK = name [name ...] β€” space-separated list of group names to remove from consideration. each name gets resolved to a numeric GID at runtime and merged into TMOUT_GIDS_NOCHECK. numeric IDs and names may be freely mixed across files.

πŸ¦‹ Readonly exemptions (numeric)

  • TMOUT_UIDS_NOREADONLY = uid [uid ...] β€” space-separated list of numeric UIDs that are exempt from readonly enforcement. when TMOUT_READONLY is set, a user whose UID is in this list still gets TMOUT set to TMOUT_SECONDS, it just won't be made readonly. this option is silently ignored in csh and tcsh.
  • TMOUT_GIDS_NOREADONLY = gid [gid ...] β€” space-separated list of numeric GIDs exempt from readonly enforcement. a user whose primary or supplementary GID is in this list gets TMOUT set but not locked. this option is silently ignored in csh and tcsh.

🌈 Readonly exemptions (by name)

  • TMOUT_USERNAMES_NOREADONLY = name [name ...] β€” space-separated list of usernames exempt from readonly enforcement. each name gets resolved to a numeric UID at runtime and merged into TMOUT_UIDS_NOREADONLY.
  • TMOUT_GROUPS_NOREADONLY = name [name ...] β€” space-separated list of group names exempt from readonly enforcement. each name gets resolved to a numeric GID at runtime and merged into TMOUT_GIDS_NOREADONLY.

πŸ” MATCHING SEMANTICS πŸ”

the UID and GID matching paths are fully independent. like, they don't talk to each other at all.

removing an entry from the UID list (via TMOUT_UIDS_NOCHECK or TMOUT_USERNAMES_NOCHECK) has zero effect on GID matching, and vice versa. so a user whose UID has been explicitly excluded can still get the timeout applied, because one of their groups is listed in TMOUT_GIDS. plot twist, i know πŸ’€

name resolution happens before list subtraction. the effective evaluation order is:

  1. Accumulate all TMOUT_UIDS and TMOUT_USERNAMES values from all configuration files (main + drop-ins).
  2. Resolve each username to its numeric UID.
  3. Accumulate all TMOUT_UIDS_NOCHECK and TMOUT_USERNAMES_NOCHECK values and resolve usernames to UIDs.
  4. Subtract the NOCHECK UIDs from the UID list.
  5. Repeat steps 1-4 for GIDs and group names.
  6. Compare the current user's UID and all their GIDs against the final lists.
  7. If a match is found, set TMOUT to TMOUT_SECONDS.
  8. If TMOUT_READONLY is set, check whether the user's UID is in TMOUT_UIDS_NOREADONLY (after resolving TMOUT_USERNAMES_NOREADONLY) or any of their GIDs is in TMOUT_GIDS_NOREADONLY (after resolving TMOUT_GROUPS_NOREADONLY). if exempt, TMOUT is left writable; otherwise it gets made readonly.

that's the whole pipeline. read it twice, it's giving algorithm πŸ’…


⭐ EXAMPLES ⭐

🌸 Timeout all members of a group, exempt one user

/etc/default/shell-timeout:

TMOUT_SECONDS=900
TMOUT_GROUPS=employees
TMOUT_READONLY=yes

/etc/default/shell-timeout.d/exceptions.conf:

# Service account does not need a timeout
TMOUT_USERNAMES_NOCHECK=svcaccount

🌸 Mix numeric IDs and names

TMOUT_SECONDS=600
TMOUT_UIDS=1042
TMOUT_USERNAMES=alice bob
TMOUT_GIDS=500
TMOUT_GROUPS=contractors

🌸 Drop-in adds a group, removes one user from a different drop-in

/etc/default/shell-timeout.d/10-base.conf:

TMOUT_GROUPS=staff

/etc/default/shell-timeout.d/20-exceptions.conf:

# Remove a specific user added by an earlier drop-in
TMOUT_UIDS_NOCHECK=1099

🌸 Global readonly with per-user exemption

/etc/default/shell-timeout:

TMOUT_SECONDS=900
TMOUT_GROUPS=employees
TMOUT_READONLY=yes

/etc/default/shell-timeout.d/sysadmin-noreadonly.conf:

# Sysadmins can adjust or unset their own timeout
TMOUT_GROUPS_NOREADONLY=sysadmins
# A specific service account by name
TMOUT_USERNAMES_NOREADONLY=deploy-bot

πŸ“ FILES πŸ“

  • /etc/default/shell-timeout β€” the main configuration file.
  • /etc/default/shell-timeout.d/*.conf β€” drop-in configuration files, processed in alphabetical order.
  • /etc/profile.d/shell-timeout.sh β€” the POSIX shell (bash/zsh) script, sourced at login.
  • /etc/profile.d/shell-timeout.csh β€” the C shell (csh/tcsh) script, sourced at login.

πŸ’œ SEE ALSO πŸ’œ

id(1), getent(1), bash(1), zsh(1), csh(1), tcsh(1)

go read those if you want the lore. iykyk.


πŸ’€ NOTES πŸ’€

the csh and tcsh interpreters do not support read-only variables, so TMOUT_READONLY has no effect in those shells. periodt. also, the inactivity timeout is implemented via the autologout shell variable, which is the number of minutes of idle time before logout (minimum 1). so like, one minute is the floor, don't try to be clever.


okay bestie that's the whole page 🫢 go set your TMOUT_SECONDS and stay safe out there. and remember: NOCHECK removes, NOREADONLY exempts, and they are not the same thing, don't @ me.

✨ this has been SHELL-TIMEOUT.CON(5), from the 03/18/2026 edition β€” mwah, bye ✨

πŸ“¦ where this page comes from