Octl, stack bundle
How ionctl ships platform configs inside its npm package
@nannier/ionctl is the local-development CLI. To make npx @nannier/ionctl deploy work from any empty directory, the package bundles all the platform configs it needs.
What's in the bundle
ionctl/stack/:
compose.dev.yml, the dev Compose file.ciam-kratos/kratos.yml, identity schemasiam-kratos/kratos.yml, identity schemasciam-hydra/hydra.ymliam-hydra/hydra.ymlCaddyfile, dev variantinit-db.sqliam-seed-dev.shpgadmin-claims-mapper.jsonnet
These are vendored copies of the corresponding files in platform/dev/.
Why vendor
Two alternatives:
- Have ionctl clone the
platformrepo at runtime. Requires network, requires the user to authenticate. - Vendor the files inside the package.
Vendoring is simpler. npx @nannier/ionctl deploy runs offline (once images are cached).
The trade-off: bundle drift. If platform/dev/ changes and the ionctl bundle isn't synced, dev environments differ from prod expectations.
Syncing the bundle
ionctl/scripts/sync-stack.sh:
#!/usr/bin/env bash
set -euo pipefail
REF=${1:-main} # platform git ref to sync from
cd $(mktemp -d)
git clone --depth 1 --branch "$REF" https://github.com/bnannier/platform .
cp -r dev/* "$OCTL_ROOT/stack/"
cd "$OCTL_ROOT"
bun run typecheck # ensure the new bundle still works with ionctl's codeRun via:
cd ionctl
bun run sync-stack -- v1.5.2 # or mainCI runs this before publishing ionctl to ensure the bundle is fresh against the platform commit being pinned.
Bundle version tracking
ionctl/stack/PLATFORM_REF records the platform git ref the bundle was synced from:
v1.5.2
abc123def456... # commit SHAWhen publishing ionctl, this is committed alongside.
Bundle vs platform divergence
If you've made local changes to platform/dev/ for testing, those don't go through ionctl. The dev stack via ionctl deploy uses the bundled configs, not the local ones.
To test local platform changes:
cd platform/dev
podman compose -f compose.dev.yml up -dSkip ionctl entirely; run compose directly.
What ionctl deploy does at runtime
- Checks for Podman; installs if missing (macOS Homebrew).
podman machine init+podman machine startif needed.- Reads bundled
compose.dev.yml. - Generates
.env.devwith development secrets (deterministic for dev, same value across runs ofionctl deployso caches work). - Runs
podman compose up -d. - Polls healthchecks.
- Prints access URLs + test credentials.
.env.dev contains:
ENCRYPTION_KEY, a dev-safe value (not on the blocklist).SESSION_SIGNING_KEY, similarly.- Per-domain reload API keys.
- Empty Turnstile (captcha disabled).
- Pointers to MailSlurper (no real email).
When the bundle becomes stale
Symptoms:
ionctl deploysucceeds but Dashboard says "schema not found."- Identity schema mismatch between dev and prod.
- New Kratos features don't work in dev.
Fix: bump ionctl. The maintainer publishes new ionctl versions as platform evolves.