upload only checked [path], which is parsed from JSON php://input and is always empty for multipart/form-data uploads. It silently fell back to a hardcoded /public_html, which does not exist at filesystem root - breaking uploads for the admin File Manager (baseDir=/) entirely, though it went unnoticed for regular hosting accounts since /public_html happens to be their real default. Now falls back through and as well.
- New File Manager page under Admin > System, built on the existing /api/files endpoint (admin sessions with no linked hosting account get baseDir=/, i.e. full filesystem).
- Fixed two baseDir=/ edge-case bugs in files.php: safe_path() double-slash prefix check, and list actions path stripping via str_replace corrupting every slash.
- Added download and chown actions to files.php.
- Added a server-enforced dangerous-path guard: write/delete/rename/chmod/chown/mkdir/upload/compress/extract targeting /etc,/boot,/root,/sys,/proc,/dev,/run,/lib*,/bin,/sbin,/var/lib,/snap are rejected with 409 unless confirm_dangerous=true is sent - matched by a client-side warning modal requiring a checkbox and typed CONFIRM.
- install.sh: added zip package (required by the existing compress action, was missing).
1. admin.js: dashboard setTimeout was after return (dead code) — restructured
to assign template to const html, run setTimeout, then return html
2. DockerManager.php createStack: replaced SELECT LAST_INSERT_ID() with
db->insert() which already returns lastInsertId correctly for SQLite
3. DockerManager.php setQuota: replaced ON DUPLICATE KEY UPDATE / VALUES()
MySQL syntax with SQLite-compatible ON CONFLICT(user_id) DO UPDATE SET
excluded.col syntax
4. post-restore.sh: PHP helper file now written ONCE at start of step 4
before any call to it (was written AFTER first call, causing silent failure)
5. post-restore.sh: git pull exit code now captured before pipeline (the
while-read loop always exited 0, masking pull failures)
6. uninstall.sh: tar backup now aborts on failure (previously 2>/dev/null
swallowed errors and rm -rf destroyed source unconditionally); also
rm -f → rm -rf for .service.d drop-in directory
- Added history chart to dashboard: fetches stats/server API, renders
24-hour CPU/RAM/Disk chart with Chart.js lazy-loaded
- setTimeout properly INSIDE function before closing brace
- Removed ONLY serverStatus() function body (2521 chars), kept initStatsChart
- pages object redirects server-status → dashboard
- Removed server-status from admin sidebar nav
- All 26 functions intact, backticks balanced, accounts/packages/DNS all kept
- Cleans orphaned DB user records before recreating webacct
- Handles both orphaned-Linux-user and orphaned-DB-user cases
- Pulls latest NovaCPX code + runs migrations
- Bumps PHP-FPM pm.max_children to 20 if still at default 5
- Creates /tmp/_nova_create_webacct.php helper separately (avoids here-doc PHP issues)
- Deploys both index.html and notes.php from web-dashboard repo
- Disables Apache2 if running
- --no-git flag to skip code pull
- Comprehensive logging with ✓/⚠ indicators
- Adminer installed at /adminer.php (MySQL + PostgreSQL)
- db-tools API now detects adminer.php file and returns its URL
- Tool cards: phpMyAdmin, Adminer (MySQL/PG), pgAdmin4
- Open buttons use API-provided URL (adminer.php for Adminer)
- Separate MySQL and PostgreSQL database sections in DB Manager
- PostgreSQL section has direct link to Adminer PG mode
- #42 Docker: already complete (full docker page with all tabs)
Previous merge accidentally deleted 38KB of page functions (accounts, packages,
DNS, etc.) by using wrong boundary. This time only removes the serverStatus()
function body. Dashboard now includes history chart + setTimeout to render it.
All other pages intact.
- Row badge updates to 'stopping…'/'starting…' instantly on click
- Buttons disabled while action runs so no double-clicks
- List stays visible while refreshing after action (no blank flash)
- container-remove changed to POST so body passes through proxies correctly
- removeImage now throws RuntimeException when docker rmi output contains
'Error' or 'conflict' so the API returns success:false with the message
- Added docker/sync-orphans endpoint (admin only) to register existing
Docker containers not tracked in the NovaCPX DB (e.g. after a restore)
Concurrent cron writes (collect-stats.php every 5min) caused DB lock errors
that aborted the entire stats response, leaving web/mail/FTP pages empty.
History insert is now non-fatal.
Using PORT_USER ?? 8880 threw Error in PHP 8 since the constant isn't defined
until Core.php is require_once'd later in the file. Every API request was
hitting the exception handler and returning 'An internal error occurred.',
breaking all logins and API calls.