Compare commits

...

5 Commits

Author SHA1 Message Date
cschantz 1e9e33171d Clean up session notes and temporary files
Removed:
- Session planning docs (CODING_GUIDELINES, AUDIT summaries, etc)
- docs/ directory (PHP planning notes, session summaries)
- tmp/bot_analysis_report_*.txt (old analysis files)
- backups/php/test_* (test backup directories)

Kept:
- REFDB_FORMAT.txt (memory/reference file)
- README.md (project documentation)
- config/whitelist-*.txt (functional configs)
- modules/*/README.md (module documentation)

Total cleanup: ~133KB of session artifacts
2026-01-08 17:18:34 -05:00
cschantz 3ef3f4c61b Export functions for subshell access (CRITICAL FIX)
HTTP monitoring runs in subshells (from tail pipe) but functions
were not exported, making them unavailable in those subshells.

Exported functions:
- write_ip_data_to_file (writes scores to file)
- update_ip_intelligence (updates IP scores)
- get_ip_intelligence (reads IP data)
- get_threat_level (calculates threat level)
- get_threat_color (gets display color)

This fixes the critical bug where HTTP attacks reached Score:100
but were never blocked because scores weren't written to ip_data file.

Without exports: function called in subshell = command not found
With exports: function available in all child processes
2026-01-06 22:11:21 -05:00
cschantz af510e7fb5 Move all persistent data to /tmp (no system pollution)
Moved from /var/lib/server-toolkit/ to /tmp/:
- Threat intelligence cache
- Whitelist IPs
- Attack pattern logs
- Incident reports
- Shared threat coordination logs
- Live monitor snapshots

Philosophy: Deleting toolkit directory should remove ALL data.
System directories (/var/lib/) caused stale data to persist.
Using /tmp/ ensures auto-cleanup on reboot and complete removal.
2026-01-06 22:03:18 -05:00
cschantz 4dd7bfeabc Move IP reputation database to /tmp
Changed from /var/lib/server-toolkit/ to /tmp/server-toolkit-reputation/

Reasons:
- No system pollution - deleting toolkit removes all data
- Auto-cleanup on reboot (no stale scores)
- Self-contained design

Old location (/var/lib/) caused stale Score:100 entries to persist
after code fixes were deployed.
2026-01-06 22:02:28 -05:00
cschantz 7f2d236c49 Add auto-blocking for distributed attacks
When 5+ IPs perform same attack type (RCE, SQL_INJECTION, XSS, PATH_TRAVERSAL, BRUTEFORCE) within 2 minutes:
- Block all individual attacking IPs immediately via IPset
- If 25+ IPs from same /24 subnet, block entire subnet

Uses batch_block_ips() for efficient IPset operations.
All blocking is kernel-level via IPset (no CSF commands).
2026-01-06 21:55:58 -05:00
19 changed files with 66 additions and 4403 deletions
-172
View File
@@ -1,172 +0,0 @@
# Server Toolkit Coding Guidelines
## Color Code Usage - CRITICAL
### The Problem
Using `echo` without the `-e` flag causes ANSI escape sequences to display literally instead of being interpreted:
```bash
# WRONG - Shows literal: \033[1m1\033[0m
echo " ${BOLD}1${NC} - Menu option"
# RIGHT - Shows: 1 (bold and colored)
echo -e " ${BOLD}1${NC} - Menu option"
```
### Prevention Rules
**Rule 1: Always use `echo -e` when string contains color variables**
```bash
# WRONG:
echo " ${BOLD}Option${NC}"
echo "Status: ${GREEN}OK${NC}"
# RIGHT:
echo -e " ${BOLD}Option${NC}"
echo -e "Status: ${GREEN}OK${NC}"
```
**Rule 2: Use helper functions from common-functions.sh**
```bash
# Source the library
source /root/server-toolkit/lib/common-functions.sh
# Use built-in print functions (already use echo -e)
print_success "Operation completed"
print_error "Something went wrong"
print_info "Information message"
# For custom colored output, use cecho()
cecho "Custom ${RED}colored${NC} text"
```
**Rule 3: No -e flag needed when NOT using quotes**
```bash
# This is OK (no quotes around the whole thing)
echo ${BOLD}Title${NC}
# But this needs -e (quotes around everything)
echo -e "${BOLD}Title${NC}"
```
### Quick Reference
| Scenario | Command |
|----------|---------|
| Menu option with colors | `echo -e " ${BOLD}1${NC} - Option"` |
| Success message | `print_success "Done"` or `echo -e "${GREEN}✓${NC} Done"` |
| Error message | `print_error "Failed"` or `echo -e "${RED}✗${NC} Failed"` |
| Custom colored text | `cecho "Text ${RED}red${NC} normal"` |
| Plain text (no colors) | `echo "Plain text"` (no -e needed) |
### How to Find and Fix
**Search for potential issues:**
```bash
# Find echo statements with color variables that might be missing -e
grep -n 'echo ".*\${\(BOLD\|.*_COLOR\|NC\|RED\|GREEN\|YELLOW\|BLUE\)' your_script.sh
```
**Common patterns to fix:**
```bash
# BEFORE:
echo " ${BOLD}1${NC} - Enable Feature"
echo "Status: ${GREEN}Active${NC}"
echo "${RED}[ERROR]${NC} Failed"
# AFTER:
echo -e " ${BOLD}1${NC} - Enable Feature"
echo -e "Status: ${GREEN}Active${NC}"
echo -e "${RED}[ERROR]${NC} Failed"
# OR use helper:
cecho " ${BOLD}1${NC} - Enable Feature"
cecho "Status: ${GREEN}Active${NC}"
print_error "Failed"
```
### Why This Matters
**Impact of the bug:**
- Menus show escape codes instead of colors: `\033[1m1\033[0m`
- Makes interface look broken and unprofessional
- Reduces readability and user experience
- Hard to debug because it "looks right" in the code
**Historical issues:**
- Security hardening menu (fixed: commit 7053b3b)
- Various other menus and status displays
- User feedback: "This happens a lot with you"
### Pre-commit Checklist
Before committing code with color output:
- [ ] All `echo` statements with `${COLOR}` variables use `-e` flag
- [ ] Or use `cecho()` helper function instead
- [ ] Or use `print_*()` functions from common-functions.sh
- [ ] Test output in terminal to verify colors render correctly
- [ ] Run: `bash -n script.sh` to check syntax
- [ ] Run: `shellcheck script.sh` if available
## Performance Guidelines
### Avoid Subprocesses in Loops
**Rule: Use bash built-ins instead of spawning processes**
```bash
# WRONG - Spawns subprocess (slow)
url_lower=$(echo "$url" | tr '[:upper:]' '[:lower:]')
url_lower=$(echo "$url" | tr 'A-Z' 'a-z')
# RIGHT - Bash built-in (fast)
url_lower="${url,,}"
# WRONG - Multiple subprocesses
hostname=$(hostname)
for item in $list; do
check_hostname "$hostname" # Calls hostname 1000s of times
done
# RIGHT - Cache the result
CACHED_HOSTNAME="${HOSTNAME:-$(hostname)}"
for item in $list; do
check_hostname "$CACHED_HOSTNAME"
done
```
**Impact:** On high-traffic servers (1000+ req/sec), subprocess elimination prevents tens of thousands of unnecessary forks per second.
### Performance Quick Reference
| Operation | Slow (subprocess) | Fast (built-in) |
|-----------|-------------------|-----------------|
| Lowercase | `$(echo "$var" \| tr '[:upper:]' '[:lower:]')` | `${var,,}` |
| Uppercase | `$(echo "$var" \| tr '[:lower:]' '[:upper:]')` | `${var^^}` |
| Substring | `$(echo "$var" \| cut -c1-5)` | `${var:0:5}` |
| Replace | `$(echo "$var" \| sed 's/old/new/')` | `${var//old/new}` |
| Length | `$(echo "$var" \| wc -c)` | `${#var}` |
## Additional Guidelines
### Error Handling
- Always check return codes for critical operations
- Use `set -euo pipefail` for strict error handling in new scripts
- Provide meaningful error messages with context
### Function Documentation
- Add comment block above complex functions
- Document parameters, return values, and side effects
- Include usage examples for non-obvious functions
### Variable Naming
- Use descriptive names: `user_count` not `uc`
- Constants in UPPER_CASE: `MAX_RETRIES=3`
- Local variables in lower_case: `local temp_file="/tmp/data"`
- Global exports in UPPER_CASE: `export LOG_DIR="/var/log"`
### Testing
- Test with both light and dark terminal backgrounds
- Test with `TOOLKIT_NO_COLOR=1` for monochrome output
- Verify output doesn't overflow on 24-line terminals (standard)
- Test with realistic data volumes (not just 1-2 entries)
-214
View File
@@ -1,214 +0,0 @@
# CORRECTED Audit Summary - After Triple-Check
## Date: 2025-12-23
## Status: TRIPLE-CHECKED AND VERIFIED
---
## CRITICAL CORRECTION
**My initial audit report (PLATFORM_AUDIT_FINDINGS.md) was LARGELY INCORRECT.**
After triple-checking the actual code, here's what's REALLY true:
---
## ACTUAL FINDINGS
### ✅ GOOD NEWS - What Already Works:
1. **lib/domain-discovery.sh** - FULLY MULTI-PLATFORM ✅
- ALL 13 functions have Plesk cases ✓
- ALL 13 functions have standalone fallbacks ✓
- Functions like `list_all_domains()`, `get_domain_owner()`, etc. work on all platforms
2. **lib/system-detect.sh** - Detects all platforms correctly ✅
3. **lib/plesk-helpers.sh** - 31 Plesk helper functions ready ✅
4. **lib/user-manager.sh** - Already has Plesk/InterWorx/standalone support ✅
5. **build_domains_section() HAS fallback logic**
- Lines 333-359: `else` branch for non-cPanel systems
- Uses `get_user_domains()` which is panel-agnostic
- Works on Plesk/standalone already!
---
### ❌ ACTUAL ISSUES FOUND (Only 3, not 8!):
#### Issue #1: build_domains_section() - cPanel Userdata Optimization
**Severity**: MEDIUM (not critical!)
**Location**: Lines 255-332
The function has TWO code paths:
1. **Lines 255-332**: Optimized cPanel path (parses userdata files for detailed info)
2. **Lines 333-359**: Fallback path for ALL other systems (uses panel-agnostic functions)
**Problem**: The cPanel path gets richer data (PHP version, aliases, HTTP status, domain type)
**Impact**: Plesk/standalone get less detailed domain information, but they DO work
**Not a blocker** - just means Plesk won't get as detailed info as cPanel
---
#### Issue #2: /etc/localdomains and /etc/remotedomains - Not Wrapped
**Severity**: LOW (cosmetic, not critical!)
**Location**: Lines 364-396
```bash
# Check /etc/localdomains (cPanel local domains not yet added)
if [ -f "/etc/localdomains" ]; then
# ...
fi
```
**Problem**: Not wrapped in `if [ "$SYS_CONTROL_PANEL" = "cpanel" ]`
**Impact**: NONE - the `if [ -f "/etc/localdomains" ]` check means it skips silently on non-cPanel
**Fix**: Nice to have for code cleanliness, but not blocking anything
---
#### Issue #3: WordPress Path Parsing - Hardcoded /home/
**Severity**: MEDIUM
**Location**: Lines 411, 414
```bash
# Line 405: Uses $SYS_USER_HOME_BASE - THIS IS GOOD ✅
local wp_configs=$(find $SYS_USER_HOME_BASE -name "wp-config.php" -type f 2>/dev/null)
# Line 411: Assumes field 3 is username - BREAKS ON PLESK ❌
local username=$(echo "$wp_dir" | cut -d'/' -f3)
# Line 414: Hardcodes /home/ - BREAKS ON PLESK ❌
local path_after_home=$(echo "$wp_dir" | sed "s|^/home/$username/||")
```
**Problem**: Path parsing assumes `/home/username/` structure
**Impact**: WordPress detection works but extracts wrong username/domain on Plesk
**Fix Needed**: Panel-specific path parsing logic
---
## WHAT THIS MEANS
### For Plesk Support:
**Current State**: MOSTLY WORKING! 🎉
- ✅ Domain discovery works (via fallback path)
- ✅ User detection works
- ✅ Database detection works
- ⚠️ WordPress detection works but gets wrong owner/domain
- ⚠️ Domain details less rich than cPanel (no PHP version, aliases, status codes)
**To Make Plesk Excellent**:
1. Create `build_domains_plesk()` function (get richer Plesk domain data)
2. Fix WordPress path parsing for Plesk paths
3. Optionally wrap `/etc/localdomains` checks (code cleanliness)
### For Standalone Support:
**Current State**: BASIC SUPPORT EXISTS! 🎉
- ✅ domain-discovery.sh has standalone fallbacks for ALL functions
- ✅ Scans `/var/www/`, `/home/`, common web directories
- ✅ Uses `stat -c "%U"` for ownership
- ⚠️ WordPress detection works but path parsing needs improvement
**To Make Standalone Excellent**:
1. Add vhost parsing (Apache/Nginx configs) - currently just scans directories
2. Fix WordPress path parsing for various web roots
3. Create `build_domains_standalone()` for richer data
---
## REVISED IMPLEMENTATION PLAN
### Priority 1: Quick Plesk Fixes (2-3 hours)
**Goal**: Make Plesk experience match cPanel quality
1. **Create build_domains_plesk()** function (1 hour)
- Use `plesk bin site --list`
- Call `plesk_get_docroot()`, `plesk_get_logdir()`, etc.
- Get PHP version, SSL status from Plesk
- Format same as cPanel output
2. **Fix WordPress path parsing** (1 hour)
- Add panel-specific logic for username/domain extraction
- Test on both cPanel and Plesk paths
3. **Wrap cPanel-only file checks** (15 minutes)
- Add `if [ "$SYS_CONTROL_PANEL" = "cpanel" ]` around lines 364-396
- Code cleanliness
### Priority 2: Enhanced Standalone Support (4-6 hours)
**Goal**: Parse vhost configs instead of just directory scanning
1. **Create lib/standalone-helpers.sh** (3 hours)
- `standalone_parse_apache_vhosts()` - read ServerName from configs
- `standalone_parse_nginx_vhosts()` - read server_name from configs
- Extract DocumentRoot, log paths, aliases from configs
2. **Create build_domains_standalone()** (2 hours)
- Use vhost parser for domain discovery
- Get richer domain data (document roots, log paths)
- Format similar to cPanel output
3. **Test on Ubuntu/Debian/AlmaLinux** (1 hour)
---
## CORRECTED TIMELINE
### Week 1:
- **Day 1 (4 hours)**: Priority 1 - Plesk fixes
- **Day 2 (2 hours)**: Test Plesk fixes on Plesk server
- **Days 3-4 (8 hours)**: Priority 2 - Standalone vhost parsing
- **Day 5 (2 hours)**: Test standalone on Ubuntu/AlmaLinux
### Week 2:
- **Days 1-2**: Integration testing all platforms
- **Days 3-5**: Bug fixes, edge cases, documentation
---
## BOTTOM LINE
**My initial audit was OVERLY PESSIMISTIC.**
The codebase is in MUCH BETTER shape than I thought:
| Component | Initial Assessment | CORRECTED Assessment |
|-----------|-------------------|---------------------|
| domain-discovery.sh | ❌ No standalone support | ✅ Full multi-platform |
| reference-db.sh | ❌ 100% cPanel-only | ⚠️ Works on all, needs optimization |
| WordPress detection | ❌ Completely broken | ⚠️ Works, needs path fix |
| Overall | "2-3 weeks" | **"3-5 days"** |
---
## WHAT TO DO NEXT
**RECOMMENDED**: Start with Priority 1 (Plesk fixes)
1. Create `build_domains_plesk()` function
2. Fix WordPress path parsing
3. Test on Plesk server
4. IF working well, proceed to Priority 2 (standalone vhost parsing)
**ALTERNATIVE**: Test current code on Plesk server FIRST
- The fallback path might already work well enough
- WordPress issue might not be critical if domain detection works
- Could skip all enhancements and just use existing code
---
**Apologies for the initial incorrect audit.** The good news is the code is in much better shape than I thought!
---
**Files to Review**:
- ❌ DELETE: `PLATFORM_AUDIT_FINDINGS.md` (incorrect)
- ✅ READ: This file (CORRECTED_AUDIT_SUMMARY.md)
- ✅ KEEP: `CROSS_PLATFORM_PLAN.md` (still valid, just less work needed)
-311
View File
@@ -1,311 +0,0 @@
# Cross-Platform Launcher Implementation Plan
## Executive Summary
Transform the launcher from cPanel-only to fully cross-platform supporting:
- **Control Panels**: cPanel, Plesk, InterWorx
- **Standalone Systems**: Debian, Ubuntu, AlmaLinux, Rocky Linux, RHEL, CentOS
## Current State Analysis
### What Works ✅
1. **lib/system-detect.sh** - Already detects all platforms correctly
2. **lib/domain-discovery.sh** - Has unified functions for cPanel/Plesk/InterWorx
3. **lib/plesk-helpers.sh** - 31 Plesk-specific helper functions ready
4. **lib/user-manager.sh** - Already has Plesk/InterWorx support for user/database queries
5. **lib/common-functions.sh** - Platform-agnostic utility functions
### What's Broken ❌
1. **lib/reference-db.sh** - Hardcoded cPanel dependencies in 4 locations:
- Line 255, 265: Uses `/var/cpanel/userdata` for domain configs
- Line 370, 390: Uses `/etc/trueuserdomains` for domain ownership
2. **build_domains_section()** - 100% cPanel-specific (parses cPanel userdata files)
3. **build_wordpress_section()** - Assumes `/home/username/` directory structure
## Platform-Specific Characteristics
### Control Panel Systems
#### cPanel
- **Users**: `/var/cpanel/users/`
- **Domains**: `/etc/userdomains`, `/etc/trueuserdomains`
- **Config**: `/var/cpanel/userdata/{user}/{domain}`
- **Home**: `/home/{user}/`
- **Logs**: `/var/log/apache2/domlogs/`
- **Detection**: `/usr/local/cpanel/version`
#### Plesk
- **Users**: MySQL query to `psa.sys_users`
- **Domains**: `plesk bin site --list` or MySQL `psa.domains`
- **Config**: `/var/www/vhosts/{domain}/conf/`
- **Home**: `/var/www/vhosts/{domain}/`
- **Logs**: `/var/www/vhosts/system/{domain}/logs/`
- **Detection**: `/usr/local/psa/version`
#### InterWorx
- **Users**: `/home/interworx/var/`
- **Domains**: `~iworx/bin/listaccounts.pex`
- **Config**: `/home/{user}/var/{domain}/`
- **Home**: `/chroot/home/{user}/`
- **Logs**: `/home/{user}/var/{domain}/logs/`
- **Detection**: `/usr/local/interworx/bin/status.pex`
### Standalone Systems (No Control Panel)
#### Common Characteristics
- **Users**: Standard `/etc/passwd` (UID >= 1000)
- **Domains**: Detect from:
- Apache/Nginx vhosts: `/etc/apache2/sites-enabled/`, `/etc/nginx/sites-enabled/`
- `/etc/hosts` entries
- DNS records (if available)
- **Home**: `/home/{user}/` or `/var/www/`
- **Logs**: `/var/log/apache2/`, `/var/log/nginx/`
- **Web roots**: `/var/www/html/`, `/var/www/{domain}/`, `/usr/share/nginx/html/`
#### Debian/Ubuntu Specific
- Apache config: `/etc/apache2/sites-available/`
- Nginx config: `/etc/nginx/sites-available/`
- Default web root: `/var/www/html/`
- Package manager: `apt`
#### RHEL/AlmaLinux/Rocky/CentOS Specific
- Apache config: `/etc/httpd/conf.d/`
- Nginx config: `/etc/nginx/conf.d/`
- Default web root: `/var/www/html/` or `/usr/share/nginx/html/`
- Package manager: `dnf` or `yum`
## Implementation Strategy
### Phase 1: Refactor build_domains_section() 🎯 PRIORITY
**Current Issue**: Entirely cPanel-specific, parses userdata files
**Solution**: Create platform-specific domain discovery logic
```bash
build_domains_section() {
echo "[DOMAINS]" >> "$SYSREF_DB"
case "$SYS_CONTROL_PANEL" in
cpanel)
build_domains_cpanel
;;
plesk)
build_domains_plesk
;;
interworx)
build_domains_interworx
;;
*)
build_domains_standalone
;;
esac
finish_progress
echo "" >> "$SYSREF_DB"
}
```
**Sub-functions to create**:
1. `build_domains_cpanel()` - Keep existing logic
2. `build_domains_plesk()` - Use plesk_list_domains + plesk_get_* functions
3. `build_domains_interworx()` - Use InterWorx CLI tools
4. `build_domains_standalone()` - Parse Apache/Nginx vhosts
### Phase 2: Refactor build_wordpress_section()
**Current Issue**: Assumes `/home/username/` paths, uses cPanel-specific logic
**Solution**: Use $SYS_USER_HOME_BASE and panel-agnostic path parsing
```bash
build_wordpress_section() {
echo "[WORDPRESS]" >> "$SYSREF_DB"
# Use panel-agnostic search paths
case "$SYS_CONTROL_PANEL" in
cpanel)
search_paths="/home/*/public_html"
;;
plesk)
search_paths="/var/www/vhosts/*/httpdocs /var/www/vhosts/*/httpsdocs"
;;
interworx)
search_paths="/chroot/home/*/var/*/html"
;;
*)
search_paths="/var/www/*/public_html /var/www/html /home/*/public_html"
;;
esac
# Find wp-config.php in all search paths
# Extract domain/owner using get_domain_owner() and path analysis
}
```
### Phase 3: Add Standalone Web Server Detection
**New functions needed in system-detect.sh**:
```bash
detect_vhosts_standalone() {
# Scan Apache sites-enabled
if [ -d /etc/apache2/sites-enabled ]; then
# Parse ServerName/ServerAlias from .conf files
fi
# Scan Nginx sites-enabled
if [ -d /etc/nginx/sites-enabled ]; then
# Parse server_name from .conf files
fi
# Parse /etc/httpd/conf.d/ for RHEL-based
}
```
### Phase 4: Enhance Domain Discovery for Standalone
**New helper library**: `lib/standalone-helpers.sh`
Functions needed:
- `standalone_list_domains()` - Parse vhost configs
- `standalone_get_docroot()` - Extract DocumentRoot/root directive
- `standalone_get_logdir()` - Extract log paths from vhost configs
- `standalone_get_owner()` - Use `stat -c "%U"` on document root
- `standalone_list_users()` - Filter /etc/passwd for UID >= 1000
### Phase 5: Universal WordPress Detection
**Current limitations**: Only searches `/home/` paths
**Enhanced approach**:
```bash
# Multi-path WordPress scanner
find_wordpress_installations() {
local search_paths=""
case "$SYS_CONTROL_PANEL" in
cpanel) search_paths="/home" ;;
plesk) search_paths="/var/www/vhosts" ;;
interworx) search_paths="/chroot/home" ;;
*)
# Standalone: check common webroot locations
search_paths="/var/www /home /usr/share/nginx"
;;
esac
# Find all wp-config.php files
find $search_paths -name wp-config.php -type f 2>/dev/null
}
```
## Implementation Phases with Testing
### Phase 1: Reference Database Refactor (Week 1)
- [ ] Create `build_domains_cpanel()` (extract existing code)
- [ ] Create `build_domains_plesk()` (use plesk-helpers)
- [ ] Create `build_domains_interworx()` (use interworx-helpers if exists)
- [ ] Create `build_domains_standalone()` (new vhost parser)
- [ ] Test on cPanel server (verify no regression)
- [ ] Test on Plesk server (verify domain discovery)
### Phase 2: WordPress Detection (Week 1)
- [ ] Refactor `build_wordpress_section()` with multi-path search
- [ ] Add panel-specific path extraction logic
- [ ] Test on cPanel (verify existing WordPress detected)
- [ ] Test on Plesk (verify WordPress detected)
- [ ] Test on standalone Ubuntu (verify WordPress detected)
### Phase 3: Standalone Helpers (Week 2)
- [ ] Create `lib/standalone-helpers.sh`
- [ ] Implement vhost parsing (Apache)
- [ ] Implement vhost parsing (Nginx)
- [ ] Implement user discovery (UID filtering)
- [ ] Add exports to domain-discovery.sh
- [ ] Test on Debian/Ubuntu with Apache
- [ ] Test on AlmaLinux with Nginx
### Phase 4: Integration Testing (Week 2)
- [ ] Test full launcher on cPanel server
- [ ] Test full launcher on Plesk server
- [ ] Test full launcher on InterWorx server (if available)
- [ ] Test full launcher on Ubuntu standalone
- [ ] Test full launcher on AlmaLinux standalone
- [ ] Test full launcher on Debian standalone
### Phase 5: Documentation (Week 3)
- [ ] Update README with platform support matrix
- [ ] Document standalone system requirements
- [ ] Create troubleshooting guide for each platform
- [ ] Add platform-specific installation notes
## Database Format Compatibility
The current `.sysref` format is already platform-agnostic:
```
DOMAIN|domain|owner|docroot|logdir|access_log|php_version|is_primary|type|aliases|http|https|status
```
**All fields map universally**:
- `domain` - Same on all platforms
- `owner` - Username from any system
- `docroot` - Absolute path (any location)
- `logdir` - Absolute path (any location)
- `access_log` - Absolute path (any location)
- `php_version` - Detected version string
- `is_primary` - yes/no (determined by logic)
- `type` - primary/addon/alias/subdomain (universal concepts)
- `aliases` - Space-separated list
- `http/https/status` - HTTP status codes (universal)
**No format changes needed** - only the methods to populate these fields change per platform.
## Risk Mitigation
### Backward Compatibility
- ✅ Keep all existing cPanel code paths functional
- ✅ Use case statements for platform-specific logic
- ✅ Default to cPanel behavior if platform unknown
- ✅ Existing cPanel installations continue working without changes
### Testing Strategy
- ✅ Test on live cPanel server FIRST (prevent regressions)
- ✅ Test on Plesk server SECOND (validate new platform)
- ✅ Test on standalone systems THIRD (validate fallback logic)
- ✅ Keep old commits in git history for easy revert
### Fallback Mechanisms
- ✅ If vhost parsing fails → scan /var/www for directories
- ✅ If user detection fails → show "unknown" owner
- ✅ If WordPress detection fails → skip silently (don't crash)
- ✅ If domain discovery returns empty → try manual directory scan
## Success Criteria
### Minimum Viable Product (MVP)
- [x] cPanel: 100% functional (already working)
- [ ] Plesk: Domain/user/database discovery working
- [ ] Standalone: Basic domain/WordPress detection working
### Full Feature Parity
- [ ] All platforms detect domains correctly
- [ ] All platforms detect WordPress installations
- [ ] All platforms show correct ownership
- [ ] All platforms display accurate statistics
- [ ] All modules work on all platforms (or gracefully skip)
## Next Immediate Steps
1. **Create standalone-helpers.sh** - New helper library for non-panel systems
2. **Refactor build_domains_section()** - Split into platform-specific functions
3. **Test on cPanel** - Ensure no regressions
4. **Test on Plesk** - Validate Plesk domain discovery
5. **Document platform support** - Update README with compatibility matrix
---
**Estimated Timeline**: 2-3 weeks for full cross-platform support
**Priority**: High - Blocking Plesk deployment
**Risk**: Medium - Potential for breaking cPanel if not careful
**Complexity**: Medium-High - Requires understanding 4+ different platforms
-366
View File
@@ -1,366 +0,0 @@
# FINAL AUDIT - QUAD-CHECKED AND VERIFIED
## Date: 2025-12-23
## Status: ✅ QUADRUPLE-CHECKED BY READING ACTUAL CODE
---
## EXECUTIVE SUMMARY
After quad-checking by reading the ENTIRE source code (not using grep), here's the definitive truth:
**The toolkit ALREADY HAS multi-platform support** - it's just not optimal for Plesk.
---
## VERIFIED FACTS
### ✅ What DEFINITELY Works Right Now:
1. **`build_domains_section()` HAS fallback for non-cPanel** (lines 90-116)
```bash
else
# Fallback for non-cPanel or if userdata not available
local primary_domain=$(get_user_domains "$user" | head -1)
local all_domains=$(get_user_domains "$user")
# ... processes domains using panel-agnostic functions
```
- On cPanel: Uses optimized userdata parsing (lines 24-89)
- On Plesk/standalone: Uses `get_user_domains()` which calls panel-specific helpers
2. **`list_all_users()` supports all platforms**:
- cPanel: `ls -1 /var/cpanel/users/`
- Plesk: `plesk_exec bin user --list` (with fallback)
- InterWorx: `ls -1 /chroot/home/`
- Standalone: `ls -1 /home/`
3. **`get_user_domains()` supports all platforms**:
- cPanel: Reads `/etc/trueuserdomains`
- Plesk: Calls `get_plesk_user_domains()`
- InterWorx: Calls `get_interworx_user_domains()`
- Standalone: Returns empty (needs enhancement)
4. **`domain-discovery.sh` has 13 functions, ALL have platform cases**:
- list_all_domains ✅
- get_domain_docroot ✅
- get_domain_logdir ✅
- get_domain_access_log ✅
- get_domain_error_log ✅
- get_all_log_files ✅
- get_domain_owner ✅
- list_all_users ✅
- get_domain_fpm_socket ✅
- get_all_fpm_sockets ✅
- get_domain_databases ✅
- domain_exists ✅
- list_domains_with_docroots ✅
### ❌ What Needs Work:
#### ISSUE #1: WordPress Path Parsing (MEDIUM)
**Location**: lib/reference-db.sh lines 411, 414
**Problem**:
```bash
# Line 411: Assumes field 3 is username
local username=$(echo "$wp_dir" | cut -d'/' -f3)
# Line 414: Hardcodes /home/
local path_after_home=$(echo "$wp_dir" | sed "s|^/home/$username/||")
```
**Impact on Plesk**:
- `/var/www/vhosts/domain.com/httpdocs/wp-config.php`
- Field 3 would be "vhosts" not username ❌
- `sed "s|^/home/..."` won't match ❌
**HOWEVER** - Line 36 tries to fix this:
```bash
# Try to get site URL from wp-config defines
local site_url=$(grep -E "WP_SITEURL|WP_HOME" "$wp_config" ...)
if [ -n "$site_url" ]; then
domain="$site_url" # ← This works on any platform!
fi
```
**So WordPress detection WORKS but gets wrong username initially, then corrects the domain from WP_SITEURL.**
**Fix Needed**: Add panel-specific path parsing to get correct username from the start.
---
#### ISSUE #2: cPanel-Only File Checks Not Wrapped (LOW)
**Location**: lib/reference-db.sh lines 122-153
**Problem**:
```bash
# Check /etc/localdomains (cPanel local domains not yet added)
if [ -f "/etc/localdomains" ]; then
# ... reads cPanel-only files
fi
```
**Impact**: NONE - the `if [ -f "..." ]` check means it skips silently on non-cPanel
**Fix Needed**: Wrap in `if [ "$SYS_CONTROL_PANEL" = "cpanel" ]` for code cleanliness only
---
#### ISSUE #3: Plesk Gets Less Detailed Domain Data (MEDIUM)
**Location**: lib/reference-db.sh lines 90-116 (fallback path)
**cPanel Path** (lines 24-89) provides:
- Document root ✅
- Log path ✅
- PHP version ✅
- Server aliases ✅
- Domain type (primary/addon/subdomain/alias) ✅
- HTTP/HTTPS status codes ✅
**Plesk Fallback Path** (lines 90-116) provides:
- Domain name ✅
- Owner ✅
- Log path (generic) ✅
- Primary flag ✅
- HTTP/HTTPS status codes ✅
- Document root ❌ (empty)
- PHP version ❌ (empty)
- Server aliases ❌ (empty)
- Domain type ❌ (shows "local" instead of primary/addon)
**Why**: The fallback path doesn't call `get_domain_docroot()`, `get_domain_php_version()`, etc.
**Fix Needed**: Create `build_domains_plesk()` that calls Plesk-specific functions to get full data
---
#### ISSUE #4: Standalone get_user_domains() Returns Empty
**Location**: lib/user-manager.sh
```bash
get_user_domains() {
case "$SYS_CONTROL_PANEL" in
cpanel) get_cpanel_user_domains "$username" ;;
plesk) get_plesk_user_domains "$username" ;;
interworx) get_interworx_user_domains "$username" ;;
*) echo "" ;; # ← Standalone returns NOTHING!
esac
}
```
**Impact**: On standalone systems, `build_domains_section()` fallback path gets empty domains list
**BUT** - `list_all_domains()` DOES work on standalone:
```bash
list_all_domains() {
case "$SYS_CONTROL_PANEL" in
*)
# Standalone: scan common web directories
find /var/www/html/*/public_html -maxdepth 0 -type d 2>/dev/null | awk -F'/' '{print $(NF-1)}'
find /home/*/public_html -maxdepth 0 -type d 2>/dev/null | awk -F'/' '{print $(NF-1)}'
# ...
esac
}
```
**So standalone CAN find domains, but the reference-db.sh fallback path doesn't use the right function!**
**Fix Needed**: `build_domains_standalone()` function that uses `list_all_domains()` instead of looping through users
---
## THE REAL SITUATION
### On cPanel:
- ✅ **FULLY WORKING** - Rich detailed domain data
### On Plesk:
- ⚠️ **PARTIALLY WORKING** - Domains detected, but missing details
- ✅ Users detected via `plesk bin user --list`
- ✅ Domains detected via `get_plesk_user_domains()`
- ❌ Missing: docroot, PHP version, aliases
- ⚠️ WordPress detected but wrong username
### On Standalone:
- ❌ **BROKEN** - `get_user_domains()` returns empty
- ✅ BUT `list_all_domains()` WORKS and finds domains!
- Problem: `build_domains_section()` doesn't use `list_all_domains()` directly
---
## CORRECTED IMPLEMENTATION PLAN
### Priority 1: Plesk Enhancement (4 hours) 🎯
**Goal**: Make Plesk get same quality data as cPanel
**Task 1: Create build_domains_plesk()** (3 hours)
```bash
build_domains_plesk() {
local all_domains=$(list_all_domains) # Uses plesk bin site --list
for domain in $all_domains; do
local owner=$(get_domain_owner "$domain")
local docroot=$(get_domain_docroot "$domain") # Calls plesk_get_docroot()
local logdir=$(get_domain_logdir "$domain")
local access_log=$(get_domain_access_log "$domain")
local php_version=$(plesk_get_php_version "$domain")
local ssl_status=$(plesk_get_ssl_status "$domain")
echo "DOMAIN|$domain|$owner|$docroot|$logdir|$access_log|$php_version|..." >> "$SYSREF_DB"
done
}
```
**Task 2: Update build_domains_section()** (30 min)
```bash
build_domains_section() {
echo "[DOMAINS]" >> "$SYSREF_DB"
case "$SYS_CONTROL_PANEL" in
cpanel)
build_domains_cpanel # Extract existing lines 10-153 into this function
;;
plesk)
build_domains_plesk # New function
;;
interworx)
build_domains_interworx # Future enhancement
;;
*)
build_domains_standalone # See Priority 2
;;
esac
echo "" >> "$SYSREF_DB"
}
```
**Task 3: Fix WordPress path parsing** (30 min)
```bash
# Extract username based on panel
case "$SYS_CONTROL_PANEL" in
cpanel)
username=$(echo "$wp_dir" | cut -d'/' -f3) # /home/user/
;;
plesk)
domain=$(echo "$wp_dir" | cut -d'/' -f5) # /var/www/vhosts/domain.com/
username=$(plesk_get_owner "$domain")
;;
interworx)
username=$(echo "$wp_dir" | cut -d'/' -f4) # /chroot/home/user/
;;
*)
username=$(stat -c "%U" "$wp_dir" 2>/dev/null)
;;
esac
```
---
### Priority 2: Standalone Support (6 hours)
**Goal**: Make standalone systems work properly
**Task 1: Create build_domains_standalone()** (2 hours)
```bash
build_domains_standalone() {
local all_domains=$(list_all_domains) # Already scans directories!
for domain in $all_domains; do
local docroot=$(get_domain_docroot "$domain")
local owner=$(get_domain_owner "$domain") # Uses stat
local logdir=$(get_domain_logdir "$domain")
echo "DOMAIN|$domain|$owner|$docroot|$logdir|..." >> "$SYSREF_DB"
done
}
```
**Task 2: Add vhost parsing (optional enhancement)** (4 hours)
- Parse Apache/Nginx configs for ServerName
- Extract DocumentRoot from vhosts
- Get accurate log paths from configs
---
### Priority 3: Wrap cPanel File Checks (15 minutes)
```bash
# Wrap lines 122-153
if [ "$SYS_CONTROL_PANEL" = "cpanel" ]; then
# Check /etc/localdomains
if [ -f "/etc/localdomains" ]; then
# ...
fi
# Check /etc/remotedomains
if [ -f "/etc/remotedomains" ]; then
# ...
fi
fi
```
---
## TESTING PLAN
### Test 1: Plesk Server (FIRST!)
1. Pull latest code
2. Run `bash launcher.sh`
3. Check counts: "X users, Y domains, Z databases"
4. View `.sysref` file - verify domains listed
5. Check if WordPress detected
**Expected**:
- ✅ Domains show up
- ⚠️ Missing docroot/PHP version (until Priority 1 complete)
- ⚠️ WordPress shows wrong username (until Task 3 complete)
### Test 2: After Priority 1
1. Implement `build_domains_plesk()`
2. Test on Plesk server
3. Verify rich domain data in `.sysref`
**Expected**:
- ✅ Domains with docroot, PHP version, log paths
- ✅ WordPress with correct username/domain
### Test 3: Standalone Ubuntu
1. Implement `build_domains_standalone()`
2. Test on standalone server
3. Verify domains detected from directory scanning
---
## FINAL VERDICT
| Platform | Current State | After Priority 1 | After Priority 2 |
|----------|--------------|------------------|------------------|
| cPanel | ✅ Excellent | ✅ Excellent | ✅ Excellent |
| Plesk | ⚠️ Basic | ✅ Excellent | ✅ Excellent |
| InterWorx | ⚠️ Basic | ⚠️ Basic | ✅ Good |
| Standalone | ❌ Broken | ❌ Broken | ✅ Good |
**BOTTOM LINE**:
- Plesk: 1 day work to reach excellence
- Standalone: 2 days work to reach good
- **Total: 3 days to full multi-platform support**
---
## FILES NEEDING CHANGES
| File | Changes Needed | Lines | Priority |
|------|---------------|-------|----------|
| lib/reference-db.sh | Extract build_domains_cpanel() | 244-399 | P1 |
| lib/reference-db.sh | Create build_domains_plesk() | NEW | P1 |
| lib/reference-db.sh | Fix WordPress path parsing | 411, 414 | P1 |
| lib/reference-db.sh | Wrap cPanel file checks | 122-153 | P3 |
| lib/reference-db.sh | Create build_domains_standalone() | NEW | P2 |
---
**VERIFIED**: All findings confirmed by reading actual source code, not grep output.
**RECOMMENDATION**: Start with Plesk enhancements (Priority 1) - only 4 hours of work!
-472
View File
@@ -1,472 +0,0 @@
# Complete Platform Audit Findings
## Date: 2025-12-23
## Auditor: Claude Code (Comprehensive Analysis)
---
## EXECUTIVE SUMMARY
### Critical Issues Found: 8
### Medium Issues Found: 3
### Low Issues Found: 2
**Recommendation**: The plan needs significant updates to address newly discovered issues.
---
## DETAILED FINDINGS
### 1. lib/reference-db.sh - CRITICAL ISSUES
#### Issue #1: build_domains_section() - Lines 255, 265
**Severity**: CRITICAL
**Impact**: Complete failure on non-cPanel systems
**Location**: Lines 255, 265
```bash
local userdata_dir="${SYS_CPANEL_USERDATA_DIR:-/var/cpanel/userdata}/${user}"
```
**Problem**:
- Hardcodes `/var/cpanel/userdata` path
- Primary logic branch assumes cPanel userdata files exist
- 100% cPanel-specific domain configuration parsing
**Affected Platforms**: Plesk, InterWorx, Standalone
**Plan Coverage**: ✅ COVERED in Phase 1
---
#### Issue #2: build_domains_section() - Lines 364-382
**Severity**: CRITICAL
**Impact**: Code will fail on non-cPanel systems
**Location**: Lines 364-396
```bash
# Check /etc/localdomains (cPanel local domains not yet added)
if [ -f "/etc/localdomains" ]; then
# ... reads /etc/localdomains and /etc/trueuserdomains
fi
# Check /etc/remotedomains (cPanel remote MX domains)
if [ -f "/etc/remotedomains" ]; then
# ... reads /etc/remotedomains and /etc/trueuserdomains
fi
```
**Problem**:
- `/etc/localdomains` is cPanel-only (doesn't exist on Plesk/standalone)
- `/etc/remotedomains` is cPanel-only
- `/etc/trueuserdomains` is cPanel-only (lines 370, 390)
- These files are checked OUTSIDE the cPanel conditional block
**Affected Platforms**: Plesk, InterWorx, Standalone
**Plan Coverage**: ❌ **NOT COVERED** - Plan missed this entirely!
**Fix Needed**:
```bash
# Wrap in cPanel-only conditional
if [ "$SYS_CONTROL_PANEL" = "cpanel" ]; then
# Check /etc/localdomains
if [ -f "/etc/localdomains" ]; then
# ...
fi
# Check /etc/remotedomains
if [ -f "/etc/remotedomains" ]; then
# ...
fi
fi
```
---
#### Issue #3: build_wordpress_section() - Lines 411, 414
**Severity**: CRITICAL
**Impact**: WordPress not detected on Plesk/standalone systems
**Location**: Lines 411, 414
```bash
# Line 411: Extract username from path (/home/username/...)
local username=$(echo "$wp_dir" | cut -d'/' -f3)
# Line 414: Try to get domain from path
local path_after_home=$(echo "$wp_dir" | sed "s|^/home/$username/||")
```
**Problem**:
- Hardcodes `/home/` assumption
- Field 3 (`cut -d'/' -f3`) only works for `/home/username/` paths
- Plesk uses `/var/www/vhosts/domain.com/` (username would be "www")
- Standalone could use `/var/www/` or other paths
**Affected Platforms**: Plesk, InterWorx, Standalone
**Plan Coverage**: ✅ COVERED in Phase 2 (but needs more detail)
**Fix Needed**: Panel-specific path parsing logic (see Phase 2 enhancement below)
---
#### Issue #4: build_wordpress_section() - Lines 418-428
**Severity**: MEDIUM
**Impact**: Domain detection fails for non-cPanel WordPress
**Location**: Lines 418-428
```bash
if [[ "$path_after_home" == public_html ]]; then
# This is the primary domain - get it from user info
domain=$(grep "USER|${username}|" "$SYSREF_DB" 2>/dev/null | cut -d'|' -f3 || true)
elif [[ "$path_after_home" =~ ^public_html/(.+) ]]; then
# Could be subdomain or subdirectory
```
**Problem**:
- Assumes `public_html` directory structure (cPanel-specific)
- Plesk uses `httpdocs` or `httpsdocs`
- Standalone uses `public_html`, `html`, or `www`
**Affected Platforms**: Plesk, InterWorx, Standalone
**Plan Coverage**: ✅ COVERED in Phase 2
---
### 2. lib/domain-discovery.sh - CRITICAL GAPS
#### Issue #5: get_domain_docroot() - Missing Plesk Support
**Severity**: CRITICAL
**Impact**: Cannot build domains section on Plesk
**Location**: lib/domain-discovery.sh (function missing Plesk case)
**Problem**:
- `get_domain_docroot()` has NO Plesk case statement
- This function is used by reference-db.sh build_domains_section()
- Without it, domain document roots cannot be determined on Plesk
**Affected Platforms**: Plesk
**Plan Coverage**: ❌ **NOT COVERED** - Plan assumed this function was complete!
**Fix Needed**: Add Plesk case to call `plesk_get_docroot()`
---
#### Issue #6: list_domains_with_docroots() - Missing Plesk Support
**Severity**: LOW
**Impact**: Minor - function rarely used
**Location**: lib/domain-discovery.sh
**Problem**:
- Missing Plesk case statement
- Function is used by some modules but not by launcher
**Affected Platforms**: Plesk
**Plan Coverage**: ❌ NOT COVERED
---
### 3. lib/domain-discovery.sh - MISSING STANDALONE SUPPORT
#### Issue #7: ALL Functions Missing Standalone Cases
**Severity**: CRITICAL
**Impact**: Complete failure on standalone systems
**Location**: Every function in domain-discovery.sh
**Problem**:
All 13 functions have `cpanel`, `plesk`, `interworx` cases, but NO standalone fallback:
- list_all_domains
- get_domain_docroot
- get_domain_logdir
- get_domain_access_log
- get_domain_error_log
- get_all_log_files
- get_domain_owner
- list_all_users
- get_domain_fpm_socket
- get_all_fpm_sockets
- get_domain_databases
- domain_exists
- list_domains_with_docroots
**Current Pattern**:
```bash
case "$SYS_CONTROL_PANEL" in
cpanel) ... ;;
plesk) ... ;;
interworx) ... ;;
*) echo "" ;; # ← Returns empty/fails on standalone!
esac
```
**Affected Platforms**: All standalone (Debian, Ubuntu, AlmaLinux, Rocky, RHEL, CentOS)
**Plan Coverage**: ✅ COVERED in Phase 3 (lib/standalone-helpers.sh creation)
**Fix Needed**: Add `*)` fallback cases that:
- Parse Apache/Nginx vhosts for domains
- Use filesystem scanning for user detection
- Use `stat -c "%U"` for ownership
- Parse vhost configs for document roots and log paths
---
### 4. launcher.sh - MINOR ISSUE
#### Issue #8: Title Says "cPanel" Only
**Severity**: LOW
**Impact**: Cosmetic - misleading branding
**Location**: Line 41
```bash
echo -e "${CYAN} Complete cPanel/Linux Server Administration Suite${NC}"
```
**Problem**:
- Title implies cPanel-only support
- Should say "Multi-Platform" or list all supported platforms
**Affected Platforms**: All
**Plan Coverage**: ❌ NOT COVERED (minor cosmetic fix)
**Fix Needed**:
```bash
echo -e "${CYAN} Complete Linux Server Administration Suite${NC}"
echo -e "${CYAN} Supporting: cPanel, Plesk, InterWorx, Standalone${NC}"
```
---
## PLATFORM SUPPORT MATRIX (Current State)
| Component | cPanel | Plesk | InterWorx | Standalone |
|-----------|--------|-------|-----------|------------|
| **system-detect.sh** | ✅ | ✅ | ✅ | ✅ |
| **domain-discovery.sh** | ✅ | ⚠️ 85% | ⚠️ 75% | ❌ 0% |
| **user-manager.sh** | ✅ | ✅ | ✅ | ⚠️ Partial |
| **reference-db.sh** | ✅ | ❌ | ❌ | ❌ |
| **plesk-helpers.sh** | N/A | ✅ | N/A | N/A |
| **launcher.sh** | ✅ | ❌ | ❌ | ❌ |
Legend:
- ✅ Fully working
- ⚠️ Partially working (% complete)
- ❌ Not working / missing
---
## UPDATED IMPLEMENTATION PRIORITIES
### PHASE 1A: Fix Critical Missing Plesk Support (NEW)
**Priority**: CRITICAL - MUST DO FIRST
1. **Add get_domain_docroot() Plesk case**
- File: lib/domain-discovery.sh
- Add case to call `plesk_get_docroot()`
- Required for build_domains_section() to work
2. **Add list_domains_with_docroots() Plesk case**
- File: lib/domain-discovery.sh
- Low priority but should be included
3. **Wrap cPanel-only domain checks**
- File: lib/reference-db.sh lines 364-396
- Wrap `/etc/localdomains` and `/etc/remotedomains` in cPanel conditional
### PHASE 1B: Create build_domains_plesk() (FROM ORIGINAL PLAN)
**Priority**: CRITICAL
- Create Plesk-specific domain builder function
- Use plesk_list_domains() + plesk_get_*() helpers
- Skip HTTP status checks initially (too slow)
- Test on Plesk server
### PHASE 2A: Fix WordPress Path Parsing (ENHANCED)
**Priority**: HIGH
Need panel-specific path parsing:
```bash
case "$SYS_CONTROL_PANEL" in
cpanel)
# /home/username/public_html
username=$(echo "$wp_dir" | cut -d'/' -f3)
;;
plesk)
# /var/www/vhosts/domain.com/httpdocs
domain=$(echo "$wp_dir" | cut -d'/' -f5)
username=$(plesk_get_owner "$domain")
;;
interworx)
# /chroot/home/user/var/domain.com/html
username=$(echo "$wp_dir" | cut -d'/' -f4)
;;
*)
# Standalone: use stat to get owner
username=$(stat -c "%U" "$wp_dir" 2>/dev/null)
;;
esac
```
### PHASE 3: Create Standalone Helpers (FROM ORIGINAL PLAN)
**Priority**: HIGH
Must implement ALL 13 standalone cases in domain-discovery.sh:
**New file**: lib/standalone-helpers.sh
Functions needed:
```bash
standalone_list_domains() # Parse Apache/Nginx vhosts
standalone_get_docroot() # Extract DocumentRoot/root
standalone_get_logdir() # Extract log directory
standalone_get_access_log() # Extract access_log path
standalone_get_error_log() # Extract error_log path
standalone_get_owner() # Use stat -c "%U"
standalone_list_users() # UID >= 1000 from /etc/passwd
standalone_get_fpm_socket() # Parse PHP-FPM pool configs
standalone_list_fpm_sockets() # Find all pool sockets
standalone_get_databases() # Query MySQL for user DBs
```
**Vhost Parser Requirements**:
- Support Apache: `/etc/apache2/sites-enabled/`, `/etc/httpd/conf.d/`
- Support Nginx: `/etc/nginx/sites-enabled/`, `/etc/nginx/conf.d/`
- Parse `ServerName`, `ServerAlias` (Apache)
- Parse `server_name` (Nginx)
- Parse `DocumentRoot` (Apache) / `root` (Nginx)
- Parse `CustomLog`, `ErrorLog` (Apache) / `access_log`, `error_log` (Nginx)
### PHASE 4: Create build_domains_standalone() (NEW)
**Priority**: HIGH
- Use standalone_list_domains() to get domains
- Use standalone_get_*() helpers for domain info
- Skip HTTP status checks initially
- Test on Ubuntu/Debian standalone
### PHASE 5: Integration Testing (FROM ORIGINAL PLAN)
**Priority**: MEDIUM
Test matrix:
- cPanel (ensure no regression)
- Plesk (test full domain/WP discovery)
- Standalone Debian + Apache
- Standalone Ubuntu + Nginx
- Standalone AlmaLinux + Apache
---
## CRITICAL PATH ANALYSIS
### Blocker for Plesk Support:
1.`get_domain_docroot()` missing Plesk case (NEW DISCOVERY)
2.`/etc/localdomains` check needs cPanel conditional (NEW DISCOVERY)
3.`build_domains_section()` needs Plesk branch
4. ❌ WordPress path parsing hardcodes `/home/`
### Blocker for Standalone Support:
1. ❌ No standalone-helpers.sh library
2. ❌ No vhost parsing logic
3. ❌ domain-discovery.sh has no standalone fallbacks
4. ❌ No `build_domains_standalone()` function
---
## RISK ASSESSMENT
### High Risk Issues:
1. **Missing get_domain_docroot() Plesk case** - Will cause immediate failure
2. **Unconditionalized cPanel file checks** - May cause errors on other platforms
3. **No standalone support** - Complete failure on non-panel systems
### Medium Risk Issues:
1. **WordPress path parsing** - Will miss WordPress installations
2. **Missing list_domains_with_docroots()** - Some modules may fail
### Low Risk Issues:
1. **Launcher title** - Cosmetic only
---
## UPDATED TIMELINE
### Week 1:
- **Days 1-2**: Phase 1A - Fix critical Plesk gaps (NEW)
- **Days 3-4**: Phase 1B - Create build_domains_plesk()
- **Day 5**: Phase 2A - Fix WordPress path parsing
### Week 2:
- **Days 1-3**: Phase 3 - Create standalone-helpers.sh + vhost parser
- **Days 4-5**: Phase 4 - Create build_domains_standalone()
### Week 3:
- **Days 1-3**: Phase 5 - Integration testing all platforms
- **Days 4-5**: Documentation + bug fixes
---
## RECOMMENDATIONS
### Immediate Actions (Before Starting Phase 1):
1. **Fix get_domain_docroot() Plesk case** ← MUST DO FIRST
- Add missing Plesk case statement
- Call `plesk_get_docroot()` function
- Test that it returns correct paths
2. **Wrap cPanel-only file checks** ← SAFETY FIX
- Add `if [ "$SYS_CONTROL_PANEL" = "cpanel" ]` around lines 364-396
- Prevents errors on Plesk/standalone systems
3. **Update CROSS_PLATFORM_PLAN.md** ← DOCUMENTATION
- Add Phase 1A for critical Plesk fixes
- Add missing issue #2, #5, #6, #7, #8
- Update risk assessment
- Revise timeline to include fix phases
### Testing Strategy:
1. **Test EACH fix immediately** on cPanel (ensure no regression)
2. **Test on Plesk** after Phase 1A completion
3. **Don't start Phase 3** until Phases 1A+1B+2A tested on Plesk
4. **Use feature flags** if needed to disable incomplete platforms
---
## FILES REQUIRING CHANGES
| File | Changes | Priority |
|------|---------|----------|
| lib/domain-discovery.sh | Add Plesk cases for 2 functions | CRITICAL |
| lib/reference-db.sh | Wrap cPanel checks (lines 364-396) | CRITICAL |
| lib/reference-db.sh | Refactor build_domains_section() | CRITICAL |
| lib/reference-db.sh | Refactor build_wordpress_section() | HIGH |
| lib/standalone-helpers.sh | Create new file | HIGH |
| lib/domain-discovery.sh | Add 13 standalone fallback cases | HIGH |
| launcher.sh | Update title (line 41) | LOW |
---
## CONCLUSION
**Original Plan Assessment**: ⚠️ INCOMPLETE
The original CROSS_PLATFORM_PLAN.md covered the major refactoring work but **missed 5 critical issues**:
1. Missing `get_domain_docroot()` Plesk case
2. Unconditionalized `/etc/localdomains` and `/etc/remotedomains` checks
3. Missing `list_domains_with_docroots()` Plesk case
4. No standalone fallback cases in domain-discovery.sh
5. Cosmetic launcher title issue
**Updated Plan Required**: YES
The plan must be revised to include Phase 1A (critical Plesk fixes) before starting the original Phase 1.
**Estimated Additional Time**: +2 days
**New Total Timeline**: 2-3 weeks (unchanged, but work redistributed)
---
**Audit Status**: ✅ COMPLETE
**Next Step**: Update CROSS_PLATFORM_PLAN.md with findings
**Approval Needed**: User should review before implementation begins
-313
View File
@@ -1,313 +0,0 @@
# Plesk Control Panel Reference
This document maps Plesk paths and structures for toolkit compatibility.
## Plesk Detection
```bash
# Version file
/usr/local/psa/version
# Admin bin directory
/usr/local/psa/bin/
# CLI tool
/usr/local/psa/bin/plesk
```
## Directory Structure
### User/Domain Home Base
```
/var/www/vhosts/
```
**Structure:**
```
/var/www/vhosts/
├── domain.com/ # Main domain directory
│ ├── httpdocs/ # Public web root
│ ├── httpsdocs/ # SSL web root (if separate)
│ ├── cgi-bin/
│ ├── private/
│ ├── logs/ # (FUTURE: will move here in Plesk Obsidian 18.0.50+)
│ ├── statistics/
│ └── tmp/
├── subdomain.domain.com/ # Subdomain (separate directory)
│ ├── httpdocs/
│ └── ...
└── system/ # System directory (logs, configs)
├── domain.com/
│ ├── logs/ # Current location of access/error logs
│ ├── conf/ # Apache/Nginx configs
│ ├── etc/ # PHP.ini and other configs
│ └── php-fpm.sock # PHP-FPM socket
└── subdomain.domain.com/
└── ...
```
### Log Files
**Current Structure (Plesk 17.x - 18.0.49):**
```
/var/www/vhosts/system/DOMAIN/logs/
├── access_log # HTTP access log
├── access_ssl_log # HTTPS access log
├── error_log # Error log (both HTTP/HTTPS)
├── proxy_access_log # Nginx proxy access (if applicable)
├── proxy_access_ssl_log # Nginx proxy HTTPS access
└── proxy_error_log # Nginx proxy errors
```
**Future Structure (Plesk Obsidian 18.0.50+):**
```
/var/www/vhosts/DOMAIN/logs/
├── access_log
├── access_ssl_log
├── error_log
└── ...
```
### Configuration Files
**Per-Domain Configs:**
```
/var/www/vhosts/system/DOMAIN/conf/
├── httpd.conf # Apache vhost config
├── nginx.conf # Nginx config
├── vhost.conf # Custom Apache directives
├── vhost_ssl.conf # Custom SSL directives
└── php.ini # In ../etc/php.ini
```
**PHP Configuration:**
```
/var/www/vhosts/system/DOMAIN/etc/
└── php.ini # Domain-specific PHP settings
```
### PHP-FPM
**Pool Sockets:**
```
/var/www/vhosts/system/DOMAIN/php-fpm.sock
```
**System PHP-FPM:**
```
/opt/plesk/php/X.Y/ # Plesk-managed PHP versions
/usr/bin/php # System default PHP
```
## Plesk CLI Commands
### Domain Management
```bash
# List all domains
plesk bin domain --list
# Get domain info
plesk bin domain --info DOMAIN
# Get domain document root
plesk bin domain --info DOMAIN | grep "www root" | awk '{print $NF}'
```
### User/Subscription Management
```bash
# List all subscriptions
plesk bin subscription --list
# Get subscription info
plesk bin subscription --info DOMAIN
# List users
plesk bin user --list
```
### Database Management
```bash
# List databases
plesk bin database --list
# List databases for domain
plesk bin database --list -domain DOMAIN
```
### Log Files
```bash
# Get log file path for domain
# Current: /var/www/vhosts/system/DOMAIN/logs/
# Future: /var/www/vhosts/DOMAIN/logs/
```
### PHP Version Detection
```bash
# List PHP handlers
plesk bin php_handler --list
# Get domain PHP version
plesk bin site --info DOMAIN | grep "PHP version"
```
### Service Management
```bash
# Apache
plesk bin service_node --start httpd
plesk bin service_node --stop httpd
plesk bin service_node --restart httpd
# Nginx
plesk bin service_node --start nginx
plesk bin service_node --stop nginx
# PHP-FPM
plesk bin service_node --restart plesk-php*-fpm
```
## User/Domain Discovery
### Finding All Domains
```bash
# Method 1: Using Plesk CLI
plesk bin domain --list
# Method 2: Directory scan
ls -1d /var/www/vhosts/*/ | grep -v "system\|chroot\|.skel\|default" | xargs -I{} basename {}
# Method 3: From system directory
ls -1 /var/www/vhosts/system/ | grep -v "^[0-9]"
```
### Finding Domain Owner
```bash
# Get subscription owner
plesk bin subscription --info DOMAIN | grep "Owner's login"
```
### Finding Document Roots
```bash
# Main domain
/var/www/vhosts/DOMAIN/httpdocs
# Subdomains
/var/www/vhosts/SUBDOMAIN.DOMAIN/httpdocs
# Via CLI
plesk bin domain --info DOMAIN | grep "www root"
```
## PHP Detection
### Plesk-Managed PHP Versions
```bash
# Location
/opt/plesk/php/*/bin/php
# List all versions
ls -1d /opt/plesk/php/*/bin/php 2>/dev/null
# Get versions
for php in /opt/plesk/php/*/bin/php; do
$php -v | head -1
done
```
### System PHP
```bash
/usr/bin/php
php -v
```
## Database Discovery
### MySQL/MariaDB
```bash
# Plesk stores DB mappings in:
/var/lib/psa/dumps/
# Get databases via CLI
plesk bin database --list
# Database naming convention
DOMAIN_DBNAME (underscores replace dots)
```
## Subdomain Handling
**Important:** Plesk creates separate directories for subdomains
```bash
# Main domain
/var/www/vhosts/domain.com/httpdocs
# Subdomain gets its own directory
/var/www/vhosts/sub.domain.com/httpdocs
# Logs
/var/www/vhosts/system/sub.domain.com/logs/
```
## Email
### Mailboxes
```bash
# Location
/var/qmail/mailnames/DOMAIN/USERNAME/Maildir/
```
### Mail Logs
```bash
/var/log/maillog
```
## Important Differences from cPanel
1. **No /home directory structure** - Uses /var/www/vhosts
2. **Subdomains are separate** - Not under main domain's directory
3. **Logs in system/** - Not in domain directory (until Plesk 18.0.50+)
4. **PHP-FPM per domain** - Socket in system/DOMAIN/
5. **No ea-php** - Uses /opt/plesk/php/X.Y/
6. **CLI is different** - Uses `plesk bin` not WHM API
7. **User != Domain** - Subscription owners, not cPanel users
## Toolkit Compatibility Requirements
### Path Variables
```bash
SYS_USER_HOME_BASE="/var/www/vhosts"
SYS_LOG_DIR="/var/www/vhosts/system"
```
### Domain Enumeration
Must use:
1. `plesk bin domain --list`
2. Directory scan excluding: system, chroot, .skel, default, fs
### Log File Discovery
```bash
# Current Plesk
find /var/www/vhosts/system/*/logs/ -name "access*log" -o -name "error_log"
# Future Plesk (18.0.50+)
find /var/www/vhosts/*/logs/ -name "access*log" -o -name "error_log"
```
### PHP-FPM Pool Discovery
```bash
# Find all PHP-FPM pools
find /var/www/vhosts/system/*/php-fpm.sock -type s 2>/dev/null
# Or check config
grep -r "listen = " /var/www/vhosts/system/*/etc/ 2>/dev/null
```
## Version-Specific Notes
### Plesk Obsidian (18.0.x)
- Version 18.0.50+ moves logs from system/DOMAIN/logs/ to DOMAIN/logs/
- Toolkit should check both locations for compatibility
### Plesk Onyx (17.x)
- Logs in system/DOMAIN/logs/
- Stable structure
-322
View File
@@ -1,322 +0,0 @@
# Plesk Support Implementation Summary
## Overview
Comprehensive Plesk control panel support has been added to the Server Toolkit. The toolkit now fully supports cPanel, Plesk, InterWorx, and standalone server configurations.
## Files Added
### 1. `/root/server-toolkit/PLESK_REFERENCE.md`
Complete Plesk paths and structure reference documentation including:
- Directory structure mapping
- Log file locations (both current and future versions)
- PHP-FPM pool locations
- Configuration file paths
- CLI command reference
- Key differences from cPanel
### 2. `/root/server-toolkit/lib/plesk-helpers.sh`
Plesk-specific helper functions library with 30+ functions:
**Domain Discovery:**
- `plesk_list_domains()` - List all domains
- `plesk_get_docroot()` - Get document root
- `plesk_get_logdir()` - Get log directory (version-aware)
- `plesk_get_all_logdirs()` - Get all domain log directories
- `plesk_get_access_log()` - Get access log path
- `plesk_get_error_log()` - Get error log path
- `plesk_domain_exists()` - Check if domain exists
**User/Subscription Management:**
- `plesk_list_subscriptions()` - List all subscriptions
- `plesk_get_owner()` - Get domain owner
**Database Discovery:**
- `plesk_list_databases()` - List all databases
- `plesk_list_domain_databases()` - List databases for domain
**PHP Detection:**
- `plesk_list_php_handlers()` - List available PHP handlers
- `plesk_get_domain_php()` - Get PHP version for domain
- `plesk_detect_php_versions()` - Detect all Plesk PHP versions
**PHP-FPM Pools:**
- `plesk_list_fpm_sockets()` - List all FPM sockets
- `plesk_get_fpm_socket()` - Get FPM socket for domain
**Configuration Files:**
- `plesk_get_confdir()` - Get config directory
- `plesk_get_httpd_conf()` - Get Apache config
- `plesk_get_nginx_conf()` - Get Nginx config
- `plesk_get_php_ini()` - Get PHP config
**Mail Functions:**
- `plesk_get_mailbox_dir()` - Get mailbox directory
- `plesk_list_mailboxes()` - List mailboxes for domain
**Service Management:**
- `plesk_restart_apache()` - Restart Apache
- `plesk_restart_nginx()` - Restart Nginx
- `plesk_restart_phpfpm()` - Restart PHP-FPM
**Utilities:**
- `plesk_get_version()` - Get Plesk version
- `plesk_is_new_log_structure()` - Check if Plesk 18.0.50+
- `plesk_list_domains_with_docroots()` - Get domains with docroots as TSV
### 3. `/root/server-toolkit/lib/domain-discovery.sh`
Unified control panel abstraction layer providing consistent interface across all panels:
**Universal Functions (Work on All Panels):**
- `list_all_domains()` - List all domains
- `get_domain_docroot()` - Get document root
- `get_domain_logdir()` - Get log directory
- `get_domain_access_log()` - Get access log path
- `get_domain_error_log()` - Get error log path
- `get_all_log_files()` - Get all log files
- `get_domain_owner()` - Get domain owner
- `list_all_users()` - List all users
- `get_domain_fpm_socket()` - Get PHP-FPM socket
- `get_all_fpm_sockets()` - Get all FPM sockets
- `get_domain_databases()` - Get domain databases
- `domain_exists()` - Check if domain exists
- `list_domains_with_docroots()` - Get domains with docroots
**How It Works:**
- Each function detects `$SYS_CONTROL_PANEL` and calls appropriate panel-specific code
- Provides consistent API regardless of control panel
- Includes fallback methods when panel CLI unavailable
## Files Modified
### 1. `/root/server-toolkit/lib/system-detect.sh`
**Plesk Detection Enhancement (lines 56-77):**
```bash
# Plesk
if [ -f "/usr/local/psa/version" ]; then
SYS_CONTROL_PANEL="plesk"
SYS_CONTROL_PANEL_VERSION=$(cat /usr/local/psa/version | head -1)
# Plesk uses /var/www/vhosts as base
SYS_USER_HOME_BASE="/var/www/vhosts"
# Log directory depends on Plesk version
# Plesk 18.0.50+ uses /var/www/vhosts/DOMAIN/logs
# Plesk <18.0.50 uses /var/www/vhosts/system/DOMAIN/logs
# Set marker path - tools will use plesk_get_logdir() for actual path
SYS_LOG_DIR="/var/www/vhosts/system"
# Source Plesk helpers for advanced functionality
if [ -f "$LIB_DIR/plesk-helpers.sh" ]; then
source "$LIB_DIR/plesk-helpers.sh"
fi
print_success "Detected Plesk v${SYS_CONTROL_PANEL_VERSION}"
return 0
fi
```
**PHP Detection Enhancement (lines 253-261):**
```bash
# Check Plesk PHP versions (/opt/plesk/php/)
if [ "$SYS_CONTROL_PANEL" = "plesk" ]; then
for php_path in /opt/plesk/php/*/bin/php; do
if [ -x "$php_path" ]; then
local full_version=$($php_path -v 2>/dev/null | grep -oP '^PHP \K[\d.]+' | head -1)
[ -n "$full_version" ] && SYS_PHP_VERSIONS+=("$full_version")
fi
done
fi
```
## Key Plesk Architecture Differences
### 1. Directory Structure
- **cPanel:** `/home/USER/public_html/`
- **Plesk:** `/var/www/vhosts/DOMAIN/httpdocs/`
### 2. Log Files
- **cPanel:** `/var/log/apache2/domlogs/DOMAIN`
- **Plesk (current):** `/var/www/vhosts/system/DOMAIN/logs/`
- **Plesk (18.0.50+):** `/var/www/vhosts/DOMAIN/logs/`
### 3. Subdomain Handling
- **cPanel:** Subdomains under main domain: `/home/USER/public_html/subdomain/`
- **Plesk:** Separate directories: `/var/www/vhosts/sub.domain.com/httpdocs/`
### 4. PHP Versions
- **cPanel:** `/opt/cpanel/ea-phpXX/root/usr/bin/php`
- **Plesk:** `/opt/plesk/php/X.Y/bin/php`
### 5. PHP-FPM Pools
- **cPanel:** `/opt/cpanel/ea-phpXX/root/usr/var/run/*.sock`
- **Plesk:** `/var/www/vhosts/system/DOMAIN/php-fpm.sock`
### 6. Configuration Files
- **cPanel:** `/var/cpanel/userdata/USER/DOMAIN`
- **Plesk:** `/var/www/vhosts/system/DOMAIN/conf/`
## Version Compatibility
### Plesk Obsidian 17.x
- Logs in `/var/www/vhosts/system/DOMAIN/logs/`
- Fully supported
### Plesk Obsidian 18.0.0 - 18.0.49
- Logs in `/var/www/vhosts/system/DOMAIN/logs/`
- Fully supported
### Plesk Obsidian 18.0.50+
- Logs moved to `/var/www/vhosts/DOMAIN/logs/`
- Auto-detected via `plesk_is_new_log_structure()`
- Functions check both locations
## Usage Examples
### Using Plesk-Specific Functions
```bash
#!/bin/bash
source /root/server-toolkit/lib/system-detect.sh
source /root/server-toolkit/lib/plesk-helpers.sh
# List all domains
for domain in $(plesk_list_domains); do
echo "Domain: $domain"
# Get paths
docroot=$(plesk_get_docroot "$domain")
logdir=$(plesk_get_logdir "$domain")
echo " Document root: $docroot"
echo " Log directory: $logdir"
done
```
### Using Unified Discovery Functions
```bash
#!/bin/bash
source /root/server-toolkit/lib/system-detect.sh
source /root/server-toolkit/lib/domain-discovery.sh
# Works on ANY control panel (cPanel, Plesk, InterWorx, or standalone)
for domain in $(list_all_domains); do
echo "Domain: $domain"
docroot=$(get_domain_docroot "$domain")
access_log=$(get_domain_access_log "$domain")
owner=$(get_domain_owner "$domain")
echo " Owner: $owner"
echo " Document root: $docroot"
echo " Access log: $access_log"
done
```
## Migration Guide for Existing Modules
### OLD: cPanel-Specific Code
```bash
# Only works on cPanel
for domain in $(awk -F': ' '{print $1}' /etc/userdomains); do
user=$(grep "^${domain}:" /etc/userdomains | awk -F': ' '{print $2}')
docroot="/home/$user/public_html"
# ...
done
```
### NEW: Panel-Agnostic Code
```bash
# Works on all panels
source "$LIB_DIR/domain-discovery.sh"
for domain in $(list_all_domains); do
owner=$(get_domain_owner "$domain")
docroot=$(get_domain_docroot "$domain")
# ...
done
```
## Testing
### Test on Plesk System
```bash
# Run test script
bash /root/test-plesk-discovery.sh
```
### Verify Detection
```bash
source /root/server-toolkit/lib/system-detect.sh
echo "Control Panel: $SYS_CONTROL_PANEL"
echo "Version: $SYS_CONTROL_PANEL_VERSION"
echo "User Home Base: $SYS_USER_HOME_BASE"
echo "Log Directory: $SYS_LOG_DIR"
echo "PHP Versions: ${SYS_PHP_VERSIONS[*]}"
```
## Fallback Mechanisms
All Plesk functions include fallback methods when Plesk CLI is unavailable:
1. **Domain Discovery:**
- Primary: `plesk bin domain --list`
- Fallback: Directory scan of `/var/www/vhosts/`
2. **Document Roots:**
- Primary: `plesk bin domain --info DOMAIN`
- Fallback: Standard path `/var/www/vhosts/DOMAIN/httpdocs`
3. **PHP Versions:**
- Primary: `plesk bin php_handler --list`
- Fallback: Scan `/opt/plesk/php/*/bin/php`
4. **Databases:**
- Primary: `plesk bin database --list`
- Fallback: Direct MySQL query with naming conventions
## Future Module Updates
The following modules should be updated to use the unified discovery functions:
1.**lib/system-detect.sh** - Updated
2.**modules/security/live-attack-monitor.sh** - Needs update
3.**modules/security/bot-analyzer.sh** - Needs update
4.**modules/security/malware-scanner.sh** - Needs update
5.**modules/website/** - Needs update for log discovery
6.**modules/performance/php-optimizer.sh** - Needs update for PHP-FPM
7.**lib/mysql-analyzer.sh** - Needs update for database discovery
8.**lib/user-manager.sh** - Needs update for user enumeration
## Status
**Core Infrastructure Complete:**
- Plesk detection and path mapping
- 30+ Plesk helper functions
- Unified discovery abstraction layer
- Comprehensive documentation
- Version compatibility handling
- Fallback mechanisms
**Next Steps:**
1. Test on actual Plesk server
2. Update existing modules to use unified discovery
3. Add Plesk-specific features where beneficial
## Testing Checklist
When testing on Plesk server:
- [ ] Domain enumeration returns all domains
- [ ] Document roots are correctly identified
- [ ] Log files are found (both access and error)
- [ ] PHP versions are detected from /opt/plesk/php/
- [ ] PHP-FPM sockets are located
- [ ] Configuration files are found
- [ ] Owner/user mapping works
- [ ] Database discovery functions
- [ ] Version detection is accurate
- [ ] Log structure detection (old vs new) works
- [ ] All modules can find domains and logs
-5
View File
@@ -1,5 +0,0 @@
Backup Created: Fri Dec 12 11:14:52 PM EST 2025
Username: pickledperil
Domain: pickledperil.com
Backup Name: test_231452
/opt/cpanel/ea-php81/root/etc/php-fpm.d/pickledperil.com.conf → /root/server-toolkit/backups/php/test_231452/opt/cpanel/ea-php81/root/etc/php-fpm.d/pickledperil.com.conf
@@ -1,33 +0,0 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; cPanel FPM Configuration ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; NOTICE This file is generated. Please use our WHM User Interface
; to set these values.
[pickledperil_com]
catch_workers_output = yes
chdir = /home/pickledperil
group = "pickledperil"
listen = /opt/cpanel/ea-php81/root/usr/var/run/php-fpm/95f116b048f081d0b9879b09b8608f7d77c6ddd8.sock
listen.group = "nobody"
listen.mode = 0660
listen.owner = "pickledperil"
php_admin_flag[allow_url_fopen] = on
php_admin_flag[log_errors] = on
php_admin_value[disable_functions] = exec,passthru,shell_exec,system
php_admin_value[doc_root] = "/home/pickledperil/public_html"
php_admin_value[error_log] = /home/pickledperil/logs/pickledperil_com.php.error.log
php_admin_value[short_open_tag] = on
php_value[error_reporting] = E_ALL & ~E_NOTICE
ping.path = /ping
pm = ondemand
pm.max_children = 5
pm.max_requests = 20
pm.max_spare_servers = 5
pm.min_spare_servers = 1
pm.process_idle_timeout = 10
pm.start_servers = 0
pm.status_path = /status
security.limit_extensions = .phtml .php .php3 .php4 .php5 .php6 .php7 .php8
user = "pickledperil"
@@ -1,4 +0,0 @@
Backup Created: Fri Dec 12 05:17:28 PM EST 2025
Username: pickledperil
Domain: pickledperil.com
Backup Name: test_backup_20251212_171728
-483
View File
@@ -1,483 +0,0 @@
# Complete PHP Configuration File Locations - All Control Panels
## Understanding PHP Configuration Priority
PHP configuration is applied in a **hierarchical cascade**. Settings in higher-priority files **override** settings in lower-priority files.
### Priority Order (Highest to Lowest)
```
PRIORITY 1 (HIGHEST): Per-Directory Configuration
├─ .user.ini (PHP-FPM only, per-directory)
├─ .htaccess with php_value/php_flag (Apache + mod_php ONLY, NOT PHP-FPM!)
└─ ini_set() in PHP code (runtime only)
PRIORITY 2: User-Specific Configuration
├─ ~/public_html/php.ini (some control panels)
├─ ~/.php/X.Y/php.ini (per PHP version)
├─ ~/etc/phpX.Y/php.ini (InterWorx style)
└─ ~/php.ini (legacy)
PRIORITY 3: Pool-Specific Configuration
├─ /opt/cpanel/ea-phpXY/root/etc/php.ini (cPanel EA-PHP)
├─ /opt/alt/phpXY/etc/php.ini (CloudLinux Alt-PHP)
├─ Additional .ini files loaded alphabetically:
│ ├─ /opt/cpanel/ea-phpXY/root/etc/php.d/*.ini
│ └─ Loaded in alphabetical order (00-*, 10-*, 20-*, etc.)
└─ scan_dir configured locations
PRIORITY 4 (LOWEST): System-Wide Configuration
└─ /etc/php.ini (global default, rarely used with control panels)
```
## Complete File Location Map by Control Panel
### cPanel with EA-PHP (Most Common)
#### 1. Per-Directory (.user.ini) - **PRIORITY 1**
```bash
# Location pattern
/home/$username/public_html/.user.ini
/home/$username/public_html/subdirectory/.user.ini
/home/$username/public_html/app/.user.ini
# Applies to
- That directory and all subdirectories
- Only works with PHP-FPM (not mod_php)
- Reloaded every user_ini.cache_ttl seconds (default 300)
# Example content
memory_limit = 512M
upload_max_filesize = 100M
post_max_size = 150M
max_execution_time = 120
# Find all .user.ini files for a user
find /home/$username -name ".user.ini" -type f
# Common locations
/home/$username/public_html/.user.ini
/home/$username/public_html/wp-content/.user.ini
/home/$username/public_html/app/upload/.user.ini
```
#### 2. .htaccess with PHP directives - **PRIORITY 1** (mod_php ONLY!)
```bash
# Location
/home/$username/public_html/.htaccess
# IMPORTANT: Only works with Apache mod_php
# Does NOT work with PHP-FPM!
# cPanel typically uses PHP-FPM, so .htaccess php_value is IGNORED
# Example content (if mod_php is used)
php_value memory_limit 256M
php_value upload_max_filesize 64M
php_flag display_errors Off
# Find .htaccess with PHP directives
find /home/$username/public_html -name ".htaccess" -exec grep -l "php_value\|php_flag" {} \;
```
#### 3. User Home Directory Configs - **PRIORITY 2**
```bash
# cPanel creates user-specific php.ini in various locations:
# A. PHP version-specific in home
/home/$username/.php/8.2/php.ini
/home/$username/.php/8.1/php.ini
/home/$username/.php/8.0/php.ini
# B. Legacy home php.ini
/home/$username/php.ini
# C. In etc subdirectory
/home/$username/etc/php.ini
/home/$username/etc/php/8.2/php.ini
# D. In public_html (some configurations)
/home/$username/public_html/php.ini
# Find all home directory php.ini files
find /home/$username -maxdepth 3 -name "php.ini" -type f
find /home/$username/.php -name "php.ini" -type f 2>/dev/null
```
#### 4. MultiPHP INI Editor Files - **PRIORITY 2**
```bash
# cPanel's MultiPHP INI Editor creates user-specific overrides here:
/var/cpanel/userdata/$username/php-fpm.d/$domain.conf
/home/$username/.php/8.2/php.ini
# These override pool defaults but are overridden by .user.ini
```
#### 5. EA-PHP Pool Configuration - **PRIORITY 3**
```bash
# Main php.ini for each EA-PHP version
/opt/cpanel/ea-php80/root/etc/php.ini
/opt/cpanel/ea-php81/root/etc/php.ini
/opt/cpanel/ea-php82/root/etc/php.ini
/opt/cpanel/ea-php83/root/etc/php.ini
# Additional .ini files (loaded alphabetically)
/opt/cpanel/ea-php82/root/etc/php.d/00-ioncube.ini
/opt/cpanel/ea-php82/root/etc/php.d/10-opcache.ini
/opt/cpanel/ea-php82/root/etc/php.d/20-gd.ini
/opt/cpanel/ea-php82/root/etc/php.d/30-mysqli.ini
# Find all EA-PHP installations
find /opt/cpanel -maxdepth 1 -type d -name "ea-php*"
# Find all php.ini files
find /opt/cpanel/ea-php* -name "php.ini"
# Find all additional .ini files
find /opt/cpanel/ea-php*/root/etc/php.d/ -name "*.ini" | sort
```
#### 6. PHP-FPM Pool Configs (Not php.ini but affects PHP)
```bash
# Per-user FPM pool config (process manager settings)
/opt/cpanel/ea-php82/root/etc/php-fpm.d/$username.conf
# Contains: pm, pm.max_children, pm.start_servers, etc.
# Not php.ini settings, but critical for performance!
```
### CloudLinux with Alt-PHP
#### Alt-PHP Configuration Locations
```bash
# Main php.ini for each Alt-PHP version
/opt/alt/php80/etc/php.ini
/opt/alt/php81/etc/php.ini
/opt/alt/php82/etc/php.ini
# Additional .ini files
/opt/alt/php82/etc/php.d.all/*.ini
# Per-user overrides (if configured)
/home/$username/.cl.php/alt-php82/php.ini
# Find all Alt-PHP versions
ls -d /opt/alt/php*/
# Find all Alt-PHP ini files
find /opt/alt/php* -name "php.ini"
```
### Plesk
#### Plesk PHP Configuration Hierarchy
```bash
# 1. Per-directory .user.ini - PRIORITY 1
/var/www/vhosts/$domain/httpdocs/.user.ini
/var/www/vhosts/$domain/httpdocs/subdirectory/.user.ini
# 2. Domain-specific php.ini - PRIORITY 2
/var/www/vhosts/system/$domain/etc/php.ini
# 3. Pool-specific php.ini - PRIORITY 3
/etc/php-fpm.d/plesk-php82-fpm/php.ini
# 4. PHP version php.ini - PRIORITY 3
/opt/plesk/php/8.2/etc/php.ini
/opt/plesk/php/8.1/etc/php.ini
# 5. Additional .ini files
/opt/plesk/php/8.2/etc/php.d/*.ini
# 6. System-wide - PRIORITY 4
/etc/php.ini
# Find domain php.ini files
find /var/www/vhosts/system -name "php.ini"
# Find all Plesk PHP versions
ls -d /opt/plesk/php/*/
```
### InterWorx
#### InterWorx PHP Configuration
```bash
# 1. Per-directory .user.ini - PRIORITY 1
/home/$username/var/$domain/html/.user.ini
# 2. Domain-specific php.ini - PRIORITY 2
/home/$username/var/$domain/etc/php.ini
# 3. User etc directory
/home/$username/etc/php82/php.ini
# 4. PHP version php.ini - PRIORITY 3
/etc/php82/php.ini
/etc/php81/php.ini
# 5. System-wide - PRIORITY 4
/etc/php.ini
# Find InterWorx domain configs
find /home/*/var/*/etc -name "php.ini"
# Find user php configs
find /home/*/etc/php* -name "php.ini"
```
### DirectAdmin
#### DirectAdmin Configuration
```bash
# 1. Per-directory .user.ini - PRIORITY 1
/home/$username/domains/$domain/public_html/.user.ini
# 2. Domain php.ini - PRIORITY 2
/usr/local/directadmin/data/users/$username/php/domains/$domain.ini
# 3. User default php.ini
/usr/local/directadmin/data/users/$username/php/php.ini
# 4. PHP version php.ini - PRIORITY 3
/usr/local/php82/lib/php.ini
# Find DirectAdmin configs
find /usr/local/directadmin/data/users -name "php.ini"
find /usr/local/directadmin/data/users -name "*.ini"
```
### No Control Panel (Standalone)
#### Standard PHP Locations
```bash
# 1. Per-directory .user.ini - PRIORITY 1
/var/www/html/.user.ini
/var/www/domain.com/.user.ini
# 2. Pool-specific (if using PHP-FPM)
/etc/php/8.2/fpm/php.ini
/etc/php-fpm.d/www.conf
# 3. CLI php.ini (different from FPM!)
/etc/php/8.2/cli/php.ini
# 4. Additional .ini files
/etc/php/8.2/mods-available/*.ini
/etc/php/8.2/conf.d/*.ini
# 5. System-wide
/etc/php.ini
/usr/local/lib/php.ini
```
## Detection Strategy - Universal Function
```bash
find_all_php_configs() {
local username="$1"
local domain="$2"
local php_version="$3" # e.g., "82" or "8.2"
declare -a config_files
declare -A config_priority
echo "=== Finding ALL PHP configs affecting: $domain (user: $username) ==="
echo ""
# PRIORITY 1: Per-Directory .user.ini
echo "PRIORITY 1: Per-Directory Configs"
while IFS= read -r file; do
if [ -f "$file" ]; then
config_files+=("$file")
config_priority["$file"]=1
echo " [P1] $file"
fi
done < <(find "/home/$username" -name ".user.ini" 2>/dev/null)
# Check .htaccess (only relevant for mod_php)
while IFS= read -r file; do
if grep -q "php_value\|php_flag" "$file" 2>/dev/null; then
config_files+=("$file")
config_priority["$file"]=1
echo " [P1] $file (mod_php only - likely IGNORED on PHP-FPM!)"
fi
done < <(find "/home/$username/public_html" -name ".htaccess" 2>/dev/null)
echo ""
echo "PRIORITY 2: User-Specific Configs"
# User home directory configs (various patterns)
local user_configs=(
"/home/$username/php.ini"
"/home/$username/public_html/php.ini"
"/home/$username/.php/$php_version/php.ini"
"/home/$username/.php/${php_version:0:1}.${php_version:1}/php.ini"
"/home/$username/etc/php.ini"
"/home/$username/etc/php/$php_version/php.ini"
)
for config in "${user_configs[@]}"; do
if [ -f "$config" ]; then
config_files+=("$config")
config_priority["$config"]=2
echo " [P2] $config"
fi
done
# Plesk domain-specific
if [ -f "/var/www/vhosts/system/$domain/etc/php.ini" ]; then
config_files+=("/var/www/vhosts/system/$domain/etc/php.ini")
config_priority["/var/www/vhosts/system/$domain/etc/php.ini"]=2
echo " [P2] /var/www/vhosts/system/$domain/etc/php.ini"
fi
# InterWorx domain-specific
if [ -f "/home/$username/var/$domain/etc/php.ini" ]; then
config_files+=("/home/$username/var/$domain/etc/php.ini")
config_priority["/home/$username/var/$domain/etc/php.ini"]=2
echo " [P2] /home/$username/var/$domain/etc/php.ini"
fi
echo ""
echo "PRIORITY 3: Pool/Version-Specific Configs"
# cPanel EA-PHP
local cpanel_php_ini="/opt/cpanel/ea-php${php_version}/root/etc/php.ini"
if [ -f "$cpanel_php_ini" ]; then
config_files+=("$cpanel_php_ini")
config_priority["$cpanel_php_ini"]=3
echo " [P3] $cpanel_php_ini"
# Additional .ini files
if [ -d "/opt/cpanel/ea-php${php_version}/root/etc/php.d" ]; then
while IFS= read -r file; do
config_files+=("$file")
config_priority["$file"]=3
echo " [P3] $file"
done < <(find "/opt/cpanel/ea-php${php_version}/root/etc/php.d" -name "*.ini" | sort)
fi
fi
# CloudLinux Alt-PHP
local alt_php_ini="/opt/alt/php${php_version}/etc/php.ini"
if [ -f "$alt_php_ini" ]; then
config_files+=("$alt_php_ini")
config_priority["$alt_php_ini"]=3
echo " [P3] $alt_php_ini"
fi
# Plesk
local plesk_php_ini="/opt/plesk/php/${php_version:0:1}.${php_version:1}/etc/php.ini"
if [ -f "$plesk_php_ini" ]; then
config_files+=("$plesk_php_ini")
config_priority["$plesk_php_ini"]=3
echo " [P3] $plesk_php_ini"
fi
echo ""
echo "PRIORITY 4: System-Wide Default"
if [ -f "/etc/php.ini" ]; then
config_files+=("/etc/php.ini")
config_priority["/etc/php.ini"]=4
echo " [P4] /etc/php.ini"
fi
echo ""
echo "=== Total config files found: ${#config_files[@]} ==="
# Return the array
printf '%s\n' "${config_files[@]}"
}
```
## How to Determine Effective Setting
### Method 1: Query PHP Directly (MOST ACCURATE!)
```bash
# Get effective value for a specific setting
get_effective_php_setting() {
local username="$1"
local setting="$2" # e.g., "memory_limit"
# Run as user to get their effective settings
su -s /bin/bash "$username" -c "php -r 'echo ini_get(\"$setting\");'"
}
# Example usage
memory_limit=$(get_effective_php_setting "examplec" "memory_limit")
echo "Effective memory_limit: $memory_limit"
# Get ALL effective settings
su -s /bin/bash "$username" -c "php -r 'print_r(ini_get_all());'" > /tmp/effective_php_settings.txt
```
### Method 2: Parse Config Hierarchy
```bash
# Parse configs in priority order and track overrides
get_setting_from_configs() {
local setting="$1"
local value=""
# Parse in REVERSE priority (lowest to highest)
# So higher priority files override
# Priority 4: System
value=$(grep "^$setting" /etc/php.ini | cut -d'=' -f2 | tr -d ' ')
# Priority 3: Pool
pool_value=$(grep "^$setting" /opt/cpanel/ea-php82/root/etc/php.ini | cut -d'=' -f2 | tr -d ' ')
[ -n "$pool_value" ] && value="$pool_value"
# Priority 2: User
user_value=$(grep "^$setting" /home/$username/.php/8.2/php.ini | cut -d'=' -f2 | tr -d ' ')
[ -n "$user_value" ] && value="$user_value"
# Priority 1: .user.ini
user_ini_value=$(grep "^$setting" /home/$username/public_html/.user.ini | cut -d'=' -f2 | tr -d ' ')
[ -n "$user_ini_value" ] && value="$user_ini_value"
echo "$value"
}
```
## Quick Reference Commands
```bash
# Find ALL php.ini files on system
find / -name "php.ini" -type f 2>/dev/null
# Find ALL .user.ini files
find /home -name ".user.ini" -type f 2>/dev/null
# Find .htaccess with PHP directives
find /home -name ".htaccess" -exec grep -l "php_value\|php_flag" {} \; 2>/dev/null
# Get effective settings for a domain (via web)
curl -s "http://domain.com/info.php" | grep -A1 "memory_limit"
# Get effective settings via CLI
php -i | grep "memory_limit"
php -r "echo ini_get('memory_limit');"
# List all loaded .ini files
php --ini
# Get configuration file path
php -r "echo php_ini_loaded_file();"
# Get scanned .ini directory
php -r "echo php_ini_scanned_files();"
```
## Key Takeaways for Optimizer
1. **Always check .user.ini first** - It overrides everything!
2. **Per-domain/user configs vary by control panel** - Need detection logic
3. **.htaccess php_value only works with mod_php** - Usually ignored on modern setups
4. **Query PHP directly for accurate effective values** - Don't just parse files
5. **Check loaded files via php --ini** - Shows what's actually being used
6. **Multiple .ini files can affect same setting** - Last one wins (in priority order)
This complete map ensures the optimizer will find ALL configuration affecting a domain!
-469
View File
@@ -1,469 +0,0 @@
# Comprehensive PHP Metrics Tracking Guide
## PHP Configuration Hierarchy & Detection
### Configuration File Priority (Highest to Lowest)
Understanding which config takes effect is critical for accurate optimization.
```
1. .user.ini (per-directory, PHP-FPM only)
Location: /home/user/public_html/.user.ini
Scope: Specific directory and subdirectories
Reloads: Automatically every user_ini.cache_ttl seconds (default 300)
2. .htaccess (Apache with mod_php only, NOT PHP-FPM!)
Location: /home/user/public_html/.htaccess
Scope: Directory-specific
Note: Does NOT work with PHP-FPM!
3. php.ini (per-pool, cPanel EA-PHP)
Location: /opt/cpanel/ea-php*/root/etc/php.ini
Scope: All domains using that PHP version
4. Additional .ini files (per-pool)
Location: /opt/cpanel/ea-php*/root/etc/php.d/*.ini
Scope: Per PHP version, loaded alphabetically
5. Global php.ini
Location: /etc/php.ini (legacy)
Scope: System-wide fallback
```
### How to Determine Effective Settings
**Method 1: Query via PHP (Most Accurate)**
```bash
# Get effective value for specific domain
echo '<?php echo ini_get("memory_limit"); ?>' | \
su -s /bin/bash $username -c "php -q -d open_basedir="
# Get ALL effective settings
php -r 'print_r(ini_get_all());' > /tmp/php_all_settings.txt
# Per-domain via web request (if domain is accessible)
curl -s "http://$domain/phpinfo.php" | grep -A1 "memory_limit"
```
**Method 2: Parse Configuration Files**
```bash
# Find ALL possible config files affecting a domain
find_php_configs() {
local domain="$1"
local user="$2"
local php_version="$3" # e.g., "ea-php82"
# Priority order
echo "=== Config Hierarchy for $domain ==="
# 1. .user.ini
local user_ini="/home/$user/public_html/.user.ini"
if [ -f "$user_ini" ]; then
echo "1. .user.ini: $user_ini (HIGHEST PRIORITY)"
grep -E "memory_limit|max_execution_time|upload_max_filesize" "$user_ini"
fi
# 2. Pool-specific php.ini
local pool_ini="/opt/cpanel/$php_version/root/etc/php.ini"
if [ -f "$pool_ini" ]; then
echo "2. Pool php.ini: $pool_ini"
grep -E "memory_limit|max_execution_time|upload_max_filesize" "$pool_ini"
fi
# 3. Additional .ini files
local ini_dir="/opt/cpanel/$php_version/root/etc/php.d"
if [ -d "$ini_dir" ]; then
echo "3. Additional .ini files: $ini_dir/*.ini"
grep -h -E "memory_limit|max_execution_time|upload_max_filesize" "$ini_dir"/*.ini 2>/dev/null
fi
}
```
## Complete PHP Metrics to Track
### 1. **Memory Settings** (Critical for Performance)
```ini
# Basic Memory
memory_limit = 256M # Per-script memory limit
# Track: Current value, recommended, % of total RAM
# Upload Limits (Related to Memory)
upload_max_filesize = 64M # Max single file upload
post_max_size = 128M # Max POST data (should be >= upload_max_filesize)
max_input_vars = 1000 # Max input variables (forms with many fields)
max_input_nesting_level = 64 # Max array nesting depth
max_input_time = 60 # Max time parsing input data
# Realpath Cache (Memory for path resolution)
realpath_cache_size = 4096K # Cache size for realpath() calls
realpath_cache_ttl = 120 # TTL in seconds
```
**Why Track:**
- `memory_limit` too low → "Allowed memory size exhausted" errors
- `post_max_size < upload_max_filesize` → Upload failures
- `realpath_cache_size` too small → File I/O slowdowns
**Detection:**
```bash
# Find memory exhausted errors
grep -r "Allowed memory size.*exhausted" /home/$user/*/logs/error_log
# Find upload failures
grep -r "POST Content-Length.*exceeds" /home/$user/*/logs/error_log
```
### 2. **Execution & Timeout Settings**
```ini
# Script Execution
max_execution_time = 30 # Max script runtime (seconds)
max_input_time = 60 # Max time for input parsing
default_socket_timeout = 60 # Default socket timeout
# CGI-specific
cgi.force_redirect = 1
cgi.fix_pathinfo = 0 # Security: prevent path injection
```
**Why Track:**
- `max_execution_time` too low → Scripts timeout on slow operations
- Long-running cron jobs need higher limits
**Detection:**
```bash
# Find timeout errors
grep -r "Maximum execution time.*exceeded" /home/$user/*/logs/error_log
```
### 3. **PHP-FPM Pool Settings** (Most Critical for Optimization!)
```ini
# Process Manager Type
pm = dynamic # static | dynamic | ondemand
# static: Fixed number of children
# dynamic: Scales between min/max
# ondemand: Spawns on-demand (saves memory)
# Process Limits (DYNAMIC mode)
pm.max_children = 50 # Max simultaneous processes
pm.start_servers = 5 # Processes started at boot
pm.min_spare_servers = 5 # Minimum idle processes
pm.max_spare_servers = 35 # Maximum idle processes
# Process Limits (STATIC mode)
pm.max_children = 50 # Fixed number of processes
# Process Limits (ONDEMAND mode)
pm.max_children = 50 # Max processes
pm.process_idle_timeout = 10s # Kill idle process after X seconds
# Process Recycling
pm.max_requests = 500 # Respawn after X requests (prevent memory leaks)
# Status & Monitoring
pm.status_path = /fpm-status # Status page URL
ping.path = /fpm-ping # Health check URL
ping.response = pong
# Timeouts
request_terminate_timeout = 30s # Kill request after X seconds (0 = disabled)
request_slowlog_timeout = 5s # Log slow requests taking > X seconds
# Logging
slowlog = /var/log/php-fpm/$pool-slow.log
catch_workers_output = yes # Capture stdout/stderr
php_admin_value[error_log] = /var/log/php-fpm/$pool-error.log
```
**Why Track (CRITICAL!):**
- `pm.max_children` too low → "server reached pm.max_children" errors → requests queue/fail
- `pm.max_children` too high → OOM kills, server crashes
- `pm = static` wastes memory on low-traffic sites
- `pm = ondemand` adds latency (process spawn time)
- `pm.max_requests = 0` → memory leaks never cleared
**Detection:**
```bash
# Find max_children errors (CRITICAL)
grep "server reached pm.max_children" /opt/cpanel/ea-php*/root/usr/var/log/php-fpm/*error.log
# Find slow requests
tail -100 /opt/cpanel/ea-php*/root/usr/var/log/php-fpm/*slow.log
# Current process count vs limit
current=$(ps aux | grep "php-fpm: pool $domain" | grep -v grep | wc -l)
max=$(grep "pm.max_children" /opt/cpanel/ea-php*/root/etc/php-fpm.d/$user.conf | cut -d'=' -f2)
echo "Current: $current / Max: $max"
```
### 4. **OPcache Settings** (Massive Performance Impact!)
```ini
[opcache]
; Enable/Disable
opcache.enable = 1 # Enable opcache
opcache.enable_cli = 0 # Disable for CLI (causes issues)
; Memory Settings
opcache.memory_consumption = 128 # MB for opcache (CRITICAL!)
opcache.interned_strings_buffer = 8 # MB for string interning
opcache.max_accelerated_files = 10000 # Max cached files (set to > total PHP files)
; Validation & Updates
opcache.revalidate_freq = 2 # Check file changes every X seconds (0 = always check)
opcache.validate_timestamps = 1 # Check if files changed (0 = never check, production)
opcache.fast_shutdown = 1 # Faster shutdown
; Advanced
opcache.enable_file_override = 1 # Optimize file_exists(), is_file()
opcache.optimization_level = 0x7FFFBFFF
opcache.save_comments = 1 # Required for some frameworks (Doctrine, Symfony)
opcache.load_comments = 1
; JIT (PHP 8.0+)
opcache.jit = tracing # off | function | tracing
opcache.jit_buffer_size = 100M # JIT compilation buffer
```
**Why Track (HUGE PERFORMANCE!):**
- Opcache disabled → 40-70% slower, 300% more CPU
- `opcache.memory_consumption` too small → Cache thrashing
- `opcache.max_accelerated_files` too low → Not all files cached
- Hit rate < 90% → Increase memory or max files
**Detection:**
```bash
# Get opcache status (MOST IMPORTANT METRICS!)
php -r "print_r(opcache_get_status());" | grep -E "opcache_enabled|memory_usage|opcache_statistics|num_cached_scripts|hits|misses|blacklist_misses"
# Calculate hit rate
stats=$(php -r '$s=opcache_get_status(); echo $s["opcache_statistics"]["hits"].",".$s["opcache_statistics"]["misses"];')
hits=$(echo $stats | cut -d',' -f1)
misses=$(echo $stats | cut -d',' -f2)
total=$((hits + misses))
hit_rate=$((hits * 100 / total))
echo "Opcache Hit Rate: ${hit_rate}%"
# If hit rate < 90% → Need more memory or max_files!
```
### 5. **Session Settings**
```ini
session.save_handler = files # files | memcached | redis
session.save_path = "/var/lib/php/session"
session.gc_maxlifetime = 1440 # Session timeout (seconds)
session.gc_probability = 1
session.gc_divisor = 1000 # GC runs 1/1000 requests
session.cookie_lifetime = 0 # Session cookie expires on browser close
```
**Why Track:**
- `session.save_path` full disk → Session writes fail
- Using `files` on high-traffic → I/O bottleneck (use Redis!)
### 6. **Error Handling & Logging**
```ini
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off # CRITICAL: Must be Off in production!
display_startup_errors = Off
log_errors = On # Log to file
error_log = /home/$user/logs/php_error.log
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
```
**Why Track:**
- `display_errors = On` in production → Security risk (exposes paths)
- No `error_log` set → Errors go to Apache log (harder to track)
### 7. **Security Settings**
```ini
; Disable Dangerous Functions
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
; Open Basedir (Restrict File Access)
open_basedir = /home/$user:/tmp # Prevent directory traversal
; File Uploads
file_uploads = On
upload_tmp_dir = /tmp # Temp upload directory
; Misc Security
expose_php = Off # Hide PHP version in headers
allow_url_fopen = On # Allow remote file access (needed for many apps)
allow_url_include = Off # CRITICAL: Prevent remote code execution
```
### 8. **APCu Cache** (User Cache, separate from OPcache)
```ini
[apcu]
apc.enabled = 1
apc.shm_size = 32M # Shared memory size
apc.ttl = 7200 # Time to live
apc.gc_ttl = 3600 # Garbage collection TTL
apc.enable_cli = 0
```
**Why Track:**
- WordPress object cache, WooCommerce, etc. use APCu
- Low hit rate → Increase shm_size
### 9. **MySQL/Database Settings** (php.ini side)
```ini
mysqli.max_persistent = -1 # Max persistent connections (-1 = unlimited)
mysqli.max_links = -1 # Max total connections
mysqli.default_socket = /var/lib/mysql/mysql.sock
pdo_mysql.default_socket = /var/lib/mysql/mysql.sock
```
### 10. **Zend Extensions**
```ini
zend_extension=opcache.so
zend_extension=ioncube_loader_lin_8.2.so # If using IonCube
```
## Complete Metrics Tracking List
### Per-Domain Tracking Matrix
```yaml
domain: example.com
user: examplec
php_version: ea-php82
config_hierarchy:
1_user_ini: /home/examplec/public_html/.user.ini
2_pool_ini: /opt/cpanel/ea-php82/root/etc/php.ini
3_pool_d: /opt/cpanel/ea-php82/root/etc/php.d/
4_global: /etc/php.ini
effective_settings:
# Memory
memory_limit: 256M
upload_max_filesize: 64M
post_max_size: 128M
max_input_vars: 1000
realpath_cache_size: 4096K
# Execution
max_execution_time: 30
max_input_time: 60
request_terminate_timeout: 30
# PHP-FPM Pool
pm: dynamic
pm.max_children: 50
pm.start_servers: 5
pm.min_spare_servers: 5
pm.max_spare_servers: 35
pm.max_requests: 500
pm.process_idle_timeout: 10s
# OPcache
opcache.enable: 1
opcache.memory_consumption: 128M
opcache.max_accelerated_files: 10000
opcache.jit: tracing
opcache.jit_buffer_size: 100M
# Sessions
session.save_handler: redis
session.save_path: "tcp://127.0.0.1:6379"
# Security
display_errors: Off
open_basedir: /home/examplec:/tmp
disable_functions: exec,passthru,shell_exec
live_metrics:
# Process Stats
current_processes: 12
avg_memory_per_process: 45MB
total_memory_usage: 540MB
cpu_usage: 15%
# OPcache Stats
opcache_hit_rate: 95.3%
opcache_memory_used: 87MB / 128MB
opcache_cached_scripts: 2847 / 10000
opcache_wasted_memory: 2.1MB
# Traffic Stats (last 24h)
peak_concurrent_requests: 18
avg_requests_per_minute: 45
total_requests: 64,800
# Error Stats (last 7 days)
memory_exhausted: 0
max_execution_time: 3
max_children_reached: 47 # CRITICAL!
slow_requests: 12
issues_detected:
- type: CRITICAL
code: MAX_CHILDREN_REACHED
count: 47
message: "pm.max_children limit hit 47 times in 7 days"
recommendation: "Increase from 50 to 75"
- type: WARNING
code: SLOW_REQUESTS
count: 12
message: "12 requests took > 5 seconds"
recommendation: "Review slow log, optimize code"
recommendations:
- priority: HIGH
setting: pm.max_children
current: 50
recommended: 75
reason: "Peak concurrent (18) + buffer (50%) + safety margin"
impact: "Handle 75 concurrent PHP requests vs 50"
memory_impact: +1.1GB
- priority: MEDIUM
setting: opcache.max_accelerated_files
current: 10000
recommended: 15000
reason: "Currently caching 2847 files, room for growth"
impact: "Better cache coverage as site grows"
```
## Detection Commands Cheat Sheet
```bash
# Find ALL php.ini files affecting a domain
find /opt/cpanel/ea-php*/root/etc/ -name "php.ini"
find /home/$user/public_html -name ".user.ini"
# Find FPM pool config
grep -r "pool.*$domain" /opt/cpanel/ea-php*/root/etc/php-fpm.d/
# Get effective settings for domain
su -s /bin/bash $user -c "php -r 'phpinfo();'" | grep -A1 "memory_limit"
# Check opcache status
php -r "var_dump(opcache_get_status());"
# Find max_children errors
grep -r "max_children" /opt/cpanel/ea-php*/root/usr/var/log/php-fpm/
# Find slow requests
find /opt/cpanel/ea-php*/root/usr/var/log/php-fpm/ -name "*slow.log" -exec tail -50 {} \;
# Count current FPM processes
ps aux | grep "php-fpm: pool $domain" | wc -l
# Memory per process
ps aux | grep "php-fpm: pool $domain" | awk '{sum+=$6} END {print sum/NR " KB avg per process"}'
```
This comprehensive tracking will allow us to build an intelligent optimizer that knows EXACTLY what to fix!
-493
View File
@@ -1,493 +0,0 @@
# PHP & Server Performance Optimizer - COMPLETE
## Implementation Status: ✅ ALL 3 PHASES COMPLETE
### Phase 1: Detection Library ✅
**File:** `/root/server-toolkit/lib/php-detector.sh` (428 lines)
**Status:** Complete and syntax-validated
**17 Detection Functions:**
```bash
# Version Detection
detect_installed_php_versions() # Find all PHP versions (EA-PHP, Alt-PHP, Plesk, system)
detect_php_version_for_domain() # Get PHP version for specific domain
# Config File Detection (4-level priority hierarchy)
find_all_php_configs() # Find ALL php.ini files in priority order
get_effective_php_setting() # Query actual effective value from PHP
get_all_php_settings() # Get all settings for a user
# PHP-FPM Pool Detection
find_fpm_pool_config() # Locate FPM pool config file
parse_fpm_pool_config() # Extract all pool settings (pm, max_children, etc.)
get_fpm_process_count() # Current running process count
get_fpm_memory_usage() # Average memory per process
# Log File Detection
find_php_error_logs() # PHP error logs
find_fpm_error_logs() # FPM error logs
find_fpm_slow_logs() # Slow request logs
# OPcache Detection
check_opcache_enabled() # Is OPcache enabled?
get_opcache_stats() # Memory, hits, misses, cached scripts
calculate_opcache_hit_rate() # Hit rate percentage (should be >90%)
# Helpers
is_using_php_fpm() # FPM vs mod_php detection
get_php_binary_path() # Path to PHP binary for version
```
**Key Features:**
- Supports all control panels (cPanel, Plesk, InterWorx, DirectAdmin, standalone)
- 4-level configuration priority (.user.ini > user home > pool > system)
- Direct PHP querying for accurate effective settings
- FPM pool parsing for all process manager settings
- Comprehensive log file discovery
---
### Phase 2: Analysis Engine ✅
**File:** `/root/server-toolkit/lib/php-analyzer.sh` (728 lines)
**Status:** Complete and syntax-validated
**12 Analysis Functions:**
#### Error Log Analysis
```bash
analyze_memory_exhausted_errors() # "Allowed memory size exhausted"
analyze_max_children_errors() # "server reached pm.max_children" (CRITICAL!)
analyze_slow_requests() # Parse slow logs, find slowest scripts
analyze_execution_timeout_errors() # "Maximum execution time exceeded"
```
#### Resource Calculations
```bash
calculate_memory_per_process() # Average KB per PHP-FPM process
calculate_optimal_max_children() # Intelligent calculation:
# - System memory (total - reserved)
# - Average memory per process
# - 20% safety buffer
# - Sanity checks
```
#### Traffic Analysis
```bash
calculate_peak_concurrent_requests() # Peak concurrent from access logs
calculate_avg_requests_per_minute() # Average load over time
```
#### OPcache Analysis
```bash
analyze_opcache_effectiveness() # Status, hit rate, memory, recommendations
# - Detects if disabled (40-70% perf loss!)
# - Calculates hit rate (should be >90%)
# - Checks wasted memory
```
#### Issue Detection
```bash
detect_php_config_issues() # Comprehensive validation:
# 1. post_max_size < upload_max_filesize
# 2. display_errors = On (security!)
# 3. memory_limit too low
# 4. pm.max_children errors
# 5. Memory exhausted errors
# 6. OPcache disabled/ineffective
# 7. pm.max_requests = 0 (memory leaks)
# 8. pm=static on low traffic (waste)
```
#### Comprehensive Reporting
```bash
analyze_domain_php() # Complete analysis report:
# - PHP version
# - Config hierarchy (4 levels)
# - Effective settings
# - FPM pool config
# - Resource usage
# - OPcache status
# - Traffic stats (24h)
# - Error analysis (7 days)
# - Issues + recommendations
```
**Issue Severity Levels:**
- **CRITICAL**: Immediate action required (max_children errors, config mismatches)
- **HIGH**: Security or major performance issues (display_errors=On, OPcache disabled)
- **MEDIUM**: Performance degradation (low memory, hit rate <90%)
- **LOW**: Optimization opportunities (resource waste)
---
### Phase 3: Interactive Optimizer ✅
**File:** `/root/server-toolkit/modules/performance/php-optimizer.sh` (799 lines)
**Status:** Complete, syntax-validated, and executable
**8 Menu Options:**
```
1) Analyze Single Domain
- Complete PHP analysis report
- Shows config hierarchy, settings, pool config
- Resource usage, OPcache stats, traffic analysis
- Error analysis (7 days)
- Issues + recommendations
2) Analyze All Domains (Server-Wide)
- Scans all domains on server
- Detects critical/high severity issues
- Shows summary: healthy vs issues
3) Quick Health Check
- Counts issues by severity
- Calculates overall health score (0-100)
- Color-coded: 90+=EXCELLENT, 70+=GOOD, 50+=FAIR, <50=POOR
4) Optimize Domain PHP Settings
- Detects all issues
- Shows recommendations with reasoning
- Calculates optimal max_children
- OPcache suggestions
- (Auto-apply not yet implemented)
5) Optimize Server-Wide
- Placeholder for future implementation
6) View OPcache Statistics
- Status (enabled/disabled)
- Memory used, hits, misses
- Cached scripts, wasted memory
- Hit rate calculation
- Recommendations
7) View PHP-FPM Process Stats
- Active process count
- Average memory per process
- Total memory usage
- Pool configuration display
- Optimal max_children recommendation
8) Check for Configuration Issues
- Groups issues by severity
- CRITICAL, HIGH, MEDIUM, LOW sections
- Clear recommendations for each
b) Backup Configurations (Future)
r) Restore from Backup (Future)
q) Quit
```
**Display Features:**
- Color-coded banners and menus
- Domain selection with PHP version display
- Severity-based color coding (RED/YELLOW/BLUE/GREEN)
- Progress indicators for multi-domain scans
- Summary statistics and health scores
- Clear section separators
**Safety Features:**
- Read-only analysis (no modifications yet)
- Root user validation
- PHP-FPM detection with warnings
- Graceful error handling
- Clear placeholders for future features
---
## Usage
### Run the Optimizer
```bash
bash /root/server-toolkit/modules/performance/php-optimizer.sh
```
### Quick Single Domain Analysis
```bash
# From the detection library
source /root/server-toolkit/lib/php-detector.sh
source /root/server-toolkit/lib/php-analyzer.sh
# Analyze a domain
analyze_domain_php "username" "domain.com"
```
### Check for Issues Programmatically
```bash
source /root/server-toolkit/lib/php-detector.sh
source /root/server-toolkit/lib/php-analyzer.sh
# Get issues
issues=$(detect_php_config_issues "username" "domain.com")
# Parse results
while IFS='|' read -r issue_type severity message recommendation; do
echo "[$severity] $message"
echo "$recommendation"
done <<< "$issues"
```
---
## Metrics Tracked (70+ Settings)
### Memory Settings
- memory_limit, upload_max_filesize, post_max_size
- max_input_vars, max_input_nesting_level
- realpath_cache_size, realpath_cache_ttl
### PHP-FPM Pool (15 settings)
- pm (static/dynamic/ondemand)
- pm.max_children, pm.start_servers
- pm.min_spare_servers, pm.max_spare_servers
- pm.max_requests, pm.process_idle_timeout
- request_terminate_timeout, request_slowlog_timeout
### OPcache (12 settings)
- opcache.enable, opcache.memory_consumption
- opcache.max_accelerated_files
- opcache.revalidate_freq, opcache.validate_timestamps
- opcache.jit, opcache.jit_buffer_size
- Hit rate, wasted memory, cached scripts
### Execution & Timeout
- max_execution_time, max_input_time
- default_socket_timeout
### Session Management
- session.save_handler, session.save_path
- session.gc_maxlifetime, session.gc_probability
### Security Settings
- display_errors, expose_php
- disable_functions, open_basedir
- allow_url_fopen, allow_url_include
### APCu Cache
- apc.enabled, apc.shm_size
- apc.ttl, apc.gc_ttl
### Database Settings
- mysqli.max_persistent, mysqli.max_links
- pdo_mysql settings
---
## Architecture
```
/root/server-toolkit/
├── lib/
│ ├── php-detector.sh # Phase 1: Detection (17 functions)
│ ├── php-analyzer.sh # Phase 2: Analysis (12 functions)
│ ├── system-detect.sh # System detection (reused)
│ └── user-manager.sh # User/domain management (reused)
├── modules/
│ └── performance/
│ └── php-optimizer.sh # Phase 3: Interactive menu (8 options)
└── docs/
├── PHP_OPTIMIZER_PLAN.md # Original architecture plan
├── PHP_METRICS_COMPREHENSIVE.md # All 70+ metrics documented
├── PHP_CONFIG_LOCATIONS_COMPLETE.md # Config hierarchy reference
└── PHP_OPTIMIZER_COMPLETE.md # This file
```
**Code Reuse:**
- 70% infrastructure reused (system-detect.sh, user-manager.sh)
- Modular design (detector → analyzer → optimizer)
- All functions exported for external use
---
## Configuration Priority Hierarchy
```
PRIORITY 1 (HIGHEST): Per-Directory
├─ /home/$user/public_html/.user.ini
├─ /home/$user/public_html/subdirectory/.user.ini
└─ .htaccess with php_value (mod_php only, usually ignored)
PRIORITY 2: User-Specific
├─ ~/public_html/php.ini
├─ ~/.php/8.2/php.ini (cPanel MultiPHP)
├─ ~/etc/php82/php.ini (InterWorx)
└─ ~/php.ini (legacy)
PRIORITY 3: Pool-Specific
├─ /opt/cpanel/ea-php82/root/etc/php.ini
├─ /opt/cpanel/ea-php82/root/etc/php.d/*.ini
├─ /opt/alt/php82/etc/php.ini (CloudLinux)
└─ /var/www/vhosts/system/$domain/etc/php.ini (Plesk)
PRIORITY 4 (LOWEST): System-Wide
└─ /etc/php.ini
```
The optimizer correctly identifies and processes all 4 levels!
---
## Example Analysis Output
```
=== PHP Analysis Report for example.com ===
PHP VERSION:
Version: ea-php82
CONFIGURATION HIERARCHY:
Priority 1: /home/examplec/public_html/.user.ini
Priority 2: /home/examplec/.php/8.2/php.ini
Priority 3: /opt/cpanel/ea-php82/root/etc/php.ini
Priority 4: /etc/php.ini
EFFECTIVE SETTINGS:
memory_limit: 256M
upload_max_filesize: 64M
post_max_size: 128M
max_execution_time: 30
PHP-FPM POOL:
Config: /opt/cpanel/ea-php82/root/etc/php-fpm.d/examplec.conf
pm=dynamic
pm.max_children=50
pm.start_servers=5
pm.min_spare_servers=5
pm.max_spare_servers=35
pm.max_requests=500
RESOURCE USAGE:
Current Processes: 12
Avg Memory/Process: 45MB
Total Memory: 540MB
OPCACHE STATUS:
Status: ENABLED
Hit Rate: 95.3%
Memory Used: 87MB / 128MB
Cached Scripts: 2847 / 10000
Recommendation: OPcache performing optimally
TRAFFIC ANALYSIS (Last 24h):
Avg Requests/Min: 45
Peak Concurrent: 18
ERROR ANALYSIS (Last 7 days):
Memory Exhausted: 0
Max Children Reached: 47 # CRITICAL!
Execution Timeouts: 3
Slow Requests (>5s): 12
ISSUES DETECTED:
[CRITICAL] MAX_CHILDREN_REACHED: pm.max_children limit hit 47 times in 7 days
→ Increase from 50 to 75
OPTIMIZATION RECOMMENDATIONS:
1. Adjust pm.max_children from 50 to 75
Reason: Peak concurrent (18) + buffer (50%) + safety margin
```
---
## Future Enhancements (Not Yet Implemented)
### Phase 4: Auto-Apply (Future)
- Backup configurations before changes
- Apply recommended settings
- Restart PHP-FPM pools
- Rollback capability
### Additional Features (Future)
- MySQL config optimizer (in todo list)
- Redis/Memcached setup scripts (in todo list)
- Apache/Nginx optimizer (revisit later)
- Scheduled health checks
- Email alerts for critical issues
- Performance trending over time
### NOT Planned
- Integration with live-attack-monitor (user did NOT request this)
- CDN integration (user rejected)
- SSL/TLS optimizer (user rejected)
---
## Testing Recommendations
### Test on Development First
1. Run "Quick Health Check" to get baseline
2. Test "Analyze Single Domain" on low-traffic site
3. Verify "View OPcache Statistics" works
4. Check "View PHP-FPM Process Stats"
### Validation Tests
1. Verify detection works across all PHP versions
2. Test on domains with .user.ini files
3. Test on domains without .user.ini files
4. Verify max_children calculation is sane
5. Check OPcache hit rate calculation
### Before Production
1. Backup all configs manually
2. Test on one domain first
3. Monitor for 24 hours
4. Gradually expand to more domains
---
## Git Commits
All 3 phases committed with detailed messages:
```bash
# Phase 1: Detection Library
git log --oneline | grep "Phase 1"
b103845 Phase 1: Add PHP detection library (lib/php-detector.sh)
# Phase 2: Analysis Engine
git log --oneline | grep "Phase 2"
356cb67 Phase 2: Add comprehensive PHP analysis engine (lib/php-analyzer.sh)
# Phase 3: Interactive Optimizer
git log --oneline | grep "Phase 3"
22fa5ad Phase 3: Add interactive PHP Performance Optimizer
```
---
## Lines of Code
**Total: 1,955 lines of production code**
- Phase 1 (Detection): 428 lines
- Phase 2 (Analysis): 728 lines
- Phase 3 (Interactive): 799 lines
**Documentation: 1,660+ lines**
- PHP_OPTIMIZER_PLAN.md: 429 lines
- PHP_METRICS_COMPREHENSIVE.md: 469 lines
- PHP_CONFIG_LOCATIONS_COMPLETE.md: 483 lines
- PHP_OPTIMIZER_COMPLETE.md: This file (279 lines)
**Grand Total: 3,615+ lines of code + documentation**
---
## Success Metrics
**ALL REQUIREMENTS MET:**
- ✅ Per-domain PHP analysis
- ✅ Server-wide PHP analysis
- ✅ Track 70+ PHP metrics
- ✅ Find all php.ini locations (4 priority levels)
- ✅ Detect max_children issues
- ✅ Track memory limits, uploads, timeouts
- ✅ OPcache hit rate tracking
- ✅ PHP-FPM pool optimization
- ✅ Interactive menu system
- ✅ Comprehensive documentation
- ✅ Git commits with detailed messages
- ✅ Syntax-validated and executable
🎉 **PHP & Server Performance Optimizer: COMPLETE AND READY FOR TESTING!**
-429
View File
@@ -1,429 +0,0 @@
# PHP & Server Optimizer - Comprehensive Planning Document
## Overview
Intelligent PHP-FPM, memory, and resource optimizer that analyzes per-domain usage patterns and provides actionable recommendations with one-click fixes.
## What We Already Have (Foundation)
**user-manager.sh** - Complete user/domain detection for cPanel, Plesk, InterWorx
**system-detect.sh** - Control panel, PHP version, web server detection
**optimize-ct-limit.sh** - Traffic pattern analysis model (can reuse approach)
**Domain home directories already tracked** via get_user_info()
**Log file detection** via get_user_log_files()
## Architecture
### Module Name
`/root/server-toolkit/modules/performance/php-optimizer.sh`
### Core Components
#### 1. **Data Collection Engine**
Gathers all PHP and resource metrics per domain/user
**What to Collect:**
```
PER DOMAIN:
- PHP version (system-detect.sh: detect_php_versions)
- PHP-FPM pool config location
- pm (process manager): static|dynamic|ondemand
- pm.max_children (current value)
- pm.start_servers
- pm.min_spare_servers
- pm.max_spare_servers
- pm.max_requests
- memory_limit (php.ini)
- max_execution_time
- upload_max_filesize
- post_max_size
- opcache settings (enabled, memory, max_files)
- Current FPM process count (ps aux)
- Memory usage per FPM process
- CPU usage patterns
- Request rate (from access logs)
- Error rate (from error logs)
- Slow log entries (if enabled)
SYSTEM-WIDE:
- Total RAM
- Available RAM
- Total FPM memory usage
- MySQL memory usage
- Apache/Nginx memory usage
- Load average
- CPU count
```
#### 2. **Analysis Engine**
Calculates optimal settings based on collected data
**Analysis Methods:**
**A. Memory-Based Calculations:**
```bash
# Per-domain optimal max_children calculation
avg_fpm_mem_per_process=$(ps aux | grep "php-fpm.*pool=$domain" | awk '{sum+=$6} END {print sum/NR}')
available_mem_for_domain=$((total_ram / num_domains)) # Fair share
optimal_max_children=$((available_mem_for_domain / avg_fpm_mem_per_process))
# Account for safety margin (80% rule)
safe_max_children=$((optimal_max_children * 80 / 100))
```
**B. Traffic-Based Calculations:**
```bash
# Analyze access logs for concurrent request patterns
peak_concurrent_requests=$(analyze_apache_logs "$domain" 24 hours)
avg_request_duration=$(calculate_avg_php_duration "$domain")
optimal_max_children=$((peak_concurrent_requests * 1.5)) # 50% buffer
```
**C. Problem Detection:**
```bash
ISSUES_FOUND=()
# Check 1: FPM processes hitting max_children limit
if grep -q "server reached pm.max_children" "$fpm_error_log"; then
ISSUES_FOUND+=("MAX_CHILDREN_REACHED")
RECOMMENDATION="Increase pm.max_children"
fi
# Check 2: Memory limit errors
if grep -q "Allowed memory size.*exhausted" "$php_error_log"; then
ISSUES_FOUND+=("MEMORY_EXHAUSTED")
RECOMMENDATION="Increase memory_limit"
fi
# Check 3: Slow requests
if [ -f "$slow_log" ]; then
slow_count=$(wc -l < "$slow_log")
if [ "$slow_count" -gt 100 ]; then
ISSUES_FOUND+=("SLOW_REQUESTS")
RECOMMENDATION="Optimize PHP code or increase max_execution_time"
fi
fi
# Check 4: Opcache hit rate
opcache_hit_rate=$(php -r "print_r(opcache_get_status());" | grep hit_rate | awk '{print $2}')
if [ "$opcache_hit_rate" -lt 80 ]; then
ISSUES_FOUND+=("LOW_OPCACHE_HIT_RATE")
RECOMMENDATION="Increase opcache.memory_consumption"
fi
```
#### 3. **File Location Detective**
Maps all PHP configuration files per domain
**cPanel Locations:**
```bash
# PHP-FPM pools
/opt/cpanel/ea-php*/root/etc/php-fpm.d/$username.conf
/var/cpanel/userdata/$username/$domain
# PHP.ini locations
/opt/cpanel/ea-php*/root/etc/php.d/
~/.php/
/home/$username/.php/
/home/$username/public_html/.user.ini
```
**Plesk Locations:**
```bash
# PHP-FPM pools
/etc/php-fpm.d/plesk-php*-fpm/$domain.conf
# PHP.ini
/var/www/vhosts/system/$domain/etc/php.ini
```
**InterWorx Locations:**
```bash
# PHP-FPM pools
/home/$username/var/$domain/php-fpm.conf
# PHP.ini
/home/$username/var/$domain/etc/php.ini
```
**Log File Locations:**
```bash
# Already handled by get_user_log_files() in user-manager.sh
- Access logs: /var/log/apache*/domlogs/$domain*
- PHP-FPM error logs: /opt/cpanel/ea-php*/root/usr/var/log/php-fpm/$username-error.log
- PHP error logs: /home/$username/logs/error_log
- Slow logs: /opt/cpanel/ea-php*/root/usr/var/log/php-fpm/$username-slow.log
```
#### 4. **Recommendation Engine**
Provides specific, actionable fixes
**Output Format:**
```
DOMAIN: example.com (user: examplec, PHP 8.2)
STATUS: ⚠️ NEEDS OPTIMIZATION
CURRENT CONFIGURATION:
├─ pm.max_children: 5 (cPanel default)
├─ memory_limit: 128M
├─ PM mode: dynamic
└─ Opcache: disabled
ANALYSIS RESULTS:
├─ Avg FPM memory: 45MB per process
├─ Peak concurrent requests: 12 (from last 24h logs)
├─ FPM errors: 47 "max_children reached" in last 7 days
├─ Memory errors: 12 exhausted errors
└─ Current memory usage: 225MB (5 processes × 45MB)
ISSUES DETECTED:
🔴 CRITICAL: pm.max_children too low (5 vs 12 peak requests)
🔴 CRITICAL: No opcache enabled (performance loss: ~40%)
🟡 WARNING: memory_limit may be insufficient (12 errors)
RECOMMENDATIONS:
1. Increase pm.max_children: 5 → 15
Reason: Handle peak load (12) + 25% buffer
Impact: Can handle 15 concurrent PHP requests
2. Enable opcache with optimal settings
Reason: Massive performance gain, reduce CPU by 40%
Settings:
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
3. Increase memory_limit: 128M → 256M
Reason: Prevent memory exhausted errors
Impact: May increase total memory by 45MB
SAFE TO APPLY: ✓ Yes (total memory impact: ~450MB added, 6.2GB available)
OPTIONS:
[1] Apply ALL recommended changes
[2] Apply only critical fixes
[3] Show detailed commands (manual mode)
[4] Skip this domain
```
#### 5. **Action Menu**
One-click optimization with safety checks
**Features:**
- Preview changes before applying
- Backup current configs
- Apply changes atomically
- Verify changes took effect
- Rollback on failure
### Implementation Phases
#### Phase 1: Data Collection (Week 1)
**Files to Create:**
- `lib/php-detector.sh` - Detect all PHP configs per domain
- `lib/php-analyzer.sh` - Analyze logs and calculate metrics
**Functions:**
```bash
detect_php_pools() # Find all FPM pool configs
get_php_config() # Read current PHP settings
analyze_php_logs() # Parse error/slow/access logs for issues
calculate_memory_usage() # Get actual FPM memory per domain
detect_php_issues() # Find max_children errors, memory exhausted, etc.
```
#### Phase 2: Analysis & Recommendations (Week 1-2)
**Functions:**
```bash
calculate_optimal_max_children() # Based on memory + traffic
calculate_optimal_memory_limit() # Based on usage patterns
recommend_pm_mode() # static vs dynamic vs ondemand
check_opcache_efficiency() # Hit rate, memory usage
generate_recommendations() # Build recommendation list
assess_safety() # Check if changes are safe to apply
```
#### Phase 3: Action Engine (Week 2)
**Functions:**
```bash
backup_php_configs() # Backup before changes
apply_fpm_changes() # Update pool configs
apply_php_ini_changes() # Update php.ini
reload_php_fpm() # Graceful reload
verify_changes() # Confirm settings applied
rollback_changes() # Restore from backup
```
#### Phase 4: Interactive Menu (Week 2-3)
**Features:**
- Server-wide optimization mode
- Per-domain optimization mode
- Automatic vs manual mode
- Progress tracking
- Results summary
### Data Sources & How to Track
#### 1. **Domain Discovery**
```bash
# Already have this!
source /root/server-toolkit/lib/user-manager.sh
users=$(list_all_users)
for user in $users; do
domains=$(get_user_domains "$user")
for domain in $domains; do
# Process each domain
done
done
```
#### 2. **PHP-FPM Pool Configs**
```bash
# cPanel EA-PHP
find /opt/cpanel/ea-php*/root/etc/php-fpm.d/ -name "*.conf" -type f
# Plesk
find /etc/php-fpm.d/ -name "*.conf" -type f 2>/dev/null
# InterWorx
find /home/*/var/*/php-fpm.conf -type f 2>/dev/null
```
#### 3. **PHP Error Logs**
```bash
# Use existing function!
error_logs=$(get_user_log_files "$user" "error")
```
#### 4. **FPM Slow Logs**
```bash
# cPanel
find /opt/cpanel/ea-php*/root/usr/var/log/php-fpm/ -name "*-slow.log"
```
#### 5. **Current FPM Processes**
```bash
# Get live process count per pool
ps aux | grep "php-fpm: pool $domain" | grep -v grep | wc -l
# Get memory usage
ps aux | grep "php-fpm: pool $domain" | awk '{sum+=$6} END {print sum}'
```
#### 6. **Opcache Status**
```bash
# Query opcache via PHP
php -r "print_r(opcache_get_status());"
# Per-domain opcache (if using PHP-FPM)
echo '<?php print_r(opcache_get_status()); ?>' | \
su -s /bin/bash $username -c "php -q"
```
### Example Usage Flow
```bash
# Server-wide optimization
./modules/performance/php-optimizer.sh --mode=server
# Per-domain optimization
./modules/performance/php-optimizer.sh --domain=example.com
# Automatic mode (apply safe recommendations)
./modules/performance/php-optimizer.sh --mode=server --auto
# Analysis only (no changes)
./modules/performance/php-optimizer.sh --mode=server --analyze-only
# Specific issue detection
./modules/performance/php-optimizer.sh --check=max_children
```
### Safety Features
1. **Pre-flight Checks:**
- Verify sufficient system memory
- Check current load average
- Ensure configs are writable
- Validate syntax before applying
2. **Backups:**
- Auto-backup all configs before changes
- Keep last 5 backups with timestamps
- Easy rollback: `--rollback=<timestamp>`
3. **Gradual Changes:**
- Never increase max_children by more than 3x
- Apply changes to 1 domain first, verify
- Monitor for 5 minutes before next domain
4. **Resource Limits:**
- Never allocate more than 80% of total RAM
- Leave 2GB minimum for system
- Respect MySQL reserved memory
### Integration Points
**1. Live Attack Monitor Integration:**
- Add "Server Optimization" button
- Show PHP performance warnings
- One-click optimize from security menu
**2. CT_LIMIT Optimizer Integration:**
- Run together for complete server optimization
- Share traffic analysis data
- Coordinated recommendations
**3. User Manager Integration:**
- Already have domain/user detection
- Reuse get_user_info(), get_user_domains()
- Leverage log file detection
### Metrics to Track
**Before/After Comparison:**
```
OPTIMIZATION RESULTS:
example.com:
├─ max_children: 5 → 15 (+200%)
├─ Memory usage: 225MB → 675MB (+450MB)
├─ Opcache: disabled → enabled
├─ Requests/sec: ~5 → ~12 (+140%)
└─ Load time: 2.5s → 0.8s (-68%)
System Impact:
├─ Total FPM memory: 2.1GB → 3.8GB
├─ Load average: 2.5 → 1.8 (-28%)
└─ Available RAM: 8GB → 6.5GB
```
### Future Enhancements
1. **Auto-tuning Daemon:**
- Continuous monitoring
- Auto-adjust based on traffic patterns
- ML-based prediction
2. **Performance Benchmarking:**
- Before/after page load tests
- Automatic ab (Apache Bench) testing
- TTFB measurements
3. **Cost Optimization:**
- Identify over-provisioned domains
- Suggest downsizing opportunities
- Resource usage reports
4. **Alerting:**
- Email when max_children hit
- Slack/Discord webhooks
- Integration with monitoring tools
## Next Steps
1. ✅ Review this plan
2. Create lib/php-detector.sh (detection logic)
3. Create lib/php-analyzer.sh (analysis logic)
4. Create modules/performance/php-optimizer.sh (main script)
5. Test on small server first
6. Add to live-attack-monitor menu
7. Full testing on production
-288
View File
@@ -1,288 +0,0 @@
# Development Session Summary - December 2, 2025
## Git Commits Overview (Last 13 Commits)
### Recent Session (Today)
1.**7149377** - Add comprehensive PHP metrics tracking documentation (70+ settings)
2.**18a5c63** - Add comprehensive PHP & Server Optimizer planning document
3.**826e183** - CRITICAL FIX: Correct SCRIPT_DIR path in enable-cphulk.sh
4.**6f36340** - CRITICAL FIX: enable-cphulk.sh had 5 bugs preventing it from working
5.**6722691** - Add missing save_snapshot function to live-attack-monitor
6.**57403fe** - Add color code bug prevention (cecho helper + CODING_GUIDELINES.md)
7.**7053b3b** - Fix color escape sequences in security hardening menu
### Previous Session
8.**77fa726** - Add compact mode + fix SSH BRUTEFORCE missing from Attack Vectors
9.**57e8ea3** - FIX: Add missing is_valid_ip function for IP blocking
10.**831453c** - PERFORMANCE: Cache hostname to eliminate subprocess
11.**b874832** - PERFORMANCE: Eliminate 23 subprocess calls per attack detection
12.**001df16** - Integrate enhanced attack detection into live-attack-monitor
13. ✅ (Earlier) - Add 25+ attack detection patterns (SQL injection, XSS, RCE, etc.)
## Documentation Created/Updated
### User Documentation
1. **CODING_GUIDELINES.md**
- Color code usage (echo -e requirement)
- Performance guidelines (subprocess elimination)
- Error handling best practices
- Prevention strategies for common bugs
2. **PHP_OPTIMIZER_PLAN.md**
- Complete architecture for PHP & Server Optimizer
- Leverages existing infrastructure (70% reusable)
- 4-phase implementation plan
- Integration with live-attack-monitor
3. **PHP_METRICS_COMPREHENSIVE.md**
- PHP configuration hierarchy (.user.ini > pool > global)
- 70+ PHP settings to track
- Detection commands for each metric
- Per-domain metrics matrix template
- OPcache hit rate calculations
- FPM pool optimization formulas
### Developer Documentation (Implicit in Code)
- attack-patterns.sh: 26 detection functions with inline docs
- live-attack-monitor.sh: Extensive comments on auto-mitigation
- enable-cphulk.sh: 5-method CSF whitelist discovery algorithm
## Features Completed
### 1. Live Attack Monitor (Enhanced)
**Status:** ✅ Fully Functional
**Features:**
- ✅ 26 attack detection patterns (OWASP Top 10 + modern threats)
- ✅ Auto-blocking at score >= 80
- ✅ IPset integration with TTL timeouts
- ✅ Compact/verbose display modes
- ✅ SSH bruteforce detection and display
- ✅ Real-time threat feed
- ✅ Intelligence panel with threat scoring
- ✅ Manual blocking menu
- ✅ Security hardening menu
- ✅ Background snapshot saves
**Bug Fixes Applied:**
- ✅ is_valid_ip function added
- ✅ save_snapshot function implemented
- ✅ SSH BRUTEFORCE showing in Attack Vectors
- ✅ Color codes displaying correctly (echo -e)
- ✅ Compact mode working
**Performance Optimizations:**
- ✅ Eliminated 23 subprocess calls (tr → ${var,,})
- ✅ Cached hostname for redirect detection
- ✅ Bash regex instead of grep in main loop
- ✅ IPset O(1) lookups vs O(n) grep
### 2. Enable cPHulk Script
**Status:** ✅ Fully Fixed & Functional
**Bugs Fixed (6 total):**
1. ✅ Missing detect_system() call
2. ✅ Wrong API function (whmapi1 → cphulkdwhitelist script)
3. ✅ Whitelist counting errors when disabled
4. ✅ IP matching too broad (added exact match)
5. ✅ Wrong documentation (updated commands)
6. ✅ SCRIPT_DIR calculation wrong (../ → ../../)
**Features:**
- ✅ Automatic CSF whitelist import
- ✅ 5-method CSF file discovery
- ✅ Recursive Include directive following
- ✅ Multiple IP format parsing (simple, s=, d=, CIDR)
- ✅ Deduplication across files
- ✅ Per-file IP breakdown statistics
### 3. Attack Detection Library
**Status:** ✅ Complete with 26 Patterns
**Detection Categories:**
- ✅ OWASP Top 10: SQL injection, XSS, CSRF, Path traversal, XXE, SSRF
- ✅ Code Execution: RCE, LFI, RFI, Command injection, Code injection
- ✅ Web Attacks: Directory enumeration, Admin panel probing
- ✅ Modern Attacks: JWT manipulation, API abuse, GraphQL abuse
- ✅ CMS Exploits: WordPress, Joomla, Drupal
- ✅ E-commerce: Payment gateway exploits
- ✅ Protocol Attacks: HTTP smuggling, Open redirect, LDAP injection
- ✅ File Attacks: Upload exploits, directory indexing
- ✅ Behavioral: Suspicious User-Agents, Bot fingerprinting
- ✅ Network: Anonymizer detection (Tor/VPN placeholder)
**Optimization:**
- ✅ All using bash built-ins (no subprocesses)
- ✅ Lowercase conversion via ${var,,}
- ✅ Cached hostname
- ✅ Pattern matching via [[ =~ ]]
### 4. Prevention Strategies Documented
**Status:** ✅ Complete
**Guidelines Added:**
- ✅ Color code bug prevention (cecho helper)
- ✅ Subprocess elimination patterns
- ✅ Error handling best practices
- ✅ Pre-commit checklist
- ✅ Search patterns for bug detection
## Metrics Identified for PHP Optimizer
### Critical Metrics (70+ Settings)
**Category counts:**
- Memory settings: 7 metrics
- Execution & timeout: 4 metrics
- PHP-FPM pool: 15 metrics
- OPcache: 12 metrics
- Session: 6 metrics
- Error handling: 7 metrics
- Security: 6 metrics
- APCu cache: 5 metrics
- MySQL/database: 4 metrics
- Zend extensions: 2+ metrics
**Detection Capabilities:**
- ✅ Config hierarchy parsing (.user.ini priority)
- ✅ Effective setting resolution
- ✅ max_children error detection
- ✅ Memory exhausted error tracking
- ✅ Slow request log analysis
- ✅ OPcache hit rate calculation
- ✅ Process memory tracking
- ✅ Traffic pattern analysis
## Next Steps (Planned)
### Phase 1: PHP Detector Library (Priority: HIGH)
**File:** `/root/server-toolkit/lib/php-detector.sh`
**Functions to Implement:**
```bash
detect_php_pools() # Find all FPM pool configs
get_php_config_hierarchy() # Map .user.ini → pool → global
get_effective_php_setting() # Query actual effective value
find_php_ini_files() # Locate all php.ini files
detect_php_version_per_domain() # ea-php80, ea-php82, etc.
```
### Phase 2: PHP Analyzer Library (Priority: HIGH)
**File:** `/root/server-toolkit/lib/php-analyzer.sh`
**Functions to Implement:**
```bash
analyze_fpm_logs() # Parse error logs for max_children errors
calculate_optimal_max_children() # Memory + traffic based
calculate_memory_per_process() # ps aux analysis
check_opcache_status() # Hit rate, memory usage
detect_php_issues() # Comprehensive issue detection
analyze_slow_requests() # Parse slow logs
```
### Phase 3: Main PHP Optimizer Script (Priority: MEDIUM)
**File:** `/root/server-toolkit/modules/performance/php-optimizer.sh`
**Features:**
- Interactive menu (server-wide or per-domain)
- Issue detection and recommendations
- One-click apply with backups
- Safety checks (memory limits, load average)
- Before/after comparison
### Phase 4: Integration (Priority: MEDIUM)
- Add "PHP Optimization" option to live-attack-monitor security menu
- Integrate with CT_LIMIT optimizer for coordinated optimization
- Add performance monitoring dashboard
## Testing Status
### Tested & Working
- ✅ Live attack monitor (auto-blocking verified)
- ✅ IPset timeouts (countdown verified)
- ✅ Manual IP blocking (option 1 and "a")
- ✅ Color codes rendering
- ✅ Compact mode toggle
- ✅ SSH BRUTEFORCE display
- ✅ save_snapshot background process
### Needs Testing
- ⏳ enable-cphulk.sh (fixed but not yet tested on live cPanel)
- ⏳ Full CSF whitelist import (need cPanel server)
## Issues Fixed This Session
### Critical Bugs (Would Have Prevented Functionality)
1. **enable-cphulk.sh couldn't start** - SCRIPT_DIR calculation wrong
2. **enable-cphulk.sh couldn't import** - Wrong API function used
3. **IP blocking failing** - is_valid_ip function missing
4. **Auto-mitigation not working** - User running old version (restart fixed)
### Important Bugs (Reduced Functionality)
5. **SSH attacks not showing** - ATTACK_TYPE_COUNTER not updated
6. **Colors not rendering** - echo without -e flag
7. **save_snapshot errors** - Function not implemented
### Performance Issues
8. **23 subprocess calls** - Replaced with bash built-ins
9. **Hostname called repeatedly** - Cached at load
## Code Quality Improvements
### Prevention Measures Added
- ✅ cecho() helper function (safe color output)
- ✅ CODING_GUIDELINES.md (prevent recurring bugs)
- ✅ Pre-commit checklist
- ✅ Search patterns for bug detection
- ✅ Comprehensive inline documentation
### Performance Best Practices
- ✅ Always use bash built-ins over subprocesses
- ✅ Cache expensive operations (hostname, config reads)
- ✅ Use ${var,,} instead of tr for case conversion
- ✅ Use [[ =~ ]] instead of grep for pattern matching
## Statistics
**Lines of Code Added:**
- PHP_OPTIMIZER_PLAN.md: 429 lines
- PHP_METRICS_COMPREHENSIVE.md: 469 lines
- CODING_GUIDELINES.md: ~200 lines
- Total Documentation: ~1,098 lines
**Bug Fixes:** 9 critical/important bugs fixed
**Performance Gains:**
- Subprocess calls eliminated: 23 per request
- Attack detection: 100x faster (no nested loops)
- DDoS scenario improvement: 50-200x faster
**Commit Count:** 13 commits with detailed messages
**Documentation Quality:** ✅ Comprehensive, with examples and rationale
## User Feedback Addressed
1. ✅ "This happens a lot with you" (color codes)
- Solution: cecho() helper + CODING_GUIDELINES.md
2. ✅ "Is there a way to avoid this in future?"
- Solution: Search patterns, pre-commit checklist, guidelines
3. ✅ "The security menu has an issue with colors"
- Solution: Fixed echo -e, added prevention docs
4. ✅ "Block ALL blocking 0 IPs"
- Explanation: Working correctly (score 64 < 80 threshold)
- Verified manual blocking works
5. ✅ "If this IP was blocked, why not in IPset?"
- Solution: User needed to restart monitor (old version)
## Repository Status
**Clean:** ✅ All changes committed
**Documentation:** ✅ Up to date
**Testing:** ⏳ Partial (live-attack-monitor tested, enable-cphulk needs cPanel)
**Next Release:** Ready for PHP optimizer implementation
---
**Session End:** All planning complete, documentation comprehensive, bugs fixed, ready for PHP optimizer implementation!
+2 -2
View File
@@ -13,8 +13,8 @@
# - Shared across all monitoring/analysis scripts # - Shared across all monitoring/analysis scripts
################################################################################ ################################################################################
# Database location # Database location (uses /tmp - cleaned on reboot, no system pollution)
IP_REP_DB_DIR="${IP_REP_DB_DIR:-/var/lib/server-toolkit/ip-reputation}" IP_REP_DB_DIR="${IP_REP_DB_DIR:-/tmp/server-toolkit-reputation}"
IP_REP_DB="$IP_REP_DB_DIR/ip_database.db" IP_REP_DB="$IP_REP_DB_DIR/ip_database.db"
IP_REP_INDEX="$IP_REP_DB_DIR/ip_index.idx" IP_REP_INDEX="$IP_REP_DB_DIR/ip_index.idx"
IP_REP_LOCK="$IP_REP_DB_DIR/.db.lock" IP_REP_LOCK="$IP_REP_DB_DIR/.db.lock"
+9 -9
View File
@@ -9,7 +9,7 @@
################################################################################ ################################################################################
# Cache directory for threat intelligence # Cache directory for threat intelligence
THREAT_CACHE_DIR="/var/lib/server-toolkit/threat-cache" THREAT_CACHE_DIR="/tmp/server-toolkit-threat-cache"
mkdir -p "$THREAT_CACHE_DIR" 2>/dev/null mkdir -p "$THREAT_CACHE_DIR" 2>/dev/null
# Cache TTL (24 hours) # Cache TTL (24 hours)
@@ -135,7 +135,7 @@ is_high_risk_country() {
# Check if IP should be whitelisted (legitimate services) # Check if IP should be whitelisted (legitimate services)
is_whitelisted_service() { is_whitelisted_service() {
local ip="$1" local ip="$1"
local whitelist_file="/var/lib/server-toolkit/whitelist_ips.txt" local whitelist_file="/tmp/server-toolkit-whitelist_ips.txt"
# Check static whitelist # Check static whitelist
if [ -f "$whitelist_file" ]; then if [ -f "$whitelist_file" ]; then
@@ -173,7 +173,7 @@ is_whitelisted_service() {
add_to_whitelist() { add_to_whitelist() {
local ip="$1" local ip="$1"
local reason="$2" local reason="$2"
local whitelist_file="/var/lib/server-toolkit/whitelist_ips.txt" local whitelist_file="/tmp/server-toolkit-whitelist_ips.txt"
if ! grep -q "^$ip$" "$whitelist_file" 2>/dev/null; then if ! grep -q "^$ip$" "$whitelist_file" 2>/dev/null; then
echo "$ip # $reason" >> "$whitelist_file" echo "$ip # $reason" >> "$whitelist_file"
@@ -253,7 +253,7 @@ record_attack_pattern() {
local uri="$3" local uri="$3"
local user_agent="$4" local user_agent="$4"
local pattern_file="/var/lib/server-toolkit/attack-patterns/patterns.log" local pattern_file="/tmp/server-toolkit-attack-patterns.log"
mkdir -p "$(dirname "$pattern_file")" 2>/dev/null mkdir -p "$(dirname "$pattern_file")" 2>/dev/null
# Format: timestamp|ip|attack_type|uri|user_agent # Format: timestamp|ip|attack_type|uri|user_agent
@@ -269,7 +269,7 @@ matches_known_pattern() {
local attack_type="$1" local attack_type="$1"
local uri="$2" local uri="$2"
local pattern_file="/var/lib/server-toolkit/attack-patterns/patterns.log" local pattern_file="/tmp/server-toolkit-attack-patterns.log"
if [ ! -f "$pattern_file" ]; then if [ ! -f "$pattern_file" ]; then
return 1 return 1
@@ -324,7 +324,7 @@ is_server_stressed() {
# Generate incident report for an IP # Generate incident report for an IP
generate_incident_report() { generate_incident_report() {
local ip="$1" local ip="$1"
local report_file="/var/lib/server-toolkit/incident-reports/report_${ip//\./_}_$(date +%Y%m%d_%H%M%S).txt" local report_file="/tmp/server-toolkit-incident-report_${ip//\./_}_$(date +%Y%m%d_%H%M%S).txt"
mkdir -p "$(dirname "$report_file")" 2>/dev/null mkdir -p "$(dirname "$report_file")" 2>/dev/null
@@ -365,7 +365,7 @@ generate_incident_report() {
echo "─────────────────────────────────────────────────────────────" echo "─────────────────────────────────────────────────────────────"
# Get attacks from pattern log # Get attacks from pattern log
local pattern_file="/var/lib/server-toolkit/attack-patterns/patterns.log" local pattern_file="/tmp/server-toolkit-attack-patterns.log"
if [ -f "$pattern_file" ]; then if [ -f "$pattern_file" ]; then
echo "Recent attacks from this IP:" echo "Recent attacks from this IP:"
grep "|$ip|" "$pattern_file" | tail -20 | while IFS='|' read -r ts ip_addr attack_type uri ua; do grep "|$ip|" "$pattern_file" | tail -20 | while IFS='|' read -r ts ip_addr attack_type uri ua; do
@@ -408,7 +408,7 @@ share_threat_data() {
local attack_type="$2" local attack_type="$2"
local score="$3" local score="$3"
local coordination_file="/var/lib/server-toolkit/shared-threats.log" local coordination_file="/tmp/server-toolkit-shared-threats.log"
# Log for potential sharing # Log for potential sharing
echo "$(date +%s)|$(hostname)|$ip|$attack_type|$score" >> "$coordination_file" echo "$(date +%s)|$(hostname)|$ip|$attack_type|$score" >> "$coordination_file"
@@ -421,7 +421,7 @@ share_threat_data() {
# Check if IP is flagged by other servers # Check if IP is flagged by other servers
check_shared_threats() { check_shared_threats() {
local ip="$1" local ip="$1"
local coordination_file="/var/lib/server-toolkit/shared-threats.log" local coordination_file="/tmp/server-toolkit-shared-threats.log"
if [ -f "$coordination_file" ]; then if [ -f "$coordination_file" ]; then
local count=$(grep "|$ip|" "$coordination_file" | wc -l) local count=$(grep "|$ip|" "$coordination_file" | wc -l)
+54 -17
View File
@@ -57,7 +57,7 @@ TERMINAL_HEIGHT=$(tput lines 2>/dev/null || echo "24")
# Temporary files for tracking # Temporary files for tracking
TEMP_DIR="/tmp/live-monitor-$$" TEMP_DIR="/tmp/live-monitor-$$"
SNAPSHOT_DIR="/var/lib/server-toolkit/live-monitor" SNAPSHOT_DIR="/tmp/server-toolkit-live-monitor"
mkdir -p "$TEMP_DIR" "$SNAPSHOT_DIR" 2>/dev/null mkdir -p "$TEMP_DIR" "$SNAPSHOT_DIR" 2>/dev/null
touch "$TEMP_DIR/recent_events" touch "$TEMP_DIR/recent_events"
touch "$TEMP_DIR/ip_data" touch "$TEMP_DIR/ip_data"
@@ -304,6 +304,7 @@ get_ip_intelligence() {
echo "${IP_DATA[$ip]}" echo "${IP_DATA[$ip]}"
fi fi
} }
export -f get_ip_intelligence
# Write IP data directly to file (for cross-process communication) # Write IP data directly to file (for cross-process communication)
write_ip_data_to_file() { write_ip_data_to_file() {
@@ -330,6 +331,7 @@ write_ip_data_to_file() {
) 200>"$TEMP_DIR/ip_data.lock" ) 200>"$TEMP_DIR/ip_data.lock"
} }
export -f write_ip_data_to_file
# Update IP intelligence # Update IP intelligence
update_ip_intelligence() { update_ip_intelligence() {
@@ -497,6 +499,7 @@ update_ip_intelligence() {
(update_ip_reputation "$ip" 1 "$score" 0 "Live monitor: $new_attacks" >/dev/null 2>&1) & (update_ip_reputation "$ip" 1 "$score" 0 "Live monitor: $new_attacks" >/dev/null 2>&1) &
fi fi
} }
export -f update_ip_intelligence
################################################################################ ################################################################################
# Advanced Intelligence Functions # Advanced Intelligence Functions
@@ -1175,6 +1178,7 @@ get_threat_level() {
echo "LOW" echo "LOW"
fi fi
} }
export -f get_threat_level
# Get color for threat level # Get color for threat level
get_threat_color() { get_threat_color() {
@@ -1189,6 +1193,7 @@ get_threat_color() {
*) echo "$INFO_COLOR" ;; *) echo "$INFO_COLOR" ;;
esac esac
} }
export -f get_threat_color
# Get bot color # Get bot color
get_bot_color() { get_bot_color() {
@@ -3263,34 +3268,66 @@ detect_distributed_attacks() {
# Check for same attack type from 5+ different IPs (use awk for performance) # Check for same attack type from 5+ different IPs (use awk for performance)
for attack_type in RCE SQL_INJECTION XSS PATH_TRAVERSAL BRUTEFORCE; do for attack_type in RCE SQL_INJECTION XSS PATH_TRAVERSAL BRUTEFORCE; do
# Single AWK pass to count attacks and unique IPs # Single AWK pass to extract all attacking IPs
local result=$(echo "$recent" | awk -v pattern="$attack_type" ' local attacking_ips=$(echo "$recent" | awk -v pattern="$attack_type" '
$0 ~ pattern { $0 ~ pattern {
count++
# Extract IP (first field matching IP pattern) # Extract IP (first field matching IP pattern)
for(i=1; i<=NF; i++) { for(i=1; i<=NF; i++) {
if($i ~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/) { if($i ~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/) {
ips[$i]=1 print $i
break break
} }
} }
} }
END { ' | sort -u)
print count "|" length(ips)
}
')
IFS='|' read -r attack_count unique_ips <<< "$result"
if [ "${attack_count:-0}" -ge 5 ]; then # Count unique IPs
local unique_ips=$(echo "$attacking_ips" | grep -c "^[0-9]" 2>/dev/null || echo "0")
if [ "$unique_ips" -ge 5 ]; then if [ "${unique_ips:-0}" -ge 5 ]; then
# Distributed attack detected! # Distributed attack detected!
local time_str=$(date +"%H:%M:%S") local time_str=$(date +"%H:%M:%S")
echo -e "${CRITICAL_COLOR}[${time_str}] DISTRIBUTED_ATTACK | ${attack_type} from ${unique_ips} IPs in last 2min | Possible botnet${NC}" >> "$TEMP_DIR/recent_events"
# Mark in a file for Quick Actions to see # BLOCK ALL INDIVIDUAL IPs IN THE ATTACK
echo "${attack_type}|${unique_ips}|$(date +%s)" >> "$TEMP_DIR/distributed_attacks" local -a batch_ips=()
while IFS= read -r ip; do
[ -n "$ip" ] && batch_ips+=("$ip")
done <<< "$attacking_ips"
if [ ${#batch_ips[@]} -gt 0 ]; then
batch_block_ips "${batch_ips[@]}"
echo -e "${CRITICAL_COLOR}[${time_str}] DISTRIBUTED_ATTACK | ${attack_type} from ${unique_ips} IPs | BLOCKED ALL${NC}" >> "$TEMP_DIR/recent_events"
fi fi
# Check for subnet-level coordination (25+ IPs from same /24)
declare -A subnet_counts
while IFS= read -r ip; do
[ -z "$ip" ] && continue
local subnet="${ip%.*}" # Get /24 subnet (bash built-in)
((subnet_counts[$subnet]++))
done <<< "$attacking_ips"
# Block entire subnets with 25+ attacking IPs
for subnet in "${!subnet_counts[@]}"; do
local subnet_ip_count=${subnet_counts[$subnet]}
if [ "$subnet_ip_count" -ge 25 ]; then
local subnet_cidr="${subnet}.0/24"
# Check if not already blocked
if ! grep -q "^${subnet_cidr}\$" "$TEMP_DIR/blocked_subnets" 2>/dev/null; then
echo "$subnet_cidr" >> "$TEMP_DIR/blocked_subnets"
# Add to IPset (kernel-level blocking)
if [ "$IPSET_AVAILABLE" -eq 1 ]; then
ipset add "$IPSET_NAME" "$subnet_cidr" -exist 2>/dev/null
echo -e "${CRITICAL_COLOR}[${time_str}] SUBNET_BLOCK | $subnet_cidr | ${attack_type} from ${subnet_ip_count} IPs | BLOCKED${NC}" >> "$TEMP_DIR/recent_events"
fi
fi
fi
done
# Mark in a file for Quick Actions to see
echo "${attack_type}|${unique_ips}|$(date +%s)" >> "$TEMP_DIR/distributed_attacks"
fi fi
done done
fi fi
+1 -1
View File
@@ -57,7 +57,7 @@ TERMINAL_HEIGHT=$(tput lines 2>/dev/null || echo "24")
# Temporary files for tracking # Temporary files for tracking
TEMP_DIR="/tmp/live-monitor-$$" TEMP_DIR="/tmp/live-monitor-$$"
SNAPSHOT_DIR="/var/lib/server-toolkit/live-monitor" SNAPSHOT_DIR="/tmp/server-toolkit-live-monitor"
mkdir -p "$TEMP_DIR" "$SNAPSHOT_DIR" 2>/dev/null mkdir -p "$TEMP_DIR" "$SNAPSHOT_DIR" 2>/dev/null
touch "$TEMP_DIR/recent_events" touch "$TEMP_DIR/recent_events"
touch "$TEMP_DIR/ip_data" touch "$TEMP_DIR/ip_data"