Command-line reference
Every versealx-server subcommand, its arguments and flags, what it prints, the messages it can give and its exit codes.
versealx-server <command> [arguments] [--config <file>]
Running versealx-server with no command, or an unknown one, prints the usage and exits with 2.
Finding the configuration
Every command except init, catalogue and --version reads the configuration file:
--config <file>, written after the command —versealx-server doctor --config /etc/versealx-server/versealx-server.toml, not before it.- Otherwise the
VERSEALX_CONFIGenvironment variable. The packaged service sets it; your shell does not. - Otherwise
versealx-server.tomlin the current directory.
--config - reads the file from standard input. Separate --config from its value with a space.
Commands that read the store or the admin socket need the permissions of the service user, so run them as sudo -u versealx versealx-server ….
Summary
| Command | What it does | Needs the server running |
|---|---|---|
--version, -V, version | Prints the version. | No |
init | Sets up a new node. | No |
check | Validates the configuration. | No |
explain | Describes what the configuration will do. | No |
run | Runs the server. | — |
doctor | Checks DNS, certificates, reverse DNS and the store. | No |
dns | Prints the DNS records a domain needs. | No |
dkim | Makes or shows a domain’s DKIM keys. | No; use the API on a running server |
dane | Changes the key a DANE record pins. | Starts without; the running node completes it |
trust | Lists a set of trusted roots: BIMI’s or S/MIME’s. | No |
keys | Rotates the key-encryption key, or hands a key file’s key to a KMS. | Must be stopped |
admin | Calls the admin API. | Yes |
sync | Reads a tenant’s LDAP or Active Directory and makes this directory agree. | No |
migrate | Copies a mailbox here from another IMAP server, Microsoft 365 or Google Workspace, or imports PST, MBOX and Maildir files. | No; it can run beside it |
backup | Writes a snapshot. | Must be stopped |
restore | Puts a snapshot back. | Must be stopped |
backups | Makes the daily backups’ key, and lists and checks them. | No; it can run beside it |
upgrade | Installs a signed release, and reviews and prepares the store for it. | Must be stopped to install; the rest no |
catalogue | Lists the capabilities this build knows about. | No |
Exit codes
| Code | Meaning |
|---|---|
0 | It worked. |
1 | admin: the API answered with an error. doctor: something needs a look. |
2 | The command could not do what was asked: a refusal, a usage mistake, a failure. doctor: something is broken. |
Errors are printed to standard error, prefixed versealx-server: .
init
Sets up a new node: writes the configuration, creates the data directory, creates the first tenant, domain and administrator, generates DKIM keys, and prints everything to publish. See the Quick start.
versealx-server init --hostname <name> --domain <domain> [--admin <address>]
[--config <file>] [--data <dir>] [--relay <host[:port]>] [--self-signed]
| Flag | Default | Meaning |
|---|---|---|
--hostname <name> | Required | The server’s host name, which it greets other servers with. Also used as the node name. |
--domain <domain> | Required | The first mail domain. Needs at least two labels. The tenant is named after it. |
--admin <address> | postmaster@<domain> | The administrator’s address. |
--config <file> | /etc/versealx-server/versealx-server.toml | Where to write the configuration. |
--data <dir> | /var/lib/versealx-server | Where the store, message files, key file, certificate and socket go. |
--relay <host[:port]> | None | Send outgoing mail through this relay: writes an [outbound.relay] table with tls = "required", the administrator’s address as user, and ${VERSEALX_RELAY_PASSWORD} as the password, and prints an SPF record that includes the relay. The port is 587 unless given. |
--self-signed | Off | Also write a self-signed certificate for the host name, valid for a year, and print its SHA-256 fingerprint. |
What it creates, with --data /var/lib/versealx-server:
versealx-server.tomlat the--configpath, mode0600, with[store],[blobs],[keys],[tls] kind = "files",[admin] socketand[mta_sts] mode = "testing".- The data directory and its
blobsandtlsdirectories, mode0700. store.db, holding the tenant, the domain (unverified), the administrator with a generated 24-character password, and an RSA and an Ed25519 DKIM key.- With
--self-signed:tls/certificate.pemandtls/key.pem, mode0600.
The key file is not created by init; the node creates it when it first starts.
| Message | Cause |
|---|---|
<path> already exists; init will not write over a configuration | A configuration is already at the --config path. |
--hostname is not a host name | The host name is not a valid DNS name. |
--domain is not a domain name | The domain is not a valid DNS name. |
--domain needs at least two labels | A single-label domain. |
--admin is an address, like postmaster@example.org | The administrator’s address has no @. |
| The usage and an example | --hostname or --domain is missing. |
making <path>: <reason>, writing <path>: <reason>, setting the mode of <path>: <reason> | A directory or file could not be made. |
Run init as the service user, so the files it writes belong to the service.
check
versealx-server check [--config <file>]
Parses and validates the configuration without opening the store. Prints ok: node `<node>` as <hostname> with roles <roles> and exits 0, or prints versealx-server: refusing to start: <reason> and exits 2. Refuses to run as root. Configuration lists every refusal.
explain
versealx-server explain [--config <file>]
Prints what the configuration will do, reading only the file, so it works before the store exists. The sections are:
| Section | What it shows |
|---|---|
node … greets as … | The node’s name and host name. |
roles on this node, what each listens on, and what each sends out: | Each role with its listeners — the default ports, or <address> (configured) — and what it sends out of the machine. |
how hard this node pushes a destination: | With relay: the pass concurrency, the default ceiling, each configured destination, and how to change them in the store. |
the most one message may be: | The size and recipient ceilings, and how to lower them in the store. |
where data lives: | The store, the message files and the key file, with a database password shown as ***. |
the filter pipeline, in order: | The built-in stages, then the scanner and milters. |
what leaves the premises beyond mail itself: | Where certificates come from, where metrics are served, the DNS trust anchors, extra trusted certificates, and a line in capitals if the node may deliver to private addresses. |
the most one message may be:
size 26214400 bytes, advertised as SIZE
recipients 100, advertised as LIMITS RCPTMAX
either may be lowered while the node runs, and neither raised past what is
built in:
versealx-server admin patch tenants/0/settings limits.message_size=10485760
where data lives:
metadata SQLite at /var/lib/versealx-server/store.db (this machine)
messages files under /var/lib/versealx-server/blobs (this machine), encrypted per tenant
keys wrapped by a key in /var/lib/versealx-server/kek (this machine)
run
versealx-server run [--as-restore] [--config <file>]
Starts the configured roles and runs until it receives SIGINT or SIGTERM. Under systemd it reports readiness once every listener is bound. It refuses to run as root, and exits with 2 and the reason if anything it needs is missing. Troubleshooting lists the messages.
--as-restore starts on a database restored from an earlier moment: the cluster gets a new identity and outgoing mail is held until restore release. See Starting on a restored database.
doctor
versealx-server doctor [--config <file>]
Checks the host name, the certificate, the clock, the resolver, reverse DNS, DANE, the store, and each domain’s MX, SPF, ownership token, DMARC, DKIM, MTA-STS and TLS reporting. Prints one line per check, a remedy under each problem, and a summary: <n> checked, <n> good, <n> to look at, <n> broken. Exits 0 when all is well, 1 with warnings, 2 with problems. See Monitoring.
If the store will not open, doctor still checks the host name, the certificate, the clock, the resolver and reverse DNS, and reports the store as BAD.
dns
versealx-server dns [<domain>] [--config <file>]
Prints every DNS record a domain needs, read from the store and the configuration: address, MX, SPF, DMARC, ownership token, DKIM, MTA-STS, TLS reporting and SRV records, then the host’s TLSA record and notes. With no domain, prints every hosted domain’s records. Works with the server stopped or running. See DNS records.
| Message | Cause |
|---|---|
<domain> is not a domain of this server | The domain is not hosted here. |
this server hosts no domains yet; add one before asking what it needs | No domains at all. |
dkim
versealx-server dkim generate <tenant> <domain> [selector] [--config <file>]
versealx-server dkim show <tenant> <domain> [--config <file>]
Opens the store directly, for a server that is not running. On a running server, use the admin API instead, which records the change in the audit log. <tenant> is the tenant’s name.
| Verb | What it does |
|---|---|
generate | Makes an RSA and an Ed25519 key under <selector>r and <selector>e, or a selector built from today’s date, and prints their records. |
show | Prints the record of every key the domain has, marking retired keys ; retired. |
See Email authentication for the messages.
trust
versealx-server trust roots <bimi|smime> [--config <file>]
Lists a set of trusted roots on this node: each with its SHA-256 fingerprint, when it expires, and whether it shipped with the server or came from the file the set’s table names. bimi is BIMI’s mark-certificate roots (Logos on mail you receive); smime is the roots S/MIME signers are chained to ([smime]). versealx-server bimi roots is the same as trust roots bimi.
dane
versealx-server dane roll [--hold <hours>] [--config <file>]
versealx-server dane status [--config <file>]
versealx-server dane cancel [--config <file>]
Changes the key the host’s DANE record pins, in the safe order, for a node using ACME. See TLS certificates.
| Verb | What it does |
|---|---|
roll | Keeps a new key in the store and prints the TLSA record to publish beside the current one. The running node switches to the new key once it has seen the record published for the hold. |
status | Prints the current and next records and where the rollover has got to. |
cancel | Abandons the rollover and deletes the next key. |
| Flag | Default | Meaning |
|---|---|---|
--hold <hours> or --hold=<hours> | 48 | How long the new record must have been seen before the switch: twice its TTL, or more. A whole number from 1 to 720. |
| Message | Cause |
|---|---|
usage: dane <roll [--hold <hours>]|status|cancel> | No verb, or an unknown one. |
a key rollover is already under way: … | roll while one is in progress. |
this node has no certificate yet, so no record can be pinning its key: … | No ACME certificate has been obtained. |
this node serves the certificate and key named in [tls], so a rollover is done by hand, … | The node uses certificate files; the message gives the manual order. |
--hold is a whole number of hours from 1 to 720: twice the TLSA record's TTL, or more | A bad --hold. |
keys
versealx-server keys new --file <key file>
versealx-server keys rotate --new-key-file <key file> [--config <file>]
versealx-server keys rotate --kms [--kms-key <key ARN>] [--config <file>]
versealx-server keys rotate --online [--config <file>]
versealx-server keys wrap --file <key file> [--config <file>]
| Verb | What it does |
|---|---|
new | Makes a new key-encryption key in a file that does not exist yet, readable only by its owner, and changes nothing else. For an online rotation. |
rotate --new-key-file | Wraps every tenant’s data key again under the key in that file, made there if the file does not exist. For [keys] kind = "file". |
rotate --online | With every node running and holding both keys, [keys] path the new one and previous_file the old, wraps every tenant’s data key again under the new key. Under a KMS, key_id names the new KMS key and previous_key_id the old: the first run makes the new key, and once every node holds both, the next run rewraps. See Rotating without stopping. |
rotate --kms | Has the KMS make a new key and wraps every tenant’s data key under it, by the KMS key [keys] names or the one --kms-key names. For [keys] kind = "kms". |
wrap --file | Hands the key in a key file to the KMS [keys] names, so a node that ran on a key file can start with kind = "kms". |
Every node must be stopped. A rotation that stops part way is finished by running the same command again. See Rotating the key-encryption key.
| Message | Cause |
|---|---|
… Nothing was rotated: stop every node first. … | A node is running: its admin socket answered, or a relay node holds its periodic lease. |
[keys] names a key file, not a KMS: rotate it with keys rotate --new-key-file <path> | --kms on a node whose key is in a file. |
[keys] names a KMS: rotate with keys rotate --kms, and the KMS makes the new key | --new-key-file on a node whose key is in a KMS. |
The store is written under that key already: a rotation to it has finished, and there is nothing to do. | The rotation was already finished. |
the key in <file> is not the one this store was written under, so it is not wrapped; nothing was changed | wrap with a key file from another store. |
sandbox-node
versealx-server sandbox-node new <directory>
versealx-server sandbox-node remove <directory>
| Verb | What it does |
|---|---|
new | Makes a whole sandbox node in an empty directory: its configuration, store, key and a certificate it made itself, every listener on a free port of this machine. Prints how to start it, where its console and port 25 answer, and how to give its administrator a password. |
remove | Deletes the directory, only when it holds a sandbox node whose store says so and the node is stopped. Never follows a link out of it. |
case open
versealx-server case open <sealed file> --out <file> [--password-stdin]
Opens a discovery export with its passphrase, asked without showing it or read from standard input. It needs no configuration and no server. The output is a new file; a file that has been changed, or the wrong passphrase, leaves nothing behind.
admin
versealx-server admin <get|post|put|patch|delete> <path> [key=value ...] [--socket <path>] [--config <file>]
Calls the admin API over the node’s local socket, as the operator. See Admin API.
| Part | Meaning |
|---|---|
| Method | get, post, put, patch or delete. |
<path> | The API path, with or without /api/v1/. |
key=value | Query parameters for get and delete; JSON body fields otherwise. true, false, null, all-digit numbers and JSON arrays or objects keep their types. |
--socket <path> | The socket to use. Otherwise [admin] socket from the configuration, or /run/versealx-server/admin.sock. |
Prints the answer as indented JSON. Exits 0 for a 2xx answer, 1 for 4xx or 5xx, and 2 if the socket cannot be reached.
Examples:
versealx-server admin get tenants
versealx-server admin post tenants name=example-org
versealx-server admin get tenants/1/domains
versealx-server admin post tenants/1/domains name=example.org
versealx-server admin post tenants/1/domains/example.org/verify
versealx-server admin post tenants/1/domains/example.org/dkim
versealx-server admin post tenants/1/accounts address=alex@example.org "displayName=Alex Morgan"
versealx-server admin put tenants/1/accounts/2/password "password=<new password>"
versealx-server admin patch tenants/1/settings mta_sts.mode=enforce
versealx-server admin patch tenants/0/settings limits.message_size=10485760
versealx-server admin patch tenants/0/settings outbound.destination.gmail.com.messages_per_minute=600
versealx-server admin patch tenants/0/settings 'oauth.console.redirect_uris=["https://console.example.com/callback"]'
versealx-server admin get queue
versealx-server admin get trace tenant=1 address=alex@example.org day=2026-09-14
versealx-server admin get audit tenant=1 limit=50
Tasks by name
versealx-server admin <noun> <verb> [what] [--option value]
versealx-server admin help
The same API, named by what you are doing rather than by its path. People are named by an address and domains by their name. Over the local socket you act as the operator: on a node with one organisation that organisation is meant, and with several, name it with --tenant <number>. With --server you act as the person you signed in as, in their own organisation, with their role.
A secret is never a command-line argument. It is read from the terminal, or made and shown once. people reset-password shows a temporary password once, and the person chooses their own at their next sign-in.
versealx-server admin help lists every command:
versealx-server admin org show | suspend | reactivate
versealx-server admin org where | residency [--rest DE,AT] [--transit DE,AT,NL]
versealx-server admin org sign-ins [--refused] [--new] [--protocol imap|jmap|…] [--with password|'app password'|token|passkey|'passkey, no password'] [--limit n] [--after cursor]
versealx-server admin org lockouts [--limit n]
versealx-server admin org second-factor off|optional|required
versealx-server admin org leaked-passwords off|on|strict
versealx-server admin org account-recovery off|on
versealx-server admin org breached-passwords [--limit n]
versealx-server admin org passkeys allowed|off | passwordless off|allowed | user-verification preferred|required
versealx-server admin org forwarding approval|allowed|off
versealx-server admin org phishing-takeback on|off [--reports n]
versealx-server admin org deleted-mail [--keep 14|off] [--trash 30|never] [--junk 30|never]
versealx-server admin org mailbox-audit [--days n] [--record-own <address>,…|none]
versealx-server admin org forwarding-destinations list | add <domain or address> | remove <domain or address>
versealx-server admin org storage 2TB|none [--warn 90%]
versealx-server admin org calendar-invitations authenticated|never
versealx-server admin org free-busy organisation|nobody
versealx-server admin org calendar-publishing details|freebusy|off
versealx-server admin usage show [--days 90] | storage [--limit 20] | breakdown
versealx-server admin server show
versealx-server admin domain list | add <domain> | show <domain> | verify <domain>
versealx-server admin domain alias <domain> <canonical> | unalias <domain>
versealx-server admin domain dns <domain> | check <domain>
versealx-server admin domain senders <domain>
versealx-server admin domain logo <domain> <file.svg> [--evidence <file.pem>] [--selector <label>] | logo-show <domain> | logo-remove <domain>
versealx-server admin dkim list <domain> | make <domain> [--selector s] | retire <domain> <selector>
versealx-server admin report list <domain> [--day YYYY-MM-DD] [--kind dmarc|tls]
versealx-server admin people list [--search text] | add <address> [--name 'Name'] [--room] [--plan <plan>]
versealx-server admin people show | suspend | reactivate | remove | reset-password | unlock <address>
versealx-server admin people sign-ins | sign-out | app-passwords | revoke-all-app-passwords <address> | revoke-app-password <address> <number>
versealx-server admin people sessions <address> | end-session <address> <number>
versealx-server admin people secure <address>
versealx-server admin people offboard <address> [--delegate <address> [--access read|organise|full] | --shared --member <address>…] [--forward <address>… [--no-copy]] [--reply 'the reply' [--reply-until YYYY-MM-DD]] [--hold 'the matter'] [--remove-after 90d|YYYY-MM-DD|never] [--keep-sessions] [--keep-app-passwords] [--keep-second-steps] [--dry-run]
versealx-server admin people undo-offboarding <address> [--dry-run]
versealx-server admin people second-factor <address> | remove-second-factor <address> [<number>]
versealx-server admin people recovery-address <address>
versealx-server admin autoreply show | stop <address> | set <address> --text 'the reply' [--subject s] [--from YYYY-MM-DD] [--until YYYY-MM-DD]
versealx-server admin people status suspended|active|removed <address>…
versealx-server admin people rename <address> 'New name'
versealx-server admin people send-as <address> <address>… | --none
versealx-server admin people delegates <address> | undelegate <address> <delegate>
versealx-server admin people plan <address> <plan>|none
versealx-server admin people delegate <address> <delegate> [--read] [--send-as] [--send-on-behalf] [--calendar]
versealx-server admin people forward <address> --to <address> [--to …] [--no-copy] | unforward <address>
versealx-server admin people senders <address> | look-at-senders <address> --reason text
versealx-server admin address add | remove <address> <another address>
versealx-server admin group add <address> [--member <address>…] [--senders anyone|organisation|members]
versealx-server admin group add-member | remove-member <group> <address> | restrict <group> anyone|organisation|members
versealx-server admin group address-books | address-book <group> --name 'Suppliers' [--access read|write] | remove-address-book <group>
versealx-server admin group add <address> --when 'department=Sales,office=London' | rule <group> '<rule>' | preview-rule <group> '<rule>' | show-rule <group> | drop-rule <group>
versealx-server admin list all | show <list> | held <list>
versealx-server admin list add <address> --owner <address>… [--moderator <address>…] [--member <address>…] [--posting anyone|organisation|members] [--moderate none|others|all] [--join open|request|closed] [--reply-to list|poster] [--archive members|none] [--tag Team|none] [--name 'Team'] [--description '…']
versealx-server admin list set <list> [the options of list add]
versealx-server admin list decide <list> <held id> approve|refuse|always
versealx-server admin list add-member | remove-member <list> <address>
versealx-server admin room add <address> [--name 'Board room'] [--booking auto|approval|none] [--capacity 12] [--location 'Floor 3'] [--max 4h|none] [--ahead 90d|none] [--hours 'mon-fri 08:00-18:00 +03:00'|any] [--booker <address>…|--everybody] [--approver <address>…] [--each-occurrence|--all-occurrences] [--show-organiser|--hide-organiser] [--equipment|--not-equipment]
versealx-server admin room show | stop <address> | booking <address> [the options of room add; each changes only itself]
versealx-server admin calendar published <address> | unpublish <address> <calendar>
versealx-server admin addressbook show | hide <address> | unhide <address> | fields title,department,phones|none
versealx-server admin journal show | add <archive> [--groups <address>,...] [--in] [--out] [--between] | remove <archive>
versealx-server admin retention show | preview | add <name> [--groups <address>,...] [--what all|received|sent] (--keep 10y [--then-delete] | --delete-after 2y) | remove <name>
versealx-server admin suppression list [--after <address>] | remove <address>
versealx-server admin complaints show [--days <1-90>]
versealx-server admin sender-history list [--after domain:<domain>|address:<address>] | forget domain|address <sender>
versealx-server admin break-glass show | set <address> [<address>]
versealx-server admin sandbox list | new <name> [--from design|empty|template:<name>] [--mail sample|none] [--seed <n>] [--per-mailbox <1-200>] [--days <1-90>] | outbox <sandbox number> | scenarios <sandbox number> [<scenario>] | start <sandbox number> <scenario> | run <sandbox number> <scenario> | scenarios-here [<scenario>] | start-here <scenario> | run-here <scenario> (inside a sandbox, as its administrator with --server) | promote <sandbox number> | remove <sandbox number>
versealx-server admin design export [--sandbox <number>] | export --signed [--file <file>] | diff <file> [--name <theirs>=<ours>] | apply <file> [--what-if] [--name <theirs>=<ours>] | history | rollback --to <version> | environments | promote --from <organisation> [--what-if] | promotion-only on|off | import <bundle> [--what-if] | discard <installation> | staging list | staging add <name> --issuer <url> --key <key> --fingerprint <hex> [--name <ours>=<theirs>] | staging remove <name>
versealx-server admin integrity show
versealx-server admin security posture | report <nis2|iso-27001> | except <control> <YYYY-MM-DD> '<why>' | unexcept <control> | floors | floor <setting> <value> [--lock] | unfloor <setting>
versealx-server admin try message --from <address> --to <address>[,...] [--ip <address>] [--file <message.eml>] | dns <domain> --record '<TYPE> <name> <value>'...
versealx-server admin impersonation show | protect-name '<name>' [--address <address>]... | unprotect-name '<name>' | protect-domain <domain> | unprotect-domain <domain> | test '<from>' [--reply-to <address>]
versealx-server admin openpgp show <domain> | on <domain> | off <domain> | remove <address>
versealx-server admin smime show <domain> | remove <address>
versealx-server admin tls list | add <domain> [--out encrypt|verify|pin] [--pin <base64 SHA-256>]... [--inbound require] [--note '…'] | remove <domain>
versealx-server admin scripts show | set [--before <file.sieve>] [--after <file.sieve>] [--no-before] [--no-after]
versealx-server admin addressbook scope set <file> | clear
versealx-server admin alias add <address> --to <address> | point <alias> <address>
versealx-server admin invite show | make | cancel <address> | activate <address> <code>
versealx-server admin role show | revoke <address> | grant <address> administrator|helpdesk|auditor|domain-admin <domain>…|'<one of the organisation's own>'
versealx-server admin roles show
versealx-server admin roles eligible | make-eligible <address> administrator|helpdesk|auditor|domain-admin <domain>…|'<one of the organisation's own>' [--minutes <longest>] | not-eligible <address> | take <minutes> --reason '…' | active | end <address>
versealx-server admin roles add '<name>' --may <action>,… [--scope domain:<domain>|group:<address>|department=<value>|title=<value>,…] [--except …] [--from administrator|helpdesk|auditor]
versealx-server admin roles change '<name>' [--name '<new name>'] [--may <action>,…] [--scope …|organisation] [--except …|nobody]
versealx-server admin roles remove '<name>' [--take-from-holders]
versealx-server admin plans show
versealx-server admin plans add <name> [--storage 5GB|none] [--messages 100000|none] [--sending 100/50/1000|none] [--protocols imap,jmap,…|all] [--no-imap] [--no-pop3] [--no-submission] [--no-jmap] [--no-dav] [--no-managesieve] [--forwarding allowed|approval|off|organisation] [--two-step|--no-two-step] [--default] [--dry-run]
versealx-server admin plans change <name> [--name <new name>] [the options of plans add] [--dry-run]
versealx-server admin plans remove <name> [--dry-run]
versealx-server admin plans assign | unassign <name> --group <address> [--dry-run]
versealx-server admin mailbox show | return | usage <address> | move <address> <premises>
versealx-server admin mailbox limit <address> 5GB|none [--messages 200000|none] [--warn 85%]
versealx-server admin mailbox recoverable <address> [--from YYYY-MM-DD] [--search text] [--limit 50] [--before n] | recover <address> <number>…
versealx-server admin mailbox backups <address> | restore <address> --from <backup> [--folder 'name']
versealx-server admin mailbox imports <address> | import <address> <file.mbox or file.pst> [--into folder] | import-cancel <address> <number>
versealx-server admin mailbox activity <address> [--by <address>] [--from YYYY-MM-DD] [--until YYYY-MM-DD] [--limit n] [--after cursor]
versealx-server admin mailbox export-activity <address> [--by <address>] [--from YYYY-MM-DD] [--until YYYY-MM-DD] [--to file.csv] (every page, as CSV)
versealx-server admin hold show | lift <address> | set <address> --reason 'the matter' [--until YYYY-MM-DD]
versealx-server admin sending show | reset <address> | set <address> [--per-hour n] [--per-message n] [--per-day n]
versealx-server admin sending top [--limit n]
versealx-server admin sending held | release | discard | exempt | watch <address>
versealx-server admin queue list [--retrying] | show <id> | pacing
versealx-server admin queue retry | hold | release <id> | remove <id> [--tell-sender]
versealx-server admin queue retry-all | hold-all | release-all | remove-all --to <address or domain> | --from <address or domain> [--tell-sender]
versealx-server admin trace search <address> [--day YYYY-MM-DD | --from YYYY-MM-DD --to YYYY-MM-DD] [--after cursor] | recent [--limit n] | show <id>
versealx-server admin trace search [<address or domain>] --outcome delivered|junked|quarantined|deferred|bounced|refused|held|removed [--day YYYY-MM-DD | --from YYYY-MM-DD --to YYYY-MM-DD] [--after cursor]
versealx-server admin message purge <queue id | Message-ID> [--dry-run]
versealx-server admin reported list | remove <id> | dismiss <id> | block <id>
versealx-server admin quarantine list | release <account>/<message> | discard <account>/<message>
versealx-server admin rules show [--history] | set <file> [--what-if] | preview <file> | enforce|report|off <rule id>
versealx-server admin classifier show | on | off | forget
versealx-server admin filter rescan --since <YYYY-MM-DD> [--until <YYYY-MM-DD>] [--what-if] | rescan-status | rescan-stop
versealx-server admin idp show | connect --issuer <url> --client-id <id> [--claim c] | on | off | disconnect
versealx-server admin sync show | connect --url <ldaps://…> --bind-dn <dn> --base-dn <dn> | pause | resume | disconnect
versealx-server admin token list | make <label> [--role administrator|helpdesk|auditor] [--days n] | revoke <id>
versealx-server admin settings show | set <key=value>… | history [--version n] | restore <version>
versealx-server admin senders list | allow <who> [--note text] | block <who> [--note text] | remove <who>
versealx-server admin senders domain <domain> show | allow <who> [--note text] | block <who> [--note text] | remove <who>
versealx-server admin alerts show | set <file> | history [--after cursor] [--limit n]
versealx-server admin branding show | set [--name 'Name'] [--colour '#rrggbb'] [--help-text 'text'] [--logo file.svg|file.png] | remove-logo
versealx-server admin audit list [--after id] [--limit n] [--role sign-in|receiving|directory-sync|operator|retention|…]
versealx-server admin audit export --since YYYY-MM-DD [--until YYYY-MM-DD] --format jsonl [--to file] (every line as the log export sends it)
versealx-server admin sign-ins network-locks (every lock on the node: --tenant 0 over its socket) | unlock-network <network or an address in it>
versealx-server admin forwarding requests | list [--limit n]
versealx-server admin forwarding approve <number> | approve-for-everybody <number> [--domain]
versealx-server admin forwarding refuse <number> --reason 'the reason' | revoke <number> [--reason 'the reason']
versealx-server admin access show | set <file> (the access rules as JSON, or a list of rules) | test <address> imap|pop3|submission|jmap|dav|managesieve|console|app:<client id> <from address> [--file rules.json] | simulate <address> --way <way> --credential password|app-password|passkey|sso --from <address> [--at <UTC moment>]
versealx-server admin shared add <address> [--name 'Name'] [--member <address>…] [--access read|organise|full] [--personal-read-state]
versealx-server admin shared show <address> | member <address> <member> read|organise|full [--send-as] [--send-on-behalf] | unmember <address> <member>
versealx-server admin shared read-state <address> shared|personal
versealx-server admin approvals list [--state waiting|approved|refused|expired|done|failed|emergency] [--limit n] | show <number>
versealx-server admin approvals approve <number> --reason 'why' | refuse <number> --reason 'why'
versealx-server admin approvals ask --reason 'why' (the operator, of an organisation that asks first: --tenant <number> over the socket; a change the organisation holds for approval takes --reason 'why', and the operator's in an emergency --emergency 'why')
versealx-server admin org approvals remove-account|purge|lift-hold|change-roles|second-factor-off|access-rules required|off
versealx-server admin org operator-access trusted|ask
versealx-server admin migrate start --source <host>[:<port>] (--people people.csv | --group <address> --passwords passwords.csv | --everyone --passwords passwords.csv) [--starttls] [--source-connect-to <host>:<port>] [--source-trust ca.pem] [--skip-junk-and-trash] [--since YYYY-MM-DD] [--at-once 4]
versealx-server admin migrate start --source m365 --tenant <tenant> --client-id <id> --secret-file <path> (--people people.csv | --group <address> | --everyone) [--skip-junk-and-trash] [--since YYYY-MM-DD] [--at-once 4]
versealx-server admin migrate start --source google --key-file <key.json> (--people people.csv | --group <address> | --everyone) [--skip-junk-and-trash] [--since YYYY-MM-DD] [--at-once 4]
versealx-server admin migrate list | status <number> | report <number>
versealx-server admin migrate retry <number> [<address> [--new-password]] | final-pass <number> | cancel <number>
versealx-server admin webhooks list | show <id> | deliveries <id>
versealx-server admin webhooks add <https-url> --events alert,quarantined,person-added,person-removed,legal-hold,audit,new-place,refused,locked [--description '…'] (the signing secret is shown once)
versealx-server admin webhooks change <id> [--url <https-url>] [--events …] [--description '…'] | secret <id> | resend <id> <delivery> | resume <id> | remove <id>
versealx-server admin log-export show | set syslog <host>[:<port>] | set https <url> [--format splunk-hec|elastic|json] (a token is asked for, or read with --secret-stdin) | resume | off
sync
versealx-server sync [<tenant>] [--dry-run] [--confirm] [--config <file>]
Runs a tenant’s directory sync now, or every configured tenant’s when none is named, and prints what it created, updated, disabled and re-enabled. --dry-run prints what it would do and changes nothing; --confirm lets through a run that the safety limits stopped. Exits 2 when a run was refused or the directory could not be read. See Syncing from LDAP or Active Directory.
migrate
versealx-server migrate imap <address> --from <host>[:<port>] (--password-file <path> | --password-stdin)
[--user <name>] [--starttls] [--only <folder>]... [--except <folder>]... [--connections <n>]
[--connect-to <host>:<port>] [--trust <ca.pem>] [--keep-deleted-flag] [--config <file>]
Copies the mailbox at --from into the account <address>, and prints what it copied. Running it again carries on from where the last run stopped and copies nothing twice. Exits 2 when it stopped early or some messages failed; run it again. A password given as an argument is refused. See Moving mail from another server.
versealx-server migrate m365 <address> --tenant <tenant id or domain> --client-id <id>
(--secret-file <path> | --secret-stdin) [--user <address>] [--config <file>]
versealx-server migrate google <address> --key-file <service account key.json> [--user <address>] [--config <file>]
Copies a person’s mail from Microsoft 365, with an app registration’s client secret, or from Google Workspace, with a service account’s key, into the account <address>, and prints what it copied. Running it again carries on and copies only what is new. Exits 2 when it stopped early or some messages failed; run it again. A secret given as an argument is refused. See From Microsoft 365 or Google Workspace.
versealx-server migrate mbox <file or directory> <address> [--into <folder>] [--config <file>]
versealx-server migrate maildir <directory> <address> [--into <folder>] [--config <file>]
versealx-server migrate pst <file> <address> [--into <folder>] [--config <file>]
Imports mail from MBOX files, a Maildir or an Outlook PST on this machine into the account <address>, under --into when given, and prints what it imported. Running it again imports nothing twice. Exits 2 when some messages failed; run it again. See Importing mail from files.
backup
versealx-server backup <directory> [--config <file>]
versealx-server backup mark "<name>" | points
versealx-server backup --cluster <directory | s3://bucket/prefix> [--key-file <path>]
Writes a snapshot of a stopped node into the directory, creating it if needed, and prints wrote <n> keys and <n> blob(s) to <directory>. See Backup and restore.
backup mark names a restore point for a cluster whose database has point-in-time recovery, and backup points lists them. See Backups of a cluster.
backup --cluster copies a running cluster on PostgreSQL into a directory or an S3-compatible bucket, sealed with the backup key, from one moment of its database. See A copy away from the database’s provider.
restore
versealx-server restore <directory> [--merge] [--config <file>]
versealx-server restore <directory | s3://bucket/prefix> --backup <name> [--key-file <path>] [--merge]
versealx-server restore check --store <path or postgres URL> [--full]
versealx-server restore held [--config <file>]
versealx-server restore release [--config <file>]
Checks a snapshot against its manifest, then writes it into a stopped node and prints restored <n> keys and <n> blob(s) from <directory>. Refuses a node that already holds data unless --merge is given. See Backup and restore.
restore check says whether a restored database is whole before any node starts on it, and exits 1 when mail it names is missing. See Checking a restored database.
restore held lists the outgoing mail held since a node started with run --as-restore, and restore release lets it go. See Starting on a restored database.
backups
versealx-server backups key <path> [--config <file>]
versealx-server backups list [--config <file>]
versealx-server backups verify [<backup>] [--sample <n>] [--config <file>]
versealx-server backups test [--config <file>]
versealx-server backups residency-exceptions [add <organisation> --reason "<why>" | remove <organisation>] [--config <file>]
versealx-server storage status [--json]
versealx-server storage organisations [--json]
versealx-server storage kinds [--tenant <tenant>] [--json]
versealx-server storage scrub status [--json]
versealx-server storage scrub now [--tenant <tenant>]
versealx-server try message --from <address> --to <address>[,...] [--ip <address>] [--helo <name>] [--tls] [--file <message.eml>] [--json]
key writes a new backup key to the file, readable only by its owner, and never over an existing file. list prints the daily backups [backup] to holds, newest first. verify reads one back — every record and every message body, or --sample of them — the newest if none is named, and prints <backup> reads back whole: <n> records, <n> blobs checked. None of them opens the store. See Daily backups.
residency-exceptions lists the organisations whose daily backups may rest outside their residency. add records one with the reason, and remove holds that organisation’s backups to its residency again. Each change is written to the installation’s audit log. See Backups and residency.
cluster
versealx-server cluster status | nodes [--json] | sites [--json] | node <name> [--json] | forget <name> | drain <name> | undrain <name>
versealx-server cluster upgrade status [--json]
versealx-server cluster upgrade --to <release> --channel <channel> [--without-backup] | --resume | --abort
versealx-server cluster finalize --to <format>
versealx-server store move --to <sqlite file | postgres://…> [--live] [--max-hold <seconds>] [--resume] [--apply] | --abandon | status
versealx-server store test <sqlite file | postgres://…>
versealx-server blobs test <directory | s3://bucket> [--endpoint <url>] [--region <region>]
versealx-server dr status
versealx-server dr follow [--server <primary>] [--once]
versealx-server dr switchover [--server <primary>] [--max-hold <seconds>]
versealx-server dr promote [--server <old primary>]
versealx-server dr fence [--epoch <n>]
versealx-server dr step-down
versealx-server dr drill [--into <file>] [--keep]
versealx-server dr follow --automatic
versealx-server dr hold
versealx-server dr take-key
versealx-server dr approve --epoch <n>
versealx-server witness serve --data <directory> --site <name>=<link directory>@<address> --site <name>=<link directory>@<address> [--approvals]
versealx-server dr dns plan --type cloud|two-premises|hybrid|single [--provider route53|cloudflare|azure|google] [--domain <d>] [--name <mx host>] [--primary <address>] [--standby <address>]
versealx-server dr dns check --domain <d> --leader <address>
versealx-server dr dns watch --name <host> --expect <address> [--for <seconds>]
versealx-server link invite --name <name> [--address <url>] [--names <a,b>] [--file <path>]
versealx-server link accept <code> [--name <name>] [--address <url>] [--names <a,b>]
versealx-server link files <name> --dir <directory>
versealx-server link renew <name> [--dir <directory>]
versealx-server console serve --from <directory> [--port <n>]
versealx-server link list | remove <name>
versealx-server blobs move --to <directory | s3://bucket> [--endpoint <url>] [--region <region>] [--from <place>] [--apply] | --delete-source
cluster status, nodes and node show the cluster’s nodes, and drain, undrain and forget take one out of service, put it back, or remove a gone one. See Nodes of a cluster. store move and blobs move move the store and the mail while the node serves; see Moving the store and the mail. cluster upgrade status lists the nodes sharing the store, with their releases and the store formats they read. cluster finalize switches the cluster to writing a newer store format once every node reads it. See The store’s format.
upgrade
versealx-server upgrade --channel <channel> --check
versealx-server upgrade --channel <channel> --snapshot <directory> [--config <file>]
versealx-server upgrade --rollback
versealx-server upgrade review [--json] [--backup <backup or snapshot>] [--config <file>]
versealx-server upgrade prepare [--backup <backup or snapshot>] [--config <file>]
versealx-server upgrade decide <change> adopt|keep [--config <file>]
versealx-server upgrade status [--config <file>]
--check says what the channel offers, the last day the running release is supported and the security fixes staying on it goes without, and changes nothing. With --snapshot, the release is fetched and checked against its signature, the store is snapshotted, the binary swapped, the store prepared by the new binary and the node checked by its doctor; the old binary comes back if either fails. --rollback puts the previous binary back.
review lists what the release changes that somebody could notice, whom each change touches and what stops the upgrade, and changes nothing. prepare keeps the old behaviour for every organisation that has not decided and records that the store is ready; a change that cannot be undone needs --backup. decide answers the installation’s own changes; an organisation’s are its administrators’. status lists every decision. See Upgrades and the changes they bring.
catalogue
versealx-server catalogue
Prints the list of capabilities this build of the server knows about, one per line, and the catalogue’s version. It is informational and reads no configuration.
Something unclear or out of date on this page? Tell us.