--- name: project-novacpx description: NovaCPX — custom Linux web hosting control panel (cPanel alternative) built from scratch metadata: node_type: memory type: project originSessionId: c454fc50-f93d-4ddd-b9f3-f3f442e89fb9 --- NovaCPX is a full web hosting control panel built from scratch with 4 dedicated ports: Admin :8882, Reseller :8881, User :8880, Webmail (Roundcube) :8883. **Why:** User wants a cPanel/Plesk alternative they own outright, with distinctive UI, auto-installer, and extensible feature system. **How to apply:** Direct SSH to VM works (no PVE hop needed). All code in /tmp/novacpx locally + pushed to GitHub myronblair/novacpx. ## VM Details - Host: PVE1 VM 120, name HostPanel-110 - IP: 10.48.200.110 (static) - OS: Ubuntu 24.04 LTS - **SSH (direct — works from Claude Code):** `sshpass -p 'Joker1974!!!' ssh -o StrictHostKeyChecking=no root@10.48.200.110` - **SCP (direct):** `sshpass -p 'Joker1974!!!' scp -o StrictHostKeyChecking=no FILE root@10.48.200.110:/path` - PVE1 hop NOT needed and currently broken (permission denied on orbisne.fortiddns.com SSH) - Panel web root: /srv/novacpx/public - Repo on VM: /opt/novacpx-src - Source of truth for deploy scripts: /opt/novacpx-src/deploy/ ## GitHub - Repo: myronblair/novacpx (private) - Branches: `main` (stable releases, PATCH auto-bump) and `beta` (beta releases, -beta.N auto-bump) - Auto-deploy: push to main or beta → GitHub webhook → VM pulls (deploy-runner.sh cron every min) - PAT: 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 ## Ports - 8880 — User panel - 8881 — Reseller panel - 8882 — Admin/datacenter panel - 8883 — Roundcube webmail ## Architecture - Backend: PHP 8.3 REST API (/api/{endpoint}/{action}) - Auth: session cookie `ncpx_session` (login returns token, set as cookie) + Bearer tokens for API. Both use SHA256 hash lookup in sessions/api_tokens tables. - DB: **SQLite** at /var/lib/novacpx/panel.db (migrated from MySQL 2026-06-09) - DB.php has translate() layer: ON DUPLICATE KEY→ON CONFLICT, DATE_ADD/DATE_SUB→datetime(), NOW()→datetime('now') - **novacpx_version table**: tracks install history; columns: id, version, installed_at, notes, git_commit - **settings table**: panel_version key tracks current version; update_channel (stable/beta) controls which GitHub branch to check/pull - Feature registry: 70+ pluggable features in 20 categories - Update channels: stable=origin/main (major/minor), beta=origin/beta (patch/pre-release) ## VM Credentials - Admin panel: `admin / Admin2026!` - Root SSH: `root / Joker1974!!!` - MySQL (customer sites): novacpx_user / 6fyWj6vYnJDKEQvNANzj - WP provisioning MySQL user: novacpx_wp / tCXAU1K2WX31xUAMY9EM - Config: /etc/novacpx/config.ini (root:www-data 640) ## JARVIS Agent - Installed 2026-06-09; agent_id: novacpx_e3b07264 - Status: online, reporting heartbeats to JARVIS every 10s - Config: /opt/jarvis-agent/config.json - Key config fields: server_url, host_header, api_key, agent_type: linux, heartbeat_interval: 10 ## Versioning (as of 2026-06-10) - Current git version: 1.0.27 (GitHub main) - Active deploy channel: beta (VM settings) - GitHub Actions auto-bumps VERSION on push to main (PATCH) or beta (-beta.N) - deploy-runner.sh writes new version to novacpx_version + settings.panel_version after every webhook deploy - deploy-runner.sh also copies VERSION to web root (/srv/novacpx/public/VERSION) — fixed 2026-06-10 - apply-novacpx-update endpoint does the same for manual updates - Updates page shows installed version, latest remote version, and active channel badge ## Settings Page - Loads current values from DB via server-options API (panel_name, default_php, nameservers, update_channel) - Saves each field via save-option API individually - Update channel dropdown shows stable vs beta with explanatory labels ## Docker App Catalog (as of 2026-06-10) - **140 apps** across 15 categories in DockerManager.php - Categories: Web/CMS, Productivity, Dev, Analytics, Wiki/Docs, Messaging/Chat, Security/Auth, Business, Design/Collab, AI/LLM, Developer Tools, Databases, Monitoring, Networking/Security, CMS/E-commerce, Project Mgmt, Communication, File/Storage, ERP/Business, Media, Smart Home, Dashboards/Admin - Security fixes applied (code review 2026-06-09): shell injection fixes in WordPressManager, PHPManager, install.sh sudoers hardening (removed `ufw *` wildcard, removed `curl *` and `env *` NOPASSWD), SQLite syntax fix, WP-CLI download size validation - Per-account uninstall (uninstall-account API action), per-stack Reinstall button - Admin Docker page has App Catalog tab to launch apps on behalf of accounts ## nginx / phpMyAdmin (fixed 2026-06-12) - Apache2 was holding port 80 — stopped and disabled: `systemctl stop apache2 && systemctl disable apache2` - nginx now running and enabled on boot - phpMyAdmin accessible at `http://10.48.200.110/phpmyadmin` (returns 200) - nginx config: `/etc/nginx/sites-enabled/default` with /phpmyadmin location block - phpmyadmin.conf in /etc/nginx/conf.d/ is empty (just a comment) — all config in sites-enabled/default ## Known Quirks - PVE1 SSH (orbisne.fortiddns.com) currently permission-denied — use direct IP 10.48.200.110 instead - api/.htaccess needed for URL routing - NOVACPX_ROOT in api/index.php is dirname(__DIR__) = /srv/novacpx/public (NOT 2 levels up) - SQLite only — never use MySQL syntax (ON DUPLICATE KEY, NOW(), etc.) - sudo tee pattern needed for writing /etc/postfix/* files as www-data - Docker stacks backed by docker_compose_stacks table (separate from docker_containers) - Panel reachable at https://10.48.200.110:8882 (self-signed cert with SAN for IP) - PHP-FPM pools are root-owned; www-data cannot file_exists()/unlink() them — must use `sudo rm -f` - git cherry-pick to beta required after each main push (GitHub Actions version bumps create divergence)