Skip to main content

Packages

The Package page (Liberty Next → Deploy → Package) is Liberty's built-in deployment mechanism: an operator on the source install picks a few screens / menu items / dashboards as seeds, the framework walks every reference they reach (queries, connectors, dictionary entries, charts), and the result ships as a ZIP. On the target install, the same screen accepts a ZIP, previews what it would change, and applies it to the live config — followed by an automatic reload. With a target instance declared, the package can also be promoted straight to it, without handling the ZIP.

The page offers three views, picked from cards at the top: Build package, Import package and Promotion. It is reserved to superusers.

This is the standard staging → production path. It's also the right tool for cross-customer reuse: build a "starter" package of curated screens, hand it to a fresh install, apply with replace_all, done.


When to use which​

SituationUse
Promote screens / dashboards from staging to production.Build on staging, apply on prod with overwrite.
Ship a curated set of screens to a brand-new install.Build, apply with replace_all.
Add a few new screens to an existing customer install without touching their edits.Build, apply with merge.
Ship a fresh release of a vendor-maintained app where the customer has local edits on a few screens.Build, apply with overwrite — entities flagged override = true on the target are preserved automatically.
Promote screens to production in one step, without the ZIP.Promote to… on Build — see Promotion.
Promote one Nomaflow job between environments.Pick it as a seed under nomaflow jobs, or use the Export icon on the job's line of the Jobs page.
Deliver a full licensed bundle (Nomasx-1 + Nomajde plugins + config).Not this. Use the liberty-apps wheel installer — see Installation → Deploy prebuilt apps.

The Package screen ships declarative config — TOML files. It does not ship Python code, Java JARs, plugin packages or database content. For those, the wheel installer is the canonical channel.


The Build view​

The left panel lists every seed candidate on the install — screens, menu items, dashboards. The right panel shows the dependency closure of whatever is ticked on the left.

Picking seeds​

Three sections in the left panel:

SectionDrawn from
ScreensEvery screen the install knows — grouped by app.
Menu itemsEvery menu item, by app.
DashboardsEvery dashboard, by scope.
Explorer modelsThe Data Explorer models, with their shipped analyses and dashboards.
nomaflow jobsThe jobs of jobs.toml.
Notification rulesThe rules of Liberty Next → Build → Notifications.
Shared actionsThe actions reused by several screens.
Assistant (starters, playbooks)What an application ships for the AI assistant — one entry per application.

A search box at the top filters the visible list by name / label / scope. The per-section select all tick respects the filter — narrow first (e.g. type audit), then tick select all to grab only the matching screens.

The seed picker is bulk-friendly: hold the filter at a customer name, tick select all and you've staged a per-customer slice. No need to click each screen one by one.

What the dependency walker does​

The moment you tick any seed, the right panel kicks off the walker (POST /admin/find-dependencies on the backend). For every seed, the walker resolves:

KindWhat's pulled
screenThe screen's main query, all referenced sub-queries (from screen actions, nested tabs, conditional fields), every dictionary entry that backs a column, every lookup the dialog uses, every sequence and enum, the connector each query belongs to (and its pool).
menu_itemThe screen, query, endpoint, dashboard or job the menu item targets, then the closure of that.
dashboardEvery chart on the dashboard, every query each chart reads from, the connectors. A dashboard named <app>.<id> is looked up in that app.
notification_ruleThe screen or the jobs its trigger names.

The closure is recursive but bounded (default depth = 50). Cycles are detected and short-circuited.

The default-excluded kinds​

The Dependencies panel pre-ticks every dep except three kinds:

KindWhy default-excluded
ConnectorsThe target install almost always already has its own connector with the right pool / credentials. Shipping the source's connector would clobber the target's secrets.
PoolsSame — pools carry DB credentials. The target's pool is the one you want.
API endpointsSame — endpoints carry auth headers / Bearer tokens specific to the source install's wiring.

This makes the typical "promote screens between envs" workflow safe out of the box: nothing that carries secrets ships unless you opt in. Tick the Connectors group manually only when the target genuinely has none — typically a brand-new install or a per-customer staging spin-up.

The frontend remembers your per-dep ticks; the select all / deselect all toggles at the group level make it cheap to flip every connector on or off at once.

Building the ZIP​

Click Download ZIP and the framework runs POST /admin/build-package, returning a ZIP with up to six TOMLs:

FileWhen present
connectors.tomlWhen at least one connector / pool / query / API endpoint is included. Connector definitions are trimmed — only the queries / endpoints in the closure are kept, the rest are dropped.
dictionary.tomlWhen the closure pulls in any dictionary entry, lookup, sequence or enum. Per-connector dictionary blocks are nested under [connectors.<name>].
screens.tomlWhen at least one screen is in the closure. Grouped by app under [screens.<app>].
menus.tomlWhen at least one menu item is in the closure. Grouped by app under [menus.<app>.items].
charts.tomlWhen at least one chart is in the closure.
dashboards.tomlWhen at least one dashboard is in the closure.

Plus one always-present file:

FileWhat it carries
MANIFEST.mdHuman-readable summary — what's in the ZIP, the seeds, per-kind counts, the env vars ${VAR} the package references (and that the operator must set on the target), the missing references (closure couldn't resolve — usually a typo or a stale rename on the source), and the operator-facing instructions.

The MANIFEST is the first thing to open on the target before applying — it tells you what to expect and what's still on you to wire (env vars, secrets, master key).

What's NOT in the package​

Worth knowing so you don't try to ship through this channel:

Not includedWhere it lives instead
Liberty Next → Administer → AppPer install — application settings, licence, sign-in. Never bundled.
auth.toml / DB-stored usersPer-install — carries Argon2 password hashes. Never bundled.
Python pluginsShipped with the liberty-apps wheel or the plugin's own release channel.
Database contentUse a DB dump (or a bundled preload job).

The Import view​

Pick the Import package card. The view offers three strategies — Merge, Overwrite (recommended for upgrades), Replace all — and a file picker.

The three strategies​

Import strategies — what happens per entity in the packageMERGEAdd only what's new.Existing entities are preserved.addedentities not on the targetskippedalready present (kept as-is)Use when adding new thingswithout touching customer editsOVERWRITE — RECOMMENDEDPackage is the new truth.Target's other entities untouched.addednew entities landreplacedexisting entities get the package versionpreserved (override = true)customer fork — left aloneDefault upgrade pathREPLACE ALLEach TOML in the ZIP replacesthe WHOLE target file.all entities in packagelanded on targetDROPPED on targetevery entity NOT in the packageBrutal — only for deploy-from-scratch.Files the package does NOT touchare left alone.Strategy applies INDEPENDENTLY to each TOML in the ZIP. A package that only carries screens.toml only touches the target's screens.toml.

The three columns map one-to-one to the radio cards in the UI:

StrategyPer-entity behaviourUse when
mergeNEW entities land. EXISTING entities on the target are kept as-is.Adding new things without disturbing customer edits. The package adds; it never overwrites.
overwriteNEW entities land. EXISTING entities are replaced by the package version — EXCEPT when the target entity is flagged override = true (then preserved, reported separately).The standard upgrade path. The package becomes the new truth for the entities it carries. Entities elsewhere on the target (those not in the package) are untouched.
replace_allFor every TOML in the ZIP, the whole target file is replaced by the package's version. EVERY entity not in the package is dropped from that file. Files the package doesn't touch are untouched.Deploy-from-scratch / vendor reset / a curated baseline.

The override = true escape hatch​

A customer install sometimes needs to fork a vendor entity — patch one screen's columns, swap a query — and keep that fork across vendor upgrades. Add override = true to the entity's TOML block:

screens.toml on the customer install
[screens.crm.customers]
label = "Customers (customer fork)"
override = true # vendor `overwrite` imports will skip this entity
query = "customers_v2_custom"
# ... rest of the customer's edit

On the next overwrite import, the framework sees the flag and leaves the entity alone. The import report shows it under preserved overrides so the operator sees exactly which entities survived the vendor push.

Two limits worth knowing:

  • merge already skips existing entities — the flag is redundant there.
  • replace_all drops the entire file — overrides are NOT preserved. Use it knowingly.

Preview, then apply​

As soon as a ZIP is picked — and again when the strategy changes — the page previews the import; nothing is written until Apply.

PartContent
State chipsThe count per state: New, Changed, Identical, Kept (override), Skipped, Removed, Errors — with From <install> · <version>, the package's origin.
WarningsA package from a newer Liberty Next — settings this instance does not know may be rejected: upgrade it first; encrypted values this instance cannot decrypt — another master key: set them again after the import.
EntitiesOne card per file. What changes comes first; Show identical adds the rest. A changed entity opens on its fields: Here now and After the import.
Apply N change(s)Writes the changes, reloads, then shows the same plan as the result with Applied + reloaded. When the instance already holds every entity as the package has it, there is nothing to apply.

What travels is merged with care:

  • a connector's queries, tables, sequences, lookups and endpoints are imported one by one: importing a package never removes the target's other queries;
  • a job that already exists on the target keeps its schedule, enabled flag, timezone, presets, alerts, retry, log level and timeout; a new job arrives disabled;
  • the package is built from the files as written: unset values and ${VAR} references travel as they are.

If the reload fails after a successful apply, the file changes are kept on disk; run Reload config (at the top of any Liberty Next editor page) once the underlying issue is fixed.


Promotion — straight to another instance​

A target instance is another Liberty Next install — production, a customer's staging — reached over its API.

Package → Promotion lists the targets: Name, Label, URL (the target's root address, with its sub-path), Account and Password of a local superuser there — the password stored encrypted —, Check the TLS certificate, Timeout (s). Test signs in on the target: Signed in on prod · 7.0.64. Save targets keeps them.

Promote to…, beside Download ZIP on Build, sends the selection to a target:

  1. pick the Target, the Strategy and an optional Comment;
  2. the target previews the import at once — the same plan as above, computed on the target: Preview on prod — nothing is written until you apply;
  3. Apply on prod applies it there.

Connectors, pools and API endpoints stay the target's unless ticked: a connector's queries still travel, merged into the target's connector. The same Promote to… on Liberty Next → Deploy → Changes sends an approved change package.

The History of the Promotion view lists the promotions applied from this instance — when, by whom, to which target, what, and the outcome; a row opens on the target's report.


Secrets and environment variables​

The package is plaintext TOML. Two patterns let the source's secrets travel without leaking the secret material:

PatternWhat happens at build / apply
Encrypted secrets — password = "ENC:base64=="The ciphertext lands verbatim in the package. The target must have the same master key (LIBERTY_MASTER_KEY) as the source — otherwise decryption fails on first use.
Env var references — password = "${DB_PASSWORD}"The literal string ${DB_PASSWORD} is in the package. The operator must set the env var on the target before reloading. MANIFEST.md lists every ${VAR} the package references.

Pick one pattern per install — mixing both inside a single config gets confusing. Encrypted secrets travel best across containerised deployments; env vars travel best across orchestrators (Kubernetes Secrets, Docker --env-file, systemd EnvironmentFile).

What you should NOT ship​

Don'tWhy
Move auth.toml between installs via the Package screen.The screen ignores auth.toml. Move users via the dedicated Users admin (or invite them per install).
Expect a package to carry Liberty Next → Administer → App.It does not — application settings, licence and sign-in stay on each install.
Ship a package with replace_all to a customer who has local edits without a heads-up.The customer's screens / queries / dictionary entries are dropped. There is no automatic undo — keep a backup of the target's config tree first.

Inspect-without-export​

The Build tab's right panel is also a standalone dependency inspector. Tick a single screen, look at the closure — that's exactly what the screen would carry into a package, and exactly what would break if you renamed / deleted the screen. No need to click Download ZIP — the inspection is the value.

Liberty also exposes a dedicated Find dependencies modal from any screen / menu item / dashboard list (the icon next to the rename button). Same backend (POST /admin/find-dependencies), simpler shape — just the closure tree for the one entity you opened it on.


Common pitfalls​

MistakeSymptomFix
Forgot to set a ${VAR} listed in MANIFEST.md before reloading the target.A connector / query fails at first use with a missing-substitution error.Read MANIFEST.md before applying. Set the env vars in the target's environment file / systemd unit / Docker env.
Source and target carry different master_keys.Encrypted ENC:... values fail to decrypt; the affected connector errors at first use.Sync the master key (or rotate the encrypted values on the target — see Build → Secure → Encrypted secrets).
Used replace_all to apply a small slice — wiped customer-specific screens.Customer screens missing from the target after import.Restore the previous TOML from your backup. Re-apply with overwrite next time.
Bundled connectors.toml (default-excluded) without checking pool names match the target.Target's pools change unexpectedly; pre-existing queries error at next reload.Leave connectors / pools default-excluded unless the target is brand-new. Or rename pools on the source before bundling.
Built from a source with unresolved references (broken rename / deleted query).MANIFEST.md lists items under Missing references.Fix on the source (rename / delete / restore) and rebuild. The target won't get the broken references — but it also won't get the screens / queries that referenced them.
A warning says the package holds values this instance cannot decrypt.The source and the target use different master keys.Set those values again on the target after the import, or share the master key.
Import landed but Applied + reloaded is missing — a reload failed warning showed.Disk has the new config; in-memory state is stale.Reload manually via Reload config (at the top of any Liberty Next editor page) once the underlying issue is fixed (often a syntax error in an unrelated TOML the reload caught).

Programmatic access​

The two endpoints behind the UI are usable headless — useful for CI / scripted promotion:

Build a package
curl -X POST \
-H "Authorization: Bearer <superuser-token>" \
-H "Content-Type: application/json" \
-d '{"seeds":[{"kind":"screen","name":"customers","scope":"crm"}]}' \
https://<source>/admin/build-package \
--output liberty-package.zip
Apply a package
curl -X POST \
-H "Authorization: Bearer <superuser-token>" \
-F "package=@liberty-package.zip" \
"https://<target>/admin/import-package?strategy=overwrite"

build-package accepts an optional include array to filter the closure (same shape as the UI's per-dep checkbox state). import-package accepts strategy as a query param (merge | overwrite | replace_all) and dry_run=true for the preview. Both endpoints require superuser auth. POST /admin/promotion/push sends a package or an approved change package to a declared target.


What's next​

  • Deploy prebuilt apps — when the package channel isn't enough (full bundle = config + Python plugins), use the liberty-apps wheel installer.
  • Nomaflow → Bundled jobs — the ready-made jobs that ship with liberty-apps, including the nomasx1-import-reference job that loads a curated reference bundle.
  • Encrypted secrets — what ENC: values are, how to rotate them when promoting across installs with different master keys.