pixop-kvm-pulse
pixop-kvm-pulse
Guest CLI for KVM Pulse credential activation: enrolls the appliance with Pixop Pulse over HTTPS, writes Basic Auth credentials to /etc/pixop-live/pulse.env, and records non-secret metadata under /var/lib/pixop-kvm-pulse/. It does not print license JWTs, Pulse passwords, or private keys.
Installed path: /opt/pixop/bin/pixop-kvm-pulse. KVM QCOW2 images ship with PIXOP_MARKETPLACE_MODE=off so AWS Marketplace activation is skipped; Pulse credentials are provisioned through this tool instead.
For the full KVM licensing workflow (host install, first boot, renewal), see KVM license and Pulse activation. Host-side SSH wrapper: pixop-install license activate.
Usage
pixop-kvm-pulse {activate|repair|retry|status|show-identity} [--json]
pixop-kvm-pulse -h|--help| Command | Mutates state? | Purpose |
|---|---|---|
activate | Yes | Contact Pulse, install or refresh pulse.env, update state.json |
repair | Yes | Re-fetch credentials from Pulse and rewrite pulse.env (same HTTPS activate call) |
retry | Yes when activation runs | Timer/operator retry after deferred activation; may no-op |
status | May migrate legacy identity paths under /var/lib/pixop-live/ into /var/lib/pixop-kvm-pulse/; no Pulse request | Local file + container apply hints (no secrets) |
show-identity | May initialize/repair local identity; no Pulse request | Public appliance id and Ed25519 public key for Pixop support / rebind (private key stays on disk only) |
--json prints a single JSON object (success or errorCode / message on failure). Human output never includes credentials.
Privileges
If not root, the script re-executes via sudo with its real path (same pattern as other guest tools). Set PIXOP_KVM_PULSE_NOSUDO=1 only in tests. Operators normally run pixop-kvm-pulse without typing sudo.
Paths and permissions
| Path | Role | Typical mode |
|---|---|---|
/etc/pixop-live/license.jwt | Customer license JWT (bind-mounted into pixop-live) | root-readable |
/etc/pixop-live/pulse.env | Pulse Basic Auth (PIXOP_LIVE_PULSE_USER / PIXOP_LIVE_PULSE_PASSWORD) | 0600 root:root |
/var/lib/pixop-kvm-pulse/ | Appliance identity + activation metadata (not Docker-mounted) | 0700 root:root |
/var/lib/pixop-kvm-pulse/appliance-key | Ed25519 private key | 0600 |
/var/lib/pixop-kvm-pulse/appliance-id | Derived appliance id | 0600 |
/var/lib/pixop-kvm-pulse/state.json | Non-secret activation metadata | 0640 |
/run/pixop-live/kvm-pulse.lock | Single-writer lock during activate/repair | runtime |
Older guests may still hold identity under /var/lib/pixop-live/; the first command moves those files into /var/lib/pixop-kvm-pulse/ when the new directory is empty (enrollment preserved).
Back up /var/lib/pixop-kvm-pulse/ with the VM. Cloning the disk copies identity. Lost keys after enrollment require Pixop support rebind (show-identity output)—do not silently regenerate identity.
License and Pulse configuration
- The license file must be a compact JWS at
/etc/pixop-live/license.jwt. - The JWT must carry the signed claim exactly
pixop.allowed_deployments: ["kvm"](Pulse rejects mixed entitlements, case variants, missing or extra array entries). AWS Marketplace license tokens are rejected for KVM activation even when instance limits are high. - Pulse base URL must be HTTPS (default
https://live-pulse.pixop.com). Overrides:PIXOP_KVM_PULSE_BASE_URLorPIXOP_LIVE_PULSE_URL. Insecure HTTP is test-only on loopback withPIXOP_KVM_PULSE_ALLOW_INSECURE_HTTP. - Activation uses
POST …/v1/kvm/activatewith protocol version 2 (signedrequestProofon every request). Customers do not call admin or revoke APIs directly.
Command behavior
activate
activate- Read license JWT and appliance identity.
- Call Pulse activate (idempotent for the same license + appliance).
- Atomically write
pulse.envand mergestate.json.
action in JSON:
| Value | Meaning |
|---|---|
activated | First successful enrollment on this appliance |
refreshed | Same deploymentId as before—credentials rewritten |
reinstalled | New deploymentId vs prior local state |
Repeat activate with the same license and appliance contacts Pulse every time and reinstalls credentials on disk. It does not restart pixop-live.
Retryable Pulse outages set pendingActivation in state.json and exit 1; first-boot init may enable pixop-kvm-pulse-retry.timer (see KVM license guide).
repair
repairSame Pulse activate call as activate, always intended to rewrite pulse.env when Pulse still authorizes the deployment. Use after credential rotation or a corrupted pulse.env when the license and appliance binding are still valid.
retry
retryUsed by pixop-kvm-pulse-retry.timer and operators after deferred activation:
- If activation is no longer pending and
deploymentIdexists →action: noop, exit 0. - If no license file →
action: skipped-no-license, exit 1. - On retryable Pulse errors →
action: pending, exit 1. - On success → same outcomes as
activate.
status
statusReads local state.json and compares on-disk pulse.env to the running pixop-live container environment (via Docker inspect). It does not validate current Pulse authorization, server-side revocation, or JWT expiry. Those conditions are revealed by the next activate / repair request, which may fail (for example errorCode pulse_rejected). For JWT expiry claims on disk, use pixop-license decode—not status.
Common non-secret JSON fields:
| Field | Meaning |
|---|---|
pendingActivation | Last activate failed with a retryable error; timer may be active |
deploymentId | Pulse deployment id from last successful activation (may be stale if revoked server-side) |
pulseEnvConfigured | pulse.env contains both user and password keys |
credentialsPendingApply | On-disk credentials differ from the running container (or inspect unavailable) |
restartRequired | true when a running container must be restarted to load new credentials; false when not needed; null when inspect could not decide |
containerPulseCredentials | matching, mismatch, missing_in_container, not_running, service_inactive, absent_on_disk, inspect_unavailable, … |
containerRunning | Whether the pixop-live container is running (when inspect works) |
applyCredentialsCommand | sudo pixopctl restart (Pixop-only—not pixop-stack restart) |
applyCredentialsNote | Reminder to restart during a maintenance window |
When restartRequired is true, apply credentials with a controlled maintenance restart—never automatic during broadcast:
pixopctl restartpixop-live loads Pulse env vars only at container create time; updating pulse.env while the container runs does not change in-process credentials.
show-identity
show-identityCalls load_identity: on first use when not yet enrolled it may create appliance-key / appliance-id, recreate a missing appliance-id when the private key exists, and fix insecure modes as root. Output is applianceId and base64 publicKey only—the private key is never printed. Provide this output to Pixop support for replacement appliance rebind. After a prior successful enrollment, a missing private key is an error (restore backup or contact support)—identity is not silently regenerated.
Exit codes
| Code | When |
|---|---|
| 0 | Success; retry noop; status / show-identity |
| 1 | KvmPulseError (missing license, Pulse rejection, config error, …); retry pending/skipped |
| 2 | Unknown subcommand |
With --json, failures still return exit 1 and print {"ok": false, "errorCode": "…", "message": "…"}.
Related
- KVM license and Pulse activation
- pixop-install —
license activatefrom the KVM host - pixopctl — apply credentials after activation
- pixop-license — JWT/Marketplace inspection (not authoritative KVM Pulse credential status)
Updated about 16 hours ago
