Release Notes
iNetPanel Changelog
Every iNetPanel release — new features, fixes, and security updates — sourced from GitHub.
v1.24.5 — Reliability release. Fixes the orphaned-vhost bug behind #17
Reliability release. Fixes the orphaned-vhost bug behind #17, where a deleted domain could leave Apache unable to start and take every site on the server down.
Fixed
Orphaned Apache vhosts (#17). Deleting an account enumerated its domains by scanning the home directory. If that directory was already gone, the vhost survived pointing at a DocumentRoot and log directory that no longer existed. Apache kept serving on its loaded config, so nothing looked wrong — until the next restart (an apt upgrade, a reboot), at which point a missing log directory is fatal and Apache refused to start. Every site on the box then returned 502. Domains are now resolved from the panel database and vhost ownership as well as the filesystem.
Apache config is validated before every reload. remove_domain.sh ran reload || restart — backwards, because a failed reload leaves the working config serving, but the restart that followed took the whole server down. Both add_domain.sh and remove_domain.sh now run apache2ctl configtest first and never escalate to a restart.
add_domain no longer overwrites a live site's index.php. Re-adding an existing domain to regenerate its vhost copied the welcome placeholder over the real homepage. The placeholder is now only written into an empty web root.
inetp status printed garbage and always claimed an update was available. The version lookup matched every line mentioning APP_VERSION, including doc comments, producing a multi-line blob that never compared equal. It also falls back to ASCII on non-UTF-8 consoles, where the status dots rendered as ?.
inetp dns_check example.com now works. It previously required --domain and rejected a bare domain.
The SSH port survives an openssh-server upgrade. The port was written into /etc/ssh/sshd_config, which is ucf-managed on Debian — accepting the maintainer's version on the upgrade prompt silently reverted it and locked you out on the next reconnect. It now lives in /etc/ssh/sshd_config.d/99-inetpanel.conf, and the change is verified to have taken effect before being reported as successful.
Added
inetp rebuild_vhosts — regenerates missing Apache vhosts from the panel database and reports orphaned ones. Run inetp rebuild_vhosts --check for a read-only report; it will tell you whether a broken vhost is waiting to take your server down on the next reboot.
Upgrading
Nothing in this release runs automatically. All of the above execute only on explicit action, so the update itself is a straight file replacement.
If you have ever deleted a domain or an account, sudo inetp rebuild_vhosts --check is worth running once after updating.
v1.24.4 — CRITICAL: php-fpm ProtectSystem fix (account creation broken on updated servers)
⚠️ CRITICAL — please read, and enable automatic backups
This release fixes a system-wide bug that can silently break account creation, domain setup, and SSL on servers that were previously working perfectly. If you run iNetPanel, update and read this.
► Enable automatic backups now
Settings → Backups → enable daily automatic backups, and take a manual backup before updating. The failures in this bug are silent — operations report success while doing nothing — so a known-good backup is your safety net.The bug — full details
- What: php-fpm's systemd unit ships with
ProtectSystem=full, which mounts/etcread-only for every process php-fpm spawns. The panel makes privileged system changes —useradd, Apache vhosts, PHP-FPM pools,vsftpdentries, Let's Encrypt certs — via root helpers launched by php-fpm, andsudodoes not escape php-fpm's mount namespace, so all of those/etcwrites fail. - Symptoms: creating an account fails with
useradd: cannot lock /etc/passwd; try again laterorRead-only file system; adding domains / issuing SSL can fail the same way. Until this release the scripts reported success anyway, leaving "phantom" accounts (ahosting_usersrow with no Linux user) that then block re-creating that username. - Why it appeared out of nowhere:
ProtectSystem=fullis part of the stock php-fpm unit; a routine PHP package update in the past few months enabled it on servers that were fine before. No panel change was involved — a working system simply stops being able to create accounts. It looks like a storage/permission problem but isn't — it happens identically on ext4 and ZFS.
The fix
A php-fpm drop-in setsProtectSystem=true (keeps /usr and /boot read-only, allows /etc). New installs get it from the installer before php-fpm first starts; existing installs get it on update.
⚠️ Applying it on an already-affected server
Most servers need no action — the nightly auto-update (runs as root via cron, outside the sandbox) applies this fix automatically. Just make sure auto-update is enabled under Settings → Updates.To apply it immediately, or if auto-update is off, run once from a root shell:
inetp panel_update # or: php /var/www/inetpanel/scripts/panel_update.php
The web "Update Now" button cannot apply this particular fix — it runs *inside* php-fpm's read-only sandbox. After the fix applies, php-fpm stops sandboxing
/etc and everything (including "Update Now") works normally again. If a username is stuck as a phantom account, delete its hosting_users row and re-create it.
---
Also in v1.24.4
create_user.sh now fails loudly when useradd fails (no more phantom accounts) — this is what finally surfaced the bug above.v1.24.3 — HTTP/1.1 origin hardening + port-collision & multi-PHP fixes
iNetPanel v1.24.3
Bug-fix release hardening multi-tenant isolation and fixing per-domain PHP switching.
Fixed
- Cross-vhost content contamination. The Cloudflare→Apache origin hop is now pinned to HTTP/1.1 via a managed
conf-available/inetpanel-origin.conf(Protocols http/1.1), applied idempotently on update (configtest + safe reload, auto-revert on failure) and by the installer for new installs. This prevents HTTP/2 connection coalescing from ever serving one domain's content (e.g.sitemap.xml) under another. Visitors keep HTTP/2/3 from Cloudflare's edge — only the origin hop changes. - Port-collision isolation.
add_domainnow allocates each vhost port atomically (flock) and scans real usage (ports file + live vhosts), refusing to co-locate two domains on one port. Backup restore re-derives unique, free ports server-side instead of trusting client-submitted values. - Per-domain PHP version switch. Switching a domain's PHP version now runs through a root
multiphp_manage --action set_domainaction using the correct{user}_{domain}pool naming, and validates the domain first. - Existing installs apply the hardening and fixes automatically on update; new installs include them in the installer.
Upgrade
v1.24.2 — Installer cascade fix (#14, #15) + per-domain disk cache
Bug Fixes
- Installer fails on fresh Debian 12 (closes #15). The installer's
exec_cmdhelper ran commands in a backgrounded subshell that didn't have/usr/sbinin PATH, soa2enmodfailed. Added a global PATH export near the top ofinstall_LAMP.shand switcheda2enmod/a2ensite/a2dissite/a2disconfto absolute/usr/sbin/paths. - Unusable MariaDB / phpMyAdmin on fresh install (closes #14). Same root cause as #15: when
a2enmodexited early, the installer skipped the sudoers file, phpMyAdmin storage DB, and panel deploy. Without the sudoers rulewww-datacouldn't read the MariaDB root password — producing *"Access denied for user 'root'@'localhost' (using password: NO)"*. Fix #15 resolves the cascade. - Same disk usage shown on every domain for multi-domain users.
accountDisk()was summing/home/<user>(the whole home dir) and the user's DB total on every row. Now a newdisk_cacheSQLite table tracks per-domain file usage,disk_cache_usertracks the per-user DB total, and the Accounts page shows each domain's actual files size plus a single *Total:* badge per user (files across all their domains + MariaDB total). - /admin/accounts load time. With 30+ domains and 100 GB+ data the page hung for seconds while
du -sbran live for every user. Newscripts/system/disk_cache_scan.shpopulates the SQLite cache every 10 minutes via cron, and fires immediately after add/remove/create/delete via backgroundinetpcalls. The API now reads cached rows — O(ms) regardless of dataset size. - README install command now pre-installs
curlfor fresh Debian 12 installs (apt-get install -y curl && bash <(curl -s …/latest)). build_release.shnow also generateslatest-betaalongsidelatest— same installer, just with the download URL swapped to the main-branch zipball so beta testers pull the latest code instead of the tagged release zip.
Performance
Docs / Packaging
v1.24.1 — Dashboard speed + www ServerAlias hotfix
Performance
- Dashboard load time —
/api/accounts?action=listwas runningdu -sb+inetp db_sizefor every hosting user on every dashboard load (5+ seconds with 31 domains), even though the dashboard only displays 6 rows and doesn't use disk usage. Added?limit=Nand?skip_disk=1query params; dashboard now requestslimit=6&skip_disk=1. Accounts page unchanged — still shows disk usage. - Apache vhost missing www ServerAlias — Apex domains (
example.com) had the DNSwwwCNAME auto-created by the Cloudflare tunnel logic, but the Apache vhost only declaredServerName ${DOMAIN}, sowww.{domain}requests fell through to the default vhost.add_domain.shandrestore_account.shnow addServerAlias www.${DOMAIN}for apex domains (dot-count heuristic: exactly 1 dot, not already prefixed withwww.).
Bug Fixes
v1.24 — Backup Restore with CF Migration Support
New Features
- Backup Restore — Full account restore from backup archives with 4-step wizard: Upload (web with progress bar, FTP, SSH/SCP) → Review (username, domains, ports, databases) → Cloudflare routing check with override → Execute with progress and credential summary.
- Domain availability checker —
inetp check_domainsuses RDAP (free, no API key) for single, bulk, and auto-generated variant checks. - CF tunnel migration — Restore override adds route to new tunnel and removes from old tunnel automatically. Searches all account tunnels for domain conflicts, not just the current server's tunnel.
- Tunnel creation fails on fresh install — Removed invalid
tunnel_secretfrom API-managed tunnel creation. - Beta channel update detection — Was always showing "up to date"; now compares commit SHAs.
- Beta version string stacking — Stripped
-beta.x-beta.ychains to just base + latest hash. - Domain deletion "Connection error" — FPM reload in
remove_domain.shkilled panel worker; deferred to after response. - Restore connection reset at 95% — Same FPM reload issue in
restore_account.sh. - Restore FTP login — Fixed nologin shell, sudo permissions, password (now copies root's shadow hash).
- Restore parse on large backups — Replaced full
tar -tzfbuffering with streaming grep pipes (constant memory). - CF CNAME safety —
removeTunnelHostname()now only deletes CNAME if it points to the specific tunnel being cleaned up, preventing breakage when domains are migrated between servers. - CF domain conflict detection —
check_domainandadd_domainnow search all account tunnels, not just the current server's.
Bug Fixes
v1.23.3 — Fix tunnel creation, beta update detection, add domain checker
Bug Fixes
- Tunnel creation fails on fresh install — Removed
tunnel_secretfromcreateTunnel(). API-managed tunnels (config_src: cloudflare) reject client-side secrets; Cloudflare's Rust serde threw a JSON deserialize error. Token is already retrieved separately viagetTunnelToken(). - Beta channel update detection broken —
update_check.phpandsettings.phpcheck_updatesaction only queried GitHub releases API, never checking main branch commits. Beta channel now compares latest commit SHA against installed SHA to properly detect available updates. - Domain availability checker — Added
check_domains.sh(inetp check_domains). Uses RDAP (free, no API key). Supports single domain, bulk file (-f), and auto-generated variant checks (-g keyword).
New Features
Hotfix
- Installer fails to download panel source —
install_LAMP.shwas pointing atinetpanel.tuxxin.com/inetpanel-latest.zip(404). The zip is a GitHub release asset, not hosted on the website. Fixed URL togithub.com/tuxxin/iNetPanel/releases/latest/download/inetpanel-latest.zip.
Install / Update
bash <(curl -s https://inetpanel.tuxxin.com/latest)
Hotfix
- Multi-PHP install fails silently on fresh installs — The
/var/www/inetpanel/storage/directory wasn't created during deployment, causing status files and logs to never be written. The API now creates the directory if missing and returns a clear error if it can't.
Install / Update
bash <(curl -s https://inetpanel.tuxxin.com/latest)
Existing installs: run inetp panel_update from the admin panel or CLI.
New: Release Channels (Stable vs Beta)
- Installer now uses release tarballs instead of
git clone— the repo (mainbranch) is now beta code, while GitHub Releases are stable.
- - Settings → Updates → Release Channel — toggle between stable and beta without reinstalling. Stable pulls from tagged releases, beta pulls the latest commit from
main. - Multi-PHP install broken on all environments —
systemd-run --scopefails silently in LXC/Proxmox containers with no fallback, leaving the status file stuck at "running" forever. Added direct background execution fallback when systemd-run fails. Simplified the API exec() call and set a 3-minute timeout.
inetpanel.tuxxin.com/latest — stable installer (downloads release zip)
- inetpanel.tuxxin.com/latest-beta — beta installer (clones main branch)
Fixes
Install / Update
bash <(curl -s https://inetpanel.tuxxin.com/latest)
Existing installs: run inetp panel_update from the admin panel or CLI.
Fixes
- Dashboard disk stats inflated —
disk_free_space()excludes ext4 reserved blocks (~5%), making "used" appear ~10 GB higher than reality. Now usesdfoutput for accurate numbers matching what the OS reports. - PHP 5.6 install timeout — Polling timeout increased from 120s to 360s. Older PHP versions take longer to install via apt.
- SSH port fix for LXC containers — Previous fix only checked
is-activeonssh.socket, which misses cases where the socket is enabled but not yet active (common in LXC). Now checkslist-unit-filesandmasks the socket unit to prevent reactivation.
Install / Update
curl -o latest https://inetpanel.tuxxin.com/latest && bash latest
Existing installs: run inetp panel_update from the admin panel or CLI.
Fixes
- SSH port ignored on Debian 12 — Installer now disables
ssh.socket(systemd socket activation hardcodes port 22, overridingsshd_config Port 1022) - SSL cert reissue blocked after self-signed fallback — Cleans up non-LE certs from
/etc/letsencrypt/live/before certbot retry - CertBot DNS propagation timeout — Added
--dns-cloudflare-propagation-seconds 30(default 10s was too short) - Dashboard graph empty on fresh install —
inetpanel_statswas missing frommanage_cron.shallowed list, so the stats collector cron was never created inetp optimize_server— Auto-tunes Apache2mpm_eventand MariaDB InnoDB/buffers based on detected RAM, CPU cores, disk type (SSD/HDD), and hosted domain count. Dry-run by default,--applyto write changes with automatic config backups.
New
Install / Update
curl -o latest https://inetpanel.tuxxin.com/latest && bash latest
Existing installs: run inetp panel_update from the admin panel or CLI.
Logo rebrand & dark mode fixes (v1.22.1)
New branding
- New logo — redesigned iNetPanel logo (PNG with transparency), replaces old
.webp - Favicon — new
Logo-Icon.webpfavicon added to admin and account portals - Logo automatically inverts to white in dark mode via CSS filter
- Account portal logo resized to 28px for cleaner navigation fit
- Table headers —
.table-light<thead>elements now display light text (previously black on dark background) - Nav tabs — dark mode styling for tabbed interfaces (multi-php, firewall pages)
- Bootstrap 5.3 subtle utilities —
bg-success-subtle,bg-primary-subtle,bg-warning-subtle,bg-danger-subtlewith proper dark variants - Close button — filter inversion for visibility on dark backgrounds
- Warning badges — retain dark text for contrast on yellow background
- Table borders — consistent border color in dark mode
Dark mode — root-level fix
The core issue with dark mode was that Bootstrap 5.3 uses internal CSS variables (--bs-body-color, --bs-table-color, --bs-border-color, etc.) that our custom [data-theme="dark"] wasn't overriding. This caused all Bootstrap components to inherit dark text colors regardless of theme.
Fix: Override all Bootstrap 5.3 internal CSS variables at the [data-theme="dark"] root level. This makes every Bootstrap component — tables, cards, headings, links, borders — automatically inherit correct dark mode colors without needing per-component overrides.
Specific fixes
Pages fixed
Accounts, DNS, Email, SSL, Firewall, Multi-PHP, Services, and all other pages that use Bootstrap tables, cards, or badges.Closes #10
Dark mode audit & fixes (v1.22)
Addresses #10 — dark mode inconsistencies and unreadable text.
CSS additions (58 new dark mode rules)
- Badges —
bg-light,text-dark,bg-secondarynow theme-aware - Alerts — info, success, warning, danger with proper dark backgrounds and contrast
- Pre/code blocks — proper dark background and text colors
- Buttons —
outline-dark,outline-secondary,btn-lightvariants - Components — breadcrumbs, nav pills, pagination, input groups, progress bars, accordion, offcanvas, toast
- Logo — brightness inversion filter for dark sidebar backgrounds
- Dashboard chart grid/tick colors now adapt to theme
- QR code colors invert in dark mode (light modules on dark background)
- Removed hardcoded
#e8f4f8alert background in settings - WireGuard code block uses theme-aware
bg-lightinstead ofbg-white
Hardcoded color fixes
Fix PHP package extension install/remove (v1.21.9)
Same root cause as v1.21.8 — dpkg triggers restart php-fpm during apt-get install/remove of individual extensions (e.g. php8.5-uploadprogress), killing the PHP worker mid-request.
Changes
- Extension install/remove now runs inside
systemd-run --scopeto escape the FPM cgroup - Frontend uses async status polling with progress modal (matches multi-php pattern)
- Modal only shown after API confirms operation started (prevents stuck modal on errors)
- Added
pkg_statusAPI endpoint for polling extension install/remove progress
Fix Multi-PHP install/remove (v1.21.8)
Root cause: dpkg triggers restart php-fpm during package install/remove, which kills all processes in the FPM cgroup — including the background apt script launched from PHP exec(). nohup/setsid don't help because systemd kills by cgroup, not process group.
Changes
- Script re-launches itself via
systemd-run --scopeto escape the FPM cgroup before running apt - Fixed status file path mismatch between API and backend script
- Fixed concurrent operation guard falling through to
exec()instead of breaking the switch - Modal now only shown after API confirms success (prevents stuck modal on errors)
- Status file removed immediately after verification, before slow post-cleanup steps
- Moved apt logic from inline PHP to dedicated
multiphp_manage.shbash script
v1.21.7 — Fix Multi-PHP: detached apt execution
Bug Fix
Multi-PHP install/remove silently fails
apt-get ran inside the PHP-FPM worker process. dpkg post-install hooks restart php-fpm, which kills the worker mid-execution — apt never completes, status file stuck at 'running', modal spins forever.
Fix: All apt operations now run in a detached bash script (sudo bash script.sh &) that survives FPM restarts. The script handles the full lifecycle: dpkg configure, apt install/purge, FPM enable/start, upload limits, module reinstall, and cleanup. Status tracking via temp file allows the polling UI to detect success (file removed) or failure (file contains 'error').
Files Changed
api/multiphp.php— Detached bash wrapper for apt operationssrc/multiphp.php— Improved polling with seenRunning state trackingTiCore/Version.php— Version bump
v1.21.6 — Fix Multi-PHP status tracking
Bug Fix
Multi-PHP status file stuck at 'running'
The v1.21.5 status file mechanism never transitioned from 'running' to 'done' because dpkg post-install hooks triggered an FPM restart that killed the PHP worker before it could update the file. The polling modal would spin until timeout.Fix: Status file is deleted immediately after apt succeeds, before any FPM operations. On apt failure, error is written and execution stops immediately.
Files Changed
api/multiphp.php— Reorder status file cleanup before FPM operationsTiCore/Version.php— Version bump
v1.21.5 — Fix Multi-PHP background failure detection
Bug Fix
Multi-PHP install/remove modal spins forever on failure
Whenapt-get failed silently in the background (e.g. package not available, dpkg lock), the polling modal would spin indefinitely since the version state never changed.
Fix: Background apt operations now write status to a temp file. The polling list action reports this status, allowing the UI to detect errors and show them immediately instead of spinning for 3 minutes.
Files Changed
api/multiphp.php— Status file tracking for background apt operationssrc/multiphp.php— Poll checks for background error statusTiCore/Version.php— Version bump
v1.21.4 — Fix Multi-PHP removal & FPM pool cleanup
Bug Fixes
Multi-PHP removal causes 500 error
Removing a PHP version via the admin UI triggered an Internal Server Error becauseapt-get purge restarted the panel's own PHP-FPM process mid-request.
Fix: apt-get now runs after fastcgi_finish_request() so the browser receives a success response before the package removal begins. The UI polls until the version is fully removed before closing the progress modal.
Multi-PHP removal leaves packages behind
The purge command only removed specific packages (fpm, cli, common, etc.) but missed sub-packages like bz2, gd, intl — leaving the binary installed.Fix: Uses wildcard php{ver}-* purge + apt-get autoremove to fully remove all packages for that version.
FPM pools not cleaned up on domain/account removal
Removing a domain or account from the admin UI deleted the pool config file but never reloaded PHP-FPM, leaving orphaned worker processes running.Fix: Both the shell script and API now reload FPM after pool removal.
Database creation SQL syntax error
Creating a database from the client portal failed with "Unknown command" due to escaped backticks in the SQL statement.New Features
inetp rebuild_pools
New CLI command to regenerate all missing PHP-FPM pool configs from the panel database. Useful for recovery after pool files are accidentally deleted.
Dashboard "Accounts & Domains"
The dashboard card now shows both account count and domain count (e.g. "3 / 5").Files Changed (9 files)
TiCore/Version.php, api/account.php, api/accounts.php, api/multiphp.php, scripts/system/inetp, scripts/system/rebuild_pools.sh, scripts/system/remove_domain.sh, src/dashboard.php, src/multiphp.php
v1.21.3 — Fix backup toggle and retention
Bug Fixes
Backup toggle not disabling backups
Toggling backups off in admin settings had no effect — the cron was always written with the backup command, and the script never checked thebackup_enabled setting. Fresh installs saw system config backups appearing even with backups toggled off.
Fix:
api/settings.php: Checksbackup_enabledbefore writing backup cron; writes a disabled comment when offbackup_accounts.sh: Exits early ifbackup_enabled = 0(safety net);--singlemode still works for domain removalapi/settings.php— Backup toggle cron logicscripts/system/backup_accounts.sh— Early exit guard + retention fixTiCore/Version.php— Version bump
Backup retention not cleaning old files
The retention cleanup never removed old backups becauseMTIME_DAYS was calculated inside the loop body but used in the find command's process substitution (which runs before the loop).
Fix: Moved MTIME_DAYS calculation before the find command.
Files Changed
v1.21.2 — Fix database creation, updated README
Bug Fix
Database creation from client portal
CREATE DATABASE used escapeshellarg() which wraps the name in single quotes — MySQL requires backticks for identifiers. All database creation attempts from /user/dashboard#database failed with ERROR 1064. Now uses backtick-wrapped identifiers with regex sanitization.
Updated
- README rewritten — streamlined with home hosting focus, technical stack details, directory layout, and links to [inetpanel.tuxxin.com](https://inetpanel.tuxxin.com) for full documentation
api/account.php— Fix CREATE DATABASE SQL syntaxREADME.md— RewriteTiCore/Version.php— Version bump
Files Changed
v1.21.1 — Fix: Missing cron jobs on fresh install
Bug Fix
Fresh installs missing stats collector and backup cron jobs
New installations were not setting up thestats_collector.sh cron (runs every minute) or the backup_accounts.sh cron (runs daily). These were only created by panel_update.php during subsequent updates, not during initial setup.
Symptoms: Dashboard graph shows no data, automated backups never run.
Fix: install.php now creates both cron jobs during initial setup:
/etc/cron.d/inetpanel_stats— stats collector every minute/etc/cron.d/lamp_backup— daily backup at configured timepublic/install.php— Add stats and backup cron setupTiCore/Version.php— Version bump to 1.21.1
Note: Existing installations already have these crons (created by panel_update.php). This fix only affects new installations.
Files Changed
v1.21 — Public Release
Public Release
iNetPanel is now open source. This release removes all private repository requirements and prepares the codebase for public access.
Changes
Repository Access
- Removed GitHub Personal Access Token (PAT) from admin settings, update system, and installer
install_LAMP.shno longer prompts for authentication — clones directly from the public repo- Update system (
panel_update.php) works without authentication tokens - Creating a server hostname DNS record with a private IP (192.168.x, 10.x, 172.16-31.x) now sets
proxied: false— Cloudflare cannot proxy traffic to private addresses - Applies to both the installer (Step 5) and admin Settings > General
- Existing installations with a
github_tokensetting: the token is harmlessly ignored and can be removed from the database - No breaking changes — all existing functionality works as before
Bug Fix: Private IP + Cloudflare DNS
Upgrade Notes
Installation
bash <(curl -s https://inetpanel.tuxxin.com/latest)
Links
v1.20.4 — Critical: FPM Pool Recovery
Critical Fix
Auto-regenerate missing PHP-FPM pools on update
After an update,panel_update.php now checks all domains in the database and regenerates any missing FPM pool configs in /etc/php/{ver}/fpm/pool.d/. This prevents 503 Service Unavailable errors when PHP-FPM reloads and finds an empty pool directory.
If you're seeing 503 errors on all Apache-hosted sites, run the panel update from Settings > Updates — it will automatically detect and recreate missing pool configs, then reload FPM and Apache.
Firewall port range display
Fixed the firewall UI not showing port ranges like40000-50000/tcp (used by FTP passive mode).
Files Changed
scripts/panel_update.php— FPM pool safety check + regeneration after every updateapi/firewall.php— Port range regex fixTiCore/Version.php— Version bump
v1.20.3 — Hardened update script
Fix
- Hardened rsync ownership handling — Added
--chown=www-data:www-datadirectly to the rsync command so files are synced with correct ownership in a single operation. The post-rsyncchownis kept as a safety net. This eliminates the 403 error that occurred in v1.20.1 where the executing (old) update script lacked the ownership fix.
v1.20.2 — Critical: Fix 403 after update
Critical Fix
- 403 Forbidden after panel update — The rsync in
panel_update.phpruns as root and overwrites file ownership toroot:root. Lighttpd/PHP-FPM runs aswww-dataand cannot read the files, causing a 403 error on all pages. Fixed by restoringwww-data:www-dataownership immediately after rsync.
chown -R www-data:www-data /var/www/inetpanel/
Then update again from the admin panel to get this permanent fix.
v1.20.1 — Patch: Migration Fix & Live Clock
Fixes
- Database migrations not running on update — rsync excluded the entire
db/directory includingdb/migrations/. Now only excludesdb/inetpanel.db,db/.installed, anddb/.admin_pass. Users updating from v1.20 will now get thestats_historytable created automatically, enabling the dashboard resource graph. - PMA config patching regex warnings — "Unknown modifier" and "Undefined variable $i" warnings during panel update. Switched regex delimiter from
/to#. - Admin header live clock — Clock now ticks live every second, matching the client portal.
v1.20 — CLI Tools, Portal Redesign & Installer Hardening
New Features
11 New CLI Commands
inetp status— Server health summary (uptime, load, disk, RAM, services, SSL, backups)inetp benchmark— Quick disk I/O, network speed, PHP opcache, MySQL query benchmarksinetp reset_password --username USER— Reset FTP/SSH/MySQL passwordinetp disk_report— Disk usage breakdown per user with top files/directoriesinetp audit— Security audit (permissions, PHP versions, open ports, weak passwords, fail2ban)inetp malware_scan --username USER— Scan for PHP backdoors/webshellsinetp cleanup— Clear temp files, old logs, orphaned FPM pools, stale sessionsinetp rotate_logs— Force logrotate on all user/system logsinetp db_repair— Check and repair all MariaDB tablesinetp dns_check --domain DOMAIN— DNS propagation, SSL chain, HTTP response, CF tunnel checkinetp speedtest— Server bandwidth test (curl-based, no dependencies)- Historical CPU, memory, and network usage with 1h/24h/7d views
- Background stats collector cron (every minute) populates
stats_historytable - Smooth Chart.js graphs with time-based x-axis labels
- Overview: All domains listed in compact table with PHP version, web root, port, disk, status
- Database: List existing databases, create new with
username_prefix, delete modal with PMA link - Multi-PHP: Change PHP version per domain with dropdown
- Optimize: Image optimization with directory selection and dry-run preview
- Backups: View and download account backups
- File Manager: .htaccess editor with directory tree + password protection
- FTP/SSH and SSH Keys moved to bottom of Overview tab
- Domain dropdown only in File Manager and Optimize tabs
- Live clock in header, user icon
- Verify button checks Cloudflare DNS for hostname existence
- Auto-create A record if hostname is available
- Server IP detection with private/public IP notice
- Configured passive port range (40000–50000) in
vsftpd.conf - Opened passive ports in firewalld
- Fixes FTP upload failures on large batch transfers (GitHub issue #8)
latestfile included in repo for web hosting atinetpanel.tuxxin.com/latest- Support widget in sidebar footer (admin) and portal footer
- Firewall rule ordering — WG rules now added before restrictive DROP rules
- Peer IP allocation — sequential /32 addresses from WG subnet
- Config validation — prevents duplicate peers and invalid IPs
- Peer cleanup on user deletion
- Uninstall script fixes ListenAddress and port fallback
- Lock file now blocks ALL requests (GET and POST) after installation
stats_historytable added to install schema (schema_version bumped to 2)- MariaDB timezone tables loaded (
mysql_tzinfo_to_sql) before setting timezone - Timezone config only persisted if runtime SET succeeds
event.target→ button parameter fix for Cloudflare test button- Server IP fallback for DNS record creation
- Null coalescing for POST values
- Settings hostname verify uses public CloudflareAPI methods (was calling private
request()) - Multi-PHP version change uses
fastcgi_finish_request()before FPM reload (prevents 500 error) - Database listing uses
sudo /bin/catfor MySQL root password (www-data can't read directly) - Admin PMA sidebar link routes through auto-login
Dashboard Resource Graph
Client Portal Redesign
Settings Hostname Verification
VSFTPD Passive Mode Fix
Installer Distribution
Buy Me a Coffee
Bug Fixes
WireGuard
Installer Hardening
Other Fixes
Files Changed (37 files, +4334 / −290)
v1.19 — Client Portal Overhaul & phpMyAdmin Auto-Login
New Features
Client Portal Overhaul
- Complete redesign with tabbed dashboard: Overview, Database, FTP / SSH, File Manager, Backups, DNS, and Email
- SSH Key Management — generate, import, and delete SSH keys directly from the portal
- .htaccess File Manager — browse directories, edit
.htaccessfiles, and password-protect directories with.htpasswd(supports multiple users) - Backups tab — view and download your account backups
- Database info — explains
username_*prefix convention for creating additional databases - Token-based signon authentication — one-click login from both admin panel (as root) and client portal (as hosting user)
- Deploys
signon.phpand patches PMA config automatically on panel update - Fallback login form prevents redirect loops when accessing PMA directly
- Toggle Under Attack Mode and Development Mode per zone from admin DNS page and client portal DNS tab
- Immediate Cloudflare API calls with status feedback
- Automated backups now include system configuration files: Apache, PHP, MariaDB, lighttpd, fail2ban, WireGuard, SSH, cron, vsftpd, and the panel SQLite database
- Same retention policy as user backups
- Changing timezone in Settings or during installation now updates MariaDB global timezone and persists to
/etc/mysql/mariadb.conf.d/99-timezone.cnf - URL hash navigation:
/admin/settings#general,#cloudflare,#updates, etc. - Hash updates in address bar on tab switch for bookmarking/sharing
- Banned username list (50+ system names) prevents creating hosting accounts with names like
root,admin,www-data,mysql, etc. - Auto-generated usernames from domains are prefixed if they collide with reserved names
- Admin PMA sidebar link now routes through
/admin/phpmyadminfor auto-login instead of linking directly to port 8443 - Portal PMA no longer falls back to root for regular user sessions
conf.d/pma_secure.phpoverride patched during panel update
phpMyAdmin Auto-Login
Cloudflare DDoS & Development Mode
System Config Backups
MySQL Timezone Sync
Settings Deep Links
Reserved Usernames
Bug Fixes
Files Changed (16 files, +1520 / -293)
README.md, TiCore/AccountAuth.php, TiCore/CloudflareAPI.php, TiCore/Version.php, api/account.php, api/accounts.php, api/dns.php, api/settings.php, public/index.php, public/install.php, scripts/panel_update.php, scripts/system/backup_accounts.sh, src/account/portal.php, src/dns.php, src/settings.php, themes/default/sidebar.php
Release notes are fetched from github.com/tuxxin/iNetPanel/releases and cached for 6 hours.