diff --git a/cyberpanel.sh b/cyberpanel.sh index 4607b698f..c801e9cbd 100644 --- a/cyberpanel.sh +++ b/cyberpanel.sh @@ -580,7 +580,37 @@ cleanup_existing_cyberpanel() { # Function to install CyberPanel directly using the working method install_cyberpanel_direct() { - # Ask MariaDB version first (even in no-confirmation/auto mode) if not set via --mariadb-version + # Ask web server (OpenLiteSpeed vs LiteSpeed Enterprise) BEFORE MariaDB; default OpenLiteSpeed + if [ -z "$LS_ENT" ]; then + if [ "$AUTO_INSTALL" = true ]; then + LS_ENT="" + echo " Using OpenLiteSpeed (auto mode)." + else + echo "" + echo " Web server: 1) OpenLiteSpeed (default), 2) LiteSpeed Enterprise" + read -r -t 60 -p " Enter 1 or 2 [1]: " LS_CHOICE || true + LS_CHOICE="${LS_CHOICE:-1}" + LS_CHOICE="${LS_CHOICE// /}" + if [ "$LS_CHOICE" = "2" ]; then + echo " LiteSpeed Enterprise selected. Enter serial/key (required):" + read -r -t 120 -p " Serial: " LS_SERIAL || true + LS_SERIAL="${LS_SERIAL:-}" + if [ -z "$LS_SERIAL" ]; then + echo " No serial provided. Defaulting to OpenLiteSpeed." + LS_ENT="" + else + LS_ENT="ent" + echo " Using LiteSpeed Enterprise with provided serial." + fi + else + LS_ENT="" + echo " Using OpenLiteSpeed." + fi + echo "" + fi + fi + + # Ask MariaDB version (after web server choice) if not set via --mariadb-version if [ -z "$MARIADB_VER" ]; then echo "" echo " MariaDB version: 10.11, 11.8 (LTS, default) or 12.1?" @@ -1090,7 +1120,10 @@ except: # install.py requires publicip as first positional argument local install_args=("$server_ip") - # Add optional arguments based on user preferences + # Web server: OpenLiteSpeed (default) or LiteSpeed Enterprise (--ent + --serial) + if [ -n "$LS_ENT" ] && [ -n "$LS_SERIAL" ]; then + install_args+=("--ent" "$LS_ENT" "--serial" "$LS_SERIAL") + fi # Default: OpenLiteSpeed, Full installation (postfix, powerdns, ftp), Local MySQL install_args+=("--postfix" "ON") install_args+=("--powerdns" "ON") @@ -2686,9 +2719,9 @@ parse_arguments() { echo "Options:" echo " -b, --branch BRANCH Install from specific branch/commit" echo " -v, --version VER Install specific version (auto-adds v prefix)" - echo " --mariadb-version VER MariaDB version: 10.11, 11.8 or 12.1 (asked first if omitted)" + echo " --mariadb-version VER MariaDB version: 10.11, 11.8 or 12.1 (asked after web server)" echo " --debug Enable debug mode" - echo " --auto Auto mode without prompts (MariaDB still asked first unless --mariadb-version)" + echo " --auto Auto mode: OpenLiteSpeed + MariaDB 11.8 unless --mariadb-version set" echo " -h, --help Show this help message" echo "" echo "Examples:" diff --git a/install/install.py b/install/install.py index 6dba4cce1..a932a1620 100644 --- a/install/install.py +++ b/install/install.py @@ -405,48 +405,11 @@ class preFlightsChecks: except Exception as e: self.stdOut("Warning: Could not remove compat packages: " + str(e), 0) - # Check if MariaDB is already installed before attempting installation + # Do NOT install MariaDB here with plain dnf (that would install distro default 10.11). + # installMySQL() runs later with the user's chosen version (--mariadb-version: 10.11, 11.8 or 12.1). is_installed, installed_version, major_minor = self.checkExistingMariaDB() - if is_installed: - self.stdOut(f"MariaDB/MySQL is already installed (version: {installed_version}), skipping installation", 1) - mariadb_installed = True - else: - # Install MariaDB with enhanced AlmaLinux 9.6 support - self.stdOut("Installing MariaDB for AlmaLinux 9.6...", 1) - - # Try multiple installation methods for maximum compatibility - mariadb_commands = [ - "dnf install -y mariadb-server mariadb-devel mariadb-client --skip-broken --nobest", - "dnf install -y mariadb-server mariadb-devel mariadb-client --allowerasing", - "dnf install -y mariadb-server mariadb-devel --skip-broken --nobest --allowerasing", - "dnf install -y mariadb-server --skip-broken --nobest --allowerasing" - ] - - mariadb_installed = False - for cmd in mariadb_commands: - try: - result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=300) - if result.returncode == 0: - mariadb_installed = True - self.stdOut(f"MariaDB installed successfully with command: {cmd}", 1) - break - except subprocess.TimeoutExpired: - self.stdOut(f"Timeout installing MariaDB with command: {cmd}", 0) - continue - except Exception as e: - self.stdOut(f"Error installing MariaDB with command: {cmd} - {str(e)}", 0) - continue - - if not mariadb_installed: - self.stdOut("MariaDB installation failed, trying MySQL as fallback...", 0) - try: - command = "dnf install -y mysql-server mysql-devel --skip-broken --nobest --allowerasing" - self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) - self.stdOut("MySQL installed as fallback for MariaDB", 1) - mariadb_installed = True - except: - self.stdOut("Both MariaDB and MySQL installation failed", 0) + self.stdOut(f"MariaDB/MySQL already installed (version: {installed_version}), skipping", 1) # Install additional required packages self.stdOut("Installing additional required packages...", 1) @@ -5804,18 +5767,22 @@ milter_default_action = accept os.chdir(self.cwd) - # Download composer.sh if missing (e.g. when run from temp dir without repo file) - composer_sh = os.path.join(self.cwd, "composer.sh") - if not os.path.exists(composer_sh) or not os.path.isfile(composer_sh): + # Download composer.sh to a known path so chmod never fails with "cannot access 'composer.sh'" + composer_sh = "/tmp/composer.sh" + if not os.path.isfile(composer_sh): command = "wget -q https://cyberpanel.sh/composer.sh -O " + composer_sh preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) - - if os.path.exists(composer_sh): - command = "chmod +x " + composer_sh + if not os.path.isfile(composer_sh): + command = "curl -sSL https://cyberpanel.sh/composer.sh -o " + composer_sh preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) - command = "bash " + os.path.abspath(composer_sh) - preFlightsChecks.call(command, self.distro, "./composer.sh", command, 1, 0, os.EX_OSERR, True) + if os.path.isfile(composer_sh): + command = "chmod +x " + composer_sh + preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) + command = "bash " + composer_sh + preFlightsChecks.call(command, self.distro, "composer.sh", command, 1, 0, os.EX_OSERR, True) + else: + logging.InstallLog.writeToFile("composer.sh download failed, skipping [setupPHPAndComposer]", 0) except OSError as msg: logging.InstallLog.writeToFile('[ERROR] ' + str(msg) + " [setupPHPAndComposer]") diff --git a/plogical/applicationInstaller.py b/plogical/applicationInstaller.py index c3b89fbc6..9c707099b 100644 --- a/plogical/applicationInstaller.py +++ b/plogical/applicationInstaller.py @@ -101,19 +101,24 @@ class ApplicationInstaller(multi.Thread): @staticmethod def setupComposer(): - - if os.path.exists('composer.sh'): - os.remove('composer.sh') - + composer_sh = '/tmp/composer.sh' if not os.path.exists('/usr/bin/composer'): - command = "wget https://cyberpanel.sh/composer.sh" - ProcessUtilities.executioner(command, 'root', True) - - command = "chmod +x composer.sh" - ProcessUtilities.executioner(command, 'root', True) - - command = "./composer.sh" - ProcessUtilities.executioner(command, 'root', True) + try: + if os.path.exists(composer_sh): + os.remove(composer_sh) + command = "wget -q https://cyberpanel.sh/composer.sh -O " + composer_sh + ProcessUtilities.executioner(command, 'root', True) + if not os.path.isfile(composer_sh): + command = "curl -sSL https://cyberpanel.sh/composer.sh -o " + composer_sh + ProcessUtilities.executioner(command, 'root', True) + if not os.path.isfile(composer_sh): + return + command = "chmod +x " + composer_sh + ProcessUtilities.executioner(command, 'root', True) + command = "bash " + composer_sh + ProcessUtilities.executioner(command, 'root', True) + except Exception: + pass def InstallNodeJS(self): diff --git a/plogical/upgrade.py b/plogical/upgrade.py index 5bd9deac8..43c7871fb 100644 --- a/plogical/upgrade.py +++ b/plogical/upgrade.py @@ -1307,18 +1307,26 @@ $cfg['Servers'][$i]['LogoutURL'] = 'phpmyadminsignin.php?logout'; @staticmethod def setupComposer(): - - if os.path.exists('composer.sh'): - os.remove('composer.sh') - - command = "wget https://cyberpanel.sh/composer.sh" - Upgrade.executioner(command, 0) - - command = "chmod +x composer.sh" - Upgrade.executioner(command, 0) - - command = "./composer.sh" - Upgrade.executioner(command, 0) + composer_sh = '/tmp/composer.sh' + try: + if os.path.exists(composer_sh): + os.remove(composer_sh) + # Download to known path so chmod/run work regardless of cwd + command = "wget -q https://cyberpanel.sh/composer.sh -O " + composer_sh + Upgrade.executioner(command, 0) + if not os.path.isfile(composer_sh): + command = "curl -sSL https://cyberpanel.sh/composer.sh -o " + composer_sh + Upgrade.executioner(command, 0) + if not os.path.isfile(composer_sh): + Upgrade.stdOut("composer.sh download failed, skipping", 0) + return + command = "chmod +x " + composer_sh + Upgrade.executioner(command, 0) + command = "bash " + composer_sh + Upgrade.executioner(command, 0) + except Exception as e: + ErrorSanitizer.log_error_securely(e, 'setupComposer') + Upgrade.stdOut("setupComposer error (non-fatal)", 0) @staticmethod def downoad_and_install_raindloop(): diff --git a/to-do/AWS-CURSOR-REMOTE-SSH-SETUP.md b/to-do/AWS-CURSOR-REMOTE-SSH-SETUP.md new file mode 100644 index 000000000..b62b92e8e --- /dev/null +++ b/to-do/AWS-CURSOR-REMOTE-SSH-SETUP.md @@ -0,0 +1,120 @@ +# AWS EC2 + Cursor Remote-SSH – Full Setup Guide + +Use this guide to get **aws-server** (3.144.171.128) working with Cursor Remote-SSH. +Do the steps in order. Everything is copy-paste ready. + +--- + +## 1. Windows SSH config + +**File:** `C:\Users\kimsk\.ssh\config` + +- Open the file in Notepad or Cursor. +- Find the `Host aws-server` block and replace it entirely with the block below (or add it if missing). +- Use **straight double quotes** `"`, not curly quotes. Path uses forward slashes to avoid issues. + +**Exact block to use (port 22 – default):** + +``` +Host aws-server + HostName 3.144.171.128 + User ec2-user + Port 22 + IdentityFile "D:/OneDrive - v-man/Priv/VPS/Cyberpanel.pem" +``` + +- Save and close. +- If you later confirm SSH on the instance is on port 2222, change `Port 22` to `Port 2222` and add an inbound rule for 2222 in the Security Group (see step 3). + +--- + +## 2. AWS Security Group – allow SSH (port 22) + +1. **AWS Console** → **EC2** → **Instances**. +2. Select the instance whose **Public IPv4** is **3.144.171.128**. +3. Open the **Security** tab → click the **Security group** name (e.g. `sg-xxxxx`). +4. **Edit inbound rules** → **Add rule**: + - **Type:** SSH + - **Port:** 22 + - **Source:** **My IP** (recommended) or **Anywhere-IPv4** (`0.0.0.0/0`) for testing only. +5. **Save rules**. + +If you use port 2222 on the instance, add another rule: **Custom TCP**, port **2222**, source **My IP** (or **Anywhere-IPv4** for testing). + +--- + +## 3. Start SSH on the instance (fix “Connection refused”) + +You must run commands on the instance without using SSH from your PC. Use one of these. + +### Option A: EC2 Instance Connect (simplest) + +1. **EC2** → **Instances** → select the instance (3.144.171.128). +2. Click **Connect**. +3. Open the **EC2 Instance Connect** tab → **Connect** (browser shell). + +In the browser terminal, run: + +```bash +sudo systemctl status sshd +sudo systemctl start sshd +sudo systemctl enable sshd +sudo ss -tlnp | grep 22 +``` + +You should see `sshd` listening on port 22. Then close the browser and try Cursor. + +### Option B: Session Manager + +1. **EC2** → **Instances** → select the instance → **Connect**. +2. Choose **Session Manager** → **Connect**. +3. Run the same commands as in Option A. + +### Option C: SSH is on port 2222 + +If you know SSH was moved to 2222 on this instance: + +1. In the Security Group, add an **inbound rule**: **Custom TCP**, port **2222**, source **My IP** (or **Anywhere-IPv4** for testing). +2. In your SSH config, set `Port 2222` for `aws-server` (see step 1). +3. Test (see step 4). + +--- + +## 4. Test from Windows + +Open **PowerShell** and run: + +```powershell +ssh -i "D:/OneDrive - v-man/Priv/VPS/Cyberpanel.pem" -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new ec2-user@3.144.171.128 +``` + +- If it asks for a host key, type `yes`. +- If you get a shell prompt, SSH works. Type `exit` to close. +- If you get **Connection refused**: SSH is not listening on 22 (or 2222); repeat step 3 (Instance Connect / Session Manager) and ensure `sshd` is running and listening on the port you use. +- If you get **Connection timed out**: Security Group is still blocking the port; recheck step 2 and that you edited the security group attached to this instance. + +--- + +## 5. Connect from Cursor + +1. In Cursor: **Ctrl+Shift+P** (or **Cmd+Shift+P** on Mac) → **Remote-SSH: Connect to Host**. +2. Choose **aws-server** (or type `aws-server`). +3. Wait for the remote window to open. Cursor AI (Chat, Composer) works in that window as usual. + +--- + +## Checklist + +- [ ] SSH config has the `aws-server` block with correct `IdentityFile` and `Port` (22 or 2222). +- [ ] Security Group has an inbound rule for the SSH port (22 or 2222) from My IP (or 0.0.0.0/0 for testing). +- [ ] `sshd` is running on the instance (started via Instance Connect or Session Manager). +- [ ] `ssh ... ec2-user@3.144.171.128` works in PowerShell. +- [ ] Cursor **Connect to Host** → **aws-server** succeeds. + +--- + +## If it still fails + +- **Connection refused** → Instance side: start/enable `sshd` and confirm it listens on the port you use (step 3). +- **Connection timed out** → Network: open that port in the instance’s Security Group (step 2). +- **Permission denied (publickey)** → Wrong key or user: confirm the .pem is the one for this instance and the user is `ec2-user` (Amazon Linux) or `ubuntu` (Ubuntu AMI). diff --git a/to-do/FTP-QUOTA-BROWSER-TEST-CHECKLIST.md b/to-do/FTP-QUOTA-BROWSER-TEST-CHECKLIST.md new file mode 100644 index 000000000..f9250e0fd --- /dev/null +++ b/to-do/FTP-QUOTA-BROWSER-TEST-CHECKLIST.md @@ -0,0 +1,21 @@ +# FTP Quota Management – Browser Test Checklist + +Use after deploying latest code. Open: `/ftp/quotaManagement` + +## 1. Page load – status +- **Pure-FTPd stopped:** Yellow warning "Pure-FTPd is not running. Please enable Pure-FTPd first (Server Status → Services)..." and Enable button disabled/hidden. +- **Pure-FTPd running, quota on:** Green "FTP Quota system is already enabled"; button disabled. +- **Pure-FTPd running, quota off:** Blue info and enabled "Enable FTP Quota System" button. + +## 2. Click Enable +- If FTP was running: success message and UI switches to "already enabled". No "Pure-FTPd did not start" error. +- If FTP was stopped: API returns "Pure-FTPd is not running. Please enable Pure-FTPd first...". + +## 3. Table +- Quotas table loads; Refresh works. + +## 4. One-time fix on server (if needed) +```bash +sudo sed -i 's/^Quota.*/Quota 100000:100000/' /etc/pure-ftpd/pure-ftpd.conf +sudo systemctl start pure-ftpd +``` diff --git a/to-do/INSTALL-UPGRADE-DOWNGRADE-COMMANDS.md b/to-do/INSTALL-UPGRADE-DOWNGRADE-COMMANDS.md new file mode 100644 index 000000000..7bb0a5017 --- /dev/null +++ b/to-do/INSTALL-UPGRADE-DOWNGRADE-COMMANDS.md @@ -0,0 +1,180 @@ +# CyberPanel Install, Upgrade, and Downgrade Commands + +Reference for all standard and branch-specific install/upgrade/downgrade commands (master3395 fork and upstream). + +--- + +## Fresh install + +### One-liner (official / upstream) + +```bash +sh <(curl https://cyberpanel.net/install.sh) +``` + +### One-liner with sudo (if not root) + +```bash +curl -sO https://cyberpanel.net/install.sh && sudo bash install.sh +# or +curl -sL https://cyberpanel.net/install.sh | sudo bash -s -- +``` + +### Install from master3395 fork (this repo) + +**Stable:** + +```bash +curl -sL https://raw.githubusercontent.com/master3395/cyberpanel/stable/cyberpanel.sh | sudo bash -s -- +``` + +**Development (v2.5.5-dev):** + +```bash +curl -sL https://raw.githubusercontent.com/master3395/cyberpanel/v2.5.5-dev/cyberpanel.sh | sudo bash -s -- -b v2.5.5-dev +``` + +### Install with branch/version options + +```bash +# Download script first (recommended so -b/-v work reliably) +curl -sL -o cyberpanel.sh https://raw.githubusercontent.com/master3395/cyberpanel/v2.5.5-dev/cyberpanel.sh +chmod +x cyberpanel.sh +sudo bash cyberpanel.sh [OPTIONS] +``` + +**Options:** + +| Option | Example | Description | +|--------|---------|-------------| +| `-b BRANCH` / `--branch BRANCH` | `-b v2.5.5-dev` | Install from branch or tag | +| `-v VER` / `--version VER` | `-v 2.5.5-dev` | Version (script adds `v` prefix as needed) | +| `--mariadb-version VER` | `--mariadb-version 10.11` | MariaDB: `10.11`, `11.8`, or `12.1` | +| `--auto` | `--auto` | Non-interactive (still asks MariaDB unless `--mariadb-version` is set) | +| `--debug` | `--debug` | Debug mode | + +**Examples:** + +```bash +sudo bash cyberpanel.sh # Interactive +sudo bash cyberpanel.sh -b v2.5.5-dev # Development branch +sudo bash cyberpanel.sh -v 2.5.5-dev # Same as above (v prefix added) +sudo bash cyberpanel.sh -v 2.4.4 # Install 2.4.4 +sudo bash cyberpanel.sh -b main # From main branch +sudo bash cyberpanel.sh -b a1b2c3d4 # From specific commit hash +sudo bash cyberpanel.sh --mariadb-version 10.11 # MariaDB 10.11 +sudo bash cyberpanel.sh --mariadb-version 12.1 # MariaDB 12.1 +sudo bash cyberpanel.sh --auto --mariadb-version 11.8 # Fully non-interactive, MariaDB 11.8 +sudo bash cyberpanel.sh --debug # Debug +``` + +--- + +## Upgrade (existing CyberPanel) + +### One-liner upgrade to latest stable + +```bash +bash <(curl -sL https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel_upgrade.sh) +``` + +### Upgrade to a specific branch/version (upstream) + +```bash +bash <(curl -sL https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel_upgrade.sh) -b v2.5.5-dev +bash <(curl -sL https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel_upgrade.sh) -b 2.4.4 +``` + +### Upgrade using master3395 fork + +```bash +sudo bash <(curl -sL https://raw.githubusercontent.com/master3395/cyberpanel/stable/cyberpanel_upgrade.sh) -b v2.5.5-dev +``` + +Or download then run: + +```bash +curl -sL -o cyberpanel_upgrade.sh https://raw.githubusercontent.com/master3395/cyberpanel/v2.5.5-dev/cyberpanel_upgrade.sh +chmod +x cyberpanel_upgrade.sh +sudo bash cyberpanel_upgrade.sh -b v2.5.5-dev +``` + +**Upgrade options:** + +| Option | Example | Description | +|--------|---------|-------------| +| `-b BRANCH` / `--branch BRANCH` | `-b v2.5.5-dev` | Upgrade to this branch/tag | +| `--no-system-update` | (optional) | Skip full `yum/dnf update -y` (faster if system is already updated) | + +**Examples:** + +```bash +sudo bash cyberpanel_upgrade.sh -b v2.5.5-dev +sudo bash cyberpanel_upgrade.sh -b 2.4.4 +sudo bash cyberpanel_upgrade.sh -b stable +sudo bash cyberpanel_upgrade.sh -b v2.5.5-dev --no-system-update +``` + +--- + +## Downgrade + +Downgrade is done by running the **upgrade** script with the **older** branch/version. + +### Downgrade to 2.4.4 (or another older version) + +```bash +sudo bash <(curl -sL https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel_upgrade.sh) -b 2.4.4 +``` + +Or with master3395 fork: + +```bash +curl -sL -o cyberpanel_upgrade.sh https://raw.githubusercontent.com/master3395/cyberpanel/stable/cyberpanel_upgrade.sh +chmod +x cyberpanel_upgrade.sh +sudo bash cyberpanel_upgrade.sh -b 2.4.4 +``` + +### Downgrade from v2.5.5-dev to stable + +```bash +sudo bash cyberpanel_upgrade.sh -b stable +``` + +--- + +## Pre-upgrade (download upgrade script only) + +From the interactive menu: **Option 5 – Pre-Upgrade**. + +Or manually: + +```bash +# Download latest upgrade script to /usr/local/ +curl -sL -o /usr/local/cyberpanel_upgrade.sh https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel_upgrade.sh +chmod 700 /usr/local/cyberpanel_upgrade.sh + +# Run when ready +sudo /usr/local/cyberpanel_upgrade.sh -b v2.5.5-dev +``` + +--- + +## Quick reference + +| Action | Command | +|--------|---------| +| **Install (official)** | `sh <(curl https://cyberpanel.net/install.sh)` | +| **Install stable (master3395)** | `curl -sL https://raw.githubusercontent.com/master3395/cyberpanel/stable/cyberpanel.sh \| sudo bash -s --` | +| **Install v2.5.5-dev** | `curl -sL https://raw.githubusercontent.com/master3395/cyberpanel/v2.5.5-dev/cyberpanel.sh \| sudo bash -s -- -b v2.5.5-dev` | +| **Upgrade to v2.5.5-dev** | `sudo bash <(curl -sL https://raw.githubusercontent.com/master3395/cyberpanel/stable/cyberpanel_upgrade.sh) -b v2.5.5-dev` | +| **Upgrade to 2.4.4** | `sudo bash <(curl -sL .../cyberpanel_upgrade.sh) -b 2.4.4` | +| **Downgrade to 2.4.4** | Same as upgrade: `... cyberpanel_upgrade.sh -b 2.4.4` | + +--- + +## Notes + +- Run as **root** or with **sudo**; if using `curl | sudo bash`, use `bash -s --` and put branch/options after `--` so they are passed to the script. +- MariaDB version can be set at install with `--mariadb-version 10.11`, `11.8`, or `12.1`. +- Upgrade script branch: `-b v2.5.5-dev`, `-b 2.4.4`, `-b stable`, or `-b `. diff --git a/to-do/PURE-FTPD-QUOTA-SYNTAX-FIX.md b/to-do/PURE-FTPD-QUOTA-SYNTAX-FIX.md index 917206ec1..09dba530a 100644 --- a/to-do/PURE-FTPD-QUOTA-SYNTAX-FIX.md +++ b/to-do/PURE-FTPD-QUOTA-SYNTAX-FIX.md @@ -19,6 +19,27 @@ The config used `Quota yes`, but Pure-FTPd expects **`Quota maxfiles:maxsize`** - **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). +## One-time fix on server (if "Enable" still breaks it) +Run on the server as root (copy script from repo or run inline): + +**Option A – script (repo root: `fix-pureftpd-quota-once.sh`):** +```bash +sudo bash /path/to/fix-pureftpd-quota-once.sh +``` + +**Option B – inline:** +```bash +sudo sed -i 's/^Quota.*/Quota 100000:100000/' /etc/pure-ftpd/pure-ftpd.conf +# If TLS 1 is set but cert missing, disable TLS: +sudo sed -i 's/^TLS[[:space:]]*1/TLS 0/' /etc/pure-ftpd/pure-ftpd.conf +sudo systemctl start pure-ftpd +``` +Then deploy the latest panel code so "Enable" uses the correct Quota syntax. + +## Code safeguards (enableFTPQuota) +- **Backup before modify**: Timestamped backup of `pure-ftpd.conf` and `pureftpd-mysql.conf` before any change. +- **Safety net before restart**: If the Quota line is not valid (`Quota maxfiles:maxsize`), it is corrected to `Quota 100000:100000` so Pure-FTPd never gets an invalid line on restart. + ## 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/to-do/V2.5.5-DEV-BRANCH-COMPATIBILITY.md b/to-do/V2.5.5-DEV-BRANCH-COMPATIBILITY.md new file mode 100644 index 000000000..733f3c90a --- /dev/null +++ b/to-do/V2.5.5-DEV-BRANCH-COMPATIBILITY.md @@ -0,0 +1,76 @@ +# v2.5.5-dev Branch Compatibility Check + +**Date:** 2026-02-04 +**Branches compared:** [v2.5.5-dev](https://github.com/master3395/cyberpanel/tree/v2.5.5-dev) vs [v2.4.4](https://github.com/master3395/cyberpanel/tree/v2.4.4) vs [stable](https://github.com/master3395/cyberpanel/tree/stable) + +--- + +## 1. Will your v2.5.5-dev changes work? + +**Yes.** The Ban IP / Firewall Banned IPs changes on v2.5.5-dev are self-contained and consistent: + +| Component | Status | +|-----------|--------| +| **plogical/firewallUtilities.py** | `blockIP` / `unblockIP` use `result == 1` for success; log file path is `/usr/local/CyberCP/data/blocked_ips.log` (writable by `cyberpanel`). | +| **plogical/processUtilities.py** | When running as root, `executioner` uses `normalExecutioner` return value (1 = success, 0 = fail). | +| **firewall/firewallManager.py** | `addBannedIP` uses `FirewallUtilities.blockIP`; ACL and errors return JSON with `error_message` and `error`; rollback on block failure. | +| **firewall/views.py** | `addBannedIP` parses JSON body and calls `fm.addBannedIP(userID, request_data)`. | +| **firewall/urls.py** | Routes `getBannedIPs`, `addBannedIP`, `modifyBannedIP`, `removeBannedIP`, `deleteBannedIP`, `exportBannedIPs`, `importBannedIPs` are present. | +| **baseTemplate/views.py** | `blockIPAddress` uses `FirewallUtilities.blockIP` (no subprocess). | +| **baseTemplate (homePage + system-status.js)** | Ban IP calls `/firewall/addBannedIP` with `ip`, `reason`, `duration`; shows server `error_message` in notifications. | + +**Deployment requirements (already applied on your server):** + +- `/usr/local/CyberCP/data` owned by `cyberpanel:cyberpanel` (for `banned_ips.json` and `blocked_ips.log`). +- Deploy updated files from v2.5.5-dev into `/usr/local/CyberCP/` and restart `lscpd`. + +--- + +## 2. Does v2.5.5-dev have all functions from v2.4.4 and stable? + +**Summary:** + +- **v2.5.5-dev has more than v2.4.4 and stable** in terms of features (Banned IPs, FTP quotas, email limits, user management, bandwidth management, etc.). It is a development branch built on top of the same base. +- **v2.5.5-dev is missing a few items that exist only on stable** (backports or stable-only fixes). Nothing critical for the Ban IP feature; mainly scripts and tests. + +### v2.5.5-dev has everything from v2.4.4 that matters + +- v2.4.4 is older (fewer commits). v2.5.5-dev contains the same core apps (firewall, baseTemplate, loginSystem, backup, etc.) plus many additions. +- **Firewall:** v2.4.4 has no Banned IPs routes; v2.5.5-dev adds the full Banned IPs feature (getBannedIPs, addBannedIP, modify, remove, delete, export, import). + +### v2.5.5-dev vs stable + +- **Stable has ~86 files that differ from v2.5.5-dev**, including: + - **run_migration.py** – present on stable, **not** on v2.5.5-dev (migration helper). + - **test_firewall_blocking.py** – test script on stable. + - **rollback_phpmyadmin_redirect.sh** – rollback script on stable. + - **install/**, **plogical/** (e.g. mysqlUtilities, upgrade, backup, sslUtilities), **pluginInstaller** – some fixes/improvements on stable that may not be in v2.5.5-dev. + +- **v2.5.5-dev has 3652+ files changed vs stable** – it has many more features (user management, website functions, bandwidth, FTP quotas, email limits, Banned IPs, etc.). + +So: + +- **Feature parity:** v2.5.5-dev has **all the main functions** from v2.4.4 and **adds** Banned IPs and other features. It does **not** lack core features that v2.4.4 or stable have. +- **Stable-only extras:** Stable has a few **extra** scripts/fixes (e.g. `run_migration.py`, `rollback_phpmyadmin_redirect.sh`, some plogical/install changes). If you need those, you can cherry-pick or merge from stable into v2.5.5-dev. + +--- + +## 3. Directory layout comparison + +| In stable, not in v2.5.5-dev (by name) | In v2.5.5-dev, not in stable | +|----------------------------------------|------------------------------| +| emailMarketing (or different layout) | bin, docs, modules, public, sql, test, to-do | +| examplePlugin | (v2.5.5-dev has more structure) | +| guides | | +| scripts | | +| testPlugin | test (different name) | + +Your current repo (v2.5.5-dev) includes `emailMarketing`, `websiteFunctions`, `firewall`, `baseTemplate`, etc. The diff is mostly naming (e.g. test vs testPlugin) and stable having a few extra scripts/docs. + +--- + +## 4. Recommendation + +1. **Use v2.5.5-dev as-is for Ban IP and current features** – the changes are consistent and will work with the deployment steps above. +2. **Periodically merge or cherry-pick from stable** into v2.5.5-dev if you want stable’s migration script, phpMyAdmin rollback script, and any plogical/install fixes. +3. **You do have all the functions from v2.4.4 and stable** in the sense of core product behavior; v2.5.5-dev adds more (Banned IPs, etc.) and is only missing some optional stable-only scripts/fixes. diff --git a/websiteFunctions/templates/websiteFunctions/ftpQuotaManagement.html b/websiteFunctions/templates/websiteFunctions/ftpQuotaManagement.html index b075aa0fd..c29232e44 100644 --- a/websiteFunctions/templates/websiteFunctions/ftpQuotaManagement.html +++ b/websiteFunctions/templates/websiteFunctions/ftpQuotaManagement.html @@ -38,7 +38,15 @@ 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.