Whether this install may run. The gate checks the stored licence at boot
and every hour, holds :licensed or {:locked, reason} where every
reader finds it without a call, and renews the licence in its term's
last week.
The host starts one gate in its supervision tree, with the options below,
and decides what a lock blocks: it reads status/1 or locked?/1 on each
page or job, and the gate calls :on_lock and :on_unlock when the
install locks or unlocks. A gate name no check has run under reads
{:locked, :not_checked}, so a host that forgets to start the gate runs
locked, not free.
Every function takes the gate's options, so a host can build them from runtime config at each call. The process only runs the boot check and the hourly tick.
load/3, activate/3 and refresh/2 trust the host to have checked who
may call them; the actor passes to the store untouched. renew/1 stores
as :system.
A running install stays licensed through a failure of its own machine (a store it cannot read, a missing machine id, a slow chip): only the licence itself locks a running install. A booting install stays locked until the check passes.
Summary
Functions
Activates with code as actor: sends this install's request to the
licensing server and loads the licence that comes back. A code that is
not 1 to 64 base32 or base64url characters makes no call.
Runs the boot check now and answers the status it holds.
This install's key and machine id hash, or the reason they are missing. Makes the install key when there is none.
The licence in force, or nil when none is stored or the store cannot be read.
Checks bytes as this install's licence and stores it as actor. The
install unlocks when it passes, and :on_unlock runs when it was locked.
Whether the install is locked.
The options every function takes
The hourly check: the boot check again, which also moves the latest time
seen. A running install it finds locked by the licence itself calls
:on_lock; a locked install it finds licensed calls :on_unlock.
Asks for this term's licence with the current seats, as actor, and loads it.
Asks for the next term's licence and loads it, as :system.
The activation request to send the licensing server, as the file's bytes.
Forgets the status under name, which then reads {:locked, :not_checked}.
Starts the gate: the boot check now, then a tick each :check_every.
The install's licence status under name.
One tick: renews when the licence's term ends within :renew_within,
whatever the lock state, so a paid renewal unlocks an install whose term
ended, then runs recheck/1. One renewal call per tick, with no retry:
the next tick is the retry.
Types
@type status() :: :licensed | {:locked, atom()}
Functions
Activates with code as actor: sends this install's request to the
licensing server and loads the licence that comes back. A code that is
not 1 to 64 base32 or base64url characters makes no call.
Runs the boot check now and answers the status it holds.
@spec context(keyword()) :: {:ok, %{install_key: {module(), keyword()}, machine_id_hash: String.t()}} | {:error, atom()}
This install's key and machine id hash, or the reason they are missing. Makes the install key when there is none.
The licence in force, or nil when none is stored or the store cannot be read.
Checks bytes as this install's licence and stores it as actor. The
install unlocks when it passes, and :on_unlock runs when it was locked.
Whether the install is locked.
@spec options() :: NimbleOptions.t()
The options every function takes:
:name(atom/0) - Required. The gate's name; its status is kept under it.:product(String.t/0) - Required. The product this app is.:product_version(String.t/0) - Required. The app's version.:root_keys(list ofString.t/0) - Required. The trusted Ed25519 root public keys, raw (Aker.PublicKeys.decode/1).:licence_dir- The folder that holds the install key.:machine_id_path- The host's machine id file (default/etc/machine-id).:require_mount(boolean/0) - Refuse with:machine_id_not_mountedunless:machine_id_pathis given, for a container whose own/etc/machine-idevery copy shares. The default value isfalse.:store(tuple ofatom/0,keyword/0values) - Required.{module, opts}of anAker.Store.:server(keyword/0) -Aker.Client's server options. The default value is[].:on_lock(function of arity 0) - Called when a running install locks.:on_unlock(function of arity 0) - Called when a locked install unlocks.:check_every(pos_integer/0) - Milliseconds between ticks. The default value is3600000.:renew_within(pos_integer/0) - Seconds before the term ends when each tick renews. The default value is604800.:tpm_device(String.t/0) - The TPM chip's device. The default value is"/dev/tpmrm0".:tpm_options(keyword/0) -Aker.InstallKey.Tpmoptions. The default value is[].:settings(keyword/0) - The setting names a log line tells the operator to set, for:licence_dir,:machine_id_pathand:server_url(default each option's own name). The default value is[].:now(struct of typeDateTime) - The time to check against, for tests only: a host that sets it freezes the gate's clock.
The hourly check: the boot check again, which also moves the latest time
seen. A running install it finds locked by the licence itself calls
:on_lock; a locked install it finds licensed calls :on_unlock.
Asks for this term's licence with the current seats, as actor, and loads it.
Asks for the next term's licence and loads it, as :system.
The activation request to send the licensing server, as the file's bytes.
@spec reset(atom()) :: :ok
Forgets the status under name, which then reads {:locked, :not_checked}.
@spec start_link(keyword()) :: GenServer.on_start()
Starts the gate: the boot check now, then a tick each :check_every.
The install's licence status under name.
One tick: renews when the licence's term ends within :renew_within,
whatever the lock state, so a paid renewal unlocks an install whose term
ended, then runs recheck/1. One renewal call per tick, with no retry:
the next tick is the retry.