Portunus
CLI Reference

portunus-server

Every subcommand of the control-plane binary, grouped by purpose.

portunus-server is the control-plane binary. Most subcommands hit the loopback HTTP API, so they require PORTUNUS_OPERATOR_TOKEN to be set.

export PORTUNUS_OPERATOR_TOKEN=<paste-token-here>

Since v1.1.0, Web UI login uses local passwords and server-side session cookies. PORTUNUS_OPERATOR_TOKEN is still for API/CLI automation only.

Run portunus-server --help (or portunus-server <subcommand> --help) for the current authoritative flag surface — the tables below are a high-level map.

Server lifecycle

SubcommandPurpose
serveStart the control plane (gRPC + operator HTTP + metrics)
gen-tokenPrint a fresh URL-safe-base64 token to stdout
bootstrap-superadmin --name <name>Legacy one-shot superadmin API token mint; bearer printed once
onboarding-tokenOffline rotation of the first-run setup token for an unbootstrapped store
portunus-server --data-dir ./srv serve

If you need non-default listeners or other overrides, place an optional ./srv/server.toml.

For normal first-run setup, start serve and use the setup token printed by the running server to complete Web UI onboarding. onboarding-token opens the store directly and serve rotates the token again on start, so it is mainly useful for offline maintenance and tests.

Clients

SubcommandPurpose
enroll-client <name> [--address <host>] [--ttl-secs <N>]Print a short-lived portunus-client enroll ... command. --ttl-secs defaults to 600; --address overrides the host clients dial
revoke <client_name>Revoke a client's bearer; immediate disconnect
list-clients [--format text|json]Show connected status for every provisioned client

Rules

SubcommandPurpose
push-rule <client> <listen_port> <target>Push a single-target TCP rule
push-rule … --protocol udpUDP variant
push-rule … --target host:port@<priority>Multi-target failover (repeat)
push-rule … --sni <pattern>TLS SNI routing
push-rule … --bandwidth-in-bps <N> etc.Rate-limit caps (v0.11+)
push-rule <client> <start>-<end> <host>:<start>-<end>Port-range rule
push-rule … --prefer-ipv6DNS targets, AAAA-first
remove-rule <rule_id>Drain + remove a rule
list-rules / list-rules --client <name>List rules (filter by client)
rule-stats <id>Aggregate per-rule counters
rule-stats <id> --per-portPer-port detail (range rules)
rule-stats <id> --per-targetPer-target detail (multi-target rules)

Users (v0.5+)

SubcommandPurpose
user-add <id> --display-name <name> [--role admin|user]Add a user (--role defaults to user)
user-listList users
user-get <id>Show user details
user-remove <id>Remove user (cascades grants + rules)
reset-password <user_id> [--temporary] [--password-stdin] [--keep-api-tokens]Local password recovery against the data dir

reset-password opens the SQLite store directly. Stop serve first if it is running against the same --data-dir.

portunus-server --data-dir /var/lib/portunus \
  reset-password admin --temporary

Use the actual superadmin user ID. For bootstrap-superadmin installs that ID is _superadmin; for Web onboarding it is the ID chosen during setup.

Without --temporary, the command prompts twice without echo. --password-stdin reads the new password from the first stdin line for automation. By default, password reset revokes Web sessions and active API tokens for that user; use --keep-api-tokens only when you are sure the reset is not incident response.

Credentials

SubcommandPurpose
credential-issue <user_id> --label <label>Issue a bearer token
credential-list <user_id>List credentials for a user
credential-revoke <user_id> <credential_id>Revoke a credential
credential-rotate <user_id> <credential_id>Rotate; old token 401s

Grants

SubcommandPurpose
grant-add --user-id <id> --client <name> --listen-port-start <N> --listen-port-end <N> --protocols <tcp,udp>Add a grant
grant-listList grants
grant-revoke <grant_id>Revoke a grant (cascades dependent rules)

Rate limiting (v0.11+)

SubcommandPurpose
owner-cap set <client> <owner> [--bandwidth-in-bps …]Set per-owner envelope
owner-cap get <client> <owner>Read per-owner envelope
owner-cap list <client>List all owner envelopes on a client
owner-cap delete <client> <owner>Remove an envelope

Pre-flight rejects an empty set envelope with exit 3 + validation.rate_limit_no_caps_provided.

Storage (v0.8+)

SubcommandPurpose
backup --out <path>Online SQLite backup (WAL-aware)
restore --in <path> [--force]Restore a backup; runs schema migrations
reset --confirmWipe state.db + sidecar files
audit prune --before <RFC3339> [--dry-run]Prune the durable audit table

Exit codes

CodeMeaning
0Success
1Generic error (config, IO, …)
2Validation error
3Pre-flight validation (e.g. validation.rate_limit_no_caps_provided)
4PORTUNUS_OPERATOR_TOKEN missing
6Activation failed (e.g. port_in_use)
8User not found for local password recovery
75Store in use by another process
78Schema-version too new (downgrade attempt)

(See per-subcommand --help for the complete code table.)

Common environment variables

VariablePurpose
PORTUNUS_OPERATOR_TOKENBearer for every operator subcommand
RUST_LOGStandard tracing-subscriber env-filter

On this page