kici-admin: configuration & database
config — orchestrator configuration
Section titled “config — orchestrator configuration”kici-admin config init [--output <path>] # Generate starter orchestrator.yamlkici-admin config seed --file <path> [--description <desc>] [--format json|yaml|table]kici-admin config get [path] [--format json|yaml|table]kici-admin config set <path> <value> [--description <desc>] [--format json|yaml|table]kici-admin config delete <path> [--description <desc>] [--format json|yaml|table]kici-admin config export [--format json|yaml]kici-admin config validate --file <path> [--type local|shared|full (default: shared)] [--offline] [--format json|yaml|table]kici-admin config diff [--format json|yaml|table]kici-admin config history [--limit <n> (default: 20)] [--format json|yaml|table]kici-admin config rollback --to <version> [--format json|yaml|table]kici-admin config reload [--drain] [--target <instance-id>] [--format json|yaml|table]seedimports a YAML file as the shared config. Sensitive values can be injected from environment variables (KICI_PLATFORM_TOKEN,KICI_SECRET_KEY,KICI_BOOTSTRAP_ADMIN_TOKEN,KICI_CLUSTER_JOIN_TOKEN).getreturns the effective config (merged local YAML + shared DB + env vars). Pass a dotted path to get a single field.validate --offlineworks without a running orchestrator (validates against local schemas).diffcompares local YAML config vs shared DB config.reloadtriggers a hot reload across the cluster. Use--drainto drain in-flight work first.initgenerates a commentedorchestrator.yamltemplate.
For full configuration details, see Configuration management.
db — database management
Section titled “db — database management”kici-admin db migrate # Run pending migrations (HTTP — orchestrator must be up)kici-admin db migrate --database-url <url> # Run pending migrations directly (orchestrator need not run)kici-admin db migrate --status # Show migration status without applyingkici-admin db migrate --to <migration> # Revert to a named migration (before a rollback)
# Infrastructure operations (direct DB — use --database-url or KICI_DATABASE_URL).# These cannot go through HTTP because the target DB may not exist yet or is about to be dropped.kici-admin db fresh --confirm [--yes] # DROP + CREATE + migrate + record content hashkici-admin db ensure <name> [--owner <role>] [--revoke-connect-public] [--grant-connect-role <role>...] # CREATE DATABASE IF NOT EXISTSkici-admin db create-role --user <name> --password <pw> [--createdb]kici-admin db create-readonly-user --user <name> --password <pw>kici-admin db check-schema [--json] # Exit 2 on migration driftkici-admin db schema-diff [--json] # Exit 2 when the live schema differs from this releasekici-admin db collation-check [--database-url <url>] [--json] # Exit 2 on collation driftkici-admin db reindex --confirm --reason <text> [--database-url <url>]kici-admin db refresh-collation-version --reason <text> [--database-url <url>]kici-admin db stats-check [--database-url <url>] [--json] # Exit 2 when a table needs ANALYZEkici-admin db analyze --table <schema.table> [--table ...] --reason <text> [--dry-run] [--database-url <url>]
# Backup / restore (direct DB — wraps pg_dump / pg_restore).kici-admin db backup [--output <path> | --output-dir <dir> [--keep <n>]] [--database-url <url>]kici-admin db backup --install-timer | --uninstall-timer [--schedule <spec>] [--output-dir <dir>] [--keep <n>] [--name <name>] [--instance-dir <path>]kici-admin db restore --input <path> [--yes] [--database-url <url>]migrategoes through the orchestrator HTTP admin API (orchestrator auto-migrates on startup by default; setKICI_AUTO_MIGRATE=falseto disable and run manually).migrate --database-url <url>runs the same migrator directly against the database, so the orchestrator does not need to run; it cannot be combined with--toor--status, and it records adb.migrateaccess-log row.migrate --to <migration>reverts every migration newer than the named one. Run it before a rollback, while the newer version still serves — only that version carries thedown()functions of its own migrations.ensurecreates the database when it is missing.--ownersets a separate owner role,--revoke-connect-publicrevokesCONNECTfromPUBLIC, and--grant-connect-role(repeatable) grantsCONNECTto a named role. Every successful migration run records the bundled-migration content hash in_migration_content_hash— including warm runs that apply zero migrations — socheck-schemareports the schema as current on a long-lived database whose migrations are already up to date.fresh/ensure/create-role/create-readonly-user/check-schema/schema-diff/collation-check/reindex/refresh-collation-version/stats-check/analyzeopen their own pool and run SQL directly — needed for deploy / bootstrap / DR workflows.freshprompts for the target database name as a confirmation. Pass--yesto skip the prompt (scripted use).create-roleandcreate-readonly-usersend the password inside a SQL statement. On a superuser connection they turn off statement logging and statement tracking for that statement. The password then does not reach the PostgreSQL server log or thepg_stat_statementsview. A connection that is not a superuser cannot change those settings. The server then logs the statement when itslog_statementisddlorall.check-schemacompares the bundled migration manifest (names + body hash) against the live schema and the stored_migration_content_hashmarker. Exit code 2 means drift — callfreshor runmigratedepending on intent. Exit code 1 means the database could not be read.--jsonprints{"current", "kind", "reason"};kindis one ofcurrent,missing,pending,unknown-applied,hash-missingorhash-mismatch.schema-diffreads the live schema from the PostgreSQL catalog — columns, constraints, indexes, functions, triggers, sequences and extensions — and compares it with the schema this release builds from its migrations. It prints one line per difference:missing(the release expects it, the database does not have it),extra(the database has it, the release does not expect it) orchanged.--jsonprints{"differences": [...]}. Exit code 0 means the schema matches, 2 means at least one difference, and 1 means an error. The indexes the orchestrator builds in the background after startup are not compared. An extension that the database has and the release does not use is not a difference, because your database host can install its own extensions. Use it after an upgrade, or after a restore, to find a schema thatcheck-schemareports as current but that a manual change or an edited migration made different.collation-checkcomparespg_database.datcollversionagainst the running libc collation version. Exit code 2 means the stamped and actual collation versions differ — a libc upgrade changed sort order out from under existing indexes.reindexrunsREINDEX DATABASE CONCURRENTLY, rebuilding every index under the current libc collation rules. Non-blocking but takes minutes and roughly 2× temporary disk. Requires--confirmand--reason.refresh-collation-versionrunsALTER DATABASE … REFRESH COLLATION VERSION— a metadata-only bump that clears the drift warning. Pair it withdb reindexafter a libc-base image rebuild so the indexes match the new collation. Requires--reason.stats-checkfinds every table that has a GIN index and checks its row estimate,pg_class.reltuples. PostgreSQL 18.6 fixed a defect where a parallel GIN index build could write a wrong estimate, such asNaNorInfinity. Autovacuum then does not process the table again, so the value stays wrong until you runANALYZE. The check reports a value as invalid when it isNaN,Infinityor-Infinity, when it is negative other than-1(the “never analyzed” marker), or when it is larger than the table’s pages can hold. Exit code 0 means every value is valid, 2 means at least one table needsANALYZE, and 1 means an error. The text output prints thedb analyzecommand that fixes the reported tables.--jsonprints{"database", "clean", "tables", "needsAnalyze"}; eachtablesentry hastable,reltuples,relpages,ginIndexesandproblem(nan,infinite,negative,exceeds_page_capacity, ornullwhen the value is valid). Run it after you upgrade PostgreSQL to a new minor version.analyzerunsANALYZEon the tables you name with--table(repeat the option for more tables). Give each name with its schema, for examplepublic.access_log. The command checks every name first. If one name is not a table, it stops with exit code 1 and analyzes nothing.--dry-runprints the statements and does not run them. Requires--reason, and records adb.analyzeaccess-log row.backupwrapspg_dump -Fcinto a custom-format dump (default./kici-orchestrator-backup-<timestamp>.dump, override with--output) and writes a sidecar<dump>.manifest.jsonrecording the creation time, byte size, secret-key version, Postgres server version, migrations hash, cluster id, and hostname. Each run is also recorded in thebackup_runstable, which is what the backup-freshness WARN threshold reads.--output-dirwrites a timestamped dump into a directory and keeps the newest--keepdumps (default 7).backup --install-timerinstalls a scheduled backup service and timer for the named orchestrator instance, then exits;--uninstall-timerremoves it. See Schedule backups for the per-platform behavior of--schedule.restorewrapspg_restore --clean --if-exists --no-ownerand is destructive — it drops and recreates the target’s objects. It prompts before proceeding; pass--yesfor scripted use. Afterwards it reports whether the dump carried encrypted secrets, because those only decrypt under the sameKICI_SECRET_KEYthe source orchestrator used.- Both require a
postgresql-clientonPATHwhose major version is at least the server’s, and both refuse rather than produce a half-usable dump when it is older. Credentials ride inPG*environment variables, never in argv, so the DB password never appears in the world-readable/proc/<pid>/cmdline.
See Database backup and restore for the full procedure, retention guidance, and the disaster-recovery drill.
Reference
Section titled “Reference”kici-admin config
Section titled “kici-admin config”Manage orchestrator configuration
Synopsis: kici-admin config
kici-admin config delete
Section titled “kici-admin config delete”Remove a field from the shared config
Synopsis: kici-admin config delete <path> [options]
Arguments
| Argument | Required | Variadic | Description |
|---|---|---|---|
path | yes | no |
Options
| Option | Default | Description |
|---|---|---|
--description <desc> | Change description | |
--format <format> | json | Output format: json|yaml|table |
kici-admin config diff
Section titled “kici-admin config diff”Compare local YAML config vs shared DB config
Synopsis: kici-admin config diff [options]
Options
| Option | Default | Description |
|---|---|---|
--format <format> | table | Output format: json|yaml|table |
kici-admin config export
Section titled “kici-admin config export”Export shared config (sensitive values redacted)
Synopsis: kici-admin config export [options]
Options
| Option | Default | Description |
|---|---|---|
--format <format> | yaml | Output format: json|yaml |
kici-admin config get
Section titled “kici-admin config get”Get current effective config (merged local + shared + env)
Synopsis: kici-admin config get [path] [options]
Arguments
| Argument | Required | Variadic | Description |
|---|---|---|---|
path | no | no |
Options
| Option | Default | Description |
|---|---|---|
--format <format> | json | Output format: json|yaml|table |
kici-admin config history
Section titled “kici-admin config history”Show config version history
Synopsis: kici-admin config history [options]
Options
| Option | Default | Description |
|---|---|---|
--limit <n> | 20 | Maximum versions to show |
--format <format> | table | Output format: json|yaml|table |
kici-admin config init
Section titled “kici-admin config init”Generate a starter orchestrator.yaml with commented defaults
Synopsis: kici-admin config init [options]
Options
| Option | Default | Description |
|---|---|---|
--output <path> | ./orchestrator.yaml | Output file path |
kici-admin config reload
Section titled “kici-admin config reload”Trigger config reload across the cluster. The result’s scaler field reports the reload of the scaler config: applied, or rejected with its errors.
Synopsis: kici-admin config reload [options]
Options
| Option | Default | Description |
|---|---|---|
--drain | Drain in-flight work before reloading | |
--target <instance-id> | Target specific instance | |
--format <format> | json | Output format: json|yaml|table |
kici-admin config rollback
Section titled “kici-admin config rollback”Rollback shared config to a specific version
Synopsis: kici-admin config rollback [options]
Options
| Option | Default | Description |
|---|---|---|
--to <version> | Target version number | |
--format <format> | json | Output format: json|yaml|table |
kici-admin config seed
Section titled “kici-admin config seed”Bulk import shared config from a YAML file
Synopsis: kici-admin config seed [options]
Options
| Option | Default | Description |
|---|---|---|
--file <path> | Path to YAML config file | |
--description <desc> | Change description | |
--format <format> | json | Output format: json|yaml|table |
kici-admin config set
Section titled “kici-admin config set”Set a single field in the shared config
Synopsis: kici-admin config set <path> <value> [options]
Arguments
| Argument | Required | Variadic | Description |
|---|---|---|---|
path | yes | no | |
value | yes | no |
Options
| Option | Default | Description |
|---|---|---|
--description <desc> | Change description | |
--format <format> | json | Output format: json|yaml|table |
kici-admin config validate
Section titled “kici-admin config validate”Validate a config file against schema
Synopsis: kici-admin config validate [options]
Options
| Option | Default | Description |
|---|---|---|
--file <path> | Path to config file | |
--type <type> | shared | Schema type: local|shared|full |
--offline | Validate locally without contacting orchestrator | |
--format <format> | json | Output format: json|yaml|table |
kici-admin db
Section titled “kici-admin db”Database management
Synopsis: kici-admin db
kici-admin db analyze
Section titled “kici-admin db analyze”ANALYZE the named tables, refreshing their planner statistics and pg_class.reltuples. Every table must exist.
Synopsis: kici-admin db analyze [options]
Options
| Option | Default | Description |
|---|---|---|
--database-url <url> | Target DB URL (else KICI_DATABASE_URL / DATABASE_URL) | |
--table <schema.table> | Table to analyze, schema-qualified. Repeatable. | |
--reason <text> | Reason (recorded in the access log) | |
--dry-run | Validate the tables and print the statements without running them |
kici-admin db backup
Section titled “kici-admin db backup”Dump the orchestrator DB to a local file (pg_dump custom format)
Synopsis: kici-admin db backup [options]
Options
| Option | Default | Description |
|---|---|---|
--database-url <url> | Source DB URL (else KICI_DATABASE_URL / DATABASE_URL) | |
--output <path> | Dump output path (default ./kici-orchestrator-backup- | |
--output-dir <path> | Write a timestamped dump into this directory, then prune it to —keep dumps | |
--keep <n> | 7 | Dumps to retain in —output-dir |
--install-timer | Install a scheduled backup service + timer and exit | |
--uninstall-timer | Remove the scheduled backup service + timer and exit | |
--schedule <spec> | daily | Timer calendar spec: a systemd OnCalendar value, or daily / HH:MM |
--platform <type> | Force the service platform (systemd, launchd, windows, compose). Default: the platform in the install manifest | |
--instance-dir <path> | Deploy folder of the orchestrator instance to schedule | |
--name <name> | Orchestrator service name to schedule (no default) | |
--system | Operate against the system-level timer (requires root) | |
--user-level | Operate against the user-level timer |
kici-admin db check-schema
Section titled “kici-admin db check-schema”Compare bundled migrations vs live schema. Exit 2 on drift.
Synopsis: kici-admin db check-schema [options]
Options
| Option | Default | Description |
|---|---|---|
--database-url <url> | Target DB URL (else KICI_DATABASE_URL / DATABASE_URL) | |
--json | false | Emit JSON instead of a human-readable line |
kici-admin db collation-check
Section titled “kici-admin db collation-check”Compare pg_database.datcollversion against the running libc collation version. Exit 2 on drift.
Synopsis: kici-admin db collation-check [options]
Options
| Option | Default | Description |
|---|---|---|
--database-url <url> | Target DB URL (else KICI_DATABASE_URL / DATABASE_URL) | |
--json | false | Emit JSON instead of a human-readable line |
kici-admin db create-readonly-user
Section titled “kici-admin db create-readonly-user”Create a read-only role with SELECT on all tables + default privileges
Synopsis: kici-admin db create-readonly-user [options]
Options
| Option | Default | Description |
|---|---|---|
--database-url <url> | Target DB URL (must connect as owner) | |
--user <name> | Read-only role name | |
--password <password> | Role password |
kici-admin db create-role
Section titled “kici-admin db create-role”CREATE / ALTER ROLE with LOGIN [+ CREATEDB] (idempotent)
Synopsis: kici-admin db create-role [options]
Options
| Option | Default | Description |
|---|---|---|
--database-url <url> | Admin DB URL (else KICI_DATABASE_URL / DATABASE_URL) | |
--user <name> | Role name to create or update | |
--password <password> | Role password (raw — quote as needed) | |
--createdb | false | Grant CREATEDB to the new role |
kici-admin db ensure
Section titled “kici-admin db ensure”CREATE DATABASE IF NOT EXISTS (idempotent)
Synopsis: kici-admin db ensure <name> [options]
Arguments
| Argument | Required | Variadic | Description |
|---|---|---|---|
name | yes | no |
Options
| Option | Default | Description |
|---|---|---|
--database-url <url> | Admin DB URL (else KICI_DATABASE_URL / DATABASE_URL) | |
--owner <role> | DB owner role (default: URL user). Pass when the admin connection is privileged but the new DB should be owned by a separate non-privileged role. | |
--revoke-connect-public | After ensure, REVOKE CONNECT ON DATABASE " | |
--grant-connect-role <role> | After ensure (and any —revoke-connect-public), GRANT CONNECT ON DATABASE " |
kici-admin db fresh
Section titled “kici-admin db fresh”DROP + CREATE the orchestrator DB, run migrations, record content hash
Synopsis: kici-admin db fresh [options]
Options
| Option | Default | Description |
|---|---|---|
--database-url <url> | Target database URL (else KICI_DATABASE_URL / DATABASE_URL) | |
--confirm | Explicit confirmation (destructive) | |
--yes | Skip interactive confirmation (for scripted use) |
kici-admin db migrate
Section titled “kici-admin db migrate”Run pending database migrations (via the orchestrator HTTP admin API, or directly with —database-url)
Synopsis: kici-admin db migrate [options]
Options
| Option | Default | Description |
|---|---|---|
--status | Show migration status without applying | |
--database-url <url> | Migrate this database directly instead of through the orchestrator HTTP API | |
--to <migration> | Migrate to a named migration, reverting newer ones. Run this BEFORE a rollback, while the newer binary is still serving — it is the only one carrying their down() functions. |
kici-admin db refresh-collation-version
Section titled “kici-admin db refresh-collation-version”ALTER DATABASE
Synopsis: kici-admin db refresh-collation-version [options]
Options
| Option | Default | Description |
|---|---|---|
--database-url <url> | Target DB URL (else KICI_DATABASE_URL / DATABASE_URL) | |
--reason <text> | Reason (recorded in stderr banner) |
kici-admin db reindex
Section titled “kici-admin db reindex”REINDEX DATABASE CONCURRENTLY
Synopsis: kici-admin db reindex [options]
Options
| Option | Default | Description |
|---|---|---|
--database-url <url> | Target DB URL (else KICI_DATABASE_URL / DATABASE_URL) | |
--confirm | Explicit confirmation (destructive — long-running) | |
--reason <text> | Reason (recorded in stderr banner) |
kici-admin db restore
Section titled “kici-admin db restore”Restore the orchestrator DB from a pg_dump file (DESTRUCTIVE)
Synopsis: kici-admin db restore [options]
Options
| Option | Default | Description |
|---|---|---|
--input <path> | Path to a .dump file produced by db backup | |
--database-url <url> | Target DB URL (else KICI_DATABASE_URL / DATABASE_URL) | |
--yes | Skip interactive confirmation (for scripted use) |
kici-admin db schema-diff
Section titled “kici-admin db schema-diff”Compare the live schema with the schema this release expects. Exit 2 on any difference.
Synopsis: kici-admin db schema-diff [options]
Options
| Option | Default | Description |
|---|---|---|
--database-url <url> | Target DB URL (else KICI_DATABASE_URL) | |
--json | false | Emit JSON instead of one line per difference |
kici-admin db stats-check
Section titled “kici-admin db stats-check”Report tables with a GIN index whose planner row estimate (pg_class.reltuples) is NaN, infinite or impossible. Exit 2 when a table needs ANALYZE.
Synopsis: kici-admin db stats-check [options]
Options
| Option | Default | Description |
|---|---|---|
--database-url <url> | Target DB URL (else KICI_DATABASE_URL / DATABASE_URL) | |
--json | false | Emit JSON instead of human-readable lines |