Skip to main content

Packages

The Packages screen (Settings → 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, lets the operator pick a merge strategy and applies it to the live config — followed by an automatic reload.

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 one Nomaflow job between environments.Use the dedicated Export job button on the job's card (covered in Nomaflow → Bundled jobs); the Package screen does not bundle jobs.
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 tab

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.

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 / dashboard / endpoint the menu item targets, then the closure of that.
dashboardEvery chart on the dashboard, every query each chart reads from, the connectors.

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
app.tomlPer-install — carries pool credentials, auth backend, frontend root. 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.
Nomaflow jobsThe Export job button on each job's card produces a single-job ZIP. Bulk job export is not yet automated. See Nomaflow → Bundled jobs.
Database contentUse a DB dump (or a bundled preload job).

The Import tab

Switch the top tab to Import package. The panel offers three strategies, a file picker and an Apply package button.

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.

Applying

StepWhat
Pick the ZIPClick the drop zone (or drag a .zip onto it). The filename + size appears once selected.
Pick a strategyDefault is overwrite. Switch only when you know you need the other behaviour.
Click Apply packageThe framework runs POST /admin/import-package?strategy=<value>, applies the diff and runs POST /admin/reload automatically.
Read the reportPer-file row showing +N added, ~N replaced, ⊘N skipped, ✗N errors plus a sample of the affected entity names.
A green Applied + reloaded badgeConfirms the reload succeeded — new config is live for the next request.

If reload fails after a successful apply, the import warning panel shows the reason but the file changes are kept on disk. Run Settings → Reload manually after fixing the underlying issue.


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 secretspassword = "ENC:base64=="The ciphertext lands verbatim in the package. The target must carry the same [crypto] master_key (or LIBERTY_MASTER_KEY env var) as the source — otherwise decryption fails on first use.
Env var referencespassword = "${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).
Move app.toml via the Package screen.The screen ignores it — would clobber connector pool credentials, frontend paths, license.
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.
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 Settings → Reload 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). Both endpoints require superuser auth.


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.