Configuration reference

v0.1.14

Reference for every setting of Mishka Installer: the application settings under :mishka_installer, the keys of the Mnesia store, the two environment variables, the processes the library starts, and the values it fixes itself. Events and plugins work with no configuration. The installer and a production deployment need the settings below.

Application settings

Set these with config :mishka_installer, key, value. In a release, put them in config/runtime.exs.

KeyDefaultMeaning
:project_pathnoneThe project root. The PROJECT_PATH environment variable wins when it is set. install/1 returns to this directory when it ends, so set it before you install. It is also the base of the default extensions path.
:project_envthe Mix environment at compile time, or :prod when Mix is not loadedThe environment name used in default paths. The MIX_ENV environment variable wins when it is set.
:extensions_path<project_path>/deployment/<env>/extensionsThe folder that holds installed packages. Point it at a writable volume in production.
:allowlist[]A keyword list with the keys in the next table.
:downloader_req_options[]Options merged into every download request made with Req: the call to the GitHub API and the download of the artifact. The library's tests use it to plug in Req.Test. See "Downloader options and a proxy" below.
:proxy[]Options merged into every download request after :downloader_req_options, so a key set in both takes its value from here. Use it for connect_options: [proxy: ...].

Allowlist keys

KeyDefaultMeaning
url_hosts[]Hosts a :url install may download from. The host of the address must equal one entry. An empty list blocks every :url install.
github_repos[]Repositories, as "owner/repo", that :github_tag and :github_latest_release may use. An empty list blocks them.
protected_apps["mishka_installer"]Applications that cannot be installed over or uninstalled. Setting the key replaces the default list.

Local :path installs never use url_hosts or github_repos. Every refusal logs a warning and emits the [:mishka_installer, :installer, :blocked] telemetry event.

Downloader options and a proxy

A :url, :github_tag or :github_latest_release install downloads with Req. Both settings are keyword lists of Req options. The library builds each request, then merges :downloader_req_options and then :proxy into it, key by key. A key set in both takes the value of :proxy, and a nested option such as headers or connect_options is replaced as a whole. A GitHub install sends two requests, one to the GitHub API for the release and one for the asset, and both get the options.

elixir
config :mishka_installer, :downloader_req_options,
  receive_timeout: 60_000

config :mishka_installer, :proxy,
  connect_options: [proxy: {:http, "proxy.internal", 3128, []}]

Req waits 15 seconds for a response unless you set :receive_timeout, so raise it for a large artifact on a slow link. The proxy value is {scheme, host, port, options}. The proxy carries an http download as a proxied request and an https download through a CONNECT tunnel.

In 0.1.13 and 0.1.14 a request that cannot be made raises a Req exception out of install/1. A refused connection, a timeout and a proxy that refuses the tunnel all do this. An answer other than 200 comes back as {:error, [%{action: :download}]}.

Mnesia store

Set these with config :mishka_installer, MishkaInstaller.MnesiaRepo, options.

KeyDefaultMeaning
:mnesia_dir".mnesia/<env>"Where Mnesia keeps its files. The store points the :mnesia application at this folder when it boots. The default is relative to the directory where the node starts, and install/1 changes the working directory, so use an absolute path in production.
:essential[MishkaInstaller.Installer.Installer, MishkaInstaller.Event.Event]Modules whose database_config/0 defines a table to create on boot. Keep both. Add a module of your own to have the store create your table too: database_config/0 returns the options of :mnesia.create_table/2. The helper modules documentation has a worked example.
:cluster_nodes:auto:auto or [] makes this node a standalone seed that owns the schema. A list of nodes makes it a joiner. A joiner wipes its local schema, joins those nodes and copies the essential tables. If none is reachable it boots :pending and joins when one connects.
:dynamic_membershiptrueWatches the Erlang cluster and joins configured peers that connect after boot. It is active only when :cluster_nodes lists peers.
:wait_timeout60_000Milliseconds in one wait for tables to load from disk.
:wait_retries5How many waits to try before the boot stops.

MishkaInstaller.__information__/0 returns the resolved values as %{path: path, env: env}.

Read the store

MishkaInstaller.MnesiaRepo.state/0 returns a %MishkaInstaller.MnesiaRepo.State{}. It is a call to the store process, so it fails while that process is not running. MishkaInstaller.MnesiaRepo.schemas/0 lists every local table except :schema, read from Mnesia on each call, as {table, [storage_type: type, local_content: boolean]}.

FieldMeaning
status:synchronized once the tables are loaded. :pending on a joiner that has not reached a configured node yet. :inconsistent after Mnesia reports a split brain, and it stays so until the process restarts.
tablesThe local tables, :schema included. Empty while the status is :pending. It is read when the node boots, joins or connects a peer.
schemasThe result of schemas/0 at the same moments. Empty while the status is :pending.
essentialThe :essential modules in use.
dynamictrue only when the node watches the cluster.

Environment variables

VariableMeaning
MIX_ENVOverrides :project_env.
PROJECT_PATHOverrides :project_path.

Processes the library starts

Under MishkaInstaller.Supervisor, one-for-one:

  1. Phoenix.PubSub named MishkaInstaller.PubSub.
  2. MishkaInstaller.Installer.CompileHandler, the install queue and the replay on boot.
  3. MishkaInstaller.Event.EventHandler, the queue that rebuilds event modules.
  4. MishkaInstaller.MnesiaRepo, the store.

The test environment

The library decides when it compiles. If its environment is :test, it starts only the PubSub, and the tables use RAM copies instead of disc copies. The periodic table check does not run. Start the three other processes yourself, in the order above. Mishka CMS does this for any of them the library did not start:

elixir
@installer_children [
  MishkaInstaller.Installer.CompileHandler,
  MishkaInstaller.Event.EventHandler,
  MishkaInstaller.MnesiaRepo
]

def installer_children,
  do: @installer_children -- MishkaInstaller.Application.supervised_children()

Because MIX_ENV wins over :project_env, a dependency built while MIX_ENV=test is exported starts only its PubSub, whatever your config says.

To start these processes in your own test suite and wait until the store is ready, read the documentation on testing plugins.

Fixed values

ValueWhere
6000 msHow long a plugin process waits for the registry table when it starts.
1000 msThe single retry of a plugin whose process starts before the library has finished its boot. It fires once, about one second after the start, without checking readiness again, and nothing schedules another. With no stored record the plugin registers, with a record that the compiled event does not hold it starts, and otherwise it only reads its stored status. If the registration fails, the plugin logs failed to register and stays unregistered.
1000 msThe default timeout of a health probe.
10_000 msThe interval of the Mnesia health check, outside the test environment.

Example: production settings

elixir
config :mishka_installer,
  project_path: "/data",
  extensions_path: "/data/extensions"

config :mishka_installer, MishkaInstaller.MnesiaRepo,
  mnesia_dir: "/data/mnesia",
  essential: [MishkaInstaller.Event.Event, MishkaInstaller.Installer.Installer]

config :mishka_installer, :allowlist,
  github_repos: ["owner/demo"],
  protected_apps: ["mishka_installer", "my_app"]