Installer — 60-second Quickstart¶
Audience: ERP integrators/installers who want to show a customer the value of RAG in under a minute, from any data in the customer's IT estate.
1. Prerequisites (once per workstation, 90 sec)¶
Install lm¶
lm builds from source (Go 1.24+) — today's official install path:
cd lm && go build -o lm ./cmd/lm
# then put ./lm on your PATH, e.g.: sudo mv lm /usr/local/bin/
Pre-built binaries (GitHub Releases) and a Homebrew tap will arrive with the public opening — they are part of the publication ritual, not shipped yet.
Run lumnik¶
See the deploy docs (Docker Compose recommended for a single customer). The
lumnik JVM must have LUMNIK_SECRET_MASTER_KEY set at startup (validated — the JVM refuses to
start without it).
Already done by
up.sh. If you came from the Deploy page,deploy/selfhost/up.shgeneratedLUMNIK_SECRET_MASTER_KEYinto.env(mode 600) — do not regenerate it. The manual recipe below is only for the non-compose paths: - systemd:openssl rand -base64 32→EnvironmentFile=/etc/lumnik/.env- Kubernetes: a Secret mounted as an env var
Point lm at the hub (once)¶
lm config set-context selfhost --server http://localhost:8080 \
--oidc-issuer http://localhost:8180/realms/lumnik
lm config use-context selfhost
lm login # prints a URL + device code — demo user: integrator / integrator
Every scenario below assumes this context: on the deployed stack, each lm call is
Bearer-authenticated — without lm login, everything returns 401.
2. Scenario A — Stripe via OpenAPI (60 sec)¶
# 1. Register the API key (AES-256-encrypted in DB via pgcrypto)
lm secret set STRIPE_API_KEY sk_test_xxx
# 2. Generate + apply the manifest from Stripe's OpenAPI (one command)
lm source rest from-openapi https://api.stripe.com/openapi.json --name stripe --tag billing --apply
# 3. Enable the scheduler on an endpoint
lm endpoint enable stripe/charges
# 4. Talk to the data
lm ask "how many payments this month?"
3. Scenario B — one-shot CSV (30 sec)¶
lm csv ingest customers.csv --scope sales --tag demo
lm ask "who are my customers in the Var?" --scope sales
The ingest creates a dormant connector (enabled=false, no scheduler) + endpoint + an
ext.<name> table + RAG chunks. Promotion to recurring ingestion: see §5.
4. Scenario C — combined (90 sec)¶
lm secret set STRIPE_API_KEY sk_test_xxx
lm source rest from-openapi https://api.stripe.com/openapi.json --name stripe --tag billing --apply
lm csv ingest contacts.csv --scope billing
lm endpoint enable stripe/charges
lm ask "list the customers who paid in May"
4bis. Scenario D — nightly SFTP export (90 sec)¶
The most common shape: a customer ERP exports to an SFTP server every night.
lm secret set ACME_SFTP_KEY - # paste the private SSH key on stdin, Ctrl+D
lm csv ingest sftp://lumnik@sftp.acme.io/export/billing-latest.csv \
--key-secret ACME_SFTP_KEY --scope billing --name acme-billing
lm ask "how many invoices in the latest export?" --scope billing
To switch to daily recurrence:
lm describe connector acme-billing > acme-nightly.yaml
# edit: transport.path: /export/*.csv, schedule: "0 6 * * *", after_process: move, archive_path: /archive/
lm validate -f acme-nightly.yaml
lm apply -f acme-nightly.yaml
lm connector resume acme-nightly # or: lm endpoint enable acme-nightly/<endpoint>
4ter. Scenario E — S3 prefix (60 sec)¶
lm secret set AWS_S3_ACCESS_KEY AKIA...
lm secret set AWS_S3_SECRET_KEY ...
lm csv ingest s3://acme-exports/billing/ \
--region eu-west-3 --suffix .csv --scope billing
lm ask "top 10 customers by invoiced amount?" --scope billing
For MinIO / Cloudflare R2 / GCS-S3-compat: add --endpoint https://....
5. From demo to production¶
Customize the generated manifest¶
lm describe connector stripe > stripe.yaml
$EDITOR stripe.yaml # adjust default_schedule, promote columns, content_template, etc.
lm validate -f stripe.yaml # optional but recommended — field-by-field errors before apply
lm apply -f stripe.yaml
Promote the CSV to recurring ingestion¶
Coming in v1.1 via lm source csv add --path /watched/*.csv --schedule "*/5 * * * *".
Until then, editing the dormant connector's YAML and lm apply -f is the escape hatch.
Enter a secret without a shell trace¶
lm secret set STRIPE_API_KEY -
# (then paste the value on stdin, end with Ctrl+D)
Keeps the value out of shell history and ps -ef.
Production security¶
- Master-key rotation: planned for v1.1 (
lm secret rotate-master-key) - Audit: every secret access emits
platform.secret.{created,updated,deleted,read}events into the outbox (SOC 2) - RBAC: permission
platform.secret.manage(granted tolm_admin) - No REST endpoint ever returns a secret's value — if the installer loses it, they rewrite it
6. Troubleshooting¶
| Error | Cause | Fix |
|---|---|---|
Bearer token unavailable (env=STRIPE_API_KEY) |
secret set neither in DB nor as an env var | lm secret list then lm secret set STRIPE_API_KEY ... |
connector "stripe" already exists on --apply |
double --apply with the same --name |
lm describe connector stripe then adjust, or lm connector pause stripe + updated apply |
429 Too Many Requests from the vendor |
too many calls for the quota | edit default_rate_limit: 50/s in the YAML, then lm apply -f |
lumnik.secret.master-key is too short at JVM startup |
env var missing or < 16 chars | regenerate with openssl rand -base64 32 + export; restart the JVM |
secret with this name already exists on secret set |
transparent update not handled | lm secret rm NAME --force then set; or the CLI already falls back to update on 409 |
For connector details: docs/connectors/rest-generic.md.