inbuxa-cli

Note

Development happens on git.coffeylabs.org/inbuxa/inbuxa-cli; the copy on GitHub is a read-only mirror. Report issues at git.coffeylabs.org/inbuxa/inbuxa-cli/issues, and join discussions at community.coffeylabs.org.

Administer an inbuxa server from the command line, and keep its settings in a file.

inbuxa-cli list Domain                         what's there
inbuxa-cli create Domain name=example.com      add to it
inbuxa-cli snapshot -o server.json             the settings, as a plan
inbuxa-cli apply server.json --dry-run         what a plan would change

Everything the console manages lives in the server's registry: domains, accounts, listeners, spam rules, tracers, about a hundred types in all. inbuxa-cli reads the server's own description of those types, so it knows every one the server knows, including types added after this program was built.

Installing

Download the archive for your machine from the releases, check it against SHA256SUMS, and put inbuxa-cli on your PATH:

curl -LO https://git.coffeylabs.org/inbuxa/inbuxa-cli/releases/latest/download/inbuxa-cli-linux-amd64.tar.gz
curl -LO https://git.coffeylabs.org/inbuxa/inbuxa-cli/releases/latest/download/SHA256SUMS
sha256sum --check --ignore-missing SHA256SUMS
tar xzf inbuxa-cli-linux-amd64.tar.gz
sudo install inbuxa-cli /usr/local/bin/

Or build it: cargo build --release leaves it in target/release/.

Signing in

Give the server's address with --url or INBUXA_URL, and an API key in INBUXA_API_KEY. Without one, inbuxa-cli asks for it. Make the key in the console under Account › Credentials › API Keys, signed in as an administrator.

export INBUXA_URL=https://mail.example.com
export INBUXA_API_KEY=API_…
inbuxa-cli types

The server takes passwords on its management API only in bootstrap and recovery mode, or when it runs with INBUXA_HTTP_BASIC_AUTH=all. There, --user [email protected] signs in with the password in INBUXA_PASSWORD, or asks for it. Secrets never go on the command line, where they would end up in the shell's history.

--insecure skips the TLS certificate check, for a test server with a self-signed certificate.

Commands

A type is named as the console's settings pages name it, with or without the x: prefix: Domain, x:Domain and domain are the same. An object is named by its id or by its key: a domain by its name, an account by its address.

Command Does
types lists the registry types
describe TYPE shows a type's properties: which are set on create only, which the server sets, which are secret, which refer to other types
list TYPE [--filter JSON] [--json] lists the objects of a type
get TYPE [ID…] prints objects as JSON
create TYPE name=value… [--file F] creates an object and prints its id
update TYPE [ID] name=value… [--file F] changes properties; a singleton needs no id
delete TYPE ID… deletes objects
reload [settings|tls|lookups|blocked-ips] applies saved settings on the running server
snapshot [TYPE…] [-o FILE] writes the settings as a plan
apply FILE [--dry-run] [--prune] [--yes] [--write-secrets] makes the server match a plan

A value that reads as JSON is JSON (true, 42, ["a","b"], {"@type":"Stdout"}); anything else is a string, so name=example.com needs no quotes. A name with slashes, such as limits/maxSize=10, changes one property inside an object. To refer to another object, write its type and key: domainId=@x:Domain/example.com.

inbuxa-cli create Account @type=User name=alice domainId=@x:Domain/example.com
inbuxa-cli update Account [email protected] description="Alice Liddell"
inbuxa-cli update Http usePermissiveCors=false
inbuxa-cli delete Account [email protected]

Most settings take effect when the server reloads its configuration. A current server does that after every write that needs it, and inbuxa-cli reports when a reload failed. An older one doesn't, and inbuxa-cli sends the reload itself. Stores (data, blob, search and the rest) take effect only when the server restarts, and inbuxa-cli says so.

Plans

A plan is the registry written down as JSON: a type and its objects, or a singleton and its properties.

{
  "x:Domain": [
    { "name": "example.com", "isEnabled": true }
  ],
  "x:Account": [
    { "@type": "Group", "@key": "[email protected]", "name": "staff",
      "domainId": "@x:Domain/example.com" },
    { "@type": "User", "@key": "[email protected]", "name": "alice",
      "domainId": "@x:Domain/example.com",
      "memberGroupIds": ["@x:Account/[email protected]"] }
  ],
  "x:Http": { "usePermissiveCors": false }
}

snapshot writes one from a server, and apply makes a server match one. Keep the server's settings in version control, review a change as a diff, and apply the same plan to a second server to set it up the same way.

  • Matching. Objects are matched by key: the property that names them, such as a domain's name. Where the server sets the key itself, as with an account's address, the plan carries it as @key. Lookup keys repeat from one list to the next, so their key is namespace/key. A type whose objects have no name, such as tracers, is matched by @id, which ties those entries to the server they came from.
  • References. Ids differ from one server to the next, so a property that refers to another object holds @<type>/<key>. apply creates what's referred to before what refers to it, including objects of the same type (a group before its members).
  • Only what's named. apply changes only the properties a plan names and leaves the rest as they are. Inside a nested object it compares property by property. A list or set is replaced whole.
  • Secrets. The server never shows a secret, so a snapshot has none: no passwords, no API keys, no DNS provider credentials. Add them to a plan by hand. apply writes them when it creates an object, but not to one that exists, since it can't compare them, unless you pass --write-secrets.
  • Set once. A property that can only be set on create (a domain's name) is reported, not changed. Delete the object and apply again.
  • Deleting. --prune deletes the objects of each type in the plan that the plan leaves out. It asks first, or takes --yes. Try --dry-run before either.

A snapshot leaves out what isn't settings: reports, logs, queued messages, tasks and other records, people's own credentials, and DKIM keys, which the server makes for each domain. Name a type to include it anyway: inbuxa-cli snapshot DkimSignature.

apply prints a line per change (+ created, ~ updated, - deleted, ! failed) and a count of each at the end.

Exit status

Status Means
0 done
2 the command line or the plan asks for something that can't work
3 the server couldn't be reached
4 the server refused the request: bad credentials, a missing permission
5 some changes failed; the rest were made

Testing

cargo test

The unit tests need no server. apply is tested against a registry held in memory. Before a release, the commands are also run by hand against a throwaway server in a container: a snapshot applied back to the server it came from changes nothing, and one applied after its objects are deleted recreates them with every reference intact.

License

AGPL-3.0-only. The text is in LICENSES.

Copyright (C) 2026, Coffey Labs LLC

S
Description
Command-line administration for inbuxa: every registry type, and the settings kept in a file you can apply.
Readme AGPL-3.0-only
102 KiB
0 Stars 1 Watchers 0 Forks
v2026.10.26
Latest
2026-10-26 15:20:10 +00:00
Languages
Rust 98.5%
Shell 1.5%