# GST Billing & POS SaaS Platform - cPanel Installation Guide

## Overview
This guide provides step-by-step instructions for deploying the GST Billing & POS SaaS Platform on a shared hosting environment using cPanel. While cPanel shared hosting has some limitations compared to VPS/dedicated servers, this guide will help you get the application running successfully.

## Important Considerations for cPanel Hosting

Before proceeding, please note:

1. **Resource Limits**: Shared hosting typically has limits on CPU, memory, and concurrent processes
2. **Queue Workers**: Background job processing (queues) may not be available or may require alternative approaches
3. **Root Access**: You won't have sudo/root access, so some server-level configurations aren't possible
4. **PHP Extensions**: Ensure required extensions are enabled via PHP Selector
5. **Execution Time**: Long-running processes may be limited by max execution time settings

## Prerequisites Checklist

Before beginning, verify your hosting plan provides:
- PHP 8.2+ (selectable via PHP Selector)
- MySQL 5.7+ or MariaDB 10.2+
- Ability to create at least 1 MySQL database and user
- File Manager access
- Ability to run Composer (via terminal or manual upload)
- Cron job functionality
- SSL/TLS support (Let's Encrypt or custom)

Required PHP extensions (enable via PHP Selector):
- bcmath
- ctype
- curl
- fileinfo
- json
- mbstring
- openssl
- pdo_mysql
- tokenizer
- xml
- zip
- gd

## Installation Steps

### Step 1: Prepare PHP Environment
1. Log in to your cPanel dashboard
2. Navigate to **Software** → **Select PHP Version** (or PHP Selector)
3. Ensure PHP version is set to **8.2 or higher**
4. Click on **Extensions** and enable these required extensions:
   - bcmath
   - ctype
   - curl
   - fileinfo
   - json
   - mbstring
   - openssl
   - pdo_mysql
   - tokenizer
   - xml
   - zip
   - gd
5. Click **Save** to apply changes

### Step 2: Create MySQL Database and User
1. In cPanel, go to **Databases** → **MySQL Databases**
2. Under **Create New Database**, enter a database name (e.g., `gstbilling_pos`) and click **Create Database**
3. Under **MySQL Users**, add a new user:
   - Username: Choose a username (e.g., `gstbilling_user`)
   - Password: Generate a strong password (use Password Generator)
   - Click **Create User**
4. Under **Add User to Database**:
   - Select the user you just created
   - Select the database you created
   - Click **Add**
   - On the next screen, select **ALL PRIVILEGES** and click **Make Changes**

### Step 3: Upload Application Files
You have two options for uploading the application:

#### Option A: Upload via File Manager (Recommended for smaller uploads)
1. In cPanel, go to **Files** → **File Manager**
2. Navigate to your web root directory (usually `public_html` or `www`)
3. Click **Upload** and select the GST Billing & POS application ZIP file
4. Once uploaded, select the ZIP file and click **Extract**
5. Move the contents of the extracted `backend` folder to your desired location (e.g., `public_html/gstbilling_pos`)
6. Remove the empty `backend` directory and the ZIP file

#### Option B: Upload via FTP (Alternative)
1. Extract net (FTP) client (FileZilla or C: Upload via FTP
1. Use an FTP client (FileZilla, WinSCP, etc.) with your cPanel FTP credentials
2. Connect to your hosting account
3. Navigate to your web root directory
4. Upload the application files maintaining the directory structure
5. Ensure the `backend` directory contents are in your desired location

### Step 4: Install Dependencies via Composer
If your hosting provider offers terminal access:

#### Option A: Using cPanel Terminal (if available)
1. In cPanel, go to **Advanced** → **Terminal**
2. Navigate to your application directory:
   ```bash
   cd /home/yourusername/public_html/gstbilling_pos/backend
   ```
3. Run Composer install:
   ```bash
   php composer.phar install --no-dev --optimize-autoloader
   ```

#### Option B: Manual Vendor Upload (if no terminal access)
1. On your local machine, run:
   ```bash
   cd /path/to/local/backend
   composer install --no-dev --optimize-autoloader
   ```
2. Upload the entire `vendor` directory to your server alongside your application files
3. Ensure the `vendor` directory is in the same location as your `backend` directory

### Step 5: Set File Permissions
1. In cPanel File Manager, navigate to your application directory
2. Select the `storage` and `bootstrap/cache` directories
3. Click **Change Permissions**
4. Set permissions to **755** (or apply recursively if available)
5. Ensure all files within these directories are writable by the web server

### Step 6: Configure Environment File
1. In File Manager, locate the `.env.example` file in your backend directory
2. Right-click and select **Copy**, then rename the copy to `.env`
3. Right-click the `.env` file and select **Edit**
4. Configure the following settings:

```
APP_NAME="GST Billing & POS"
APP_ENV=production
APP_KEY=  # Leave blank for now, we'll generate it next
APP_DEBUG=false
APP_URL=https://yourdomain.com  # or http:// if SSL not yet configured

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=your_database_name
DB_USERNAME=your_database_user
DB_PASSWORD=your_database_password

BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=database  # or sync if queues not available
SESSION_DRIVER=file
SESSION_LIFETIME=120

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com  # or your SMTP host
MAIL_PORT=587
MAIL_USERNAME=your_email@gmail.com
MAIL_PASSWORD=your_app_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="${APP_NAME}"
MAIL_FROM_NAME="${APP_NAME}"

# JWT Configuration
JWT_SECRET=  # Leave blank for now
JWT_TTL=60
JWT_REFRESH_TTL=20160

# GST Configuration
GST_DEBUG=false
```

5. Click **Save Changes**

### Step 7: Generate Application Key
If you have terminal access:
```bash
php artisan key:generate
php artisan jwt:secret
```

If you don't have terminal access, you can:
1. Create a temporary PHP file in your public directory with:
   ```php
   <?php
   echo "APP_KEY=" . base64_encode(random_bytes(32)) . "\n";
   echo "JWT_SECRET=" . bin2hex(random_bytes(32)) . "\n";
   ?>
   ```
2. Access it via your browser to get the values
3. Copy the generated values into your `.env` file
4. Delete the temporary PHP file for security

### Step 8: Run Database Migrations
If you have terminal access:
```bash
php artisan migrate --force
```

If you don't have terminal access, you can:
1. Create a route in `routes/web.php` temporarily:
   ```php
   Route::get('/migrate', function () {
       Artisan::call('migrate --force');
       return 'Migration completed';
   });
   ```
2. Visit `https://yourdomain.com/migrate` in your browser
3. **IMPORTANT**: Remove this route immediately after migration completes for security

### Step 9: Seed Initial Data (Optional)
Repeat the same process as migrations but with:
```bash
php artisan db:seed --force
```
Or create a route for `/seed` and visit it in your browser.

### Step 10: Create Super Admin User
If you have terminal access:
```bash
php artisan tinker
>>> App\Models\User::factory()->create([
    'name' => 'Super Admin',
    'email' => 'admin@yourdomain.com',
    'password' => bcrypt('SecurePassword123!'),
    'email_verified_at' => now(),
]);
>>> exit
```

Without terminal access, create a temporary route:
```php
Route::get('/create-admin', function () {
    \App\Models\User::factory()->create([
        'name' => 'Super Admin',
        'email' => 'admin@yourdomain.com',
        'password' => bcrypt('SecurePassword123!'),
        'email_verified_at' => now(),
    ]);
    return 'Admin user created';
});
```
Visit the URL, then remove the route immediately.

### Step 11: Configure Public Directory (Important for Security)
For security, your application's public directory should be the web root. If your application is installed in a subdirectory:

#### Option A: Document Root Points to Public (Preferred)
If you can set the document root:
1. In cPanel, go to **Domains** → **Domains** (or **Addon Domains**)
2. Click the pencil icon to edit your domain
3. Set the document root to: `public_html/gstbilling_pos/backend/public`
4. Save changes

#### Option B: Using .htaccess (if you cannot change document root)
If your application must remain in a subdirectory and you can't change the document root:
1. Move all contents from `backend/public` to your web root (e.g., `public_html`)
2. Move all other `backend` files and directories (except `public`) to a folder above web root (e.g., `private_app`)
3. Update the paths in `public/index.php`:
   ```php
   // Change from:
   require __DIR__.'/../vendor/autoload.php';
   $app = require_once __DIR__.'/../bootstrap/app.php';
   
   // To (adjust paths based on your structure):
   require __DIR__.'/../private_app/vendor/autoload.php';
   $app = require_once __DIR__.'/../private_app/bootstrap/app.php';
   ```
4. Also update the `.env` file path if needed in `bootstrap/app.php`

### Step 12: Set Up Cron Jobs
Laravel scheduler needs to run every minute. In cPanel:

1. Go to **Advanced** → **Cron Jobs**
2. Under **Add New Cron Job**, select **Once Per Minute** from the Common Settings dropdown
3. In the Command field, enter:
   ```
   php /home/yourusername/public_html/gstbilling_pos/backend/artisan schedule:run >> /dev/null 2>&1
   ```
   (Adjust the path to match your actual installation)
4. Click **Add New Cron Job**

### Step 13: Configure Queue Worker (If Available)
Note: Many shared hosting plans don't allow persistent processes. Check with your host.

If queue workers are permitted:
1. In cPanel Terminal (if available):
   ```bash
   nohup php artisan queue:work --sleep=3 --tries=3 &
   ```
2. Or create a cron job that runs every 5 minutes:
   ```
   */5 * * * * php /home/yourusername/public_html/gstbilling_pos/backend/artisan queue:work --once --quiet >> /dev/null 2>&1
   ```

If queue workers are NOT available:
- Set `QUEUE_CONNECTION=sync` in your `.env` file
- Note: This means jobs will run synchronously during HTTP requests, which may slow down user actions
- Consider limiting features that rely heavily on queues (notifications, emails, etc.)

### Step 14: SSL/TLS Configuration
1. In cPanel, go to **Security** → **Let's Encrypt SSL**
2. Select your domain and click **Issue** or **Install**
3. Once SSL is active, update your `.env` file:
   ```
   APP_URL=https://yourdomain.com
   ```
4. To force HTTPS, you can add to your `.htaccess` file:
   ```
   RewriteEngine On
   RewriteCond %{HTTPS} !=on
   RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
   ```

## Testing Your Installation
1. Visit your domain in a web browser
2. You should see the application landing page or be redirected to login
3. Try logging in with the admin credentials you created
4. Test basic functionality:
   - Navigate to different modules
   - Try creating a business/tenant
   - Test GST calculation features
   - Try generating an invoice

## Troubleshooting Common cPanel Issues

### 500 Internal Server Error
- Check file permissions (storage and bootstrap/cache should be writable)
- Verify `.env` file exists and has correct database credentials
- Check PHP error logs in cPanel → **Metrics** → **Errors**
- Ensure all required PHP extensions are enabled

### Database Connection Errors
- Double-check database name, username, and password in `.env`
- Verify the user has ALL privileges on the database
- Confirm `DB_HOST=localhost` (usually correct for cPanel)
- Check if remote MySQL connections are allowed (usually not needed for localhost)

### Composer Issues
- If you get memory errors during composer install, try:
  ```bash
  php -d memory_limit=-1 composer.phar install --no-dev
  ```
- Or upload the vendor directory as described earlier

### Permission Errors
- Use File Manager to set `storage` and `bootstrap/cache` to 755
- Apply permissions recursively if option available
- Ensure files are owned by your user (usually automatic with cPanel uploads)

### Session/Driver Errors
- If using `SESSION_DRIVER=database`, ensure sessions table is migrated
- Consider using `SESSION_DRIVER=file` for simpler setup on shared hosting
- Make sure `storage/framework/sessions` directory exists and is writable

### Cron Job Not Running
- Verify the command path is correct
- Check that PHP CLI version matches your web PHP version
- Look at cron logs in cPanel if available
- Test the command manually in terminal first

## Security Recommendations for cPanel Hosting

1. **Strong Passwords**: Use unique, strong passwords for:
   - cPanel account
   - MySQL database user
   - Application admin account
   - FTP/SSH accounts (if applicable)

2. **File Permissions**:
   - Never set permissions to 777
   - Keep `storage` and `bootstrap/cache` at 755 maximum
   - Ensure `.env` file is not web accessible (should be outside public_html or protected via .htaccess)

3. **PHP Settings** (via PHP Selector or .user.ini if available):
   ```
   disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
   allow_url_fopen = Off
   expose_php = Off
   display_errors = Off
   log_errors = On
   ```

4. **Regular Updates**:
   - Periodically run `composer update` (be cautious with production)
   - Keep PHP version updated
   - Apply Laravel security patches when available

5. **Backup Strategy**:
   - Use cPanel's Backup Wizard to schedule regular backups
   - Or manually download your files and database export periodically
   - Consider using a backup plugin if available

## Limitations of Shared Hosting vs VPS/Dedicated

| Feature | Shared Hosting (cPanel) | VPS/Dedicated Server |
|---------|------------------------|----------------------|
| **Performance** | Limited by shared resources | Dedicated resources |
| **Queue Workers** | Often not available or limited | Fully supported |
| **Cron Jobs** | Usually available (minute-level) | Full control |
| **Root Access** | No | Yes |
| **Custom PHP Config** | Limited (via PHP Selector/.user.ini) | Full control |
| **SSL Certificates** | Usually via Let's Encrypt (free) | Full flexibility |
| **Server Updates** | Managed by host | Your responsibility |
| **Scalability** | Limited by hosting plan | Vertical/horizontal scaling |
| **Custom Firewall** | Limited | Full control (iptables, firewalld, etc.) |
| **Email Sending** | Often restricted | Full SMTP control |

## When to Consider Upgrading
Consider moving to a VPS or dedicated server if you experience:
- Frequent resource limit errors (CPU, memory, entry processes)
- Need for real-time queue processing
- Requirement for custom server configurations
- High traffic volumes exceeding shared hosting limits
- Need for root-level access or specific software installations

## Support and Resources
- **Laravel Documentation**: https://laravel.com/docs
- **cPanel Documentation**: https://docs.cpanel.net/
- **GST Billing & POS Documentation**: Refer to the main README.md
- **Community Support**: Check for Laravel/IPB forums or your host's knowledge base

## Maintenance Tips
1. Regularly check disk usage in cPanel
2. Monitor bandwidth usage
3. Keep applications and plugins updated
4. Review error logs periodically
5. Test backups regularly by restoring to a test environment
6. Stay informed about PHP and security updates from your hosting provider

---

**Last Updated**: July 25, 2026  
**Version**: 1.0.0-cpanel

*Note: Always consult your hosting provider's specific documentation and support for environment-specific limitations and features.*