XFS Project Quotas
If you want hard per-workspace storage limits, Docker container size limits are not enough for Meowbert.
Meowbert task sandboxes write into the real workspace and project paths through bind mounts, so the strict limit must live on the actual host filesystem path that backs workspace storage.
For Linux deployments, the recommended approach is:
- keep each workspace in its own storage unit directory
- keep projects nested under that workspace storage unit
- enforce a hard quota on that workspace directory with XFS project quotas
What Meowbert expects
Meowbert can provision XFS project quotas for local storage backends when:
- the local backend is configured explicitly in
storage.backends - that backend includes
xfsProjectQuota - the backend
workspacesRootlives on an XFS mount with project quotas enabled runtime.sandbox.resources.storageMbis set
The hard XFS quota uses the same workspace limit value Meowbert already uses for preflight storage checks.
If you are migrating an existing install, use a new XFS-backed workspaces path first instead of mounting over the old one. Otherwise the old data becomes hidden under the new mount and Meowbert cannot relocate it for you.
If you are deploying with Coolify and need to move the whole runtime bind onto a new stable host path first, see Coolify Runtime Storage & XFS Migration.
Mounted-path backends are managed outside Meowbert, so any remote-cache limits for tools like rclone mount must also be managed outside Meowbert on the host.
Example config
{
"storage": {
"defaultWorkspaceBackendId": "local-default",
"backends": [
{
"id": "local-default",
"label": "Local (XFS quotas)",
"type": "local",
"workspacesRoot": "/app/runtime/workspaces-xfs",
"projectsRoot": "/app/runtime/projects",
"xfsProjectQuota": {
"mountPath": "/app/runtime/workspaces-xfs",
"projectIdBase": 10000
}
}
]
},
"runtime": {
"sandbox": {
"resources": {
"storageMb": 30720
}
}
}
}What the XFS fields mean
| Field | Meaning |
|---|---|
mountPath | The XFS mount inside the API/worker container where project quotas are enabled |
projectIdBase | The minimum project id Meowbert should start allocating |
command | Optional path/name override for xfs_quota |
Recommended host setup
This is the safest setup when using the repo’s default Docker Compose layout and you already have existing local workspace data to migrate.
1. Prepare an XFS filesystem on the host
Create or choose a block device and format it as XFS:
sudo mkfs.xfs /dev/<your-device>2. Mount it at the host path that backs workspace storage
With the default compose file, API and worker bind ./runtime into /app/runtime with rshared propagation. If you are only doing local Docker Desktop development on macOS/Windows, you may need to override MEOWBERT_RUNTIME_BIND_PROPAGATION=rprivate, but this Linux/XFS setup expects rshared.
That means you can mount XFS under the runtime tree on the host, for example:
sudo mkdir -p /srv/meowbert/runtime/workspaces-xfs
sudo mount -o prjquota /dev/<your-device> /srv/meowbert/runtime/workspaces-xfsThen make your compose bind source point at /srv/meowbert/runtime instead of the repo-local ./runtime, or run compose from a checkout where ./runtime/workspaces-xfs is that mounted XFS path.
The important part is:
- old local workspace path stays accessible, for example:
/srv/meowbert/runtime/workspaces - new XFS mount:
/srv/meowbert/runtime/workspaces-xfs - container path for the XFS backend:
/app/runtime/workspaces-xfs - config
workspacesRoot:/app/runtime/workspaces-xfs - config
xfsProjectQuota.mountPath:/app/runtime/workspaces-xfs
This lets Meowbert copy existing workspace roots from the old local path into the new XFS-backed path during the admin migration.
If this is a brand new deployment with no existing local data, you can mount XFS directly at the final workspace path instead.
3. Persist the mount
Add an /etc/fstab entry with project quotas enabled:
/dev/<your-device> /srv/meowbert/runtime/workspaces-xfs xfs defaults,prjquota 0 0Depending on distro, pquota may be accepted as an alias. prjquota is the clearest choice.
4. Install host tools
The host should have XFS tooling available:
sudo apt-get install -y xfsprogsMeowbert’s API and worker containers also need xfs_quota available. The Dockerfiles in this repo now install xfsprogs.
5. Verify project quota support
On the host:
sudo xfs_quota -x -c 'state -p' /srv/meowbert/runtime/workspaces-xfsInside the API or worker container, the equivalent path should also work:
xfs_quota -x -c 'state -p' /app/runtime/workspaces-xfsYou want project quota accounting and enforcement to be available before running the Meowbert migration.
Recommended migration order in Meowbert
After the host mount and config are ready:
- restart API + worker
- open Admin → Migrations
- run Nest projects under workspace storage units
- run Migrate local workspaces to XFS storage units
That order matters.
The first migration moves legacy project roots under each workspace storage unit. Without that, a workspace quota would only cover the workspace root and miss older project data.
What the XFS migration actually does
When you run the XFS migration, Meowbert:
- moves each local workspace root onto the configured managed XFS path when needed
- assigns a stable
storage_project_idto each workspace on the configured local backend - applies that project id to the workspace storage unit directory
- sets a hard XFS quota based on
runtime.sandbox.resources.storageMb
New workspaces on that backend will also get quotas automatically when their storage root is initialized.
Mounted-path backends and cache limits
If you mount something like OneDrive with rclone mount on the host, Meowbert now treats that as a normal externally mounted path.
That means any cache path, cache quota, or mount tuning for that remote is a host-side concern, not a Meowbert config feature.
If you want to cap a host-side rclone cache with XFS, do it in the host mount setup itself and keep that cache directory outside Meowbert's storage backend config.
What this does not do
This does not convert a remote mounted filesystem into a hard-quota filesystem.
XFS project quotas only apply to local filesystem paths that Meowbert controls directly.
Notes
- Keep Meowbert’s own storage checks. They still provide better preflight UX and admin visibility.
- XFS quota failures show up as normal filesystem write failures (
ENOSPC) once the hard limit is reached. - If you already had old project paths under a separate legacy tree, run the project nesting migration first.
- A helper host script now exists at
scripts/setup-xfs-storage.shto prepare workspace XFS mountpoints.
References
- Red Hat: Limiting storage space usage on XFS with quotas
xfs_quotareference: man7 xfs_quota(8)