- PHP 91.4%
- Shell 4.9%
- CSS 3.7%
Loop task 270: move customer name + two warning-email recipients out of Nextcloud's oc_appconfig (which any NC admin can edit) into a JSON file on the host. The file is bind-mounted read-only into the container, so only the host root can change which customer this instance reports on or where warnings go. - new lib/Service/HostConfig.php reads + validates the file - QuotaService no longer takes a $customer arg; pulls it from HostConfig - admin UI becomes display-only for those three fields (form + JS removed) - xfs_quota_path and mount remain in oc_appconfig (deployment plumbing) - warning emails are stored but not yet sent (cron worker = future work, noted in README roadmap) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| appinfo | ||
| bin | ||
| css | ||
| lib | ||
| templates | ||
| .gitignore | ||
| README.md | ||
customquota — Nextcloud "Customer XFS quota" app
Surfaces the real on-host filesystem quota of /srv for the configured customer
inside Nextcloud's admin settings, by parsing the output of:
xfs_quota -x -c "report -h" /srv
The output is filtered to rows whose first column (project/user/group name) matches the configured customer substring.
Host config — /etc/customquota/config.json
The customer name and warning-email recipients are read from a JSON file
on the host. The file is bind-mounted read-only into the Nextcloud container
so that Nextcloud admins (who can edit oc_appconfig) cannot change which
customer this instance reports on or where warnings go — only the host root
can edit it.
{
"customer": "acme",
"warning_email_primary": "ops@example.com",
"warning_email_secondary": "billing@example.com"
}
customer— substring filter against the first column of the xfs_quota report. Validated[A-Za-z0-9._-]{1,64}.warning_email_primary/warning_email_secondary— recipients for quota-warning notifications. Either can be empty (string).
Required file perms on the host (raf:raf installation):
sudo install -d -m 0755 -o root -g root /etc/customquota
sudo install -m 0644 -o root -g root config.json /etc/customquota/config.json
The bind mount is declared in ~/.config/containers/systemd/nextcloud-app.container:
Volume=/etc/customquota:/etc/customquota:ro
App-config (occ) — deployment plumbing only
Two settings live in Nextcloud's app-config because they're deployment plumbing, not customer-facing config:
# path to the xfs_quota binary (default: "xfs_quota" via PATH)
podman exec -u www-data nextcloud-app php occ config:app:set customquota \
xfs_quota_path --value=/var/www/html/custom_apps/customquota/bin/xfs_quota-mock
# mount to inspect (default: /srv)
podman exec -u www-data nextcloud-app php occ config:app:set customquota mount --value=/srv
Files
appinfo/{info.xml,routes.php}
lib/AppInfo/Application.php
lib/Settings/{AdminSection,Admin}.php
lib/Service/HostConfig.php — loads /etc/customquota/config.json + validates
lib/Service/QuotaService.php — xfs_quota invocation + parser
lib/Controller/QuotaController.php
templates/admin.php — read-only admin panel
css/admin.css
bin/xfs_quota-mock — fake xfs_quota for local demo
Security model
- Customer name is regex-validated
[A-Za-z0-9._-]{1,64}before use; emails are validated viafilter_var(FILTER_VALIDATE_EMAIL). xfs_quotais invoked viaproc_openwith an argv array, never a shell string — no metacharacter escaping concerns.- Filtering is a literal PHP
stripos()substring match in PHP-land; the customer string never reaches the shell. - Host config is mounted read-only; Nextcloud admins cannot edit it from the admin UI.
Versions
- 0.2.0 (2026-05-20) — customer + warning emails moved into
/etc/customquota/config.json(root-only writable); admin UI is now display-only for those values (loop task 270). - 0.1.0 (2026-05-20) — initial release (loop task 267).
Roadmap — not yet implemented
- A cron-driven worker reading the report, checking per-row
usedagainstsoft/hard, and emailingwarning_email_primary(and_secondary) when crossings happen. v0.2.0 stores the addresses but does not yet send any mail. Likely a smallCron\SendQuotaWarningsbackground job + a state file so warnings aren't re-sent every tick.