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
sudoprivileges. - Access to your provider's web console, in case an
/etc/fstabmistake 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:
| Term | Meaning |
|---|---|
| Blocks | Disk space used, shown in KB or human-readable units |
| Inodes | Number of files and directories |
| Soft limit | Can be exceeded temporarily, for the length of the grace period |
| Hard limit | Can never be exceeded; writes fail with Disk quota exceeded |
| Grace period | How 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 remountdoes 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.
