pam_cgfs(8)

πŸ’… pam_cgfs(8) β€” the girlies' guide to cgroup management for unprivileged LXC containers

Okay so bestie, buckle up, because this is pam_cgfs(8) and it's genuinely one of the most underrated little modules out there. It's a PAM module, it's iconic, and it's about to make your unprivileged containers behave. 🫢


✨ NAME ✨

pam_cgfs β€” cgroup management for unprivileged LXC containers. That's the whole vibe. No cap.


πŸŽ€ SYNOPSIS πŸŽ€

pam_cgfs.so {-c kernel_controller,name=named_controller}

That's it. That's the whole thing. One option, but she serves. πŸ’…


🌸 DESCRIPTION 🌸

So, storytime. LXC has been out here supporting fully unprivileged containers since LXC 1.0, and lowkey these are the safest containers you can run. They're run by normal, non-root users, and the way that works is user namespaces β€” you map a whole range of UIDs and GIDs on the host to a different (and unprivileged!) range of UIDs and GIDs inside the container. Which means: uid 0 (root) inside the container is actually mapped to some unprivileged user id outside of it (something like 1000000), and it only has rights over resources that it actually owns itself. No sneaky host takeover, no drama. πŸ”₯

Now, cgroup management of fully unprivileged containers is all about restricting what those containers can use β€” like limiting the CPU usage of a container, or the number of processes it's allowed to spawn, or the memory it's allowed to consume. And it's clear (like, obvious) that fully unprivileged containers are run by normal users, so there's a real need to limit and manage resource consumption among all the containers. But unprivileged cgroup management is not easy with most init systems. So pam_cgfs.so came into existence. Main character energy, honestly. πŸ‘‘

Here's the technical tea, bestie β€” write it down:

  • The pam_cgfs.so module can handle pure cgroupfs v1 (/sys/fs/cgroup/$controller) and mixed mounts, where some controllers are mounted in a standard cgroupfs v1 hierarchy (/sys/fs/cgroup/$controller) and others in a cgroupfs v2 hierarchy (/sys/fs/cgroup/unified).
  • Writeable cgroups are either created for all controllers, or β€” if you specify them β€” for only the controllers listed as arguments on the command line.
  • > Pure cgroup v2 mount is NOT covered by the pam_cgfs.so module. Sorry babe. 😭

The cgroup created is user/$user/n, and that's for the *n*th session under that cgroup kernel controller hierarchy. Numbered sessions, so organized. πŸŽ€

Systemd systems get special treatment, both for cgroupfs v1 and cgroupfs v2. For both of them, the module checks whether systemd already placed the user in a cgroup it created β€” user.slice/user-$uid/session-n.scope β€” by checking whether $uid == login uid. If so, the login user chowns the session-n.scope. Otherwise, a cgroup is created as outlined above (user/$user/n) and chowned to the login uid. And if the init system has already placed the login user inside a session-specific group, pam_cgfs.so is smart enough to detect it and just re-use that cgroup. She's perceptive like that. 🧚

In essence: pam_cgfs.so takes care of placing unprivileged (non-root) users into writable cgroups at login, and cleaning up those cgroup hierarchies on logout, so they're free to delegate resources to containers as needed β€” resources that have been provided to them. In and out, tidy, periodt. πŸ’–


🌈 OPTIONS 🌈

  • -c controller-list β€” takes a string argument that sets the list of kernel controllers and named controllers, delimited by commas in-between ,. Named controllers need to be specified in the form name=$namedcontroller. You can use all to enable all cgroup resource controller hierarchies. ⚠️ But heads up: specifying all and other controllers explicitly returns PAM_SESSION_ERR. That's a hard no. 🚫

πŸ¦‹ MODULE TYPES PROVIDED πŸ¦‹

Only the session module type is provided β€” and needed. That's it. One type. She's focused. ✨


⭐ RETURN VALUES ⭐

  • PAM_SUCCESS β€” writeable cgroups have been created for the user. Slay! πŸŽ‰
  • PAM_SESSION_ERR β€” failed to create writable cgroups for the user. πŸ’€

πŸ“ FILES πŸ“

  • /etc/pam.d/common-session{,-noninteractive} β€” the default configuration is added at the end of these files.

πŸ’œ EXAMPLE πŸ’œ

session optional    pam_cgfs.so -c freezer,memory,named=systemd
# default configuration
# user writable cgroups are created under freezer, memory and named cgroup systemd hierarchies.
# /sys/fs/cgroup/$controller/user/$user/n for freezer,memory.
# /sys/fs/cgroup/systemd/user.slice/user-$uid/session-n.scope for systemd.
session optional    pam_cgfs.so -c all
# user writable cgroups are created under all cgroup controllers.
session optional    pam_cgfs.so -c all,memory,freezer
# invalid argument and returns PAM_SESSION_ERR

See that last one? That's the all-plus-extras trap we warned you about. Do not do it. πŸ™ˆ


πŸ‘‘ SEE ALSO πŸ‘‘

lxc-cgroup(1), cgroups(7), user_namespaces(7), namespaces(7), pam(8)


Okay that's the whole page, bestie β€” go forth and let your unprivileged containers have exactly the resources they deserve and not one crumb more. This was pam_cgfs(8), dated 2026-05-01, and honestly? Iconic of her. πŸ’…βœ¨πŸŽ€πŸ«Ά

πŸ“¦ where this page comes from