Designer Experty Paper to Pixel, Clear and Crystal

How to Create a Staging Site for OpenCart 3 (cPanel)

A staging site is a private copy of your live store where you test changes before they touch production. The whole job is: copy the files, copy the database, then point every path, URL and database setting at the copy.

This guide covers OpenCart 3.0.x (tested on 3.0.3.9 with the Journal theme) on a cPanel server, with staging in its own cPanel account. Example values used throughout:

Item Live Staging
Domain demo.com staging.demo.com
cPanel account demo stagingdemo
Web root /home/demo/public_html/ /home/stagingdemo/public_html/
Storage folder /home/demo/storage/ /home/stagingdemo/storage/
Admin folder admin admin
Database demo_oc stagingdemo_oc

The golden rule: once setup is done, nothing on staging may point at a live path, the live database, live payment keys or real customer email. Most staging errors come from one leftover /home/demo/ path.

Step 1: Prepare the account, subdomain and DNS

  1. In WHM, create a new cPanel account for staging (e.g. stagingdemo) with staging.demo.com as its domain. A separate account keeps staging isolated, so it can’t read or break live files.
  2. In cPanel → MultiPHP Manager, set the same PHP version as live (e.g. PHP 8.2). Also match the PHP extensions the live site uses (ionCube, zip, gd, curl, mbstring).
  3. In your DNS (e.g. Cloudflare), add one A record: staging → your server IP. Set it to DNS only (grey cloud) while setting up.
  4. Make sure there is only one staging A record. A leftover record pointing at an old server causes random 522 errors.
  5. In cPanel → SSL/TLS Status, run AutoSSL so https works.

Step 2: Copy the files

You need to copy two things: the web root and the storage folder. OpenCart 3 usually keeps storage outside public_html, which makes it easy to forget.

The fastest way is over SSH: zip on the live side, then unzip on staging.

cd /home/demo
zip -r /home/stagingdemo/site.zip public_html -x 'public_html/image/cache/*'
zip -r /home/stagingdemo/storage.zip storage -x 'storage/cache/*' 'storage/modification/*' 'storage/logs/*'

cd /home/stagingdemo
unzip -o site.zip && unzip -o storage.zip
rm site.zip storage.zip

Without SSH: in cPanel File Manager on the live account, compress public_html and storage, download both, upload them into /home/stagingdemo/, then extract.

Leaving out image/cache, storage/cache and storage/modification saves a lot of space, and OpenCart rebuilds them automatically. On a large catalogue, image/cache alone can be several GB.

Step 3: Copy the database

  1. In the staging cPanel → MySQL Databases, create a database (e.g. stagingdemo_oc) and a user. Add the user to the database with ALL PRIVILEGES.
  2. Export the live database. For large stores use SSH, because phpMyAdmin often times out:
    mysqldump -u LIVE_DB_USER -p demo_oc > /home/stagingdemo/live.sql
  3. Import it into the staging database:
    mysql -u stagingdemo_user -p stagingdemo_oc < /home/stagingdemo/live.sql
    rm /home/stagingdemo/live.sql

Without SSH: use phpMyAdmin → Export (Quick, SQL) on the live account, then Import on staging. Compress the file as .gz if it’s large.

Never point staging at the live database. Every change you make on staging would change your real products, orders and customers.

Step 4: Edit both config.php files

OpenCart has two config files, and both must be updated:

  • Replace /home/demo/ with /home/stagingdemo/ in the paths.
  • Replace demo.com with staging.demo.com in the URLs.
  • Change the DB lines to the staging database.

Front end: /home/stagingdemo/public_html/config.php

define('HTTP_SERVER', 'https://staging.demo.com/');
define('HTTPS_SERVER', 'https://staging.demo.com/');

define('DIR_APPLICATION', '/home/stagingdemo/public_html/catalog/');
define('DIR_SYSTEM', '/home/stagingdemo/public_html/system/');
define('DIR_IMAGE', '/home/stagingdemo/public_html/image/');
define('DIR_STORAGE', '/home/stagingdemo/storage/');
// DIR_LANGUAGE, DIR_CACHE, etc. are built from these, leave them

define('DB_HOSTNAME', 'localhost');
define('DB_USERNAME', 'stagingdemo_user');
define('DB_PASSWORD', 'your-staging-db-password');
define('DB_DATABASE', 'stagingdemo_oc');
define('DB_PREFIX', 'oc_'); // same as live

Admin: /home/stagingdemo/public_html/admin/config.php (or your renamed admin folder)

define('HTTP_SERVER', 'https://staging.demo.com/admin/');
define('HTTP_CATALOG', 'https://staging.demo.com/');
define('HTTPS_SERVER', 'https://staging.demo.com/admin/');
define('HTTPS_CATALOG', 'https://staging.demo.com/');

define('DIR_APPLICATION', '/home/stagingdemo/public_html/admin/');
define('DIR_SYSTEM', '/home/stagingdemo/public_html/system/');
define('DIR_IMAGE', '/home/stagingdemo/public_html/image/');
define('DIR_STORAGE', '/home/stagingdemo/storage/');
define('DIR_CATALOG', '/home/stagingdemo/public_html/catalog/');
// same DB_ lines as the front-end config

Don’t edit index.php or system/startup.php. They build their paths from these constants, so fixing the config fixes them.

Next, search for any live paths left over in custom code, .htaccess files or extensions:

grep -rln "/home/demo/" /home/stagingdemo/public_html /home/stagingdemo/storage 2>/dev/null
grep -rn "demo.com" /home/stagingdemo/public_html/.htaccess

Make the same replacement in every file the search lists. In .htaccess, update any RewriteCond %{HTTP_HOST} rule or redirect that forces demo.com, otherwise staging will redirect to your live site.

Step 5: Fix ownership and permissions

Files copied as root, or from another account, keep the wrong owner. PHP runs as the stagingdemo user, so it can’t write to cache, modification, session or image/cache. The most common symptom is that Refresh in Modifications silently does nothing.

Run as root (WHM → Terminal):

chown -R stagingdemo:stagingdemo /home/stagingdemo/public_html/* /home/stagingdemo/public_html/.htaccess /home/stagingdemo/storage
chown stagingdemo:nobody /home/stagingdemo/public_html

find /home/stagingdemo/public_html /home/stagingdemo/storage -type d -exec chmod 755 {} \;
find /home/stagingdemo/public_html /home/stagingdemo/storage -type f -exec chmod 644 {} \;
chmod 750 /home/stagingdemo/public_html

To check, run ls -l /home/stagingdemo/storage. Every folder should show stagingdemo stagingdemo as the owner. Never use 777.

Step 6: Log in, update settings and rebuild caches

Log in at https://staging.demo.com/admin/ with your live admin username and password. They work because the database is a copy.

  1. Rebuild modifications: go to Extensions → Modifications and click Refresh (the blue button, top right). storage/modification/ should now fill with folders.
  2. Clear the theme cache: Dashboard → gear icon (top right) → refresh both the theme cache and the SASS cache.
  3. Clear your theme’s own cache if it has one. For Journal, use the Journal menu in the admin sidebar.
  4. Check store URLs if you run more than one store:
    SELECT store_id, name, url, ssl FROM oc_store;
  5. Look for live URLs saved in settings. Themes, SEO extensions and others sometimes store them:
    SELECT `code`, `key` FROM oc_setting WHERE `value` LIKE '%://demo.com%';

Fix any results through the admin screens, not with SQL. Some of these values are serialized, and a raw find-and-replace can break them.

Step 7: Make staging safe

  1. Password-protect the whole site: cPanel → Directory Privacy → public_html → enable it and add a user. This keeps out Google, bots and customers.
  2. Block indexing as a backup. Replace robots.txt with:
    User-agent: *
    Disallow: /
  3. Payments: Extensions → Payments → disable live gateways or switch them to sandbox/test keys.
  4. Email: System → Settings → Mail → point it to a test inbox or remove the SMTP details, so customers don’t get order or newsletter emails.
  5. Turn off outside connections that use live credentials: Google Merchant feeds, marketplace sync, SMS, courier APIs and cPanel cron jobs.
  6. Remove debug lines (error_reporting, display_errors) from config.php once everything works. For later problems, check storage/logs/error.log instead.

Troubleshooting Common Errors

Symptom Cause Fix
Cloudflare 522 Duplicate or old A record, or server firewall Keep one staging A record pointing to the right IP; open ports 80/443
Failed opening required /home/demo/... Permission denied config.php still has live paths Change /home/demo/ to /home/stagingdemo/ in both config files
Blank HTTP 500 Error is hidden Temporarily add display_errors to config.php, or read cPanel → Errors / error_log
Admin gives 500 but the front end works Admin config.php not updated Edit admin/config.php (Step 4)
Modifications Refresh does nothing, storage/modification stays empty Wrong file owner, or DIR_STORAGE points elsewhere Run the Step 5 chown and check DIR_STORAGE in both configs
Session or cache errors Storage folder not copied Copy /home/demo/storage to /home/stagingdemo/storage
Staging redirects to demo.com .htaccess rule or store URL Fix the .htaccess host rules and HTTP_SERVER
Database connection error Wrong DB name, user or password Use the staging values and make sure the user is added to the DB
Pages load without styling Theme cache Refresh the theme/SASS cache and your theme’s own cache
“Not secure” warning No SSL on the account Run AutoSSL in cPanel

Final Checklist

  • One staging DNS record, SSL working
  • Files in /home/stagingdemo/public_html/, storage in /home/stagingdemo/storage/
  • Staging database imported, database user added
  • Both config.php files use staging URLs, /home/stagingdemo/ paths and the staging DB
  • grep finds no /home/demo/ paths left
  • Files owned by stagingdemo
  • Admin login works, modifications refreshed, theme cache cleared
  • Site password-protected, robots.txt blocks everything
  • Payments in test mode, emails off, feeds and crons off
  • Debug lines removed from config.php

Need a staging site set up for your OpenCart store? Contact us and we’ll handle it for you.

 

Leave A Comment