Getting Started

Getting Started

This guide takes a fresh server to a working QoinPay Enterprise installation. QoinPay ships as a self-contained PHP application that you deploy on your own infrastructure and connect to a MariaDB or MySQL database. There is no mandatory outbound connectivity beyond an initial license activation, which can also be performed offline for air-gapped sites.

Install, configure the database, activate, create an admin, then go live.
Install, configure the database, activate, create an admin, then go live.

Environment requirements

Provision a single host (or the app tier of a multi-node cluster) that meets the following:

  • PHP 8.2 or newer (8.5 recommended) with the extensions: pdo_mysql, openssl, sodium, mbstring, gd, and zip. The sodium extension is mandatory — it backs license verification, TOTP secret encryption, and webhook signing.
  • MariaDB 10.6+ or MySQL 8.0+, using the utf8mb4 character set and InnoDB storage engine.
  • A web server (nginx or Apache) with a PHP-FPM pool, or the bundled PHP runtime for evaluation only.
  • A writable storage/ directory tree for logs, generated payslips, queued jobs, and the activated license file. The web server user must own storage/ and storage/cache/.

Verify extensions before you begin:

php -m | grep -E 'pdo_mysql|sodium|openssl|mbstring|gd|zip'
php -r 'echo PHP_VERSION, PHP_EOL;'

1. Unpack and set permissions

Extract the release tarball into your deployment root and set ownership so PHP-FPM can write runtime state but cannot modify code:

tar -xzf qoinpay-enterprise-<version>.tar.gz -C /opt/qoinpay
cd /opt/qoinpay
chown -R www-data:www-data storage/
chmod -R 750 storage/

Point your web server document root at public/. Never expose storage/, config/, or vendor/ to the web.

2. Configure the database connection

Create an empty database and a dedicated user with full privileges on it:

CREATE DATABASE qoinpay CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'qoinpay'@'10.%' IDENTIFIED BY 'change-me';
GRANT ALL PRIVILEGES ON qoinpay.* TO 'qoinpay'@'10.%';

Copy .env.example to .env and set the connection and application secrets:

APP_ENV=production
APP_KEY=            # generated by the wizard if blank
DB_HOST=10.0.1.20
DB_PORT=3306
DB_NAME=qoinpay
DB_USER=qoinpay
DB_PASS=change-me

3. Run the first-run install wizard

Browse to https://your-host/install. The wizard runs only while the application is uninitialised and disables itself once setup completes. It performs, in order:

  1. Preflight — re-checks PHP version, extensions, and storage/ writability, refusing to continue on any failure.
  2. Application key — generates and writes APP_KEY if one is not already present. This key encrypts secrets at rest; back it up, because losing it makes stored TOTP secrets and other encrypted columns unrecoverable.
  3. Database migrations — applies the schema (see below).

To run migrations from the CLI instead — required for automated or air-gapped deployments — use:

php bin/console migrate --no-interaction

Migrations are idempotent and versioned; running them again after an upgrade applies only the pending changes. Check status with php bin/console migrate:status.

4. Create the first administrator

The first admin is created through the wizard or non-interactively:

php bin/console admin:create --email=ops@example.com --name="Ops Admin"

Two-factor authentication (TOTP) is mandatory for every administrator and cannot be disabled. On first sign-in the account presents a QR code and a set of one-time recovery codes. Store the recovery codes offline before leaving the screen — they are the only way back in if the authenticator device is lost. TOTP secrets are stored encrypted with APP_KEY.

5. Activate your license

QoinPay runs unlicensed in a restricted evaluation mode until activated. Enter your license key (QPAY-XXXXX-XXXXX-XXXXX) under Settings → Licensing, or drop your .qplic file for offline sites. See Licensing & Activation for the full flow.

6. Set up the cron worker

Background work — payroll run processing, payslip generation, webhook delivery, license heartbeats, and scheduled reports — is handled by a queue worker driven by a single cron entry. Install it for the web server user:

* * * * * cd /opt/qoinpay && php bin/console schedule:run >> storage/logs/cron.log 2>&1

The schedule:run command is a lightweight dispatcher; it claims due jobs and returns quickly, so a one-minute cadence is correct. For higher throughput run a long-lived worker under a process supervisor instead:

php bin/console queue:work --sleep=1 --max-jobs=500

Supervise it with systemd or supervisord so it restarts on exit. Never run both a long-lived worker and the cron dispatcher against the same queue.

Go-live checklist

  • [ ] TLS terminates in front of public/ with a valid certificate; HTTP redirects to HTTPS.
  • [ ] APP_KEY and the .env file are backed up in your secrets manager.
  • [ ] migrate:status shows no pending migrations.
  • [ ] License shows Active with the expected seat count.
  • [ ] The cron worker is installed and storage/logs/cron.log shows recent activity.
  • [ ] Automated database and storage/ backups are scheduled and test-restored.
  • [ ] The /install route is confirmed disabled.

With these complete, your installation is production-ready. Continue with Deployment for hardening and sizing, and the API Overview to integrate surrounding systems.