NAME
skeid - Skeid control-plane CLI and proxy launcher
VERSION
version 0.003
SYNOPSIS
skeid serve [--listen host:port] [--config skeid.yaml] [--admin-api-key KEY] [--workers N]
skeid usage [--config skeid.yaml] [--since ISO8601] [--limit N] [--json]
[--backend jsonlog|sqlite|postgresql] [--log-path /path/to/events/]
[--db /path/to.sqlite] [--dsn dbi:Pg:...]
[--db-user USER] [--db-pass PASS | --db-pass-env VAR]
[--api-key-id ID] [--model NAME]
skeid keyid [KEY ...]
DESCRIPTION
Runs the Skeid proxy (Langertha::Skeid::Proxy), reports recorded usage, and prints the customer key id a key routes and bills under. With no command, or when the first argument is an option, the command is serve. An unknown command prints the usage text and exits non-zero.
The config file is described in "CONFIGURATION" in Langertha::Skeid.
COMMANDS
serve
skeid serve --config /etc/skeid/skeid.yaml --listen 0.0.0.0:8090 --workers 4
Builds the app with "build_app" in Langertha::Skeid::Proxy and serves it -- with Mojo::Server::Daemon, or Mojo::Server::Prefork when --workers is above 1. Prints the address and config it starts with, and warns for every node whose max_conns cannot be split across the workers and frontends ("worker_share_warnings" in Langertha::Skeid).
--listen, -l
host:port to listen on (default 127.0.0.1:8090).
--config, -c
The YAML config. A path given here that is not an existing file ends the command with ERROR: config file not found: ... on standard error and exit code 2 -- Skeid does not start without the config it was told to use. Without --config, skeid.yaml in the working directory is used when it exists; when it does not, Skeid starts without a config, with no nodes (the admin API can add them). A config file that disappears while Skeid runs keeps the config in force and is warned about once ("maybe_reload_config" in Langertha::Skeid).
--admin-api-key
Admin API key. It wins over any key the config names, on every reload; without it the key comes from the config, else from SKEID_ADMIN_API_KEY (see "admin" in Langertha::Skeid). A key on the command line is visible in the process list, so in production prefer admin.api_key_env in the config.
--workers, -w
Prefork worker count (default 1; below 1 counts as 1). Each worker admits its share of every node's max_conns and polls capacity probes at its share of the rate (ADR 0010). Under several workers a SQLite usage store is unsafe, and an admin API write reaches only the worker that served it.
A usage store with flush_interval_ms holds events in memory until they are written; stopping the server writes them. Stop a prefork server with SIGQUIT (graceful): on SIGINT or SIGTERM Mojolicious's prefork manager kills its workers with SIGKILL, and what they still held is lost. A single process (--workers 1) flushes on SIGINT, SIGTERM and SIGQUIT.
usage
skeid usage --config /etc/skeid/skeid.yaml --since 2026-09-01T00:00:00Z --limit 50
Prints a usage report: the backend and store (a jsonlog path, the SQLite file, or configured DSN), totals, per API key id, per model, and the newest events. The store is the config's usage_store; any of --backend, --log-path, --db, --dsn, --db-user, --db-pass or --db-pass-env replaces it with a store built from those options alone. Exits 0, or 2 after printing ERROR: ... when the report fails (no store configured, say) or --config names no file.
--config, -c
As for serve: a missing file is an error; without the option, skeid.yaml is read when it exists.
--since
Only events with created_at at or after this ISO 8601 UTC timestamp.
--limit
How many recent events to list (default 20, at most 500; below 1 means 20).
--json
Print the report as JSON instead of the text summary.
--backend
jsonlog, sqlite or postgresql. Implied by --log-path, --db or --dsn.
--log-path, --jsonlog
A jsonlog store: its event directory (one file per event) or its JSON-lines file. An existing directory, or a path ending in /, is read as a directory; anything else as a file.
--db, --sqlite
SQLite database file.
--dsn
PostgreSQL DSN, dbi:Pg:....
--db-user, --db-pass
PostgreSQL credentials. A password on the command line lands in the shell history; prefer --db-pass-env.
--db-pass-env
Name of an environment variable holding the PostgreSQL password.
--api-key-id
Only events of this customer key id.
--model
Only events for this served model.
keyid
echo -n "$CUSTOMER_KEY" | skeid keyid
skeid keyid sk-alice-secret
Prints the customer key id ("key_id_for_key" in Langertha::Skeid) of each key given, one per line -- the id a config's keys: and names: sections use, so the config never holds the key. Without arguments it reads one key per line from standard input, which keeps the key out of the shell history. With no key at all it prints the usage text and exits non-zero.
ENVIRONMENT
serve and usage build a Langertha::Skeid, which reads SKEID_ROUTE_WAIT_TIMEOUT_MS, SKEID_ROUTE_WAIT_POLL_MS, SKEID_TRUST_KEY_ID_HEADER, SKEID_FRONTEND_COUNT, SKEID_ADMIN_API_KEY, SKEID_USAGE_DB, SKEID_CAPACITY_MAX_AGE_MS and SKEID_CONFIG_RELOAD_INTERVAL ("ENVIRONMENT" in Langertha::Skeid), and whatever variables the config names. serve also reads:
OPENBAO_ROLE_ID, OPENBAO_SECRET_ID
Both set: upstream keys (api_key_ref) are resolved from OpenBao through AppRole.
OPENBAO_ADDR
The OpenBao address (default http://127.0.0.1:8200).
OPENBAO_VERIFY_SSL
0, false, no or off disables TLS verification towards OpenBao -- for a dev vault only.
SKEID_UPSTREAM_POOL
Upstream connections kept per process (default 100).
SKEID_UPSTREAM_TIMEOUT
Seconds an upstream request may take, and may be silent for (default 300; a positive integer). The client's connection is kept open for as long on top of the server's own inactivity timeout, on the routes that call an upstream -- see "build_app" in Langertha::Skeid::Proxy.
SEE ALSO
Langertha::Skeid, Langertha::Skeid::Proxy
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha-skeid/issues.
IRC
Join #langertha on irc.perl.org or message Getty directly.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.