Skip to main content
  1. License Server/

Operating the License Server

Table of Contents

force_table_of_contents
#

This guide covers installing, configuring, and operating the license server — from initial setup through day-to-day administration.

You do not need Go, Docker, or any other development tools installed. The server is a single self-contained binary.

Quick start
#

  1. Extract the zip and cd into it.

  2. Get your server ID and send it to your license provider.

./isohedron-license-server get-server-id
  1. Once you receive .lic files, drop them into a licenses/ folder.
mkdir -p licenses
cp *.lic licenses/
  1. Start the server. ./isohedron-license-server -pubkey public.key

The dashboard is at http://localhost:8848. That’s it — clients can now check out licenses.

What you should have received
#

File Description
isohedron-license-server The server binary (or isohedron-license-server.exe on Windows)
public.key The public key used to verify license files
README.md This guide
LICENSE.md Software license
docker-compose.yml Docker Compose file for running the server in a container
.env Configuration for Docker Compose (bind address, port, admin key)

You may also have received .lic license files. If not, you’ll request them after setting up the server (see Step 4 below).

Setup
#

1. Create a directory for the server
#

Pick a location on the machine that will run the server. For example:

Linux/macOS:

sudo mkdir -p /opt/isohedron-license-server/licenses

Windows:

mkdir C:\isohedron-license-server\licenses

2. Copy files into place
#

Place the binary and public key into the directory:

/opt/isohedron-license-server/
├── isohedron-license-server       # the binary
├── public.key                     # the public key
└── licenses/                      # empty for now — licenses go here later

On Linux/macOS, make the binary executable. The licenses/ directory must be writable by the server process (it stores lease data and lock files there):

chmod +x /opt/isohedron-license-server/isohedron-license-server

3. Choose a port and admin key, then start the server
#

Port: The server listens on port 8848 by default. Pick a port that isn’t used by anything else on this machine. Your license provider may ask for this when creating server-bound licenses.

Admin key: Protects administrative operations (releasing stuck seats, purging expired licenses, reloading licenses, shutting down). You make this up yourself — it’s just a password you pick. There’s no registration or approval process. Pick something long and random:

# Linux/macOS — generate a random key
openssl rand -hex 32

Then start the server:

cd /opt/isohedron-license-server

./isohedron-license-server \
  -licenses ./licenses \
  -pubkey public.key \
  -addr :8848 \
  -admin-key "an-admin-key-you-make-up"

The server will start even without any license files. The dashboard at http://your-server:8848/ will show a warning that no licenses are loaded — that’s expected.

Client applications do not need any key. The signed license files are what controls access.

4. Request your licenses
#

Your license provider needs some information from you to create your licenses. Send them the following.

Your server ID (required for server-bound licenses):

Run this on the server machine. The ID is a hash unique to this machine and port:

isohedron-license-server get-server-id
# → iso-a7f3b2c1e9d4

If you’re using a non-default port, pass --port:

isohedron-license-server get-server-id --port 9000
# → iso-f5e6d7c8b9a0

Machine details for node-locked licenses (if applicable):

For each workstation you want to lock a license to, find its hostname and system ID:

  • Hostname: run hostname in a terminal on the machine
  • System ID (machine UUID):
    • Linux: cat /etc/machine-id
    • macOS: ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID
    • Windows: run in PowerShell: (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Cryptography').MachineGuid

Send the hostname and system ID for each machine to your license provider.

5. Install your licenses
#

When you receive .lic files from your provider, copy them into the licenses/ directory and tell the server to reload:

cp *.lic /opt/isohedron-license-server/licenses/

isohedron-license-server reload --admin-key "your-admin-key"

The dashboard should now show your licensed products. You can also verify from the command line:

isohedron-license-server health
{
  "status": "ok",
  "server_version": "0.1.0",
  "license_version": 1,
  "min_license_version": 1,
  "products": 1,
  "leases": 0
}

6. Run the smoke test
#

Verify that everything is working end-to-end — checkout, heartbeat, checkin, and cleanup:

isohedron-license-server test

7. Configure client machines
#

Client applications only need to know the server URL. Set the appropriate environment variable or configuration for your tool. For example, for Houdini HDAs:

ISOHEDRON_LICENSE_SERVER=http://your-server:8848

No API key is needed on client machines.

8. Adding more licenses later
#

Whenever you receive additional .lic files (more seats, new products, renewals):

  1. Copy the new .lic files into the licenses/ directory.
  2. The server automatically detects the change and reloads within 60 seconds. To reload immediately:
isohedron-license-server reload --admin-key "your-admin-key"

Active sessions are not interrupted. New seats become available immediately.

Configuration reference
#

Flag Default Description
-licenses ./licenses Directory containing your .lic files
-pubkey public.key Path to the public key file
-addr :8848 Address and port to listen on
-admin-key (none) Admin key for privileged operations (force-release, purge-expired, reload). You make this up. Alternatively, set ISOHEDRON_ADMIN_KEY_FILE to read the key from a file.
-heartbeat 2m How often clients should send heartbeats
-ttl 5m How long to wait before reclaiming a seat from a silent client
-tls-cert (none) Path to a TLS certificate file (enables HTTPS)
-tls-key (none) Path to a TLS private key file (enables HTTPS)

CLI commands
#

The server binary includes built-in commands for managing a running server. You don’t need curl or any other tools.

Release stuck seats
#

If a machine’s seats are stuck (e.g., after a crash), you can release a specific lease by ID or all leases for a machine:

# Release a specific lease (get the ID from status)
isohedron-license-server force-release \
  --lease-id "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" \
  --admin-key "your-admin-key"

# Release all leases for a machine
isohedron-license-server force-release \
  --product my-product \
  --machine-id "WORKSTATION-A-7a8b9c0d" \
  --admin-key "your-admin-key"

Get this server’s ID
#

If your license provider needs to create a server-bound license, they’ll ask for your server ID:

isohedron-license-server get-server-id

If you’re using a non-default port, include --port:

isohedron-license-server get-server-id --port 9000

Send the output (e.g., iso-a7f3b2c1e9d4) to whoever creates your licenses.

Check server health
#

Shows whether the server is running, how many products are licensed, and how many active leases there are. Also reports warnings if the licenses directory is missing or no licenses are loaded.

isohedron-license-server health

View loaded licenses
#

See every license file the server has loaded, including its type, capacity, expiry date, days remaining, and whether it’s active or expired. Useful for checking when renewals are needed.

isohedron-license-server licenses

Purge expired licenses
#

Move expired license files out of the active licenses directory into an expired/ subdirectory. The server reloads automatically afterward.

isohedron-license-server purge-expired --admin-key "your-admin-key"

You can also do this from the dashboard using the Purge Expired button.

Reload license files
#

After adding new .lic files to the licenses/ directory:

isohedron-license-server reload --admin-key "your-admin-key"

Shut down the server
#

isohedron-license-server shutdown --admin-key "your-admin-key"

View license status
#

Shows detailed information about each licensed product: how many floating seats are available and in use, how many node-locked machines are configured, who has what checked out, and when licenses expire.

See all products:

isohedron-license-server status

See a specific product:

isohedron-license-server status my-product

Run a smoke test
#

Verify that everything is working — checkout, license proof, response signature, heartbeat, checkin, and cleanup:

isohedron-license-server test

All commands default to http://localhost:8848. To target a remote server, add --server:

isohedron-license-server status --server http://other-host:8848

Running as a background service
#

Linux (systemd)
#

Create /etc/systemd/system/isohedron-license-server.service:

[Unit]
Description=Isohedron License Server
After=network.target

[Service]
ExecStart=/opt/isohedron-license-server/isohedron-license-server \
  -licenses /opt/isohedron-license-server/licenses \
  -pubkey /opt/isohedron-license-server/public.key \
  -addr :8848 \
  -admin-key "an-admin-key-you-make-up"
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
WorkingDirectory=/opt/isohedron-license-server

[Install]
WantedBy=multi-user.target

Then:

sudo systemctl daemon-reload
sudo systemctl enable isohedron-license-server
sudo systemctl start isohedron-license-server

Check status:

sudo systemctl status isohedron-license-server

View logs:

journalctl -u isohedron-license-server -f

Linux (supervisord)
#

If you’re using Supervisor instead of systemd, create /etc/supervisor/conf.d/isohedron-license-server.conf:

[program:isohedron-license-server]
command=/opt/isohedron-license-server/isohedron-license-server
  -licenses /opt/isohedron-license-server/licenses
  -pubkey /opt/isohedron-license-server/public.key
  -addr :8848
  -admin-key "an-admin-key-you-make-up"
directory=/opt/isohedron-license-server
autostart=true
autorestart=true
stdout_logfile=/var/log/isohedron-license-server.log
stderr_logfile=/var/log/isohedron-license-server.log

Then:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start isohedron-license-server

Check status:

sudo supervisorctl status isohedron-license-server

View logs:

tail -f /var/log/isohedron-license-server.log

macOS (launchd)
#

Create ~/Library/LaunchAgents/com.isohedron.license-server.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.isohedron.license-server</string>
  <key>ProgramArguments</key>
  <array>
    <string>/opt/isohedron-license-server/isohedron-license-server</string>
    <string>-licenses</string>
    <string>/opt/isohedron-license-server/licenses</string>
    <string>-pubkey</string>
    <string>/opt/isohedron-license-server/public.key</string>
    <string>-addr</string>
    <string>:8848</string>
    <string>-admin-key</string>
    <string>an-admin-key-you-make-up</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>KeepAlive</key>
  <true/>
  <key>StandardOutPath</key>
  <string>/opt/isohedron-license-server/server.log</string>
  <key>StandardErrorPath</key>
  <string>/opt/isohedron-license-server/server.log</string>
</dict>
</plist>

Then:

launchctl load ~/Library/LaunchAgents/com.isohedron.license-server.plist

Windows
#

The simplest approach is to use NSSM (the Non-Sucking Service Manager):

nssm install IsohedronLicenseServer C:\isohedron-license-server\isohedron-license-server.exe
nssm set IsohedronLicenseServer AppParameters -licenses C:\isohedron-license-server\licenses -pubkey C:\isohedron-license-server\public.key -addr :8848 -admin-key "an-admin-key-you-make-up"
nssm set IsohedronLicenseServer AppDirectory C:\isohedron-license-server
nssm set IsohedronLicenseServer AppStdout C:\isohedron-license-server\server.log
nssm set IsohedronLicenseServer AppStderr C:\isohedron-license-server\server.log
nssm start IsohedronLicenseServer

Or run it directly in a terminal:

cd C:\isohedron-license-server
isohedron-license-server.exe -licenses .\licenses -pubkey public.key -addr :8848 -admin-key "an-admin-key-you-make-up"

Docker Compose
#

A docker-compose.yml and .env file are included in the distribution. Place them alongside the binary, public key, and licenses directory:

your-directory/
├── .env                          # configuration (bind address, port, admin key)
├── docker-compose.yml
├── isohedron-license-server      # the Linux binary
├── public.key
└── licenses/
    └── *.lic

Edit .env to configure the server:

# Which interface to accept connections on (0.0.0.0 = all, 127.0.0.1 = localhost only)
ISOHEDRON_BIND_ADDRESS=0.0.0.0

# Port to expose on the host
ISOHEDRON_PORT=8848

# Admin key for privileged operations (empty = no auth)
ISOHEDRON_ADMIN_KEY=an-admin-key-you-make-up

# Or read the admin key from a file instead (more secure):
# ISOHEDRON_ADMIN_KEY_FILE=/run/secrets/admin-key

Then start:

docker compose up -d

The server is available at http://localhost:8848 (or whichever port you configured). Logs are accessible via docker compose logs -f.

To reload licenses after adding new .lic files:

isohedron-license-server reload --admin-key "your-admin-key"

To stop:

docker compose down

Adding new license files
#

When you receive additional .lic files (e.g., more seats, new products):

  1. Copy the new .lic file into the licenses/ directory.
  2. The server automatically detects the change and reloads within 60 seconds.

If you need the reload to take effect immediately, you can trigger it manually:

CLI command:

isohedron-license-server reload --admin-key "your-admin-key"

Signal (Linux/macOS only):

kill -HUP $(pidof isohedron-license-server)

systemd (Linux):

sudo systemctl reload isohedron-license-server

Active sessions are not interrupted. New seats become available immediately.

Dashboard
#

Open http://your-server:8848/ in a browser to see:

  • Which products are licensed and how many seats are available
  • Who currently has a license checked out
  • How many days until the earliest license expires

The dashboard updates automatically every 30 seconds. No login is required.

REST API endpoints
#

The server exposes a REST API on the configured address (default :8848). Admin endpoints require the X-API-Key header if -admin-key is set.

Admin endpoints
#

Method Path Description
POST /v1/admin/force-release Force-release a lease by ID or by machine
POST /v1/admin/purge-expired Move expired license files to expired/ subdirectory
POST /v1/admin/reload Hot-reload license files from disk
POST /v1/admin/shutdown Gracefully shut down the server

Informational endpoints
#

Method Path Description
GET / Web dashboard
GET /v1/health Health check (includes server version, product/lease counts)
GET /v1/licenses List all loaded license files with expiry status
GET /v1/metrics Prometheus-format metrics
GET /v1/server-id This server’s hashed ID (for server-bound licenses)
GET /v1/status Query all products, seats, and active leases
GET /v1/version Server version

See the README for the full API reference, including client integration endpoints (checkout, checkin, heartbeat).

Common issues
#

Server won’t start
#

  • “failed to load public key” — The server can’t find public.key. Check the path in your -pubkey flag.

Server started but no licenses are loaded
#

  • “no license files found” — The licenses/ directory is empty or doesn’t contain any .lic files. Make sure your license files have the .lic extension. The server runs without licenses but all checkouts will be denied.
  • “skipping license with bad signature” — The .lic files were signed with a different key than the public.key you have. Contact whoever provided you with the files.
  • “skipping license bound to different server” — A .lic file has a server_id that doesn’t match this server. Run isohedron-license-server get-server-id to check your server’s ID and confirm it matches what was used when the license was created.

Clients can’t connect
#

  • Make sure the server is reachable from client machines (check firewalls, port 8848).
  • Make sure clients are using the correct server URL (e.g., http://your-server:8848).

Checkout rejected due to clock skew
#

  • “server clock appears to be more than 24h behind client” — The server’s system clock is significantly behind the client machine’s clock. This check prevents license expiry bypass. Fix the server’s clock (check NTP configuration). A skew of more than 12 hours logs a warning; more than 24 hours rejects the checkout.

Seats are stuck / all in use
#

Crashed clients hold seats until the TTL expires (default: 5 minutes). To see who’s holding seats, run:

isohedron-license-server status

The output includes a leases section for each product. Look for the stuck lease:

{
  "products": [
    {
      "product": "my-product",
      "floating_seats": 5,
      "floating_in_use": 3,
      "leases": [
        {
          "lease_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
          "user": "ben",
          "machine_id": "WORKSTATION-A-7a8b9c0d",
          "product": "my-product",
          "lease_type": "floating",
          "checked_out_at": "2026-05-07T10:00:00Z",
          "processes": {
            "12345": {"pid": "12345", "last_heartbeat": "2026-05-07T10:02:00Z"}
          }
        }
      ]
    }
  ]
}

A lease with stale process heartbeats is likely stuck. Free it using its id:

isohedron-license-server force-release \
  --lease-id "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" \
  --admin-key "your-admin-key"

Or release all leases for that machine at once:

isohedron-license-server force-release \
  --machine-id "WORKSTATION-A-7a8b9c0d" \
  --admin-key "your-admin-key"

You can also check the dashboard at http://your-server:8848/ which shows the same information visually.

Server crashed — will I lose active leases?
#

No. Active leases are saved to .leases inside the licenses directory on every change. When the server restarts, it reloads them. Any leases that expired while the server was down are cleaned up automatically.

Getting help
#

If you’re seeing errors not covered here, check the server logs. All output is JSON, and the msg field describes what happened:

# Linux (systemd)
journalctl -u isohedron-license-server --since "5 minutes ago"

# Linux (supervisord)
tail -100 /var/log/isohedron-license-server.log

# macOS (launchd)
tail -100 /opt/isohedron-license-server/server.log

# Docker Compose
docker compose logs --since 5m

# Windows (NSSM) — if you configured NSSM with log files:
nssm get IsohedronLicenseServer AppStdout
# Then view that file, or check the Windows Event Viewer under
# Applications and Services Logs > IsohedronLicenseServer

# Windows (PowerShell) — if running with output redirected to a file:
Get-Content C:\isohedron-license-server\server.log -Tail 100

# Any platform — just look at the terminal where the server is running