New: Offline-first licensing with cryptographic validation. Learn more

Sneakernet CLI Reference

Complete reference for offline license activation using the licenz sneakernet commands. Sneakernet enables license activation on air-gapped machines without network connectivity.

Overview

The sneakernet workflow enables license activation for machines that cannot connect to the internet. This is essential for air-gapped environments, secure facilities, and industrial systems without network access.

Workflow Summary

  1. Request: Generate an activation request file (.req) on the air-gapped machine
  2. Transfer: Move the request file to a connected machine (USB drive, etc.)
  3. Process: Upload the request to the Licenz server to generate a response
  4. Transfer: Move the response file (.resp) back to the air-gapped machine
  5. Install: Install the license from the response file

Commands

licenz sneakernet request

Generate an activation request file containing the machine's hardware fingerprint. This file is safe to transfer and contains no sensitive information.

Synopsis

licenz sneakernet request \
  --product <PRODUCT_ID> \
  [--output <FILE>] \
  [--features <FEATURES>] \
  [--name <CUSTOMER_NAME>] \
  [--email <CUSTOMER_EMAIL>] \
  [--reference <ORDER_REF>] \
  [--text]

Options

Option Description Default
-p, --product <ID> Product ID to request license for (required) -
-o, --output <FILE> Output file path for the request activation.req
-f, --features <LIST> Comma-separated list of requested features -
--name <NAME> Customer name to include in request -
--email <EMAIL> Customer email to include in request -
--reference <REF> Order or purchase reference number -
--text Use Base64 text format instead of binary false

Examples

# Basic request
licenz sneakernet request --product prod_abc123

# Request with custom output path
licenz sneakernet request \
  --product prod_abc123 \
  --output /mnt/usb/machine1.req

# Request with customer metadata
licenz sneakernet request \
  --product prod_abc123 \
  --name "Acme Corporation" \
  --email "it@acme.com" \
  --reference "PO-2024-1234"

# Request specific features
licenz sneakernet request \
  --product prod_abc123 \
  --features "enterprise,analytics,export"

# Use text format for email transfer
licenz sneakernet request \
  --product prod_abc123 \
  --text \
  --output activation.txt

Output

The command displays:

  • Request ID (unique identifier for tracking)
  • Product ID
  • Requested features (if any)
  • Customer metadata (if provided)
  • Hardware fingerprint summary (MAC count, disk count, hostname detection)
  • Output file path and format
  • Next steps instructions

Request File Contents

The generated .req file contains:

  • Unique request ID
  • Product ID
  • Hardware fingerprint (hashed MAC addresses, disk IDs, hostname)
  • Requested features list
  • Customer metadata
  • Timestamp and version
  • Integrity checksum

licenz sneakernet install

Install a license from an activation response file. This validates the response integrity and expiration, then extracts and saves the signed license.

Synopsis

licenz sneakernet install <RESPONSE_FILE> \
  [--output <FILE>] \
  [--json]

Arguments

Argument Description
<RESPONSE_FILE> Path to the .resp file received from the server

Options

Option Description Default
-o, --output <FILE> Output path for the installed license license.lic
--json Save license in JSON format instead of binary false

Examples

# Install from response file
licenz sneakernet install activation.resp

# Install with custom output path
licenz sneakernet install /mnt/usb/response.resp \
  --output /opt/myapp/license.lic

# Install as JSON format
licenz sneakernet install activation.resp --json

# Install to specific location
licenz sneakernet install response.resp \
  -o /etc/myapp/license.lic

Validation

The install command performs these checks:

  • Integrity: Verifies the response file has not been corrupted or tampered with
  • Expiration: Checks if the response file is still valid (responses expire after a set period)

Output

On successful installation, displays:

  • License ID and serial number
  • Product ID
  • Customer ID
  • Enabled features
  • Validity period (valid from/until)
  • Maximum seats
  • Response metadata (request ID, server message, days remaining)
  • Output file path

Error Conditions

Error Cause Solution
Integrity check failed File corrupted during transfer Re-download the response file
Response expired Too much time passed since generation Generate a new response from the server
Failed to load response Invalid file format Ensure correct file and format

licenz sneakernet status

Display detailed information about a pending activation request file. Useful for verifying the request before transfer.

Synopsis

licenz sneakernet status <REQUEST_FILE> \
  [--json]

Arguments

Argument Description
<REQUEST_FILE> Path to the .req file to inspect

Options

Option Description Default
--json Output as JSON for scripting false

Examples

# View request details
licenz sneakernet status activation.req

# JSON output for scripting
licenz sneakernet status activation.req --json

# Inspect request from USB drive
licenz sneakernet status /mnt/usb/machine1.req

Output

Displays:

  • Request ID
  • Product ID
  • Creation timestamp
  • Request version
  • Requested features (if any)
  • Customer metadata (if any)
  • Hardware fingerprint details (combined hash, MAC count, disk count, hostname status)
  • Integrity status (checksum validation)
  • Instructions for processing

JSON Output Format

{
  "request_id": "550e8400-e29b-41d4-a716-446655440000",
  "product_id": "prod_abc123",
  "timestamp": "2024-01-15T10:30:00Z",
  "version": 1,
  "requested_features": ["enterprise", "analytics"],
  "metadata": {
    "customer_name": "Acme Corporation",
    "customer_email": "it@acme.com"
  },
  "fingerprint": {
    "combined_hash": "a1b2c3d4e5f6...",
    "mac_hashes": 2,
    "disk_hashes": 1,
    "hostname_hash": true
  },
  "integrity_valid": true
}

licenz sneakernet response-info

Display detailed information about an activation response file before installing it. Useful for verifying the license details match expectations.

Synopsis

licenz sneakernet response-info <RESPONSE_FILE> \
  [--json]

Arguments

Argument Description
<RESPONSE_FILE> Path to the .resp file to inspect

Options

Option Description Default
--json Output as JSON for scripting false

Examples

# View response details before installing
licenz sneakernet response-info activation.resp

# JSON output
licenz sneakernet response-info activation.resp --json

# Check response from USB drive
licenz sneakernet response-info /mnt/usb/response.resp

Output

Displays:

  • Request ID (matches the original request)
  • Server timestamp
  • Expiration date and days remaining
  • Response version
  • Server message (if any)
  • License details (ID, serial, product, customer, features, validity, seats)
  • Integrity status
  • Expiration status
  • Install command hint (if ready to install)

JSON Output Format

{
  "request_id": "550e8400-e29b-41d4-a716-446655440000",
  "server_timestamp": "2024-01-15T10:35:00Z",
  "expires_at": "2024-01-22T10:35:00Z",
  "days_until_expiry": 7,
  "version": 1,
  "message": "License generated successfully",
  "is_expired": false,
  "integrity_valid": true,
  "license": {
    "id": "lic_xyz789",
    "serial": "LIC-XXXXX-XXXXX-XXXXX",
    "product_id": "prod_abc123",
    "customer_id": "cust_def456",
    "features": ["enterprise", "analytics"],
    "valid_from": "2024-01-15T00:00:00Z",
    "valid_until": "2025-01-15T00:00:00Z",
    "max_seats": 10
  }
}

Complete Workflow Example

Here is a complete example of activating a license on an air-gapped machine:

Step 1: Generate Request (Air-Gapped Machine)

# On the air-gapped machine
licenz sneakernet request \
  --product prod_abc123 \
  --name "Secure Facility #7" \
  --email "admin@facility7.internal" \
  --reference "PO-2024-5678" \
  --features "enterprise,compliance,audit" \
  --output /mnt/usb/facility7.req

# Verify the request was created correctly
licenz sneakernet status /mnt/usb/facility7.req

Step 2: Process Request (Connected Machine)

# On a machine with internet access
# Upload via Licenz web portal or API
# Download the generated .resp file to USB drive

Step 3: Verify Response (Optional)

# Back on the air-gapped machine
# Verify the response before installing
licenz sneakernet response-info /mnt/usb/facility7.resp

Step 4: Install License (Air-Gapped Machine)

# Install the license
licenz sneakernet install /mnt/usb/facility7.resp \
  --output /opt/myapp/license.lic

# Verify the installed license
licenz license status

Hardware Fingerprinting

The activation request includes a hardware fingerprint to bind the license to the specific machine. The fingerprint is generated from:

  • MAC Addresses: Network interface hardware addresses (hashed)
  • Disk IDs: Storage device serial numbers (hashed)
  • Hostname: Machine hostname (hashed, optional)

All values are cryptographically hashed before being included in the request, ensuring no sensitive system information is exposed.

File Formats

Binary Format (Default)

The default binary format is compact and efficient for file transfer. Use this format when transferring via USB drives or other media.

Text Format (Base64)

The text format encodes the data as Base64, making it suitable for:

  • Email transfer
  • Copy/paste operations
  • Systems that don't handle binary files well
# Generate text format request
licenz sneakernet request --product prod_abc123 --text

Security Considerations

  • Request files do not contain sensitive information - safe to transfer
  • Response files contain signed licenses - handle according to your security policy
  • Hardware fingerprints are one-way hashes - original values cannot be recovered
  • Response files have an expiration period - install promptly
  • Verify file integrity after transfer using the status and response-info commands

Troubleshooting

Request Generation Fails

# Run with verbose output
licenz --verbose sneakernet request --product prod_abc123

# Check hardware detection
licenz hardware

Response Expired

Response files have a limited validity period. If expired, you need to generate a new response from the server using the original request file.

Integrity Check Failed

File corruption during transfer. Ensure:

  • Transfer method preserves binary data (no text conversion)
  • USB drive has no bad sectors
  • File is completely transferred (check file size)

Hardware Mismatch After Installation

If the license fails validation due to hardware mismatch, the hardware may have changed since the request was generated. Generate a new request and response.