Command Reference

Operator-oriented reference for Vaulthalla CLI command families and common examples.

Command Reference

This is an operator reference for the command families exposed through vh. Use vh help <namespace> on the host for the exact help text shipped by the installed version.

Global

CommandPurpose
vh helpShow root help.
vh help <namespace>Show help for a namespace or subcommand.
vh versionPrint the installed CLI version.
vh statusPrint runtime/service status.

Setup And Teardown

1vh setup assign-admin2vh setup set-super-admin-password3sudo vh setup db4sudo vh setup remote-db --host <host> --port 5432 --user <user> --database <name> --password-file <path>5sudo vh setup nginx --domain vault.example.com6sudo vh setup nginx --domain vault.example.com --certbot7sudo vh setup nginx --domain vaulthalla.dev --s3-domain s3.vaulthalla.dev --certbot-dns-cloudflare /etc/vaulthalla/certbot/cloudflare.ini8sudo vh teardown nginx9sudo vh teardown db10sudo vh setup caddy --domain <name> [--s3-domain <name>|none] [--internal] [--ca-scope <domain>]11sudo vh setup caddy --domain <name> --email <address> [--acme-staging]12sudo vh setup caddy --domain <name> --dns-cloudflare <credentials>13sudo vh setup caddy --domain <name> --cert <file> --key <file>14sudo vh setup caddy [--listen <address>] [--trust] [--hosts-entry] [--dry-run] [--status]15sudo vh teardown caddy [--purge]

setup db, setup remote-db, setup nginx and their teardowns are Linux commands; setup caddy and teardown caddy (alias https) are macOS commands, and each platform says so instead of running the other's. Every setup caddy option is described in Serve Vaulthalla With Caddy.

The --s3-domain form needs a Cloudflare API token in a root-only credentials file (dns_cloudflare_api_token = <token>). See S3 Gateway Setup.

setup assign-admin and setup set-super-admin-password are normal CLI commands. setup set-super-admin-password changes the web console password of the built-in admin account; only the local user bound as the super admin may run it, without sudo, and it removes the generated initial password file. The database, remote database, nginx, Caddy, and teardown commands are privileged lifecycle commands and must be run with sudo.

setup nginx checks for the generated initial admin password first. If it is still in use and its plaintext copy (/var/lib/vaulthalla/super_admin_initial_password) still exists, it offers to change the password, delete the file and keep the password, continue, or cancel. Run without a terminal, it warns and continues.

Users

Aliases include vh users, vh user, and vh u.

1vh user create <username> --role <role-or-id> [--email <email>] [--linux-uid <uid>]2vh user info <username-or-id>3vh user update <username-or-id> --name <new-name> --email <email> --role <role-or-id> --linux-uid <uid>4vh user delete <username-or-id>

The built-in super_admin role and user are protected from normal create, update, and delete operations.

Groups

1vh group create <name> [--desc <description>] [--linux-gid <gid>]2vh group info <name-or-id>3vh group update <name-or-id> --name <new-name> --desc <description> --linux-gid <gid>4vh group delete <name-or-id>5vh group user add <group> <user>6vh group user remove <group> <user>7vh group users <group>

Use groups when permissions should follow a team rather than an individual user.

Roles And Permissions

List supported permissions:

1vh permissions2vh permissions --type user3vh permissions --type vault

Admin roles:

1vh role admin list2vh role admin info <role>3vh role admin create <name> --manage-users --manage-vaults4vh role admin update <role> --audit-log-access5vh role admin delete <role>

Vault roles:

1vh role vault list2vh role vault info <role>3vh role vault create <name> --list --download --sync4vh role vault update <role> --share5vh role vault delete <role>

Admin permissions include user, group, role, vault, API key, encryption key, audit, and admin management capabilities. Vault permissions include list, create, download, delete, rename, move, share, sync, version, tag, metadata, file lock, access, and vault management capabilities.

API Keys

Aliases include vh api-key, vh aku, and vh ak.

1vh api-key list2vh api-key create <name> \3  --access <access-key> \4  --secret <secret-key> \5  --provider <provider> \6  --endpoint <url> \7  [--region <region>]8vh api-key info <name-or-id>9vh api-key delete <name-or-id>

Supported provider values include aws, cloudflare-r2, wasabi, backblaze-b2, digitalocean, minio, ceph, storj, and other.

Cloudflare R2 example:

1vh api-key create r2-main \2  --access <access-key> \3  --secret <secret-key> \4  --provider cloudflare-r2 \5  --endpoint https://<account-id>.r2.cloudflarestorage.com

The endpoint is required. The default region is auto.

Vaults

1vh vaults2vh vaults --local3vh vaults --s3 --limit 54vh vaults --json5vh vault info <id-or-name> [--owner <user-or-id>]6vh vault delete <id-or-name> [--owner <user-or-id>] [--now] [--delete-upstream | --keep-upstream] [--accept-key-loss] [--yes]7vh vault deleted [--json]8vh vault restore <id-or-name> [--owner <user-or-id>]

vault delete schedules the deletion: the vault disappears at once and vault restore brings it back until vaults.retention_window ends (default 5m); then its data is purged. --now purges right away and needs --yes (or a typed confirmation in a terminal). For S3 vaults, --delete-upstream also deletes the bucket's objects at purge time; the default keeps them, and keeping encrypted objects whose key was never exported needs --accept-key-loss. In a terminal, without --yes, the command asks instead. vault deleted lists pending, purging and purged vaults whose key is still kept. See Deleting And Restoring Vaults.

Create a local vault:

1vh vault create docs --local --desc "Team documents" --quota 50G --on-sync-conflict keep_both

Create an S3/R2 vault:

1vh vault create archive \2  --s3 \3  --api-key r2-main \4  --bucket vaulthalla-archive \5  --sync-strategy cache \6  --on-sync-conflict keep_local \7  --encrypt

Update a vault:

1vh vault update archive --sync-strategy sync --interval 15m

Vault Access

Assign a vault role to a user or group:

1vh vault role assign <vault> <role-id> --user alice2vh vault role assign <vault> <role-id> --group operators

Remove a vault role:

1vh vault role unassign <vault> <role-id> --user alice2vh vault role list <vault>

Add permission overrides for a path pattern:

1vh vault role override add <vault> --user alice --pattern "/finance/*" --download --disable2vh vault role override list <vault>3vh vault role override remove <vault> <override-id>

Sync

1vh vault sync <vault>2vh vault sync info <vault>3vh vault sync set <vault> --interval 15m4vh vault sync dry-run <vault>5vh vault sync inventory <vault> --file inventory.csv6vh vault sync events <vault> --file s3-events.json7vh vault sync reconcile <vault> --allow-list-scan

S3/R2 sync policy fields include strategy, conflict policy, interval, request budgets, and maximum remote-index age. See Sync and Request Budgets.

Sync Conflicts

Conflicts recorded under the ask policy (S3/R2 vaults) wait for a decision:

1vh sync resolve                                         # interactive session (needs a terminal)2vh sync resolve --list [--vault <vault>] [--json]3vh sync resolve <id>... --keep-local | --keep-remote [--json]4vh sync resolve --vault <vault> --all --keep-local | --keep-remote [--yes]

vh resolve takes the same arguments. Keep local uploads the local copy over the remote object; keep remote downloads the remote object over the local copy. A decision needs vault.sync.action.resolve_conflicts and Overwrite on the file, and is refused when either side changed since the conflict was recorded. Exit status is 2 when any conflict was not resolved; each one is reported with its reason. Without a terminal, --all needs --yes. See Resolving Conflicts.

Vault Files

1vh fs ls <vault> <path> [--owner <user>]2vh fs get <vault> <path> [-o <file>|-] [--owner <user>]3vh fs put <vault> <local-file|-> <path> [--overwrite] [--owner <user>]
Interim

vh fs is a stopgap for hosts without a usable mount (macOS today). It will be retired once the macOS FUSE identity adapter maps each local user to their own Vaulthalla identity on the mount; scripts should not treat it as permanent.

Reads and writes vault files without a mount, through the control socket. vh itself reads the local file (or standard input) for put and writes the local file for get; the daemon only ever sees the vault path. Permissions are the web console's: ls needs List, get needs Read, put needs Write on the new path (missing folders are created) and --overwrite needs Overwrite on the existing file. A path you can't read reports "permission denied" whether or not it exists.

get -o <file> writes to a temporary file next to <file> and replaces <file> only when every byte arrived and the stored file passed its integrity check; anything else leaves <file> as it was. Without -o, the bytes go to standard output, and vh refuses to write them to a terminal unless you pass -o -. A put stores nothing unless the whole file arrives, and a replacement fails if the file changed while uploading. Removing someone's access stops their running transfer.

Exit status: 0 done; 64 invalid arguments; 65 a damaged or incomplete transfer; 66 no such file (local or, where you can read, in the vault); 73 the vault path exists (no --overwrite) or the local output can't be written; 74 reading or writing a local file failed; 75 too many transfers in progress; 77 permission denied.

Vault Keys

1vh vault keys export <vault-or-all> --recipient <gpg-fingerprint> --output vaulthalla-vault-keys.json.gpg2vh vault keys export <vault-or-all> --output vaulthalla-vault-keys.json3vh vault keys rotate <vault-or-all> [--sync-now]

Unencrypted key exports are dangerous. Prefer --recipient and --output.

Internal Secrets

1vh secret set db-password /root/db-password2vh secret set jwt-secret /root/jwt-secret3vh secret export db-password --recipient <gpg-fingerprint> --output db-password.json.gpg4vh secret export jwt-secret --recipient <gpg-fingerprint> --output jwt-secret.json.gpg5vh secret export all --recipient <gpg-fingerprint> --output vaulthalla-secrets.json.gpg

secret set reads the secret value from the file path you pass.

S3 Gateway

1vh s3-gateway status2vh s3-gateway enable3vh s3-gateway disable4vh s3-gateway creds create laptop --scope user-access --json5vh s3-gateway creds list6vh s3-gateway creds create backup --scope vault-allowlist --default-role reader --selected-vault archive --json7vh s3-gateway creds scope backup set --scope vault-allowlist --default-role reader --selected-vault archive8vh s3-gateway creds role assign backup --vault archive --role contributor9vh s3-gateway creds role override add backup --vault archive --pattern "/private/*" --permission download --effect deny10vh s3-gateway creds role override list backup --vault archive11vh s3-gateway creds role override remove backup --vault archive 4212vh s3-gateway creds role revoke backup --vault archive13vh s3-gateway bucket create-local archive14vh s3-gateway bucket bind archive --vault 12 --mode local15vh s3-gateway budget set-key backup --monthly 5 --mode enforce --currency USD

Gateway authorization is RBAC-native. user_access inherits the principal user's Vaulthalla RBAC. vault_allowlist uses selected vaults plus a key-level default vault role and optional per-vault exceptions. global requires an admin principal and a key-level default vault role. Boolean credential scope flags and creds scope allow-vault remain compatibility shorthand only.

Pricing Budgets

1vh pricing budget list2vh pricing budget set-global --mode warn --max-daily 5 --currency USD3vh pricing budget set-provider aws-s3 --mode enforce --max-run 1 --max-daily 104vh pricing budget set-vault <vault> --mode report --max-run 0.255vh pricing budget status6vh pricing budget ledger --limit 1007vh pricing budget disable-vault <vault>

See Price Budgets.

Email

1vh email provider resend set2vh email provider ses set3vh email doctor4vh email test --dry-run5vh email test --send --to [email protected]6vh email history --limit 100

See Operator Emails.

Command Reference | Vaulthalla