Home / Alt manpages / pam_setquota(8)

  • pam_setquota(8)
  • Admin command
  • linux

Apply Session-Start Disk Quotas with pam_setquota

You will finish with a PAM session rule that applies block and inode limits to a chosen UID range when a session opens. The examples use pam_setquota from Ubuntu's libpam-modules version 1.5.3-5ubuntu5.7, installed here as /usr/lib/x86_64-linux-gnu/security/pam_setquota.so.

Allow about 20 minutes, plus a maintenance window if the rule will affect a real login service. You need root access, a filesystem with quotas configured, and a test account whose UID you can identify. This module changes quota state during PAM session setup, so do not test it first on a production-wide range.

Checkpoint

The working configuration is the PAM line, not a standalone command. The module is called by a service such as SSH when that service opens a session.

1. Confirm the installed module

Start with read-only checks. These do not require elevated privileges:

$ dpkg-query -W -f='${Package} ${Version}\n' libpam-modules:amd64
libpam-modules 1.5.3-5ubuntu5.7
$ test -r /usr/lib/x86_64-linux-gnu/security/pam_setquota.so && echo module-present
module-present

Your package version may differ. Keep the local manual page beside the package when checking a different release, because option defaults and implementation details belong to the installed module. pam_setquota is a PAM module, so running pam_setquota at a shell prompt is not a useful test.

2. Choose a narrow UID range

Find the test account's numeric UID and its home directory:

$ id --user testquota
1500
$ getent passwd testquota
testquota:x:1500:1500:Quota test account:/home/testquota:/bin/bash

Replace testquota with an account that already exists. The module defaults startuid to the system's UID_MIN setting, and defaults enduid to 0. That zero means an open-ended range, including every UID greater than or equal to startuid, not an empty range. For a first test, use the exact UID by setting both ends to 1500. This prevents a typo from changing every ordinary user's quota.

Check which filesystem contains the home directory before choosing fs:

$ findmnt --target /home/testquota --output TARGET,SOURCE,FSTYPE
TARGET SOURCE    FSTYPE
/home  /dev/sda1 ext4

The output is host-specific. The module accepts a device file or mountpoint. If fs is omitted, it looks for the filesystem containing the user's home directory. An explicit mountpoint is easier to audit, but it must identify the filesystem where the quota is enabled.

3. Decide the limits before editing PAM

Block limits are passed as quota blocks to quotactl(2), not as a promise that the user can store that many decimal megabytes. Inode limits count files and directories. Set each soft and hard pair together: bsoftlimit with bhardlimit, and isoftlimit with ihardlimit.

This example allows 1,000 soft and 2,000 hard blocks, plus 1,000 soft and 2,000 hard inodes, for UID 1500 on /home:

bsoftlimit=1000 bhardlimit=2000 isoftlimit=1000 ihardlimit=2000 startuid=1500 enduid=1500 fs=/home

The numbers are deliberately small for a test and are not a recommendation. Confirm your quota unit convention and desired capacity before using real values. Supplying only one half of either pair is an error and returns PAM_PERM_DENIED.

4. Back up the PAM file

Warning

A malformed or misplaced PAM session rule can prevent logins through that service. Keep an existing root shell or console session open while testing, and make a root-owned backup before changing the file.

# cp --preserve=all /etc/pam.d/sshd /etc/pam.d/sshd.before-pam-setquota
# ls -l /etc/pam.d/sshd /etc/pam.d/sshd.before-pam-setquota

Use the PAM file for the service that should apply the policy. The example uses SSH; select another file if your sessions come from a different service. Do not add this line to every PAM service unless that scope is intentional.

5. Add one session rule

Edit the chosen file as root and add one line in its session section:

session required pam_setquota.so bsoftlimit=1000 bhardlimit=2000 isoftlimit=1000 ihardlimit=2000 startuid=1500 enduid=1500 fs=/home

The required control means the session stack records a failure while continuing through the remaining session modules; the service ultimately treats the session as failed if a required module failed. Place the rule where it fits the service's existing session policy, then inspect the exact saved line:

$ grep -nF 'pam_setquota.so' /etc/pam.d/sshd
42:session required pam_setquota.so bsoftlimit=1000 bhardlimit=2000 isoftlimit=1000 ihardlimit=2000 startuid=1500 enduid=1500 fs=/home

6. Test one new session

Open a new session as the selected account without closing your existing administrative session. For SSH, log in from a separate terminal:

$ ssh testquota@HOSTNAME
$ id --user
1500

The module returns PAM_SUCCESS when it sets the quota. It returns PAM_IGNORE when the UID is outside the range, a quota already exists and overwrite=1 was not configured, or no limits were configured. A successful login alone does not prove that the quota was applied, so inspect the quota with the host's quota reporting tool and check the service logs for module diagnostics.

For a diagnostic run, temporarily change the rule to include debug=1, open one test session, then remove it. The module's debug output includes the old and new quota and may expose account policy details in logs. Treat those logs as sensitive and do not leave debugging enabled.

7. Add broader ranges only after the test works

Once the exact-UID test is understood, widen the range deliberately. For example, this covers UIDs 2001 through 3000:

session required pam_setquota.so bsoftlimit=19000 bhardlimit=20000 isoftlimit=3000 ihardlimit=4000 startuid=2001 enduid=3000 fs=/dev/sda1

You can use multiple pam_setquota.so lines for different ranges. The last matching entry defines the resulting quota. Review ordering carefully. A later line with overwrite=1 can replace an earlier result, while leaving overwrite at its default of 0 preserves an existing quota instead of replacing it.

Do not add overwrite=1 casually. The manual warns that it removes the administrator's ability to maintain different per-user values with edquota(8) on that filesystem. If you need to undo the PAM policy, remove or comment out the rule, restore the backup, and then correct existing quotas separately with your normal quota administration process. Removing the PAM line does not itself restore quotas already written.

Common failure checks

  • No action: confirm the test UID is inside startuid through enduid. With enduid=0, the range is open-ended above startuid.
  • Permission denied: check that the filesystem or device exists, quota support is enabled, both members of the relevant limit pair are present, and the session service has the privilege needed to set quotas. Read the service's syslog or journal entry for the module's detailed reason.
  • Existing values remain: this is expected with the default overwrite=0. Decide whether preserving manual values is the desired policy before changing it.
  • All users are affected: inspect every matching line and remember that enduid=0 is open-ended. Restore the PAM backup if the scope is wrong, then review any quotas already changed.

Done means

  • The installed module and package version were confirmed.
  • The filesystem, test UID and block and inode pairs were chosen explicitly.
  • A backup exists and the rule is in the intended service's session stack.
  • A new test session matched the intended UID range and the resulting quota was checked.
  • overwrite=1 is absent unless replacing existing per-user values is an intentional, documented policy.