Limit Disk size for Apps
-
Cloudron already lets me dial in memory and CPU per app (
memoryLimit,cpuQuotain the app record, enforced via the container runtime). The missing third resource is disk.The problem
A single misbehaving app, a runaway log, a chat server caching media or a user accidentally uploading the Kimi 3 Weights in your Nextcloud instance can fill the entire data disk and take down every app on Cloudron. Currently, the only mitigations are reactive: the low-disk email notification, or manually moving an app to its own volume. There is no way to say "this app gets 20 GB, period" the way I can say "this app gets 2 GB of RAM".
Why I believe this is very feasible on Cloudron specifically
App container root filesystems are read-only; effectively all growable app disk usage lives in the bind-mounted
appsdatadirectory (/app/data) plus tmpfs mounts that are already size-capped. So "limit disk for an app" reduces to "put a quota on one directory tree" — and the platform already has the key ingredient: volumes mounted as XFS are already mounted withpquota(project quotas) by box today (src/mounts.js). ext4 supports the same viaprjquota.Concrete proposal
- Add a
diskQuotafield per app, alongsidememoryLimitandcpuQuota, exposed in the same App → Resources UI (slider/input,0= unlimited, sensible default unlimited so nothing changes for existing installs). - Enforce it with a filesystem project quota on the app's
appsdatadirectory:- assign each app a project ID (e.g. derived from the app id),
xfs_quota -x -c 'project -s …' / 'limit -p bhard=20g …'on XFS,chattr -p+setquota -Pon ext4.
- When the quota is hit, the app gets
ENOSPCinside/app/data, exactly what it would see on a full disk, but scoped to that app. Every other app and the platform keep running. - Surface it in the dashboard: show per-app usage vs. quota (the disk-usage numbers are already collected per app today), and fire the existing notification path at e.g. 80%.
- Docs note for the root-disk case: project quotas need the mount option (
pquota/prjquota); where the root filesystem can't provide it, the setting could simply be unavailable (same pattern as features that depend on the underlying storage).
Out of scope / non-goals
- No need to touch Docker
--storage-opt(it doesn't cover bind mounts and has backing-filesystem constraints anyway). The bind-mount quota is the better layer. - Databases live in the shared service containers (PostgreSQL/MySQL addons), so this targets file storage; that's fine. File data (media, uploads, logs, caches) is what actually fills disks in practice.
This would complete the resource-isolation story: RAM, CPU, and disk, all per-app, all from the dashboard.
- Add a
-
Hello @andreasdueren
Just leaving the guide for XFS here as well: https://docs.cloudron.io/guides/per-app-storage-limit#external-xfs-block-storage-with-project-quotas
For using
quotaandsetquotathe/etc/fstabneeds to be edited if not the root partition needs this.
AFAIK most Ubuntu systems from Cloud providers just use the one partition layout.Like this:
blkid /dev/sdb: LABEL="linode-swap" UUID="f1408ea6-59a0-11ed-bc9d-525400000001" TYPE="swap" /dev/sda: LABEL="linode-root" UUID="1d04c97f-e790-1364-de89-d53605b5d7aa" BLOCK_SIZE="4096" TYPE="ext4"On modern Ubuntu,
/(root) is mounted early, so instead of/etc/fstabthe options for the kernel command line need to be added via GRUB (rootflags=usrquota,grpquota) or usesystemd.ext4also supports quotas as a built-in feature (tune2fs -O quota -Q prjquota /dev/sdXN), which stores quota in hidden inodes and doesn't strictly need thefstabmount options, but can't be used for/, which is problematic again.But also to enable this for
/you need to offline edit the disk/partition with e.g.: a recovery boot for root, since you can't unmount/.All this makes it a bigger issue for existing Cloudron systems where we should not edit users
/etc/fstabfile, tinker with GRUB or simply can't even live-boot to edit the disk/partition.
This could lead to catastrophic failures.Not to mention how to handle this when installing Cloudron.
It currently is a BASH script. We would need to rethink the whole 'install Cloudron' way to ensure these requirenments are checked.
Just hypothetical, but when doing all that, why not use XFS directly.
But all this makes Cloudron way more complex then just running a bash script to install Cloudron. -
Hello @andreasdueren
Just leaving the guide for XFS here as well: https://docs.cloudron.io/guides/per-app-storage-limit#external-xfs-block-storage-with-project-quotas
For using
quotaandsetquotathe/etc/fstabneeds to be edited if not the root partition needs this.
AFAIK most Ubuntu systems from Cloud providers just use the one partition layout.Like this:
blkid /dev/sdb: LABEL="linode-swap" UUID="f1408ea6-59a0-11ed-bc9d-525400000001" TYPE="swap" /dev/sda: LABEL="linode-root" UUID="1d04c97f-e790-1364-de89-d53605b5d7aa" BLOCK_SIZE="4096" TYPE="ext4"On modern Ubuntu,
/(root) is mounted early, so instead of/etc/fstabthe options for the kernel command line need to be added via GRUB (rootflags=usrquota,grpquota) or usesystemd.ext4also supports quotas as a built-in feature (tune2fs -O quota -Q prjquota /dev/sdXN), which stores quota in hidden inodes and doesn't strictly need thefstabmount options, but can't be used for/, which is problematic again.But also to enable this for
/you need to offline edit the disk/partition with e.g.: a recovery boot for root, since you can't unmount/.All this makes it a bigger issue for existing Cloudron systems where we should not edit users
/etc/fstabfile, tinker with GRUB or simply can't even live-boot to edit the disk/partition.
This could lead to catastrophic failures.Not to mention how to handle this when installing Cloudron.
It currently is a BASH script. We would need to rethink the whole 'install Cloudron' way to ensure these requirenments are checked.
Just hypothetical, but when doing all that, why not use XFS directly.
But all this makes Cloudron way more complex then just running a bash script to install Cloudron.@james Thanks for the link, I actually didn't know that guide existed. It's essentially the manual version of what I'm asking for, which makes the request much smaller than it first sounds.
And agreed on all the root filesystem points. Retrofitting
prjquotaonto a mounted/is exactly the part I would not ask for. That's why I'd frame this as a capability-gated feature rather than a platform-wide guarantee:-
Where it works today, expose it. Cloudron already mounts XFS volumes with
pquota(that's insrc/mounts.js), and the guide shows the rest is just project ID assignment plusxfs_quota limit. So for any app whose data directory lives on an XFS volume, everything needed is already in place. Box would just need to do those steps itself and show a quota field in App → Resources. No fstab edits, no GRUB, no installer changes. -
Where it doesn't, grey it out. Apps on an ext4 root without quota support simply don't get the setting, with a hint like "move this app's data to an XFS volume to enable disk limits". Same pattern as other storage-dependent features. Existing systems stay untouched, so none of the catastrophic-failure scenarios you describe can happen.
-
Optional fs-agnostic fallback (later, if ever). A per-app loopback image (fixed-size file, mounted as the app's data dir) gives a hard cap on any backing filesystem with no quota support at all, at the cost of pre-allocation and a resize step. Debatable whether it's worth the complexity, but it's the escape hatch that doesn't touch
/either.
So the ask shrinks to: dashboard field, project ID assignment, and
xfs_quota limiton storage that already supports it. The hard cases stay manual or unsupported, just like today. But the common case of an app on an XFS volume becomes a slider instead of a shell session. -
-
I just pondered how kubernetes does enforce limits and asked Claude.
On a plain single-partition ext4 root with no quotas and a hostPath/local-style backing, Kubernetes does not enforce the capacity at all.
The capacity field is a scheduling/matching hint, not an enforcement mechanism. It's used by the scheduler for binding a PVC to a PV and for capacity-aware scheduling. Nothing in core Kubernetes watches a directory and stops writes when it exceeds the number. A hostPath or local PV of "5Gi" will happily fill the whole disk.
Actual enforcement comes from the CSI driver / storage backend, not from Kubernetes or Docker. Where a size limit is real, it's because the underlying storage provides a real boundary:- Block-based volumes (AWS EBS, GCE PD, Ceph RBD, iSCSI LUNs, LVM logical volumes): the volume is a block device of exactly N GiB, formatted with a filesystem. You physically cannot write past the device size. This is the common, reliable case.
- Network filesystems (NFS, CephFS): enforcement depends on the backend's own quota support; often it's not enforced.
Aha!
That explains why the storage limitation never worked for me when I tinkered with k8s/k3s and just used local storage volumes on my plain ext4 linux. -
@james Thanks for the link, I actually didn't know that guide existed. It's essentially the manual version of what I'm asking for, which makes the request much smaller than it first sounds.
And agreed on all the root filesystem points. Retrofitting
prjquotaonto a mounted/is exactly the part I would not ask for. That's why I'd frame this as a capability-gated feature rather than a platform-wide guarantee:-
Where it works today, expose it. Cloudron already mounts XFS volumes with
pquota(that's insrc/mounts.js), and the guide shows the rest is just project ID assignment plusxfs_quota limit. So for any app whose data directory lives on an XFS volume, everything needed is already in place. Box would just need to do those steps itself and show a quota field in App → Resources. No fstab edits, no GRUB, no installer changes. -
Where it doesn't, grey it out. Apps on an ext4 root without quota support simply don't get the setting, with a hint like "move this app's data to an XFS volume to enable disk limits". Same pattern as other storage-dependent features. Existing systems stay untouched, so none of the catastrophic-failure scenarios you describe can happen.
-
Optional fs-agnostic fallback (later, if ever). A per-app loopback image (fixed-size file, mounted as the app's data dir) gives a hard cap on any backing filesystem with no quota support at all, at the cost of pre-allocation and a resize step. Debatable whether it's worth the complexity, but it's the escape hatch that doesn't touch
/either.
So the ask shrinks to: dashboard field, project ID assignment, and
xfs_quota limiton storage that already supports it. The hard cases stay manual or unsupported, just like today. But the common case of an app on an XFS volume becomes a slider instead of a shell session.Hello @andreasdueren
On
1.:
I see your point there.
Maybe that is doable.On
3.:
Could maybe even be fully automated.
Click an app, enable storage limitation, set the size, Cloudron creates the loopback device, moves the data etc.
When 'resizing' the storage limit, stop app, edit loopback device or create new, move data and so on.Something to think about.
-
-
Hello @andreasdueren
On
1.:
I see your point there.
Maybe that is doable.On
3.:
Could maybe even be fully automated.
Click an app, enable storage limitation, set the size, Cloudron creates the loopback device, moves the data etc.
When 'resizing' the storage limit, stop app, edit loopback device or create new, move data and so on.Something to think about.
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login