Configuration
proxxx reads a single TOML file. Profiles, secrets, TLS, SSH, HITL, PBS, and alerts all live there.
File location
| Platform | Path |
|---|---|
| Linux | ~/.config/proxxx/config.toml |
| macOS | ~/Library/Application Support/dev.proxxx.proxxx/config.toml |
| Windows | %APPDATA%\dev\proxxx\proxxx\config.toml |
The path follows the directories crate's project-dirs convention (dev.proxxx.proxxx).
Minimum viable
url = "https://pve1.lan:8006/"
user = "root@pam"
auth = "token"
token_id = "proxxx"
token_secret = "00000000-0000-0000-0000-000000000000"
verify_tls = falseThat's enough for read-only and most write operations against a single cluster.
Auth modes
auth = "token" # API token (recommended — scoped, revocable)
auth = "password" # username/password ticket flow (legacy)For auth = "token", set token_id and one of: token_secret, token_secret_file, PROXXX_TOKEN_SECRET env, or store it in the keychain.
For auth = "password", set password, password_file, PROXXX_PASSWORD env, or keychain.
Secrets
The resolution order for token / password / PBS secret is:
- CLI flag (
--token-secret VALUE) — highest priority, takes precedence over everything else. - Environment variable —
PROXXX_TOKEN_SECRET,PROXXX_PASSWORD, orPROXXX_PBS_TOKEN_SECRET. - File reference —
token_secret_file = "/etc/proxxx/token". The file must be readable; mode 0600 is recommended (proxxx does not enforce, but flags non-0600 files in the audit log). - OS keychain — last resort. Service
proxxx, keytoken_secret/password/pbs_token_secret. Disabled if you build with--no-default-features.
Once loaded, secrets live in Zeroizing<String> — they are wiped from the heap on Drop . They are never written to logs.
TLS
verify_tls = true # default in production
verify_tls = false # accept self-signed (homelab)Setting verify_tls = false enables danger_accept_invalid_certs on the reqwest client AND mirrors the bypass into the WebSocket client used for serial console (wsterm::tls::dangerous_no_verify_config).
It does NOT disable SSH host key verification. SSH uses its own TOFU known_hosts at $XDG_CONFIG_HOME/proxxx/known_hosts (separate from ~/.ssh/known_hosts).
Profiles
Multiple clusters, one config:
default = "homelab"
[profiles.homelab]
url = "https://pve1.lan:8006/"
user = "root@pam"
auth = "token"
token_id = "proxxx"
token_secret = "00000000-0000-0000-0000-000000000000"
verify_tls = false
[profiles.prod]
url = "https://pve.example.org:8006/"
user = "ops@pve"
auth = "token"
token_id = "ci"
token_secret_file = "/etc/proxxx/prod-token"
verify_tls = trueSwitch with proxxx --profile prod ls nodes. The flat top-level profile (no [profiles.X]) is treated as the default if no default key is set.
SSH
For proxxx ssh <vmid>, proxxx perms, and the patching orchestrator:
[ssh]
key = "/home/fab/.ssh/proxxx_homelab" # ed25519 private key, no passphrase
host = "10.0.0.1" # default node for `proxxx perms`
port = 22 # optional, defaults to 22
user = "root" # optional, defaults to "root"
[ssh.guests."100"]
host = "10.10.10.100"
user = "fab"
[ssh.guests."200"]
host = "10.10.10.200"
key = "/home/fab/.ssh/k8s_master"SSH uses publickey only — no passphrase prompt, no agent. If your key is encrypted, set PROXXX_SSH_KEY_PASSPHRASE. The known_hosts file is TOFU on first connect with a warning log.
PBS
For proxxx pbs ...:
[pbs]
url = "https://pbs.lan:8007/"
user = "proxxx@pbs"
token_id = "reader"
token_secret = "00000000-0000-0000-0000-000000000000"
verify_tls = false
rate_limit = 10 # max requests/secondWARNING
PBS uses PBSAPIToken=user!tokenid:secret — note the colon between token id and secret. PVE uses =. If you copy a PVE-style header to PBS you'll get a 401 with no useful diagnostic.
Telegram (HITL + alerts)
[telegram]
bot_token = "123456:ABC..."
chat_id = -1001234567890Get bot_token from @BotFather, chat_id from any message metadata to your bot (e.g. via https://api.telegram.org/bot<token>/getUpdates).
HITL policies
[[policies]]
action = "delete" # delete | stop | restart | migrate | exec | move_disk | resize_disk
target = "tag:prod" # tag:<X> | <vmid> | *
require_approval = true
timeout_secs = 120 # default 120Multiple policies are evaluated in order; the first matching one wins. See HITL via Telegram.
Alerts
[[alerts]]
name = "node_down"
trigger = "node_offline"
threshold = 60 # seconds offline before firing
route = ["telegram", "ntfy:proxxx-prod"]
dedup_secs = 600 # don't re-fire within 10 minSee Alerts for the full predicate set.
Schema reference
Full type-by-type schema with defaults: Configuration schema.