# Installation Guide --- ## 1. Requirements | Component | Minimum | Recommended | | --- | --- | --- | | PHP | 8.0 | 8.2 / 8.3 | | MySQL | 5.7 | 8.0 (or MariaDB 10.5+) | | Extensions | `pdo_mysql`, `json`, `mbstring`, `openssl` | + `curl`, `zip` | | Web server | Apache 2.4 with `mod_rewrite` | Apache or Nginx behind HTTPS | | TLS | strongly recommended | mandatory in production | Browser support for the panels: any evergreen Chrome, Edge, Firefox or Safari. --- ## 2. Upload the files Upload the whole project to your web root, for example: ``` /var/www/lms/ api/ admin/ reseller/ keygen/ extension/ assets/ database/ config/ uploads/ logs/ docs/ cron/ ``` Set permissions: ```bash cd /var/www/lms chown -R www-data:www-data . find . -type d -exec chmod 755 {} \; find . -type f -exec chmod 644 {} \; chmod -R 775 logs uploads ``` --- ## 3. Create the database user ```sql CREATE DATABASE lms_licenses CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'lms_user'@'localhost' IDENTIFIED BY 'a-long-random-password'; GRANT ALL PRIVILEGES ON lms_licenses.* TO 'lms_user'@'localhost'; FLUSH PRIVILEGES; ``` --- ## 4. Configure `config/config.php` Edit these values before installing: ```php 'database' => [ 'host' => '127.0.0.1', 'port' => 3306, 'name' => 'lms_licenses', 'user' => 'lms_user', 'pass' => 'a-long-random-password', ], 'security' => [ 'jwt_secret' => '<64 random characters>', // openssl rand -hex 32 'hash_pepper' => '<64 random characters>', // openssl rand -hex 32 ], 'app' => [ 'cron_token' => '<32 random characters>', // only needed for HTTP cron ], ``` Generate secrets with: ```bash openssl rand -hex 32 ``` > **Never** reuse the sample values. `hash_pepper` must never change after go-live — changing it invalidates every stored device fingerprint. Every value can also come from environment variables (see the `env()` helper at the top of `config/config.php`), which is the preferred approach on managed hosting. --- ## 5. Run the installer ### Option A — browser wizard Open: ``` https://your-domain.com/database/install.php ``` The wizard checks the environment, imports `schema.sql` and `seed.sql`, and creates your super administrator with a bcrypt hash. ### Option B — command line ```bash php database/install.php \ --user=admin \ --email=you@example.com \ --password='Sup3r-Strong-Pass' \ --name='Super Administrator' \ --url=https://your-domain.com ``` ### Option C — manual import ```bash mysql -u lms_user -p lms_licenses < database/schema.sql mysql -u lms_user -p lms_licenses < database/seed.sql ``` Then still run `install.php` once to create the administrator, because the password hash must be produced by PHP's `password_hash()`. ### After a successful install ```bash rm database/install.php ``` This is mandatory. The installer can overwrite the administrator account. --- ## 6. Verify the API ```bash curl https://your-domain.com/api/health ``` Expected: ```json { "success": true, "data": { "status": "ok", "database": "connected", "time": "..." } } ``` If you get a 404, `mod_rewrite` is not active or `AllowOverride` is not set to `All` for the folder. See `docs/DEPLOYMENT.md`. --- ## 7. First login | Panel | URL | | --- | --- | | Admin | `https://your-domain.com/admin/` | | Reseller | `https://your-domain.com/reseller/` | | Key generator | `keygen/keygen.html` (double-click locally, or host it) | After logging in as admin: 1. **Settings → General** — set the site name, timezone, logo and API URL. 2. **Settings → SMTP** — configure mail and press *Send test email*. 3. **Products** — confirm or rename the seeded `lovable-unlimited` product. 4. **Resellers** — create your first reseller with a quota and an expiry date. 5. **Licenses → Generate** — issue a test key and activate it from the extension. --- ## 8. Install the cron jobs ```bash crontab -e # paste the contents of cron/crontab.txt, adjusting the paths ``` Without cron, licenses still expire logically (the API always compares against the current time), but the stored status will not flip to `expired`, reseller accounts will not auto-expire, and no backups or log pruning will run. On shared hosting without shell access, set `app.cron_token` and call the tasks over HTTPS — the alternative schedule is documented at the bottom of `cron/crontab.txt`. --- ## 9. Connect the extension Continue with `docs/INTEGRATION.md`. --- ## Troubleshooting | Symptom | Cause and fix | | --- | --- | | `500` on every API call | Check `logs/error.log`; usually wrong DB credentials in `config/config.php`. | | `404` on `/api/...` | `mod_rewrite` disabled or `AllowOverride None`. | | `Authorization` header missing | Add the `E=HTTP_AUTHORIZATION` rewrite rule (already in `api/.htaccess`); on Nginx pass `$http_authorization`. | | Login says "Invalid credentials" right after install | The installer was interrupted before creating the admin — re-run it with `--force`. | | Reseller cannot log in | The account status is `expired` or `suspended`; extend the expiry from **Resellers → Extend**. | | Panels load but tables stay empty | The API URL in `Settings → General` points at the wrong host, or CORS blocks the browser. | | Backups fail | `uploads/backups` is not writable, or the DB user lacks `SELECT` on some table. |