Commit Graph

127 Commits

Author SHA1 Message Date
github-actions[bot] db033732b4 chore: bump version to 1.0.26 [skip ci] 2026-06-10 13:01:12 +00:00
myron 9bc427f8a2 feat: per-stack Reinstall + fix stack ownership enforcement
- API: stack-action/stack-remove now verify ownership for non-admin users
- API: add stack-reinstall action (pull latest images → down → up)
- User panel: add Reinstall button per stack; fix bug where remove-stack was called instead of stack-remove
- Admin panel: add Reinstall button per stack + dockerStackReinstall() handler
- User panel: Remove All My Apps now only removes the calling user's own containers/stacks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 13:01:01 +00:00
github-actions[bot] f17210fd3b chore: bump version to 1.0.25 [skip ci] 2026-06-10 12:58:54 +00:00
myron 7a42be8d01 feat: Docker catalog in admin panel + per-account app removal
- Admin Docker page: add App Catalog tab (60 apps, account-picker modal)
- Admin Docker page: add dockerAdminLaunchApp() for launching apps on behalf of any account
- User panel: add 'Remove All My Apps' button — stops/removes only that user's own containers and stacks
- API: add uninstall-account action (user-scoped; admin can specify account_id, users limited to own account)
- Admin panel: no global Docker uninstall (would affect all users on the server)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:58:43 +00:00
github-actions[bot] 2e96c2b0b9 chore: bump version to 1.0.24 [skip ci] 2026-06-10 12:55:47 +00:00
myron 61329ff343 feat: expand Docker app catalog from 21 to 60 apps
Adds 39 new apps across 8 categories:
- Media & Files: Jellyfin, Navidrome, Kavita, Paperless-ngx, File Browser, Seafile, Immich
- Monitoring & DevOps: Adminer, Grafana, Prometheus, Netdata, Glances, Healthchecks, Docker Registry, Verdaccio, Watchtower
- Git & CI/CD: Forgejo, Woodpecker CI
- Knowledge: BookStack, HedgeDoc, FreshRSS, Wallabag, Homepage
- Auth & Security: Keycloak, Authentik, Passbolt CE
- Analytics: Plausible (Postgres + ClickHouse)
- Low-code / No-code: Baserow, Appsmith CE, NocoDB
- Communication: Rocket.Chat, Chatwoot, Zammad
- Business: Invoice Ninja, Linkding, Mealie
- Design: Penpot, Excalidraw, Stirling PDF

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:55:35 +00:00
github-actions[bot] 81a8ea88f4 chore: bump version to 1.0.23 [skip ci] 2026-06-10 12:45:41 +00:00
myron 2cc219f9fa feat: add 12 Docker app catalog entries
Adds Uptime Kuma, Portainer CE, MinIO, n8n, Directus, Listmonk, Umami,
PhotoPrism, Meilisearch, Wiki.js, Vikunja, and Mattermost — each with
catalog metadata and a complete docker-compose template.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:45:30 +00:00
github-actions[bot] e87e1a14b8 chore: bump version to 1.0.22 [skip ci] 2026-06-10 12:32:17 +00:00
myron 2fa1f10901 Security: fix 8 code-review findings
- install.sh: replace /usr/sbin/ufw * with scoped subcommands
- install.sh: remove /usr/bin/curl * and /usr/bin/env * NOPASSWD (trivial root escalation)
- PHPManager: switchVersion() uses sudo rm -f instead of unlink() for old pool
- PHPManager: updateConfig() SQLite syntax (ON CONFLICT / datetime('now'))
- WordPressManager: cloneStaging() escapeshellarg() on all shell-interpolated paths
- WordPressManager: delete() removes DB record before filesystem to avoid phantom records
- WordPressManager: ensureWpCli() validates download size and enforces 30s timeout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:32:06 +00:00
github-actions[bot] 5037633f5f chore: bump version to 1.0.21 [skip ci] 2026-06-10 05:53:34 +00:00
myron 658e2f9057 Fix PHP-FPM pool not removed on account termination
Two bugs that together left stale pool files behind after termination,
crashing php-fpm on next startup (exit-code 78, user not found):

1. removePool() used file_exists() to guard the rm — fails silently when
   www-data can't read /etc/php/*/fpm/pool.d/; now always attempts sudo rm -f
2. reloadFPM() called systemctl without sudo — silently failed as www-data,
   leaving the old pool loaded even when the file was successfully removed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 05:53:25 +00:00
github-actions[bot] 7107d230c8 chore: bump version to 1.0.20 [skip ci] 2026-06-10 05:51:17 +00:00
myron e6550f0a90 Add full service sudoers rules to installer
Previous installer only granted www-data access to nginx/apache2/fail2ban.
Added NOPASSWD rules for all panel-managed services:
postfix, dovecot, rspamd, proftpd, vsftpd, pure-ftpd,
named/bind9/pdns/nsd, mysql, mariadb, php*-fpm.
Without these, service restart/stop/start buttons returned 502
(shell_exec hung waiting for sudo password → Apache timeout).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 05:51:08 +00:00
github-actions[bot] b0ac6e7aa2 chore: bump version to 1.0.19 [skip ci] 2026-06-10 05:45:42 +00:00
myron b9c37030b6 Fix terminate 500: require DatabaseManager before calling drop
AccountManager::terminate() called DatabaseManager::drop() without
requiring the class first — fatal class not found error on every
account termination.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 05:45:33 +00:00
github-actions[bot] 892034d3a7 chore: bump version to 1.0.18 [skip ci] Nova1014 2026-06-10 03:17:50 +00:00
myron 57949214de Fix WordPress manager 500: define DB_HOST, lazy-load MySQL provDb
- Core.php: add DB_HOST constant (was undefined, causing fatal error on any
  WordPress manager page load in PHP 8)
- WordPressManager: make provDb lazy (only connects to MySQL when actually
  needed for install/clone/delete — not on list/info which only use SQLite)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 03:17:39 +00:00
github-actions[bot] 8f32c973cb chore: bump version to 1.0.17 [skip ci] 2026-06-10 03:06:23 +00:00
myron 4d7c35076b Fix 10 code review findings: security, correctness, and SQLite compat
- system.php: fix null dereference on fetchOne (TypeError on null['value'])
- system.php: validate update_channel to ['stable','beta'] to prevent shell injection
- system.php: escapeshellarg remoteBranch in git log/show calls (was RCE vector)
- system.php: fix backup path — rsync contents, not directory, so restore is symmetric
- system.php: syntax check only changed files (git diff) not all 300+ panel files
- system.php: copy VERSION to $webRoot/VERSION not $webRoot/../VERSION (wrong path)
- system.php: fix 3× ON DUPLICATE KEY UPDATE → SQLite ON CONFLICT syntax
- deploy-runner.sh: hoist DB_PATH/CHANNEL above while loop
- deploy-runner.sh: sanitize NEW_VERSION and commit hashes before SQL interpolation
- deploy-runner.sh: parse queued branch (4th field) from webhook queue entry
- webhook.php: remove dead $branch config variable
- webhook.php: include pushed branch in queue entry to eliminate TOCTOU race

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 03:06:14 +00:00
github-actions[bot] 64c9569104 chore: bump version to 1.0.16 [skip ci] 2026-06-09 23:10:31 +00:00
myron 7367fe658c Update documentation with all current features and services
- README: full feature matrix (hosting, DNS, email, databases, files, SSL, security, Docker,
  monitoring, update channels/versioning, reseller branding, settings, API)
- Admin guide: update channels section with stable/beta table; Settings section now documents
  all DB-backed fields including update channel
- User guide: email domain dropdown note

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 23:10:19 +00:00
github-actions[bot] 95cc4914cd chore: bump version to 1.0.15 [skip ci] 2026-06-09 22:55:54 +00:00
myron 14aa6e8b4d Fix column name: commit_hash → git_commit in novacpx_version INSERT
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:55:43 +00:00
github-actions[bot] 3b47fc27e7 chore: bump version to 1.0.14 [skip ci] 2026-06-09 22:44:58 +00:00
myron 9cabe8af5e Wire update channel (stable/beta) into settings, check, deploy, and version tracking
- Settings page now loads current values from DB and saves via save-option API
- check-novacpx-update reads update_channel setting, checks origin/main or origin/beta
- apply-novacpx-update pulls from channel branch, fixes backup dir (/tmp), fixes SQLite migration syntax, records new version in novacpx_version table + settings.panel_version
- deploy-runner.sh reads update_channel from DB, pulls correct branch, records version after deploy
- webhook.php accepts pushes to both main and beta branches
- Updates page shows channel badge and latest remote version

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:44:46 +00:00
github-actions[bot] d53eb309eb chore: bump version to 1.0.13 [skip ci] 2026-06-09 22:31:02 +00:00
myron 846683c7a2 Add SEO meta description, keywords, and noindex to all three panel pages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:30:53 +00:00
github-actions[bot] 9dd75bfff8 chore: bump version to 1.0.12 [skip ci] 2026-06-09 22:25:00 +00:00
myron f9d423b15a Fix OS upgrade script: date format and backup dir permission
- date -u +%H:%M:%S UTC → ts() helper with date -u +"%H:%M:%S UTC"
  (UTC as a separate word was being treated as an extra date argument)
- Backup dir changed from /var/novacpx/backups/ (root-owned, doesn't exist)
  to /tmp/novacpx-backup-TIMESTAMP/ (always writable by www-data)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:24:50 +00:00
github-actions[bot] 2f141973c1 chore: bump version to 1.0.11 [skip ci] 2026-06-09 22:23:55 +00:00
myron 09bd0820a5 Updates page: serve cached results instantly, nightly cron refreshes cache
- check-novacpx-update and check-os-update return cached data (12h TTL)
  immediately instead of running slow git fetch / apt-get update on page load
- Cache stored in settings table (update_cache_novacpx, update_cache_os)
- Updates page shows "Cached · last checked X ago" when serving cache
- "Refresh now" button forces a live re-check and updates cache
- bin/cache-update-check.php: standalone cron script that warms cache nightly
- Cron registered at 2am daily on panel server

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:23:45 +00:00
github-actions[bot] 0c32c8a018 chore: bump version to 1.0.10 [skip ci] 2026-06-09 22:18:49 +00:00
myron 877f157665 Docker page: show compose stacks in My Apps tab instead of raw containers
launchFromCatalog creates compose stacks, not docker_containers entries.
Replace My Containers tab with My Apps tab backed by docker/stacks endpoint.
Add Refresh, Start/Stop, Logs, Remove actions per stack row.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:18:39 +00:00
github-actions[bot] cdb92c5ef2 chore: bump version to 1.0.9 [skip ci] 2026-06-09 22:15:52 +00:00
myron 1ac9728fd7 Fix Docker async launch, email SUBSTRING_INDEX (SQLite), postfix sudo writes
- Docker app launch now runs docker compose up -d in background (nohup &)
  so the API returns immediately instead of timing out during image pulls
- EmailManager syncPostfix: replace MySQL SUBSTRING_INDEX with SQLite SUBSTR/INSTR
- EmailManager syncPostfix: write postfix files via sudo tee (www-data permission fix)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:15:41 +00:00
github-actions[bot] b90ef41677 chore: bump version to 1.0.8 [skip ci] 2026-06-09 22:13:39 +00:00
myron 24a2434ccd Email create modal: split input into local-part + domain dropdown
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:13:29 +00:00
github-actions[bot] 071f32ce76 chore: bump version to 1.0.7 [skip ci] 2026-06-09 22:10:06 +00:00
myron dc8829e2c9 Fix DockerManager stack directory creation using sudo mkdir for www-data
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:09:55 +00:00
github-actions[bot] 24e0ce3633 chore: bump version to 1.0.6 [skip ci] 2026-06-09 22:04:29 +00:00
myron 89996cc0ea Fix _branding.php session lookup using correct column name (id not token)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:04:18 +00:00
github-actions[bot] 978ea6082c chore: bump version to 1.0.5 [skip ci] 2026-06-09 18:58:00 +00:00
myron b90f753890 Add version badge to reseller and user panel sidebars
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 18:57:48 +00:00
github-actions[bot] 8a11458220 chore: bump version to 1.0.4 [skip ci] 2026-06-09 18:42:41 +00:00
myron ddd81d73e7 Fix MySQL create: sanitize db names, fix empty db_user default, catch RuntimeException
Dots/dashes in names were failing validateName; now stripped to underscores.
Empty db_user field sent as "" (not null) so ?? fallback never fired; fixed
to check for empty string explicitly.  Wrap createMySQL/Postgres in try/catch
so validation errors return 400 JSON instead of 500.  Also pass db_type from
JS (was being sent as db_type not type).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 18:42:24 +00:00
github-actions[bot] 8716299201 chore: bump version to 1.0.3 [skip ci] 2026-06-09 18:32:26 +00:00
myron c22e1fd067 Fix multiple user panel 500 errors
- domains: VhostManager::create() called with array instead of 4 params
- PHPManager: VhostManager not required; pool writes use sudo tee (permission);
  updateConfig creates pool if missing instead of throwing
- DatabaseManager: MySQL ops used SQLite panel PDO; add dedicated mysqlPdo()
  using MariaDB socket auth
- BackupManager: column name is size_mb not size; diskUsage returns float
- DB.php: add LAST_INSERT_ID() → last_insert_rowid() translation
- user.js: SSL issue/submit used Nova.api (JSON) but endpoint streams SSE;
  add _sslStream() helper matching admin panel behavior
- schema/migration: add enc_password column to email_accounts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 18:32:10 +00:00
github-actions[bot] 563386b8b8 chore: bump version to 1.0.2 [skip ci] 2026-06-09 18:22:22 +00:00
myron 8179326526 Fix NOVACPX_ROOT undefined on panel pages (black screen)
Constants were only defined in api/index.php, so direct requests to
admin/reseller/user index.php got a fatal error before rendering any HTML.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 18:22:05 +00:00