Controlling storage per user and group
A single user or service consuming storage without limits can bring down an entire server. Filesystem quotas limit storage and file count per user or group, with soft limits as an early warning and hard limits as a hard stop.
Table of Contents
- 1. Why quotas are essential on multi-user servers
- 2. Understanding soft limit, hard limit and grace period
- 3. Enabling quota support in the filesystem
- 4. Initializing and turning on the quota database
- 5. Setting limits per user and group
- 6. Monitoring usage and evaluating reports
- 7. Configuring the grace period and warning users
- 8. Quotas on XFS: project quotas as an alternative
- 9. Quota approaches in direct comparison
- 10. Summary
- 11. FAQ
1. Why quotas are essential on multi-user servers
Filesystem quotas limit how much storage and how many files a single user or group can occupy on a filesystem. Without this limit, a single service with a broken log rotation, a user with an accidentally recursive backup script, or a compromised account is enough to fill an entire partition and thereby affect the whole server, including services that have nothing to do with the actual culprit.
On shared hosting environments with multiple customers on the same server, quotas are practically mandatory, but even on internal servers with several technical users, for example separate accounts for different applications or developers, filesystem quotas prevent a single faulty process from occupying all available storage and thereby crashing unrelated services because the root filesystem suddenly fills up.
In practice, the value of quotas shows up especially with automated processes: a CI runner writing build artifacts into a shared directory, or a cron job stuck in an infinite loop writing log files after a bug, are classic triggers for a filled up partition. Filesystem quotas catch exactly these cases before they turn into a production wide incident.
2. Understanding soft limit, hard limit and grace period
Linux quotas distinguish two types of limits, each for both storage (blocks) and file count (inodes). The soft limit can be temporarily exceeded, but triggers a warning and starts the so called grace period as soon as it is exceeded, a defined time span within which the user must fall back below the soft limit. The hard limit is absolute, once reached, further write attempts fail with EDQUOT (disk quota exceeded), regardless of the grace period.
This two tier structure allows short term spikes, for example during a deployment or a temporary export, without being blocked immediately, while still preventing sustained overuse. If the grace period is not observed, the soft limit then behaves like a hard limit until usage falls below it again. For most use cases, a grace period between seven and fourteen days is a sensible compromise between flexibility and control.
An often overlooked aspect: both soft and hard limits apply per filesystem, not globally across the entire server. A user with access to multiple mounted partitions therefore needs separate quota entries for each individual partition, there is no server wide summation across multiple mount points.
3. Enabling quota support in the filesystem
Before quotas can be set, the filesystem itself must enable quota accounting. On ext4 this happens through the mount options usrquota and grpquota in /etc/fstab, separate for user based and group based limits, both can be enabled independently of each other.
# /etc/fstab: enable user and group quota accounting on ext4
UUID=2a9e7c31-5b4d-4e8a-9f21-6c3d0e7a1b55 /home ext4 defaults,usrquota,grpquota 0 2
# Remount without a reboot to apply the new mount options
sudo mount -o remount /home
A remount is usually enough to apply the new mount options without a reboot, but on the root filesystem itself a reboot may be necessary, because the root filesystem is mounted at a very early stage during boot. Important: the mount options alone only enable the technical prerequisite, the actual quota database must be initialized separately afterward.
A look into /proc/mounts after the remount confirms whether the quota options were actually applied, especially with network filesystems or unusual mount orders this check is worth doing before relying on working quotas.
4. Initializing and turning on the quota database
After enabling the mount options, quotacheck must scan the entire filesystem once, attribute the actually occupied blocks and inodes to every user and group, and generate the internal quota files aquota.user and aquota.group at the root of the mount point.
# Scan the filesystem and create the quota accounting files
sudo quotacheck -cug /home
# Turn quota enforcement on for the mount point
sudo quotaon /home
# Verify that accounting is active
sudo quotaon -p /home
quotacheck should ideally run on a filesystem with as little activity as possible, because concurrent writes during the scan can lead to slightly inconsistent initial values, which usually correct themselves at the next regular pass. After a successful quotaon, accounting is active without any limits being set yet, at this point usage is only being tracked, not yet limited.
After significant filesystem growth or after restoring from a backup, running quotacheck again is advisable, because actual usage may have changed significantly in the meantime and the internally stored values would otherwise diverge from reality.
5. Setting limits per user and group
The actual limits are set with setquota, which expects four values for each user or group: soft and hard limit for blocks (in kilobytes), and soft and hard limit for inodes. Recurring limits, for example for all developer accounts on a team, can be efficiently copied from an already configured reference user to several other accounts via edquota -p.
# Set soft/hard limits for blocks and inodes for a single user
# setquota <user> <block-soft> <block-hard> <inode-soft> <inode-hard> <mountpoint>
sudo setquota -u deploy 5000000 5500000 200000 220000 /home
# Set the same limits for an entire group at once
sudo setquota -g www-data 20000000 22000000 500000 550000 /home
# Copy quota settings from one user to a list of others
sudo edquota -p deploy -u www-user2 www-user3
A common mistake during initial configuration: the inode limit is forgotten and only the block limit is set. A user who creates many very small files, for example millions of tiny cache or session files, can push a filesystem to its inode limit long before the actual storage (blocks) is exhausted. Both limit types should therefore always be maintained together.
For hosting environments with many similar accounts, a simple wrapper script around setquota is worthwhile, reading limits centrally from a configuration file instead of typing them in manually for every user, which reduces typos and makes changes to default limits traceable across all accounts at once.
6. Monitoring usage and evaluating reports
For a single user, quota -u shows current usage compared to the set limits, useful for the user themselves or for targeted support requests. For an overview of every user with active quota entries on a mount point, repquota provides a full, sortable table.
# Check a single user's current usage against their limits
sudo quota -u deploy
# Report every user with active quota entries on a mount point
sudo repquota -a
# Human-readable, sorted by usage
sudo repquota -as | sort -k3 -h -r | head -20
In practice, a regular, automated repquota -a run via cron job is worthwhile, its output filtered for users close to their soft limit and sent to the operations team by email. This way, bottlenecks can be detected before a user actually enters the grace period or hits the hard limit, causing production processes to fail.
In addition to repquota, quota -uqv provides a compact output for the calling user themselves, only when a limit is actually set, which works great in login scripts without generating unnecessary output for users with no limits configured.
7. Configuring the grace period and warning users
The grace period is configured globally per filesystem with setquota -t, separately for block and inode limits, specified in seconds. It defines how long a user may operate above the soft limit but below the hard limit before the system treats the soft limit like a hard limit.
# /etc/quotatab or via setquota: default grace period once soft limit is hit
sudo setquota -t 604800 604800 /home # 7 days for blocks and inodes
# Check remaining grace period for a specific user
sudo repquota -a | grep deploy
# Output columns include days left until the hard limit becomes enforced
Important in practice: by default, users do not receive an automatic warning outside an interactive shell session where a login script calls quota. For servers without interactive logins, for example pure application servers, monitoring should therefore run through automated repquota reports, otherwise nobody notices that the grace period is already running until the hard limit kicks in and write access suddenly fails.
If no explicit grace period is set, a system wide default applies, which is seven days on most distributions, but for production environments with different use cases a deliberate, documented decision is almost always worthwhile instead of relying on the default.
8. Quotas on XFS: project quotas as an alternative
XFS implements quotas fundamentally differently from ext4, configuration does not happen through usrquota/grpquota in fstab, but through the mount option uquota/gquota or pquota for project quotas, and management runs through the standalone command xfs_quota instead of setquota and repquota.
Project quotas are an XFS specific feature with no direct ext4 equivalent: instead of binding limits to a user or group, an arbitrary directory is assigned to a project, regardless of which user creates files inside it. This is excellent for hosting scenarios where a customer directory needs to be limited, regardless of which system user a PHP-FPM pool or a cron job writes as within that directory.
The command xfs_quota -x -c 'report -h' provides an overview very similar to repquota, human readable, so switching from ext4 to XFS from the perspective of day to day quota administration usually comes down to getting used to a new command, not a fundamentally different concept.
9. Quota approaches in direct comparison
Depending on the filesystem and use case, a different quota mechanism fits better. The following overview classifies the most important options.
| Requirement | Unsuitable approach | Recommended approach | Benefit |
|---|---|---|---|
| Limiting a single user | Manual monitoring via du | usrquota + setquota -u | Automatic enforcement instead of manual checking |
| Limiting an entire team or group | Separate limits per member | grpquota + setquota -g | One shared limit for the whole group |
| Allowing short term spikes | Hard limit with no tolerance | Soft limit + grace period | Flexibility during deployments and exports |
| Limiting many small files | Setting only a block limit | Setting an inode limit as well | Also protects against inode exhaustion |
| Limiting a customer directory regardless of system user | usrquota on XFS | XFS project quota (pquota) | Limit per directory instead of per user |
For classic multi-user servers with ext4, usrquota and grpquota are the direct, well documented path. For hosting environments with XFS and separate directories per customer, project quotas are often the cleaner solution, because they are not bound to individual system users.
Mironsoft
Linux server administration, multi-user environments and storage control
One user filling up the entire server?
We set up filesystem quotas on your multi-user and hosting servers, including sensible soft and hard limits, automated reporting, and, where appropriate, XFS project quotas for customer separated directories.
Quota setup
Configuring usrquota, grpquota or XFS project quotas matched to the use case
Monitoring and alerting
Automated repquota reports warning before the grace period is reached
Hosting protection
Reliably limiting customer separated directories on multi-tenant servers
10. Summary
Filesystem quotas prevent a single user, group, or faulty process from filling an entire filesystem and thereby affecting unrelated services. Soft limits with a grace period allow short term spikes, hard limits set an absolute ceiling.
Setup happens in three steps: enable mount options, initialize with quotacheck, and assign limits with setquota, always for blocks and inodes together. Regular reporting via repquota turns a one time configuration into a continuously monitored system.
Filesystem Quotas: The essentials at a glance
Two limit types
Soft limit allows temporary overuse with a grace period, hard limit stops write access immediately and absolutely.
Activation
usrquota/grpquota in fstab, then quotacheck to initialize and quotaon to turn on enforcement.
Blocks and inodes
Always set both limit types, otherwise many small files can block the filesystem despite free storage space.
XFS alternative
Project quotas on XFS limit directories regardless of the system user, ideal for hosting environments.