Installation

The fastest production path is the VM appliance: import, boot, answer five questions, done. Docker Compose and bare binaries are available too.

Documentation for 1.0.38. Screenshots show example data.

What you need

  • ▸The appliance image for your hypervisor — .ova (VMware/ESXi), .vhdx (Hyper-V), or .qcow2 (Proxmox/KVM). Sign in and request the trial; once approved, the images appear under the downloads in your account (personal, time-limited links). License customers receive their delivery channel with the contract.
  • ▸2 vCPU / 4 GB RAM / 50 GB disk as the floor; DHCP or a reserved IP on the network you attach it to.
  • ▸A DNS name for the server (e.g. pki.example.com) — agents and browsers will verify the TLS certificate against it.

Import and boot

VMware (vSphere / ESXi)

Deploy OVF Template → select the .ova. Give it a network with DHCP or a reserved IP.

Microsoft Hyper-V

New → Virtual Machine → Generation 1, attach the .vhdx as the disk, connect a virtual switch. Generation 2 works too if you disable Secure Boot.

Proxmox VE

The image is BIOS-based: create the VM with the defaults (Machine i440fx, BIOS SeaBIOS) and SCSI Controller VirtIO SCSI single, then import the qcow2 as its disk:

# create an empty VM shell (VMID 107 here; vmbr0 = your bridge)
qm create 107 --name ens0key --memory 4096 --cores 2 --ostype l26 \
  --scsihw virtio-scsi-single --net0 virtio,bridge=vmbr0 --agent 1

# import the disk into your storage (check names with pvesm status)
qm importdisk 107 /root/ens0key-<version>.qcow2 local-lvm

# attach the volume importdisk printed, boot from it, start
qm set 107 --scsi0 local-lvm:vm-107-disk-0
qm set 107 --boot order=scsi0
qm start 107

Then open the VM Console (noVNC). Resize the disk later with qm resize 107 scsi0 +20G if needed. Plain KVM/libvirt also works: virt-install --import with the qcow2 (BIOS, virtio disk and network).

First-boot wizard

The appliance boots straight into a console wizard. It asks five things:

  1. 01Hostname — e.g. pki.example.com.
  2. 02Network — DHCP, or a static IP/CIDR with gateway and DNS.
  3. 03Admin password — for the UI/API user admin. The wizard also generates the database password and the vault master key.
  4. 04OS/SSH password — for the ens0key Linux user, used for the console/SSH ops tools and troubleshooting.
  5. 05Confirm — the wizard writes the configuration, starts the stack, and disables itself. It prints the URL to open.
Immediately copy ENS0KEY_MASTER_KEY out of /opt/ens0key/.env into your secrets manager. Every encrypted secret — private keys, backups — depends on it; without it they can never be decrypted.

Open https://<ip>, accept the temporary self-signed certificate, and sign in as admin. To change the network or hostname later, re-run sudo /opt/ens0key/firstboot.sh --force — secrets are not touched.

Real TLS certificate

The appliance starts on a self-signed certificate. Replace it before going live — pick one of three ways:

  • ▸From the GUI (recommended): issue or import a certificate into the inventory (with its private key), then Settings → Access & security → Platform HTTPS → pick it. It is served immediately via a runtime swap, no restart, and persists.
  • ▸Console helper: copy the pair to the appliance and run sudo ens0key-set-tls fullchain.pem key.pem. Re-run to rotate.
  • ▸Manually: point ENS0KEY_TLS_CERT / ENS0KEY_TLS_KEY in /opt/ens0key/.env at your PEM pair.
This matters for agents: the default self-signed certificate has SAN localhost only, so a remote agent cannot verify the server by hostname. Serve a certificate whose SAN is the server's real FQDN/IP, and agents verify it cleanly — no insecure mode.

Alternative: Docker Compose or binaries

Prefer your own infrastructure conventions? The same stack runs as Docker Compose (server + PostgreSQL, one port for API and UI) or as a single Go binary with your own PostgreSQL — the appliance is convenience, not a requirement. The compose bundle ships with the release archive.

Upgrading

For the current release, start with the upgrade guide. The notes below explain compatibility boundaries when upgrading older installations through 1.0.35.

Back up the database and preserve the master key before an upgrade. Validate the release in your target environment, then use the appliance upgrade procedure for the approved version. Application image updates do not install updated host scripts or upgrade every remote agent. Existing appliances need the hardened upgrade-backup script installed separately; GUI backup repositories are a separate mechanism.

Upgrades from before 1.0.24 require a maintenance window, paused agents and a review of jobs cancelled by the security migration. From 1.0.26, test local MFA and recovery before enforcing a policy. Migrations are forward-only; image rollback alone cannot reverse them.

  • ▸Order: upgrade the server with the normal backup and health checks, then upgrade both agent supervisor and worker for 1.0.35 execution telemetry, durable results and keystore readiness. Older agents remain compatible. Confirm the version and a fresh heartbeat for the same ID; keep the private agent state directory persistent and writable.
  • ▸Linux migration: installations through 1.0.27 need the current host installer run once to move binaries into the service-writable directory. Already migrated installations support GUI upgrades. See agent upgrade instructions.
  • ▸Nginx: helper installation and updates remain host-admin operations. Version 1.0.33 requires no new helper or host-console script change relative to 1.0.32; existing profiles, paths and permissions remain.

Version 1.0.35 applies additive migrations 0086–0090 on startup, retaining identity, credentials and store configuration. Store schedules and notification rules are not enabled automatically. Configure the desired email/Teams channels and rules explicitly, use an HTTPS application origin reachable by recipients, and verify actual message receipt. Inspect pending result delivery and uncertain host outcomes before restarting or retrying operations.

Upgrading from 1.0.29 also applies migration 0080 for key/template selection and 0081 for WLC recovery records. Version 1.0.34 adds forward-only migrations 0082–0085. Preserve license, MFA, configuration and identity. An upgrade does not deploy or reissue a device certificate.

Existing LDAP/SSO sessions require a fresh sign-in after 1.0.34 to bind immutable directory identity. Local accounts and MFA are retained. Review the default RBAC role and configure DNS/CA trust for verified LDAPS. New Packer appliances include the journal bridge; an existing appliance requires a separate host installation after the server upgrade. Follow the in-app Logs/SIEM instructions and verify collection and receiver parsing; changing the server image alone does not install the host service.

Existing Catalyst 9800 targets without an explicit transfer mode now use verified HTTPS upload. Configure trust for the currently served device certificate before deploying. Review the WLC guide for recovery and compatibility limits. Before a downgrade, assess schema compatibility, post-upgrade writes and pending recovery records; reverting an image does not restore device configuration.

Migration 0079 makes HTTPS checks unique by store, host, port and SNI. An image-only rollback to 1.0.28 is incompatible with this database change. Retain the matching pre-upgrade database and environment backup, and assess writes made after the upgrade before restoring it. Migrations 0077 and 0078 introduced agent FQDN and separate SNI respectively.
Read the product updates and upgrade notes →

Trial and license

A fresh install starts the trial automatically on first boot — every feature, for 30 days or 10 issued certificates, whichever comes first. No license file and no registration on the appliance itself; the registration happens once, on this site, to get the download. To activate a purchased license, upload your signed .lic file under Settings → Maintenance → License — verification is fully offline (Ed25519), no phone-home. If a license lapses, read-only inventory, monitoring, discovery and reports keep working; only issuance, renewal and deployment pause.

Activating or removing a license now refreshes the global license banner immediately. An application upgrade must preserve the existing license and trial start; it does not start a new trial.