Skip to Content

Commands Reference

Global Options

These flags are accepted by every command:

OptionDescription
-v, --verboseDetailed logging output
-q, --quietMinimal 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-envFallback 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 services

Initialization

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 init

Version

jiji version

Show the compiled jiji version.

jiji version

jiji 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
OptionDescription
--checkReport 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)
OptionDescription
--no-cacheBuild without using the cache
--push / --no-pushPush 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
OptionDescription
--buildBuild images before deploying
--no-cacheBuild without cache (only relevant with --build)
--skip-proxySkip jiji-proxy route activation
-y, --yesAuto-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-lockReplace 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
OptionDescription
-y, --yesSkip the confirmation prompt
--rotate-keyForce a fresh WireGuard keypair on the targeted hosts, fencing out their old identity
--importOnce a targeted host’s agent is running, assess it and import any pre-existing container as historical (Stopped) catalog history
--import-dry-runPreview --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:

  1. JIJI_AGENT_BINARY - an explicit local override. An invalid path here is always a hard failure, never a silent fallback to the next step.
  2. A jiji-agent binary already sitting next to the running jiji (the case for mise install and in-repo dev builds).
  3. 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 sha256 checksum 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
OptionDescription
-y, --yesSkip 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 jiji requires) - 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
OptionDescription
--interactiveAttach a PTY even when a command is given (requires exactly one matched host)
--sequentialWith 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
OptionDescription
-y, --yesSkip the destructive confirmation prompt
--volumesAlso remove jiji-owned named volumes for this project
--dry-runPrint 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 plan

Shows 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 web1

Idempotent, 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 web1

jiji 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
OptionDescription
--jsonEmit one JSON object per server

jiji network compact

Compact each selected host’s superseded replicated operation history.

jiji network compact

jiji 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
OptionDescription
--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
OptionDescription
--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
OptionDescription
--input <PATH>Path to the encrypted backup to recover from
--passphrase-file <PATH>File containing the encryption passphrase
-y, --yesConfirm 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 machine

jiji 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-remote

jiji registry teardown

Remove the jiji-managed local registry container.

jiji registry teardown jiji registry teardown --dry-run # Show what would be removed
OptionDescription
-y, --yesSkip the destructive confirmation prompt
--dry-runShow 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 web1

jiji 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
OptionDescription
-n, --linesNumber of lines to show
-s, --sinceShow logs since this timestamp or relative duration
-g, --grepFilter log lines
-f, --followFollow 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
OptionDescription
-n, --linesNumber of lines to show
-s, --sinceShow logs since this timestamp or relative duration
-g, --grepFilter log lines
--grep-optionsExtra flags passed to grep (e.g. -i for case-insensitive)
-f, --followFollow logs (requires exactly one target)
--container-idShow 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
OptionDescription
--lock-timeout <SECONDS>Wait up to this many seconds for an existing lock to clear (default: 300)
--force-lockReplace 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 api

A 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.

OptionDescription
--lock-timeout <SECONDS>Wait up to this many seconds for an existing lock to clear (default: 300)
--force-lockReplace 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
OptionDescription
-y, --yesSkip the destructive confirmation prompt
--volumesAlso 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-lockReplace 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
OptionDescription
N (positional)Set the runtime desired instance count on each of the service’s servers:
--resetReturn to the configured scale: value
--dry-runPrint placement and mutations without changing state
-y, --yesSkip 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 worker

The 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 worker

The 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
OptionDescription
--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, --followFollow 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
OptionDescription
--followStream 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
OptionDescription
-r, --retainNumber 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 caution

Shows [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 locked

jiji 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
OptionDescription
--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 --json

jiji 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
OptionDescription
-n, --linesNumber of entries to show per server (default: 20)
-g, --grepFilter entries by action or message (substring match)
--statusFilter by status: success or failed
--jsonOutput entries as newline-delimited JSON, or one structured object with --stats
--statsShow overall, per-action, and per-server success-rate and duration statistics
-s, --sinceLimit statistics to a relative window such as 30m, 12h, or 7d (requires --stats)
-f, --followFollow 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 staging

Deploy a specific service to a specific host

jiji deploy -S api -H web1

View logs with filtering

jiji service logs -S api --since 1h --grep "ERROR" --follow

Execute 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 api

View recent failed deployments

jiji audit --status failed

Force acquire a stuck project-maintenance lock

jiji lock acquire "Taking over stuck network maintenance" --force

Release a stuck replica lock without waiting on the project lock

jiji lock release --replica <replica-id>
Last updated on