Commands Reference
Global Options
These flags are accepted by every command:
| Option | Description |
|---|---|
-v, --verbose | Detailed logging output |
-q, --quiet | Minimal output (suppress host headers and extra messages) |
-c, --config <path> | Path to config file |
-e, --environment <env> | Use environment-specific config (e.g. staging -> jiji.staging.yml) |
--version <version> | Run against a specific app version (e.g. jiji deploy --version 1.2.3) |
-H, --hosts <pattern> | Target specific hosts instead of all (comma-separated, supports wildcards) |
-S, --services <pattern> | Target specific services instead of all (comma-separated, supports wildcards) |
--host-env | Fallback to host environment variables when secrets aren’t found in .env files |
Wildcard Patterns
Host and service filters support wildcards:
jiji deploy -H "web*" # All hosts starting with "web"
jiji deploy -S "*-backend" # All services ending with "-backend"
jiji deploy -H "prod*" -S "api" # Combine filters
jiji deploy -S "api,worker" # Multiple servicesInitialization
jiji init
Create a configuration stub at .jiji/deploy.yml. Jiji derives a stable /24
management range and /16 container range from project:. The generated file
omits network: because most projects do not need an override.
jiji initVersion
jiji version
Show the compiled jiji version.
jiji versionjiji update
Detect and install a newer jiji binary release. Config-free, like init
and version — this never touches remote servers, jiji-agent, or
jiji-proxy.
jiji update # Update to the latest release
jiji update --check # Report available versions without installing
jiji update --release v1.2.3 # Pin or roll back to a specific release| Option | Description |
|---|---|
--check | Report the current and latest version without changing anything |
--release <version> | Install a specific release instead of latest (also the rollback path) |
Downloads the matching platform artifact and its .sha256 checksum, rejects
a mismatch, and installs atomically (temp file on the same filesystem, then
rename) preserving the existing binary’s permissions. After updating, run
jiji server upgrade -e <environment> for each
environment configuration to bring jiji-agent and jiji-proxy up to date
on your servers.
Build
jiji build
Build and push images for services with build: configured.
jiji build
jiji build -S api # Build a specific service
jiji build --no-cache # Build without cache
jiji build --no-push # Build without pushing (single-architecture only)| Option | Description |
|---|---|
--no-cache | Build without using the cache |
--push / --no-push | Push built images (default: push) |
Deploy
jiji deploy
Deploy configured services across their target servers. Rolling services keep
the healthy version serving until its replacement passes health checks.
stop_first services trade that for a brief stop-then-start window. A
service with a fixed host-port binding needs stop_first too, or its
deploys fail outright rather than degrading gracefully - see
Stateful Services.
jiji deploy
jiji deploy --build # Build images before deploying
jiji deploy --build --no-cache # Build without cache before deploying
jiji deploy --version 1.2.3 # Deploy a specific version
jiji deploy -S "api,worker" # Deploy specific services
jiji deploy -H "prod*" # Deploy to matching hosts
jiji deploy -e production # Use jiji.production.yml
jiji deploy -y # Skip the confirmation prompt| Option | Description |
|---|---|
--build | Build images before deploying |
--no-cache | Build without cache (only relevant with --build) |
--skip-proxy | Skip jiji-proxy route activation |
-y, --yes | Auto-confirm the deployment plan; required when running non-interactively (e.g. CI/CD) |
--lock-timeout <SECONDS> | Wait up to this many seconds for an existing lock to clear (default: 300) |
--force-lock | Replace an existing deployment lock instead of waiting for it |
--wait-for-peers <N> | After a successful deploy, best-effort check up to N other peers’ catalogs for the new deployment (never blocks past a short bound, never affects the exit code) |
jiji deploy prints the deployment plan (project, environment, target
servers/endpoints, and the flags above) and asks for confirmation before
doing anything - before build, mesh reconciliation, or any mutating SSH
connection. -y/--yes skips the prompt. Without it and without a
real terminal attached, jiji deploy exits with an error instead of
hanging on a prompt nothing can answer - always pass -y in CI/CD.
After confirmation, jiji deploy locks and connects only the selected
replica owners plus eligible ingress owners (see
Deployment Locks below), not every configured server.
Service deployment does not recompile or reconcile the WireGuard mesh
unless a targeted host is actually stale. Locks are released after the
deploy succeeds or fails.
Server Management
jiji server setup
Install or reconcile the container engine and complete private network on each server. Existing Podman installations older than the required 5.8.4 are upgraded.
jiji server setup
jiji server setup -H "web*" # Only web servers
jiji server setup --rotate-key # Force a fresh WireGuard keypair on the targeted hosts
jiji server setup --import # Seed pre-existing containers as historical catalog history
jiji server setup --import-dry-run # Preview --import without committing anything| Option | Description |
|---|---|
-y, --yes | Skip the confirmation prompt |
--rotate-key | Force a fresh WireGuard keypair on the targeted hosts, fencing out their old identity |
--import | Once a targeted host’s agent is running, assess it and import any pre-existing container as historical (Stopped) catalog history |
--import-dry-run | Preview --import without committing anything |
On Debian and Ubuntu, jiji installs a pinned
mgoltzsche/podman-static
5.8.4 bundle. This is an unofficial, single-maintainer distribution, so it
has a different supply-chain trust boundary from distro packages. Jiji
verifies the pinned archive checksum before installing it.
Every run also reconciles membership: it compares each target’s freshly
observed WireGuard public key and endpoint against its last known record.
Endpoint-only drift bumps the record’s revision, while a changed key fences
a new owner epoch. Any server still marked active in the gathered mesh view
but no longer listed in servers: is tombstoned. Both are gated by
confirmation unless -y/--yes is passed, and the command bails with an
actionable message instead of hanging when there is no TTY and no --yes.
--import, once each targeted host’s agent is up, first prints a read-only
assessment (legacy runtime, enrollment, catalog count, importable, migrated,
or orphaned) and then one-way seeds any pre-existing container as
historical (Stopped) catalog history. It never marks anything active,
never allocates an address lease, and never touches a replica that already
has a live catalog record: a normal jiji deploy remains the only way to
actually bring a service up on the dynamic-lease runtime. --import-dry-run
prints the same plan without committing it.
There is no standalone assess, import, decommission,
update-endpoint, rotate-key, or replace command. jiji server setup
absorbs all of it.
Agent installation
jiji server setup also installs jiji-agent, the per-project systemd
service that owns WireGuard repair, DNS, the service catalog, and container
reconciliation on that host. Jiji resolves which binary to install, in
order:
JIJI_AGENT_BINARY- an explicit local override. An invalid path here is always a hard failure, never a silent fallback to the next step.- A
jiji-agentbinary already sitting next to the runningjiji(the case formise installand in-repo dev builds). - The default for a release install: a host-side script that downloads
the matching-version agent directly onto each server from the GitHub
release and verifies it against a published
sha256checksum before installing it.
Set JIJI_AGENT_VERSION to pin a different release tag than the running
CLI’s own version, or JIJI_RELEASE_BASE_URL to fetch from a self-hosted
mirror.
jiji server upgrade
Bring jiji-agent and the shared jiji-proxy container on selected servers
up to the versions the local jiji binary requires, after running
jiji update. This replaces the manual sequence of re-running
jiji server setup, conditionally running jiji proxy restart, and then
jiji network diagnostics.
jiji server upgrade
jiji server upgrade -H "web*"
jiji server upgrade -y| Option | Description |
|---|---|
-y, --yes | Skip the confirmation prompt |
For each selected server, jiji reads the running jiji-agent version (over
its own socket) and the running jiji-proxy version (jiji-proxy version
inside the container), and compares both against the versions the local
jiji binary was built against:
- Outdated - the agent binary is replaced and jiji-proxy is recreated with the current image.
- Current - the agent’s configuration, systemd unit, and membership are still refreshed (this is a normal, idempotent no-op most of the time); jiji-proxy’s daemon configuration is refreshed without an interruption.
- Ahead (a server running something newer than this
jijirequires) - never touched. Jiji does not downgrade a component that’s ahead of what the local binary asks for. - Unavailable (unreachable host, or a component that was never installed) - skipped and reported; the command exits non-zero if this happens anywhere.
Component versions are read and compared per host, so one host’s outdated
proxy never blocks another host’s already-current agent from having its
configuration refreshed. jiji server upgrade finishes by running
jiji network diagnostics against the same selection.
-S/--services is rejected: this command upgrades host-level components
shared across every service on a host, not per-service state.
Run jiji server upgrade again for each other environment configuration
(-e staging, -e production, …).
jiji server exec
Run a command on any number of selected servers, or attach an interactive shell to exactly one.
jiji server exec "docker ps" # Every configured server, concurrently
jiji server exec "docker ps" -H "web*" # Only matching servers
jiji server exec "docker ps" --sequential # One host at a time instead of concurrently
jiji server exec -H web1 # Interactive login shell
jiji server exec "top" -H web1 --interactive # Attach a PTY to a command| Option | Description |
|---|---|
--interactive | Attach a PTY even when a command is given (requires exactly one matched host) |
--sequential | With multiple matched hosts, run one at a time instead of concurrently |
An interactive session (no command given, or --interactive) is bound to
one local terminal, so -H/--hosts must resolve to exactly one server in
that case; a plain command has no such limit. Interactive sessions
automatically downgrade to non-interactive if stdin/stdout isn’t a real
TTY.
jiji server teardown
Remove jiji-managed applications and the private network from selected servers.
jiji server teardown
jiji server teardown -H web1 # Specific server
jiji server teardown --dry-run # Print the plan without changing anything
jiji server teardown --volumes # Also remove jiji-owned named volumes| Option | Description |
|---|---|
-y, --yes | Skip the destructive confirmation prompt |
--volumes | Also remove jiji-owned named volumes for this project |
--dry-run | Print the teardown plan without changing any host |
-S/--services is rejected - teardown always acts on the whole project.
Network Management
jiji network plan
Print the deterministic private network plan without changing any host.
jiji network planShows the exact per-project derived names (WireGuard interface, port, bridge, slug) for your configuration.
jiji network setup
Install or repair the complete private network.
jiji network setup
jiji network setup -H web1Idempotent, with rollback on partial failure. If configured CIDRs change, setup migrates the project bridge, reattaches its service containers and the shared proxy at their newly planned addresses, and refreshes proxy ingress and routes. A failed activation restores the previous bridge and addresses. jiji server setup and jiji deploy both call this same path when a host’s network is missing or stale.
jiji network catalog
Read-only inspection of a selected host’s locally replicated service catalog.
jiji network catalog
jiji network catalog -H web1jiji network diagnostics
Read-only inspection of a selected host’s agent self-healing, replication, quota, and component diagnostics.
jiji network diagnostics
jiji network diagnostics --json| Option | Description |
|---|---|
--json | Emit one JSON object per server |
jiji network compact
Compact each selected host’s superseded replicated operation history.
jiji network compactjiji network backup
Export an encrypted, operator-controlled backup of project identity, recovery
epoch, catalog and desired-state operations, and address claims. Membership is
not included: jiji server setup derives it again from the current
configuration before restore or recovery. The backup never includes host
WireGuard private keys or deployed secrets.
jiji network backup --output backup.enc --passphrase-file passphrase.txt| Option | Description |
|---|---|
--output <PATH> | Where to write the encrypted backup |
--passphrase-file <PATH> | File containing the encryption passphrase |
jiji network restore
Restore an encrypted backup into surviving hosts in the same recovery epoch.
jiji network restore --input backup.enc --passphrase-file passphrase.txt| Option | Description |
|---|---|
--input <PATH> | Path to the encrypted backup to restore |
--passphrase-file <PATH> | File containing the encryption passphrase |
jiji network recover
Recover a lost control plane into a new fenced recovery epoch. Destructive: advances the recovery epoch, so it always requires explicit confirmation.
jiji network recover --input backup.enc --passphrase-file passphrase.txt -y| Option | Description |
|---|---|
--input <PATH> | Path to the encrypted backup to recover from |
--passphrase-file <PATH> | File containing the encryption passphrase |
-y, --yes | Confirm the destructive epoch advancement |
Node decommissioning, endpoint updates, and key rotation are not separate
commands: re-running jiji server setup handles all of it. It reconciles
membership on every run (see above), and --rotate-key forces a fresh
WireGuard keypair on the targeted hosts.
Registry Management
jiji registry login
Authenticate the local machine and/or configured servers to the configured registry.
jiji registry login
jiji registry login --skip-local # Only authenticate servers
jiji registry login --skip-remote # Only authenticate the local machinejiji registry logout
Remove registry credentials from the local machine and/or configured servers.
jiji registry logout
jiji registry logout --skip-local
jiji registry logout --skip-remotejiji registry teardown
Remove the jiji-managed local registry container.
jiji registry teardown
jiji registry teardown --dry-run # Show what would be removed| Option | Description |
|---|---|
-y, --yes | Skip the destructive confirmation prompt |
--dry-run | Show what would be removed without changing anything |
Proxy Management
jiji proxy restart
Pull and recreate jiji-proxy on selected servers.
jiji proxy restart
jiji proxy restart -H web1jiji proxy logs
View jiji-proxy logs on selected servers.
jiji proxy logs
jiji proxy logs -H web1
jiji proxy logs --since 1h
jiji proxy logs --grep "error"
jiji proxy logs --follow # Requires exactly one host| Option | Description |
|---|---|
-n, --lines | Number of lines to show |
-s, --since | Show logs since this timestamp or relative duration |
-g, --grep | Filter log lines |
-f, --follow | Follow logs (requires exactly one host) |
Service Management
jiji service logs
Tail the Active catalog deployment for each selected replica.
jiji service logs
jiji service logs -S api
jiji service logs --lines 100
jiji service logs --since 30m
jiji service logs --grep "error"
jiji service logs --follow
jiji service logs -H web1 -S api| Option | Description |
|---|---|
-n, --lines | Number of lines to show |
-s, --since | Show logs since this timestamp or relative duration |
-g, --grep | Filter log lines |
--grep-options | Extra flags passed to grep (e.g. -i for case-insensitive) |
-f, --follow | Follow logs (requires exactly one target) |
--container-id | Show logs for an arbitrary container name instead of a configured service |
jiji service restart
Restart running services with the same Candidate, health, Active, proxy
reconciliation, and draining transaction as jiji deploy. The logical replica
ID stays stable, but the replacement gets a fresh deployment ID and address
lease. Jiji reuses the currently running image.
jiji service restart
jiji service restart -S api
jiji service restart -H web1| Option | Description |
|---|---|
--lock-timeout <SECONDS> | Wait up to this many seconds for an existing lock to clear (default: 300) |
--force-lock | Replace an existing lock on an affected replica |
jiji service rollback
Roll back services to a previously built image through the same
catalog-driven replacement strategy configured for a normal deploy. Requires
--version.
jiji service rollback --version 1.2.2
jiji service rollback --version 1.2.2 -S apiA build-configured service resolves the target from builder.registry +
project + service name (no rebuild, trusting the tag was already pushed by
a prior jiji build/jiji deploy --build). A static-image: service gets
--version applied the same way jiji deploy --version does.
| Option | Description |
|---|---|
--lock-timeout <SECONDS> | Wait up to this many seconds for an existing lock to clear (default: 300) |
--force-lock | Replace an existing lock on an affected replica |
jiji service remove
Retire selected catalog deployments, remove their containers and address leases, and reconcile proxy routes.
jiji service remove
jiji service remove -S api
jiji service remove --volumes # Also remove named volumes| Option | Description |
|---|---|
-y, --yes | Skip the destructive confirmation prompt |
--volumes | Also remove jiji-owned named volumes for selected services |
--lock-timeout <SECONDS> | Wait up to this many seconds for an existing lock to clear (default: 300) |
--force-lock | Replace an existing lock on an affected replica |
jiji service scale
Change the replicated desired instance count, per server, for exactly one service:
jiji service scale 4 -S web
jiji service scale 0 -S web
jiji service scale --reset -S web
jiji service scale 3 -S web --dry-run| Option | Description |
|---|---|
N (positional) | Set the runtime desired instance count on each of the service’s servers: |
--reset | Return to the configured scale: value |
--dry-run | Print placement and mutations without changing state |
-y, --yes | Skip confirmation |
-S must match exactly one service. -H is rejected: servers: is the
literal deploy target list already, so there’s no separate host filter to
apply. Interrupted scale operations are resumable by retrying the same
command.
jiji service cron list
Show configured cron jobs and their installation state.
jiji service cron list
jiji service cron list -S workerThe state is installed, not-deployed, or drifted. A drifted job has
configuration changes that a deploy did not install yet.
jiji service cron status
Show durable scheduler and run state from each assigned agent.
jiji service cron status
jiji service cron status -S workerThe output includes the owner, next run, last result, active run, and skipped overlap count.
jiji service cron logs
Show output for one job. This command requires one service and one cron name.
jiji service cron logs sync-reports -S worker
jiji service cron logs sync-reports -S worker --run <run-id>
jiji service cron logs sync-reports -S worker --lines 100
jiji service cron logs sync-reports -S worker --since 30m
jiji service cron logs sync-reports -S worker --follow| Option | Description |
|---|---|
--run <ID> | Show one retained run instead of the latest run |
-n, --lines <N> | Show this number of lines |
-s, --since <TIMESTAMP> | Show logs since a timestamp or relative duration |
-f, --follow | Follow the active run |
--follow cannot be combined with --run.
jiji service cron run
Start one configured job immediately. The manual run does not change the next scheduled time.
jiji service cron run sync-reports -S worker
jiji service cron run sync-reports -S worker --follow| Option | Description |
|---|---|
--follow | Stream output after the agent accepts the run |
An active run causes an overlap conflict because overlap: forbid is the
only supported policy. See Scheduled Jobs for the
full execution model.
jiji service prune
Clean up old container images for build-configured services (services with
only a static image: are never pruned).
jiji service prune
jiji service prune -S api
jiji service prune --retain 5 # Keep 5 versions instead of the configured default| Option | Description |
|---|---|
-r, --retain | Number of image versions to keep (default: the service’s configured retain, normally 3) |
Secrets
jiji secrets print
Print resolved secrets and their resolution status for debugging.
jiji secrets print
jiji secrets print -e production
jiji secrets print --show-values # Reveal actual values, use with cautionShows [SET]/[MISSING] for every secret-shaped reference in
configuration. environment.secrets, build.secrets,
builder.registry.password, ALL_CAPS references in SSH keys, ALL_CAPS
build-arg values, and proxy SSL cert references are resolved from
.env/host-env; SSH key passphrases and ${VAR} command interpolation are
scanned and reported for visibility only, since Jiji uses those values as
literal configuration rather than resolving them.
Deployment Locks
Locking scope matches what a command actually mutates, not the whole
project. jiji deploy, service restart/rollback/remove, and service scale each lock only the specific logical replicas they touch (plus a
shared proxy lock when a route on an ingress host is involved) - an
unrelated offline host or a different replica never blocks a targeted
operation. server setup/teardown lock the whole targeted host.
network setup/backup/restore/recover/compact use the
project-maintenance lock. server setup --import stays within the targeted
host-runtime locks that server setup already holds. Every automatic lock is
released on both the success and failure path of the command that took it.
jiji lock acquire/release default to that same whole-project scope -
not the per-replica scope a normal deploy uses, so acquiring the
project lock does not block an unrelated jiji deploy, service restart,
or service rollback; it only blocks other project-scoped commands
(network setup/backup/restore/recover/compact, and any other
jiji lock acquire). Use it to reserve a maintenance window around those
operations, or use jiji lock release --replica/--service/--scope to clear
a specific stuck finer-grained lock (see below) instead.
jiji lock acquire
jiji lock acquire "Network maintenance window"
jiji lock acquire "CI maintenance" --timeout 300 # Seconds to wait for an existing lock (default: 300)
jiji lock acquire "Emergency fix" --force # Force acquire even if already lockedjiji lock release
jiji lock release # Release the project-maintenance lock
jiji lock release --replica <replica-id> # Release one stuck logical-replica lock
jiji lock release --service <name> # Release one stuck service-scale lock
jiji lock release --scope host-runtime # Release a stuck host-runtime lock
jiji lock release --scope proxy # Release the host-global proxy lock| Option | Description |
|---|---|
--replica <REPLICA_ID> | Release the logical-replica lock for this replica ID instead of the project lock |
--service <NAME> | Release the service-scale lock for this service instead of the project lock |
--scope <host-runtime|proxy> | Release the named host-scoped lock instead of the project lock |
jiji lock status
jiji lock status
jiji lock status --jsonjiji lock show
jiji lock show-S/--services is rejected for every lock subcommand - locks are
host-scoped, not service-scoped.
Audit Trail
jiji audit
Show the per-server, append-only audit trail at .jiji/{project}/audit.log.
jiji audit
jiji audit --lines 50
jiji audit --grep deploy
jiji audit --status success
jiji audit --json
jiji audit --stats
jiji audit --stats --since 24h
jiji audit --stats --since 7d --json
jiji audit --follow # Requires exactly one host| Option | Description |
|---|---|
-n, --lines | Number of entries to show per server (default: 20) |
-g, --grep | Filter entries by action or message (substring match) |
--status | Filter by status: success or failed |
--json | Output entries as newline-delimited JSON, or one structured object with --stats |
--stats | Show overall, per-action, and per-server success-rate and duration statistics |
-s, --since | Limit statistics to a relative window such as 30m, 12h, or 7d (requires --stats) |
-f, --follow | Follow the audit trail as new entries are appended (requires exactly one host) |
Statistics read the full live project audit log from every selected server on
each invocation; no local cache is maintained. Entries without duration_ms
still count toward totals and success rates, but are excluded from the average
duration. The output reports timed-entry coverage so that distinction remains
visible. --stats cannot be combined with --lines or --follow. With
--stats --json, Jiji emits one structured object containing overall,
by_action, and by_server aggregates.
-S/--services is rejected - the trail is host-scoped, not
service-scoped. Current writers are deploy, service restart/rollback/remove/prune/scale, server setup/teardown/upgrade,
network setup/compact/restore, registry login/logout, proxy restart,
server exec, service cron run, jiji build (the builder.remote path
only), and lock acquire/release. proxy restart and server exec do not
hold a lock today, so their audit entries carry no lock scope.
A local build opens no SSH session, so it has no host to write an entry
through. registry teardown, local (non--H) registry login/logout,
and network recover are local-only operations with the same no-host
reasoning, and are unaudited by design, not by gap.
Examples
Deploy to staging
jiji deploy --build -e stagingDeploy a specific service to a specific host
jiji deploy -S api -H web1View logs with filtering
jiji service logs -S api --since 1h --grep "ERROR" --followExecute a command across all servers
jiji server exec "docker system prune -f"Roll back a failed release
jiji service rollback --version 1.2.2 -S apiView recent failed deployments
jiji audit --status failedForce acquire a stuck project-maintenance lock
jiji lock acquire "Taking over stuck network maintenance" --forceRelease a stuck replica lock without waiting on the project lock
jiji lock release --replica <replica-id>