DTL_LicenseServer — User Guide

Service installation and detailed integration into a Windows application.

versionv1.0-6dateJuly 21, 2026audienceadministrators and developerslanguageFrançaislicenseMIT

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

Example address. Every command uses https://licenses.example.org/api/licenses. Replace it with the actual HTTPS address of your installation.

Create the MariaDB schema

  1. Create an empty database and a dedicated account whose privileges are restricted to that database.
  2. Import database/netdtl_licenses.sql with your hosting tool or the MariaDB client.
  3. Confirm that products, licenses, activations, license_events, and admin_users exist, together with the license_status view.
  4. Keep the MYPRODUCT sample product for testing or create your own active product.
mariadb.exe -h DB_HOST -u DB_USER -p DB_NAME < database\netdtl_licenses.sql

The script contains neither CREATE DATABASE nor USE, so the destination database must be selected during import.

Create the private configuration

Copy-Item .\server\config.example.php .\server\config.php

Edit server/config.php, replacing every CHANGE_ME value and adapting the default product.

KeyExpected value
db.host / portMariaDB address and port, normally 3306.
db.name / user / passwordDatabase and dedicated service account.
db.charsetutf8mb4.
admin_api_keyLong random secret reserved for administration.
signing_*_key_b64Base64-encoded Ed25519 key pair.
default_product_codeActive 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

php .\server\generate_signing_keys.php
  1. Copy signing_public_key_b64 into the configuration.
  2. Copy signing_secret_key_b64 into the protected configuration.
  3. Back up the private key in a separate encrypted location.
  4. Immediately remove generate_signing_keys.php from 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:

{ "success": true, "service": "DTL_LicenseServer", "version": "1.0.6", "database": "ok" }

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.

$env:NETDTL_LICENSE_API = 'https://licenses.example.org/api/licenses' $env:NETDTL_ADMIN_KEY = 'same-secret-as-config.php' $env:DTL_LANGUAGE = 'en'

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

python -m admin.DTLlicense create ` --email 'customer@example.org' ` --customer-name 'Example Customer' ` --product 'MYPRODUCT' ` --machines 2 ` --expires '2027-12-31 23:59:59' ` --notes 'Order 2026-001'
OptionRole
--emailEmail associated with the license; prompted when absent.
--customer-nameOptional customer name.
--productActive code in the products table.
--machinesPermitted number of machines, from 1 to 1000.
--expiresOptional MariaDB expiry in the displayed format.
--notesFree-form administration note.
One-time key. The plaintext key is displayed only once. Immediately store it in a secret manager or send it through an appropriate channel.

Integrate the Windows client

Copy client/dtl_license_client.py into the application source. Before testing, replace its product-specific values:

PRODUCT_CODE = "MYPRODUCT" CLIENT_VERSION = "1.0.2" DEFAULT_API_BASE = "https://licenses.example.org/api/licenses" TOKEN_FILE = Path(os.environ.get("PROGRAMDATA", ".")) / "Vendor" / "MyProduct" / "license.json"

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:

from dtl_license_client import activate result = activate( email=entered_email, license_key=entered_key, app_version=APP_VERSION, api_base="https://licenses.example.org/api/licenses", )

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

from dtl_license_client import LicenseError, validate try: validate(api_base="https://licenses.example.org/api/licenses") except LicenseError as exc: show_license_error(str(exc)) close_application()

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

from dtl_license_client import deactivate deactivate(api_base="https://licenses.example.org/api/licenses")

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

Minimum acceptance test

  1. Confirm that health.php reports an operational database.
  2. Create a test license limited to one machine.
  3. Activate and validate the first machine.
  4. Confirm that a second machine is refused.
  5. Deactivate the first and confirm that its old token is refused.
  6. Reactivate it and confirm that the same activation ID is reused.
  7. 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

MessageCheck
SERVER_NOT_CONFIGUREDPresence and readability of server/config.php.
DATABASE_UNAVAILABLEHost, port, credentials, privileges, and schema import.
SODIUM_NOT_AVAILABLESodium extension enabled in PHP.
INVALID_SIGNING_KEYComplete Base64 values and matching key pair.
PRODUCT_NOT_FOUNDCode exists and is active in products.
UNAUTHORIZEDNETDTL_ADMIN_KEY matches admin_api_key.
ACTIVATION_LIMIT_REACHEDNon-revoked activation count and license quota.
ACTIVATION_REVOKEDOld deactivated token; activate again with the credentials.

File quick reference

Server

server/*.phpdatabase/netdtl_licenses.sql

API, private configuration, one-time generator, and MariaDB schema.

Administration

admin/DTLlicense.pydtl_licenseserver_i18n.py

License creation and bilingual messages.

Application

client/dtl_license_client.py%ProgramData%\Vendor\MyProduct\license.json

Client to adapt and local token created after activation.