Skip to content

kubectl plugin (`kubectl kopiur`)

Kopiur ships a kubectl plugin that wraps the day-to-day operations, so you do not have to hand-write CR YAML for routine tasks. It suspends and resumes resources, inspects snapshots, triggers backups and restores, runs maintenance, browses snapshot contents and reads files out of them, and migrates from VolSync.

To see these commands in the context of a full install-to-restore journey, follow the Complete walkthrough.

The plugin is a single static binary, shipped as kopiur. kubectl discovers plugins by binary name: any executable called kubectl-kopiur on your PATH makes kubectl kopiur … work. krew creates that link for you, and Homebrew installs the standalone kopiur command instead. Having both installed never causes a collision.

The plugin talks to the cluster with the same configuration kubectl uses, so $KUBECONFIG, ~/.kube/config, or in-cluster credentials. It needs nothing besides API-server access.

Command What it does Page
snapshot now Run a SnapshotPolicy immediately (a manual Snapshot CR) Backups, restores & logs
restore The Restore CRD’s source × target matrix as one command line Backups, restores & logs
logs Stream a Snapshot/Restore mover Job’s logs Backups, restores & logs
snapshots list A richer kubectl get snapshots (origin, kopia id, size, filters) Inspecting & browsing
ls / cat / download / browse Read snapshot contents without restoring Inspecting & browsing
session end End a warm browse session early Inspecting & browsing
status One-screen health overview Operations
doctor Diagnose an installation, exit 1 on failure Operations
maintenance run Trigger an out-of-band maintenance run Operations
suspend / resume Pause/unpause reconciliation declaratively Operations
migrate volsync Translate VolSync restic objects into kopiur manifests Migrating from VolSync

Install with krew. The plugin is in the official krew-index, so no extra index is needed:

Terminal window
$ kubectl krew install kopiur
$ kubectl kopiur --version

kubectl krew upgrade kopiur picks up new releases. Each release automatically opens a version-bump pull request against krew-index, and the new version is installable once that merges.

Or install with Homebrew. The release workflow publishes a cask to home-operations/homebrew-tap from the same release assets, covering macOS and Linux on amd64 and arm64. Brew installs the standalone kopiur command rather than the kubectl-kopiur shim, so it coexists with a krew install of the same plugin:

Terminal window
$ brew install home-operations/tap/kopiur
$ kopiur --version

brew upgrade picks up new releases.

Without krew or Homebrew, use the release assets. Every GitHub release attaches per-platform archives named kubectl-kopiur_<version>_<os>_<arch>.tar.gz, for linux and darwin on amd64 and arm64, and the Linux binaries are fully static musl builds. Each archive ships with a .sha256 checksum, an SBOM, and a keyless Cosign signature.

Put the archive’s kopiur binary on your PATH, named kubectl-kopiur if you want kubectl discovery, or left as-is for the standalone command.

From source, with the repo checked out and mise installed:

Terminal window
$ mise run build
$ install -m 0755 target/debug/kopiur ~/.local/bin/kubectl-kopiur

Stand up a small playground that the rest of the CLI pages build on, then prove the plugin can see it with doctor.

The playground is one apply-ready bundle, deploy/examples/tryit/cli-playground.yaml. It contains a media Namespace, a PVC seeded with a config/app.yaml file and a multi-MB blob, the backend Secret, an S3 Repository called nas, and a SnapshotPolicy plus SnapshotSchedule called nightly. It deliberately has no Snapshot, because the other CLI arcs create those.

This is the shared starting point. Every CLI page’s “Try it end-to-end” assumes you have applied this bundle and that the repository is Ready.

1. Apply the playground. Fill in the AWS_* and KOPIA_PASSWORD REPLACE_ME values first, then apply and wait for the repository:

Terminal window
$ kubectl apply -f deploy/examples/tryit/cli-playground.yaml
$ kubectl -n media wait --for=condition=Ready repository/nas --timeout=2m
$ kubectl -n media wait --for=condition=complete job/seed-app-data --timeout=2m

2. Install the plugin with krew:

Terminal window
$ kubectl krew install kopiur
$ kubectl kopiur --version

3. Prove the install with doctor (deep). It exits 0 when all nine checks pass:

Terminal window
$ kubectl kopiur doctor -n media
ok CRDs installed
ok controller running
ok webhook running
ok webhook admission (live dry-run probe)
ok repositories ready
ok credential secrets present
ok no blocked or stuck work
ok no recent failed snapshots/restores
ok recent warning events
9 check(s): 0 failed, 0 warning(s)
$ echo $?
0

A non-zero exit, plus a FAIL line with why: and fix:, means something needs attention. See doctor for the full check list and for how a restricted kubeconfig degrades to warnings.

From here, follow any CLI page’s “Try it end-to-end” against this same media playground: take a backup and restore it, browse a snapshot’s files, run day-2 operations, or migrate from VolSync.

Every subcommand accepts the same connection and output flags kubectl uses:

Flag Meaning
--kubeconfig PATH Use this kubeconfig instead of $KUBECONFIG / ~/.kube/config.
--context NAME Use this kubeconfig context instead of the current one.
-n, --namespace NS Operate in this namespace (default: the context’s namespace).
-A, --all-namespaces List across all namespaces (list commands).
-o, --output FORMAT table (default), wide, yaml, json, or name.
-v / -vv Debug / trace diagnostics on stderr (KOPIUR_LOG accepts a full filter).

-o yaml and -o json always emit the exact Kubernetes objects, and a v1/List for list commands. The output is therefore ready to pipe into kubectl apply, jq or yq; the table is just one rendering of the same data.