Skip to content

CLI (iolakectl)

iolakectl manages a cluster through the gateway's admin API, signed with SigV4 like the SDKs. Every command goes through the same authentication, tenant scoping, validation, Block Public Access and audit as any other caller. It never talks to meta directly, so meta's ports can stay closed to everything but the cluster.

Bucket lifecycle, CORS and bucket-level public access block are S3 calls, signed the same way. sts assume-role-with-web-identity needs no key. volume and snapshot talk to the block gateway (--block-endpoint, default http://localhost:9300).

Configure

iolakectl configure                 # prompts for endpoint, key and secret
iolakectl --profile acme configure --endpoint https://s3.example.com \
  --access-key AKIA… --secret-key … --non-interactive
iolakectl configure --list          # secrets masked

Profiles live in ~/.objectio/config (mode 0600). Settings are resolved in this order: 1. flags (--endpoint, --access-key/--secret-key, --region); 2. --profile; 3. the environment, as the SDKs read it: IOLAKE_ENDPOINT, IOLAKE_ACCESS_KEY(_FILE), IOLAKE_SECRET_KEY(_FILE), with the AWS_* names as fallbacks; 4. the IOLAKE_PROFILE or default profile.

The key must be unscoped: a key confined to a bucket is refused on the admin API. The system admin and tenant admins use the same CLI; without --tenant, a command acts in the caller's own tenant.

Output

Tables by default. -o json prints the API's JSON for scripting:

iolakectl -o json user create alice | jq -r .user_id

On error the exit code is non-zero and stderr carries the server's message. A secret is printed only when it's created.

Commands

group commands
tenant list, show, create, update, delete, admin list\|add\|remove
user list, show, create, update, suspend, activate, delete
key list, create [--scope s3://b/p/ --read-only], activate, deactivate, delete
policy list, show, create --file, update, delete, attach, detach, attached
group list, show, create, delete, add-user, remove-user
role list, show, create --trust-file, update, delete
oidc list, show, put --file, delete, tenant-name
sts assume-role-with-web-identity --role-arn --token[-file] [--env]
public-access-block get, put, delete (tenant/cluster); bucket get\|put\|delete\|policy-status
audit get, put --file, delete
replication target list\|set\|delete, resync start\|status\|cancel, settings get\|set (replication)
bucket list, show, create [--pool], delete, set-owner, set-quota [--bytes] [--objects], policy …, dedup …, lifecycle …, cors …
provision bucket B --user U (bucket + scoped key), rotate-key, deprovision
cluster info, topology, usage, drain-status, validate-placement, rebalance status\|pause\|resume
upgrade status, finalize (upgrades)
meta export [--file F]: a backup of meta's whole state, system admin (failure recovery)
node list, show
osd set-state ID in\|out\|draining
pool list, show, create, update, delete, placement-groups
pg list [--pool] [--state], get <pg_id>, scrub <pg_id>
kms status, keys list\|create\|show
warehouse list (a tenant admin its tenant's, the system admin every tenant's), create, delete
config list, get, set, delete
metrics query, query-range (PromQL, through the gateway to the Prometheus named by its --prometheus-url; refused without one)
volume list, create, show, resize, delete, attach [--read-only], detach, attachments
snapshot list, create, show, delete, clone
skills list, install (agent skills for coding agents)

iolakectl <group> --help lists each command's options. The source tree has the full command → API route map in bin/cli/README.md.

Examples

Onboard a tenant, as the system admin:

iolakectl tenant create acme --display-name "Acme" --quota-bytes 2T --default-pool standard
ADMIN=$(iolakectl -o json user create acme-admin --tenant acme | jq -r .user_id)
iolakectl tenant admin add acme "$ADMIN"
iolakectl key create "$ADMIN"          # hand this to acme's admin

As acme's admin:

iolakectl user create alice
iolakectl policy create read-logs --file read-logs.json
iolakectl policy attach read-logs --user <alice-id>
iolakectl public-access-block put --all
iolakectl bucket create logs
iolakectl bucket lifecycle put logs --file lifecycle.xml

Back meta up, as the system admin (on a schedule, and before every upgrade):

iolakectl meta export --file meta-$(date +%F).backup

The file is checked as it downloads and gets its name only once whole; it holds every secret meta keeps, so it is written readable by its owner only. It is restored with iolake-meta restore, with meta stopped (failure recovery).

Make pools, one per protection scheme (--ec-type 0 is Reed-Solomon, 1 LRC, 2 replication):

iolakectl pool create standard --ec-type 0 --ec-k 4 --ec-m 2 --failure-domain host
iolakectl pool create wide --ec-type 1 --ec-k 6 --ec-local-parity 2 --ec-global-parity 2
iolakectl pool create copies --ec-type 2 --replication-count 3

A pool's placement-group count is fixed for its life. Leave --pg-count out (or give 0) and meta sizes it from the OSDs in service: about 100 PG members an OSD (config pg/members_per_osd) over the copies a PG holds, rounded up to a power of two, from 256 to 4096. Six OSDs at 4+2 get 256.

A scheme the codecs can't keep is refused, with what is wrong with it, and no pool is made: Reed-Solomon with no parity (--ec-m 0; one unprotected copy is --ec-type 2 --replication-count 1) or a profile some loss of m shards wouldn't decode; LRC whose data shards don't split into its local groups evenly, or with no local or global parity; replication of 0 copies; more than 255 shards. An LRC pool survives every loss of its global parity count, more by where they fall. The rules are in data protection.

Take an OSD out of service:

iolakectl osd set-state <osd-id> draining
iolakectl cluster drain-status

Temporary credentials from a CI job's OIDC token:

eval "$(iolakectl sts assume-role-with-web-identity \
  --role-arn arn:obio:iam::acme:role/ci --token-file "$TOKEN_FILE" --env)"