From ba087190ebc51583c9461a78407870cdd61e49bf Mon Sep 17 00:00:00 2001 From: master3395 Date: Wed, 4 Feb 2026 03:00:57 +0100 Subject: [PATCH] Fix Pure-FTPd quota syntax and service start; improve services/API error reporting - Pure-FTPd: use Quota maxfiles:maxsize (100000:100000) instead of invalid 'Quota yes' in install templates and enableFTPQuota (website.py) so daemon starts - serverStatus: run systemctl as root, return detailed error on service start failure - FTP quota UI: better error display and feedback for enable quota action - Doc: to-do/PURE-FTPD-QUOTA-SYNTAX-FIX.md --- install/pure-ftpd-one/pure-ftpd.conf | 4 +- install/pure-ftpd/pure-ftpd.conf | 4 +- .../static/serverStatus/serverStatus.js | 5 +- .../templates/serverStatus/services.html | 1 + serverStatus/views.py | 40 +++++-- to-do/PURE-FTPD-QUOTA-SYNTAX-FIX.md | 24 ++++ .../websiteFunctions/ftpQuotaManagement.html | 104 +++++++++++----- websiteFunctions/website.py | 112 +++++++++++------- 8 files changed, 202 insertions(+), 92 deletions(-) create mode 100644 to-do/PURE-FTPD-QUOTA-SYNTAX-FIX.md diff --git a/install/pure-ftpd-one/pure-ftpd.conf b/install/pure-ftpd-one/pure-ftpd.conf index 27f4d1544..9298bb32d 100644 --- a/install/pure-ftpd-one/pure-ftpd.conf +++ b/install/pure-ftpd-one/pure-ftpd.conf @@ -31,6 +31,6 @@ MaxDiskUsage 99 CustomerProof yes TLS 1 PassivePortRange 40110 40210 -# Quota enforcement -Quota yes +# Quota enforcement (maxfiles:maxsizeMB; enables MySQL per-user quotas) +Quota 100000:100000 diff --git a/install/pure-ftpd/pure-ftpd.conf b/install/pure-ftpd/pure-ftpd.conf index 27f4d1544..9298bb32d 100644 --- a/install/pure-ftpd/pure-ftpd.conf +++ b/install/pure-ftpd/pure-ftpd.conf @@ -31,6 +31,6 @@ MaxDiskUsage 99 CustomerProof yes TLS 1 PassivePortRange 40110 40210 -# Quota enforcement -Quota yes +# Quota enforcement (maxfiles:maxsizeMB; enables MySQL per-user quotas) +Quota 100000:100000 diff --git a/serverStatus/static/serverStatus/serverStatus.js b/serverStatus/static/serverStatus/serverStatus.js index f16d66701..733d26a96 100644 --- a/serverStatus/static/serverStatus/serverStatus.js +++ b/serverStatus/static/serverStatus/serverStatus.js @@ -641,11 +641,15 @@ app.controller('servicesManager', function ($scope, $http) { getServiceStatus(); $scope.ActionSuccessfull = true; $scope.ActionFailed = false; + $scope.actionErrorMsg = ''; $scope.couldNotConnect = false; $scope.actionLoader = false; $scope.btnDisable = false; }, 3000); } else { + var errMsg = (response.data && response.data.error_message) ? response.data.error_message : 'Action failed'; + if (errMsg === 0) errMsg = 'Action failed'; + $scope.actionErrorMsg = errMsg; setTimeout(function () { getServiceStatus(); $scope.ActionSuccessfull = false; @@ -654,7 +658,6 @@ app.controller('servicesManager', function ($scope, $http) { $scope.actionLoader = false; $scope.btnDisable = false; }, 5000); - } } diff --git a/serverStatus/templates/serverStatus/services.html b/serverStatus/templates/serverStatus/services.html index 11fdcd624..db6b6084d 100644 --- a/serverStatus/templates/serverStatus/services.html +++ b/serverStatus/templates/serverStatus/services.html @@ -622,6 +622,7 @@
{% trans "Action Failed" %} + {% trans "Details:" %}
diff --git a/serverStatus/views.py b/serverStatus/views.py index 9d5d54bd2..8f051b86f 100644 --- a/serverStatus/views.py +++ b/serverStatus/views.py @@ -319,18 +319,36 @@ def servicesAction(request): final_json = json.dumps(final_dic) return HttpResponse(final_json) - else: - if service == 'pure-ftpd': - if os.path.exists("/etc/lsb-release"): - service = 'pure-ftpd-mysql' - else: - service = 'pure-ftpd' + if service == 'pure-ftpd': + if os.path.exists("/etc/lsb-release"): + service = 'pure-ftpd-mysql' + else: + service = 'pure-ftpd' - command = 'sudo systemctl %s %s' % (action, service) - ProcessUtilities.executioner(command) - final_dic = {'serviceAction': 1, "error_message": 0} - final_json = json.dumps(final_dic) - return HttpResponse(final_json) + # Run as root with shell so systemctl has permission (panel may run as lscpd) + command = 'systemctl %s %s' % (action, service) + ProcessUtilities.executioner(command, 'root', True) + time.sleep(1) + + # For start action, verify service actually came up; return error if not + if action == 'start': + try: + out = ProcessUtilities.outputExecutioner('systemctl is-active %s' % service, 'root', True) + if not (out and out.strip() == 'active'): + status_out = ProcessUtilities.outputExecutioner( + 'systemctl status %s --no-pager -l 2>&1 | head -15' % service, 'root', True) + err_msg = (status_out or '').strip().replace('\n', ' ')[:400] + final_dic = {'serviceAction': 0, 'error_message': 'Service did not start. ' + err_msg} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + except Exception as e: + final_dic = {'serviceAction': 0, 'error_message': 'Service did not start: %s' % str(e)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + final_dic = {'serviceAction': 1, "error_message": 0} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) except BaseException as msg: diff --git a/to-do/PURE-FTPD-QUOTA-SYNTAX-FIX.md b/to-do/PURE-FTPD-QUOTA-SYNTAX-FIX.md new file mode 100644 index 000000000..917206ec1 --- /dev/null +++ b/to-do/PURE-FTPD-QUOTA-SYNTAX-FIX.md @@ -0,0 +1,24 @@ +# Pure-FTPd Quota Syntax Fix (2026-02-04) + +## Problem +Pure-FTPd failed to start with: +``` +/etc/pure-ftpd/pure-ftpd.conf:35:1: syntax error line 35: [Quota ...]. +``` + +## Cause +The config used `Quota yes`, but Pure-FTPd expects **`Quota maxfiles:maxsize`** (e.g. `Quota 1000:10` for 1000 files and 10 MB). The value is not a boolean. + +## Fix applied + +### On the server +- `/etc/pure-ftpd/pure-ftpd.conf`: line 35 set to `Quota 100000:100000` (high default so MySQL per-user quotas apply). +- Service started successfully: `systemctl start pure-ftpd`. + +### In the repo +- **install/pure-ftpd/pure-ftpd.conf** and **install/pure-ftpd-one/pure-ftpd.conf**: `Quota yes` → `Quota 100000:100000`. +- **websiteFunctions/website.py** (`enableFTPQuota`): sed/echo now write `Quota 100000:100000` instead of `Quota yes` (or tabs). + +## Reference +- Upstream: https://github.com/jedisct1/pure-ftpd/blob/master/pure-ftpd.conf.in (comment: "Quota 1000:10"). +- `pure-ftpd --help`: `-n --quota `. diff --git a/websiteFunctions/templates/websiteFunctions/ftpQuotaManagement.html b/websiteFunctions/templates/websiteFunctions/ftpQuotaManagement.html index 8f2545a5c..b075aa0fd 100644 --- a/websiteFunctions/templates/websiteFunctions/ftpQuotaManagement.html +++ b/websiteFunctions/templates/websiteFunctions/ftpQuotaManagement.html @@ -41,8 +41,8 @@ FTP Quota Management - CyberPanel
FTP Quota System

Enable and manage individual FTP user quotas. This allows you to set storage limits for each FTP user.

-
@@ -125,15 +125,79 @@ FTP Quota Management - CyberPanel