Disk quotas limit how much space and how many files a user or group can use on a filesystem. They stop a single account, a runaway log or a shared hosting customer from filling a disk that everyone depends on. In this tutorial you will enable user and group quotas on an ext4 filesystem on Ubuntu 24.04, set and test limits, adjust the grace period, and then see how the same job is done on XFS, including per-directory project quotas.

Prerequisites

  • A server running Ubuntu 24.04 LTS, for example a CubePath VPS.
  • A non-root user with sudo privileges.
  • Access to your provider's web console, in case an /etc/fstab mistake prevents the server from booting.
  • Basic familiarity with /etc/fstab, since quotas are enabled through mount options.

The examples enable quotas on the root filesystem /, which is where /home lives on most servers. If your users' data is on a separate disk, use its mount point (for example /mnt/data) wherever this guide uses /.

Quota concepts

Every quota has two resources and two kinds of limits:

TermMeaning
BlocksDisk space used, shown in KB or human-readable units
InodesNumber of files and directories
Soft limitCan be exceeded temporarily, for the length of the grace period
Hard limitCan never be exceeded; writes fail with Disk quota exceeded
Grace periodHow long a user may stay above the soft limit before it is enforced like a hard limit (7 days by default)

A limit of 0 means unlimited.

Step 1 - Installing the quota tools

Install the quota package, which provides quotacheck, quotaon, setquota, repquota and the other ext4 tools:

sudo apt update
sudo apt install quota
quota --version
Quota utilities version 4.06.

ext4 quotas need the kernel's quota format support (quota_v2). Check how your running kernel provides it:

grep -E 'CONFIG_QFMT_V2|CONFIG_QUOTA_TREE' /boot/config-$(uname -r)
CONFIG_QFMT_V2=m
CONFIG_QUOTA_TREE=m

=y means the support is built into the kernel and you can continue. =m means it is a module; confirm the module file exists:

find /lib/modules/$(uname -r) -type f -name 'quota_v2.ko*'
/lib/modules/6.8.0-84-generic/kernel/fs/quota/quota_v2.ko.zst

If the command prints nothing, the module is in the extra modules package for your kernel. Install it and load the module:

sudo apt install linux-modules-extra-$(uname -r)
sudo modprobe quota_v2

Step 2 - Enabling quota mount options

Quotas are switched on per filesystem with the usrquota (user) and grpquota (group) mount options. Back up /etc/fstab and open it:

sudo cp /etc/fstab /etc/fstab.bak
sudo nano /etc/fstab

Find the line for the filesystem you want to limit. On an Ubuntu 24.04 cloud image the root line looks like this:

LABEL=cloudimg-rootfs   /        ext4   discard,commit=30,errors=remount-ro     0 1

Add usrquota,grpquota to the options field (the fourth field), with commas and no spaces:

LABEL=cloudimg-rootfs   /        ext4   discard,commit=30,errors=remount-ro,usrquota,grpquota     0 1

Leave the rest of the line as it is. Save the file and check it:

sudo findmnt --verify
Success, no errors or warnings detected

Apply the new options without rebooting by remounting the filesystem, then confirm that they are active:

sudo systemctl daemon-reload
sudo mount -o remount /
findmnt -no OPTIONS /
rw,relatime,discard,usrquota,grpquota,errors=remount-ro,commit=30

Step 3 - Creating the quota files and turning quotas on

quotacheck scans the filesystem, counts the current usage of every user and group and writes it to the quota files aquota.user and aquota.group at the root of the filesystem:

sudo quotacheck -cugm /

The flags mean: -c create new files, -u and -g user and group quotas, -m do not try to remount the filesystem read-only (required on a mounted root filesystem). The scan can take a while on large disks. When it finishes, the files are in place:

ls -l /aquota.*
-rw------- 1 root root 8192 Sep 25 10:31 /aquota.group
-rw------- 1 root root 8192 Sep 25 10:31 /aquota.user

Turn enforcement on:

sudo quotaon -v /
/dev/vda1 [/]: group quotas turned on
/dev/vda1 [/]: user quotas turned on

Step 4 - Setting a user quota

setquota sets limits in one command, which is easy to script. The arguments are the block soft and hard limits, the inode soft and hard limits, and the filesystem. The quota tools accept K, M, G and T suffixes for block limits.

This example gives the user sammy a soft limit of 1 GB and a hard limit of 1.2 GB, with no limit on the number of files. Replace sammy with a real user:

sudo setquota -u sammy 1G 1200M 0 0 /

Check the result with quota. The -s flag prints human-readable sizes:

sudo quota -vs sammy
Disk quotas for user sammy (uid 1001):
     Filesystem   space   quota   limit   grace   files   quota   limit   grace
      /dev/vda1     32K   1024M   1200M               8       0       0

space is the current usage, quota the soft limit and limit the hard limit.

If you prefer an editor, sudo edquota -u sammy opens the same values in your default editor. To apply one user's limits to other users, use it as a template:

sudo edquota -p sammy -u alice bob

Step 5 - Setting a group quota

Group quotas limit the total space used by files owned by a group, regardless of which user created them. This is useful for shared project directories. Set a 10 GB soft and 12 GB hard limit for the group developers:

sudo setquota -g developers 10G 12G 0 0 /
sudo quota -gvs developers
Disk quotas for group developers (gid 1002):
     Filesystem   space   quota   limit   grace   files   quota   limit   grace
      /dev/vda1   1204M  10240M  12288M              347       0       0

Step 6 - Testing enforcement

Confirm that the hard limit really stops writes. As sammy, try to write 1.3 GB in their home directory:

sudo -u sammy dd if=/dev/zero of=/home/sammy/quota-test bs=1M count=1300
dd: error writing '/home/sammy/quota-test': Disk quota exceeded
1199+0 records in
1198+0 records out

The write stopped at the hard limit. The quota report now shows the user over the soft limit, with the grace period counting down:

sudo quota -vs sammy
Disk quotas for user sammy (uid 1001):
     Filesystem   space   quota   limit   grace   files   quota   limit   grace
      /dev/vda1   1200M*  1024M   1200M   6days       9       0       0

The asterisk marks the exceeded limit. Remove the test file:

sudo rm /home/sammy/quota-test

Step 7 - Adjusting the grace period

The grace period applies to all users (or all groups) on a filesystem. Set it with setquota -t, giving the block and inode grace times in seconds. This sets 3 days (259200 seconds) for user quotas:

sudo setquota -t 259200 259200 /

Use sudo setquota -t -g 259200 259200 / for group quotas. The next section shows the new value in the report header.

Step 8 - Reporting usage

repquota prints the usage and limits of every user on a filesystem, which is the command you will use most for monitoring:

sudo repquota -s /
*** Report for user quotas on device /dev/vda1
Block grace time: 3days; Inode grace time: 3days
                        Space limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --   2410M      0K      0K          81k     0     0
sammy     --     32K   1024M   1200M            8     0     0

The two characters after the user name show the block and inode state: - is within limits and + means the soft limit is exceeded. Use sudo repquota -gs / for groups and sudo repquota -as for all filesystems with quotas.

Quotas stay enabled across reboots because the options are in /etc/fstab. After the next reboot, confirm it with:

sudo quotaon -pa
group quota on / (/dev/vda1) is on
user quota on / (/dev/vda1) is on

Quotas on XFS

XFS keeps quota accounting inside the filesystem, so it does not use quotacheck, quotaon or quota files. It has two differences you must know:

  • Quota options must be present when the filesystem is mounted. mount -o remount does not turn them on, so you need an unmount and mount (or a reboot).
  • For the root filesystem, the options have to be passed on the kernel command line with rootflags=, which is why XFS quotas are normally used on data disks.

The example below assumes an XFS data disk mounted at /srv/data. The xfs_quota tool comes with the xfsprogs package, which Ubuntu Server installs by default.

Enabling user and project quotas

Edit the disk's line in /etc/fstab and add uquota (user quotas) and pquota (project quotas):

UUID=9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d  /srv/data  xfs  defaults,uquota,pquota,nofail  0  0

Remount the disk by unmounting and mounting it again, then check the quota state:

sudo systemctl daemon-reload
sudo umount /srv/data
sudo mount /srv/data
sudo xfs_quota -x -c 'state' /srv/data
User quota state on /srv/data (/dev/vdb1)
  Accounting: ON
  Enforcement: ON
...
Project quota state on /srv/data (/dev/vdb1)
  Accounting: ON
  Enforcement: ON

Setting a user limit

Set a 5 GB soft and 6 GB hard limit for sammy and print a report:

sudo xfs_quota -x -c 'limit bsoft=5g bhard=6g sammy' /srv/data
sudo xfs_quota -x -c 'report -u -h' /srv/data
User quota on /srv/data (/dev/vdb1)
                        Blocks
User ID      Used   Soft   Hard Warn/Grace
---------- ---------------------------------
root            0      0      0  00 [------]
sammy           0     5G     6G  00 [------]

Limiting a directory with a project quota

Project quotas limit a directory tree no matter which user writes to it, for example one site's upload folder. Create the directory and register it as project ID 10 named web:

sudo mkdir -p /srv/data/web
echo "10:/srv/data/web" | sudo tee -a /etc/projects
echo "web:10" | sudo tee -a /etc/projid

Initialize the project, which tags the directory with the project ID, then set a 20 GB hard limit:

sudo xfs_quota -x -c 'project -s web' /srv/data
sudo xfs_quota -x -c 'limit -p bhard=20g web' /srv/data
sudo xfs_quota -x -c 'report -p -h' /srv/data
Project quota on /srv/data (/dev/vdb1)
                        Blocks
Project ID   Used   Soft   Hard Warn/Grace
---------- ---------------------------------
#0              0      0      0  00 [------]
web             0      0    20G  00 [------]

Tools such as df run inside /srv/data/web now report the project limit as the size of the filesystem.

Troubleshooting

quotaon: using //aquota.user on /dev/vda1 [/]: No such process or Quota format not supported in kernel. The quota_v2 format is not available. Go back to Step 1, install linux-modules-extra-$(uname -r) if needed and run sudo modprobe quota_v2.

quotacheck: Cannot find filesystem to check or filesystem not mounted with quota option. The remount did not apply the options. Check findmnt -no OPTIONS / for usrquota,grpquota and review the /etc/fstab line.

Limits are set but users can still write past them. Enforcement is off. Run sudo quotaon -pa; if it reports off, turn it on with sudo quotaon -v /. Remember that root is never limited.

A user gets Disk quota exceeded while showing free space. They have probably hit an inode limit rather than a block limit. Check the files columns of sudo quota -vs user.

The server does not boot after editing /etc/fstab. Log in through the web console, run mount -o remount,rw /, restore the backup with cp /etc/fstab.bak /etc/fstab and reboot.

Conclusion

You enabled user and group quotas on an ext4 filesystem, set soft and hard limits with setquota, proved that the hard limit stops writes, changed the grace period and learned to read repquota reports. You also saw how XFS handles user and project quotas with xfs_quota. From here, you can schedule a daily repquota -as report by email with cron, apply quotas to a shared Samba or NFS directory, or use project quotas to cap the space of each site on a web server.