DTL_LicenseServer — User Guide
Service installation and detailed integration into a Windows application.
Purpose and audience
This guide explains how to implement DTL_LicenseServer: prepare MariaDB and PHP, protect secrets, deploy the API, create licenses, and integrate the client into Windows software. It is intended for server administrators and client-application developers.
For the system’s responsibilities, data, and guarantees, see the Reference Manual.
What the tool does
DTL_LicenseServer centralizes the creation, activation, validation, and deactivation of licenses limited to a number of machines. The PHP API signs tokens with Ed25519, MariaDB stores authoritative state, and the Windows client sends only a SHA-256 machine fingerprint. A deactivated machine can reactivate when quota is available.
Prepare the environment
Server requirements
- HTTPS Web server capable of running PHP 8.1 or newer;
- PHP extensions
pdo_mysql,sodium, andmbstring; - MariaDB database with InnoDB tables and
utf8mb4encoding; - dedicated MariaDB account for the service;
- Python 3.10 or newer on the administration workstation and in the client application.
https://licenses.example.org/api/licenses. Replace it with the actual HTTPS address of your installation.Create the MariaDB schema
- Create an empty database and a dedicated account whose privileges are restricted to that database.
- Import
database/netdtl_licenses.sqlwith your hosting tool or the MariaDB client. - Confirm that
products,licenses,activations,license_events, andadmin_usersexist, together with thelicense_statusview. - Keep the
MYPRODUCTsample product for testing or create your own active product.
The script contains neither CREATE DATABASE nor USE, so the destination database must be selected during import.
Create the private configuration
Edit server/config.php, replacing every CHANGE_ME value and adapting the default product.
| Key | Expected value |
|---|---|
| db.host / port | MariaDB address and port, normally 3306. |
| db.name / user / password | Database and dedicated service account. |
| db.charset | utf8mb4. |
| admin_api_key | Long random secret reserved for administration. |
| signing_*_key_b64 | Base64-encoded Ed25519 key pair. |
| default_product_code | Active code in products, such as MYPRODUCT. |
config.php must never be placed in Git, sent to a client, or served as text. The activation_attempt_* settings are reserved for future rate limiting and are not yet automatically enforced.
Generate the Ed25519 keys
- Copy
signing_public_key_b64into the configuration. - Copy
signing_secret_key_b64into the protected configuration. - Back up the private key in a separate encrypted location.
- Immediately remove
generate_signing_keys.phpfrom the public Web directory.
Changing this pair later invalidates existing tokens and requires clients to activate again.
Deploy the API
The public HTTPS directory should contain only activate.php, validate.php, deactivate.php, health.php, admin_create_license.php, lib.php, and the private config.php. Do not publish the Python tools, schema, backups, or key generator.
Protect admin_create_license.php carefully. In addition to X-Admin-Key, use an IP restriction, Web-server authentication, or a non-public URL name when possible.
Check the service
Open https://licenses.example.org/api/licenses/health.php. A working installation returns JSON containing at least:
HTTP 503 with DATABASE_UNAVAILABLE means PHP is responding but the MariaDB connection or schema is not operational.
Configure administration
Run the tool from the project root so the bilingual catalog can be imported. Put the address and key in the PowerShell session; the key may be omitted and entered without echo.
The global --base-url and --admin-key options must precede the create subcommand. Avoid --admin-key on a shared computer because its value may remain in command history.
Create a license
| Option | Role |
|---|---|
| Email associated with the license; prompted when absent. | |
| --customer-name | Optional customer name. |
| --product | Active code in the products table. |
| --machines | Permitted number of machines, from 1 to 1000. |
| --expires | Optional MariaDB expiry in the displayed format. |
| --notes | Free-form administration note. |
Integrate the Windows client
Copy client/dtl_license_client.py into the application source. Before testing, replace its product-specific values:
Also adapt the %DTL4U-... message prefix if the application displays these diagnostics. The product code must exactly match an active products row. The module uses only Python’s standard library.
Trigger activation
Your activation screen should collect the email and key, then call:
On success, the module writes the token, machine fingerprint, validation time, and scheduling values to TOKEN_FILE. Never log the plaintext key. Display LicenseError messages to the user without exposing a technical traceback.
Validate at startup
Validation first confirms that the local file exists and belongs to the current machine, then contacts the server. Call it before enabling protected features. The supplied client stores next_check_days and offline_grace_days but does not implement an offline decision. Until the product adds that policy, treat a network failure as a validation failure.
Deactivate an installation
After user confirmation, this revokes the activation on the server and removes the local token. If no local file exists, it succeeds and reports that no deactivation occurred.
Reactivate a machine
A deactivated machine reactivates with the same email and key by calling activate() again. The server first recounts non-revoked activations. When a slot is available it reuses the existing row, clears its revocation time, and issues a new token; otherwise it returns ACTIVATION_LIMIT_REACHED.
Production checklist
- enforce HTTPS with a valid certificate;
- restrict the MariaDB account to the service database;
- protect
config.php, the private key, and backups; - restrict the administration endpoint and monitor
license_events; - protect the NTFS permissions of the local token directory;
- include both the database and private key in disaster recovery;
- do not advertise offline operation until it is implemented in the product.
Minimum acceptance test
- Confirm that
health.phpreports an operational database. - Create a test license limited to one machine.
- Activate and validate the first machine.
- Confirm that a second machine is refused.
- Deactivate the first and confirm that its old token is refused.
- Reactivate it and confirm that the same activation ID is reused.
- Review the corresponding MariaDB events.
The repository does not yet contain automated tests. Run this acceptance test against a test service and database before production.
Troubleshooting
| Message | Check |
|---|---|
| SERVER_NOT_CONFIGURED | Presence and readability of server/config.php. |
| DATABASE_UNAVAILABLE | Host, port, credentials, privileges, and schema import. |
| SODIUM_NOT_AVAILABLE | Sodium extension enabled in PHP. |
| INVALID_SIGNING_KEY | Complete Base64 values and matching key pair. |
| PRODUCT_NOT_FOUND | Code exists and is active in products. |
| UNAUTHORIZED | NETDTL_ADMIN_KEY matches admin_api_key. |
| ACTIVATION_LIMIT_REACHED | Non-revoked activation count and license quota. |
| ACTIVATION_REVOKED | Old deactivated token; activate again with the credentials. |
File quick reference
Server
server/*.phpdatabase/netdtl_licenses.sqlAPI, private configuration, one-time generator, and MariaDB schema.
Administration
admin/DTLlicense.pydtl_licenseserver_i18n.pyLicense creation and bilingual messages.
Application
client/dtl_license_client.py%ProgramData%\Vendor\MyProduct\license.jsonClient to adapt and local token created after activation.