Official Technical Documentation & User Manual
Installation
Verified Guide • Updated 17 Oct 2026
Installation Verified Guide

#I-02: Step-by-Step Deployment: cPanel / VPS / Local Stack, MySQL Provisioning & The Web Installer Wizard

Updated 2 hours ago 7 min read 7 views
Installation Category · Part 2 of 4 File Upload & MySQL Setup Web Installer Wizard Walkthrough

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
  1. Log in to cPanel and open File Manager.
  2. Click Settings in the top-right corner of File Manager and ensure Show Hidden Files (dotfiles) is ticked so .htaccess is visible and extracted.
  3. Navigate to your target document root—for example, public_html/ for a main domain or billing.yourdomain.co.za/ for a subdomain.
  4. Click Upload, select keystonex-v1.4.3.zip, wait for the progress bar to turn 100% green, and return to File Manager.
  5. Right-click the .zip file, click Extract, and delete the .zip archive afterward.
Option B: Linux VPS (SSH) or Local Dev Stack (AMPPS / XAMPP)

On a Linux VPS via SSH:

cd /var/www/billing.yourdomain.co.za sudo unzip keystonex-v1.4.3.zip sudo rm keystonex-v1.4.3.zip sudo chown -R www-data:www-data /var/www/billing.yourdomain.co.za sudo find . -type d -exec chmod 755 {} \; sudo find . -type f -exec chmod 644 {} \; sudo chmod -R 775 app/config cache uploads

On Windows AMPPS / XAMPP / Laragon: Extract the archive into d:\AMPPS\www\keystonex.local (or C:\xampp\htdocs\keystonex).

📸 SCREENSHOT PLACEHOLDER: install-step1-extracted-root-directory.png
  1. Open your File Manager or IDE directory tree at the root of the extracted project.
  2. Ensure .htaccess, index.php, license_check.php, cron.php, cron_runner.php, version.php, and the folders app/, cache/, install/, public/, and uploads/ are visible.
  3. 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)
  1. In cPanel, click MySQL® Database Wizard under the Databases section.
  2. Step 1 — Create A Database: Enter a name such as cpaneluser_keystone and click Next Step.
  3. 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.
  4. 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:

CREATE DATABASE keystonepro_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'kx_user'@'127.0.0.1' IDENTIFIED BY 'StrongPassword#2026!'; GRANT ALL PRIVILEGES ON keystonepro_db.* TO 'kx_user'@'127.0.0.1'; FLUSH PRIVILEGES;
📸 SCREENSHOT PLACEHOLDER: install-step2-mysql-privileges-screen.png
  1. Open cPanel → MySQL Database Wizard (Step 3: Add User to Database) or phpMyAdmin.
  2. Show the database user granted ALL PRIVILEGES on the new utf8mb4 database.

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:

<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^ - [L] RewriteRule ^(.*)$ index.php?url=$1 [L,QSA] </IfModule>
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:

<IfModule mod_rewrite.c> RewriteEngine On RewriteBase /erp/ RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^ - [L] RewriteRule ^(.*)$ index.php?url=$1 [L,QSA] </IfModule>

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!

📸 SCREENSHOT PLACEHOLDER: install-step4-web-installer-wizard.png
  1. Navigate to /install/ in your browser before app/config/config.php is created.
  2. 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
  • Database Host (DB_HOST): Use 127.0.0.1 (recommended over localhost to force fast TCP/IP PDO sockets without Unix socket path issues).
  • Database Name (DB_NAME): The database you created in Step 2 (e.g., keystonepro_db).
  • Database Username (DB_USER) & Password (DB_PASS): Your MySQL user credentials.
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 Configuration
if (!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 Constants
if (!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']) &amp;&amp; $_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 Paths
if (!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');
Was this technical guide helpful?
Back to top