Step-by-Step Deployment: cPanel / VPS / Local Stack, MySQL Provisioning & The Web Installer Wizard
Follow this step-by-step deployment walkthrough to upload the Keystone X release archive, provision your MySQL/MariaDB database and user privileges, configure your web server virtual host or .htaccess RewriteBase, and complete the automated Web Installer Wizard.
Step 1: Uploading & Extracting the Keystone X Application Files
Download the latest official Keystone X Release Archive (keystonex-v1.4.3.zip) from your Licensing Customer Portal (https://keystonex.co.za).
Option A: cPanel / DirectAdmin / Plesk File Manager
- Log in to cPanel and open File Manager.
- Click Settings in the top-right corner of File Manager and ensure Show Hidden Files (dotfiles) is ticked so
.htaccessis visible and extracted. - Navigate to your target document root—for example,
public_html/for a main domain orbilling.yourdomain.co.za/for a subdomain. - Click Upload, select
keystonex-v1.4.3.zip, wait for the progress bar to turn 100% green, and return to File Manager. - Right-click the
.zipfile, click Extract, and delete the.ziparchive afterward.
Option B: Linux VPS (SSH) or Local Dev Stack (AMPPS / XAMPP)
On a Linux VPS via SSH:
On Windows AMPPS / XAMPP / Laragon: Extract the archive into d:\AMPPS\www\keystonex.local (or C:\xampp\htdocs\keystonex).
install-step1-extracted-root-directory.png- Open your File Manager or IDE directory tree at the root of the extracted project.
- Ensure
.htaccess,index.php,license_check.php,cron.php,cron_runner.php,version.php, and the foldersapp/,cache/,install/,public/, anduploads/are visible. - Capture the clean root directory structure.
Step 2: Creating Your MySQL / MariaDB Database & User
Keystone X requires an empty MySQL or MariaDB database using the utf8mb4 character set.
Creating the Database in cPanel (MySQL Database Wizard)
- In cPanel, click MySQL® Database Wizard under the Databases section.
- Step 1 — Create A Database: Enter a name such as
cpaneluser_keystoneand click Next Step. - Step 2 — Create Database Users: Enter a username (e.g.,
cpaneluser_kxadmin), generate a strong password, copy both to a secure notepad, and click Create User. - Step 3 — Add User to Database: Tick the ALL PRIVILEGES checkbox at the very top and click Make Changes.
Creating the Database via MySQL CLI / phpMyAdmin
Run the following SQL commands as root:
install-step2-mysql-privileges-screen.png- Open cPanel → MySQL Database Wizard (Step 3: Add User to Database) or phpMyAdmin.
- Show the database user granted ALL PRIVILEGES on the new
utf8mb4database.
Step 3: Configuring .htaccess RewriteBase & Virtual Hosts
Keystone X routes all clean URLs (such as /invoice/index or /Cashbook/addJournal) through the root index.php front controller using .htaccess:
Scenario A: Installed in Root Domain or Subdomain (Recommended)
If you access Keystone X at https://billing.yourdomain.co.za/ or http://keystonex.local/, leave .htaccess exactly as shipped:
Scenario B: Installed Inside a Subfolder (e.g. /erp/)
If you access Keystone X inside a subdirectory such as https://yourdomain.co.za/erp/, update line 6 of .htaccess (RewriteBase) to match your subfolder name:
Step 4: Running the Automated Web Installer Wizard (/install)
Open your web browser and navigate to your Keystone X URL (for example, https://billing.yourdomain.co.za/). As configured in index.php (lines 25–39), when app/config/config.php does not yet exist, Keystone X automatically redirects your browser to /install/ to launch the interactive Web Installer Wizard!
install-step4-web-installer-wizard.png- Navigate to
/install/in your browser beforeapp/config/config.phpis created. - Capture the Web Installer Wizard screen showing the Server Pre-Flight Environment Checks, Database Connection fields (
DB_HOST,DB_NAME,DB_USER,DB_PASS), Initial Admin Account fields, and License Key input.
| Installer Wizard Stage | Inputs Required & Automated Actions Performed |
|---|---|
| 1. Environment & Permission Pre-Check | Verifies PHP 8.0+, required extensions (PDO, cURL, GD, mbstring, XML, Zip), and write permissions on /app/config, /cache, and /uploads. All indicators must show green Passed badges. |
| 2. Database Connection Setup |
|
| 3. Company, License & First Admin Account | Enter your Company / Site Name, your Keystone X License Key (APP-XXXX-XXXX-XXXX), and your primary System Administrator Email & Password. |
| 4. Automated Schema Build & Config Generation | Clicking Install Keystone X imports the complete ERP schema, seeds the IFRS Chart of Accounts (1000–6999), SARS Statutory Tax Rates (STD, ZERO, EXM), Default Payment Terms, Email Templates, and RBAC Roles, writes /app/config/config.php and /app/config/license.key, and redirects you to the Login Screen (user/login). |
Alternative: Manual app/config/config.php Reference (For Server Migrations)
If you are migrating an existing Keystone X database to a new server manually without running the web wizard, create app/config/config.php using the exact structure below (note that Keystone X intentionally omits a closing ?> PHP tag to prevent stray whitespace from corrupting PDF downloads):
if (!defined('ENVIRONMENT')) {
define('ENVIRONMENT', 'production');}error_reporting(E_ALL);ini_set('display_errors', '0');ini_set('display_startup_errors', '0');ini_set('log_errors', '1');ini_set('error_log', dirname(__DIR__, 2) . '/error.log');date_default_timezone_set('Africa/Johannesburg');// Database Configurationif (!defined('DB_HOST')) define('DB_HOST', '127.0.0.1');if (!defined('DB_USER')) define('DB_USER', 'your_db_user');if (!defined('DB_PASS')) define('DB_PASS', 'your_db_password');if (!defined('DB_NAME')) define('DB_NAME', 'your_db_name');// Path Constantsif (!defined('APP_ROOT')) { define('APP_ROOT', dirname(__DIR__)); }if (!defined('PROJECT_ROOT')) { define('PROJECT_ROOT', dirname(APP_ROOT)); }if (!defined('APPROOT')) { define('APPROOT', PROJECT_ROOT); }// Dynamic Base URL Calculation$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || ($_SERVER['SERVER_PORT'] ?? 80) == 443) ? "https://" : "http://";$host = $_SERVER['HTTP_HOST'] ?? 'localhost';$script_path = rtrim(str_replace('/index.php', '', $_SERVER['SCRIPT_NAME'] ?? ''), '/');if (!defined('BASE_URL')) define('BASE_URL', $protocol . $host . $script_path . '/');if (!defined('URL_ROOT')) define('URL_ROOT', rtrim(BASE_URL, '/'));if (!defined('URLROOT')) define('URLROOT', rtrim(BASE_URL, '/'));// Upload Pathsif (!defined('UPLOADS_DIR')) define('UPLOADS_DIR', PROJECT_ROOT . '/uploads');if (!defined('UPLOADS_URL')) define('UPLOADS_URL', BASE_URL . 'uploads');if (!defined('POPS_DIR')) define('POPS_DIR', PROJECT_ROOT . '/uploads/pops');if (!defined('POPS_URL')) define('POPS_URL', BASE_URL . 'uploads/pops');if (!defined('RECEIPTS_DIR')) define('RECEIPTS_DIR', PROJECT_ROOT . '/uploads/receipts');if (!defined('RECEIPTS_URL')) define('RECEIPTS_URL', BASE_URL . 'uploads/receipts');if (!defined('URL_MODE')) define('URL_MODE', 'pretty');if (!defined('SITE_NAME')) define('SITE_NAME', 'Keystone X');if (!defined('DEV_EMAIL')) define('DEV_EMAIL', 'support@keystonex.co.za');$versionFile = PROJECT_ROOT . '/version.php';if (!defined('SITE_VERSION')) define('SITE_VERSION', file_exists($versionFile) ? include $versionFile : '1.4.3');if (!defined('DEFAULT_CONTROLLER')) define('DEFAULT_CONTROLLER', 'HomeController');if (!defined('DEFAULT_METHOD')) define('DEFAULT_METHOD', 'index');if (!defined('LICENSE_SERVER_URL')) define('LICENSE_SERVER_URL', 'https://keystonex.co.za');