Perfex CRM stores its identity in several places at once: a hardcoded base URL and database credentials in application/config/app-config.php, an encryption key used for stored passwords and tokens, absolute file paths referenced by the uploads system, and a cron command tied to the physical document root. When you move the install to a new account, clone it into a staging subdomain, or replace the primary domain, these values stop matching reality. The symptom is almost never a clean error. Instead you get broken CSS and JavaScript (because assets load from the old URL), login loops, blank admin pages, decryption failures on SMTP or gateway passwords, and a cron job that silently stops firing. Understanding which value points where is what makes the migration predictable.
Why a domain or path change breaks Perfex
Perfex is built on CodeIgniter, so its routing and asset generation depend on a single base_url setting. Unlike WordPress, Perfex does not auto-detect the host on every request by default. The value is written once during installation and read on every page load. When the domain changes but the stored value does not, the application keeps emitting links, form actions, AJAX endpoints, and <script> tags pointing at the old hostname. Browsers block mixed-origin or stale requests, which is why the dashboard loads as unstyled HTML with non-functional buttons.
The second landmine is the encryption key. Perfex encrypts SMTP passwords, payment gateway secrets, and API tokens using the encryption_key defined in the config file. If you copy a database into a fresh install that generated its own key, every encrypted field becomes unreadable, and you will see email sending fail or gateway credentials appear corrupted. Keeping the original key from the source install is mandatory during any migration. The third issue is paths: the cron job and some upload routines reference the absolute server path such as /home/olduser/public_html, which changes the moment you land on a new account or move into a subdirectory.
Because you are operating as an unprivileged hosting user, every one of these corrections is reachable through File Manager, phpMyAdmin, and the cPanel or DirectAdmin cron interface. There is no need for shell access, and nothing here touches server-level configuration.
Moving files and the database cleanly
Start on the source account. In cPanel, open File Manager, navigate to the Perfex root (commonly public_html or public_html/crm), select all files including hidden ones, and use Compress to create a single .zip archive. Download it. For the database, open phpMyAdmin, select the Perfex database, choose the Export tab, pick the Custom method, and enable Add DROP TABLE so re-imports stay clean. Download the .sql file. Large installs with many years of email tracking and activity logs can produce heavy dumps, so if phpMyAdmin times out, export the largest tables (tbltracked_mails, tblactivity_log, tblsessions) separately or truncate tblsessions first since session rows are disposable.
On the destination account, create a new database and database user under MySQL Databases (cPanel) or MySQL Management (DirectAdmin), then assign the user to the database with all privileges. Upload and extract the files archive into the target document root through File Manager. Import the .sql file through phpMyAdmin on the new account. If the dump exceeds the phpMyAdmin upload limit, split the export or raise the limit locally by adding a .user.ini in the directory that holds phpMyAdmin is not possible on shared setups, so instead use the per-table export approach above to keep each file under the limit.
Once files and data are in place, open the configuration file at application/config/app-config.php in the File Manager editor and update the database block to match the new credentials:
define('APP_DB_HOSTNAME', 'localhost');
define('APP_DB_USERNAME', 'newuser_crm');
define('APP_DB_PASSWORD', 'the-new-password');
define('APP_DB_NAME', 'newuser_crmdb');
define('APP_BASE_URL', 'https://newdomain.com/');Copy the ENCRYPTION_KEY value from the original file exactly. Do not let the installer regenerate it. If you are reusing the same account and only changing the domain, the database and key stay identical and only APP_BASE_URL needs editing.
Rebasing the base URL and stored references
The config file handles the primary URL, but older Perfex versions and some add-on modules also cache the site URL inside the tbloptions table. In phpMyAdmin, open the destination database, browse tbloptions, and search the name column for a row named siteurl or any option storing the full domain. Edit its value to the new address. Run a targeted search for the old domain across option values rather than a blind database-wide replace, which can corrupt serialized settings. A safe SQL statement for the options table looks like this:
UPDATE tbloptions
SET value = REPLACE(value, 'https://olddomain.com', 'https://newdomain.com')
WHERE value LIKE '%olddomain.com%';Email templates stored in tblemailtemplates frequently embed the full domain in links and logo image tags, so run the same REPLACE pattern against the message and fromname columns of that table. Check any client portal links in tblcontacts or stored PDF header HTML as well. After each change, reload the Perfex login page; styled output confirms the base URL now resolves correctly.
If assets still fail to load after the config edit, clear the server-side cache by deleting the contents of application/cache/ (keep the index.html placeholder) and remove any compiled asset bundles. Browsers also cache aggressively during a domain switch, so test in a private window.
Cron, paths, and the .htaccess rewrite base
Perfex depends on a cron job for reminders, recurring invoices, auto-close tickets, and scheduled email. The old command points at the previous document root, so recreate it under Cron Jobs in cPanel or DirectAdmin using the new absolute path and the PHP binary selected in MultiPHP Manager or PHP Selector:
/usr/local/bin/php /home/newuser/public_html/crons/cron.phpSet the schedule to every five minutes (*/5 * * * *). Confirm the PHP version chosen for the account matches what Perfex requires, since a mismatched CLI binary will throw fatal errors that only surface in the local error_log inside the Perfex root. Watch that file after the first cron run to confirm clean execution.
When Perfex lives in a subdirectory or you changed the document root, the rewrite rules in .htaccess need the correct base. The shipped file typically contains:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]If the install now sits at /crm/, add RewriteBase /crm/ directly below RewriteEngine On so LiteSpeed resolves routes against the right prefix. Force HTTPS during the move with a canonical redirect, which also helps clear any lingering old-domain references:
RewriteCond %{HTTP_HOST} ^olddomain\.com [NC]
RewriteRule ^(.*)$ https://newdomain.com/$1 [R=301,L]Finally, raise temporary limits for the import and first full page builds by placing a .user.ini in the Perfex root with memory_limit = 256M and max_execution_time = 120, then revert to leaner values once the site is stable. With files, credentials, encryption key, stored URLs, cron path, and rewrite base all pointing at the new location, the migrated instance behaves identically to the original.