Forkr gives you two ways to capture a box’s root filesystem.
  • Snapshots are point-in-time, read-only copies of a single box’s root. You restore them back onto the same box to roll its state forward or backward.
  • Bases are reusable, read-only templates. Every box you create is a writable clone of a base, so a base is how you bake an environment once and stamp out many boxes from it.
Both are btrfs copy-on-write snapshots of the root filesystem only.
Internally the API calls a box a “fork”, so you will see fork-flavored names in some CLI argument help. User-facing tools and this documentation call it a box. Both terms refer to the same thing.
Snapshots and bases capture the root filesystem. They do not capture data volumes. Files on a mounted data volume are unaffected by 4kr snapshot restore, and they are not copied when you save or build a base. To snapshot or back up volume data, see Data volumes.

Snapshots

A snapshot is a read-only copy of one box’s root filesystem at a moment in time. Snapshots are namespaced per box: you can only restore a snapshot onto the box it was taken from. There is no cross-box restore.

Create a snapshot

4kr snapshot create web-1
The snapshot name is auto-generated if you omit it. The server names snapshots v0, v1, v2, and so on, picking the next number above the highest existing one. To set the name yourself, pass it as a positional argument, and add a description with -m:
4kr snapshot create web-1 before-upgrade -m "Clean state before the Postgres 17 upgrade"
You can also pass the name with the --name flag, which overrides the positional argument. Creating a snapshot whose name already exists returns a conflict.
Snapshot names accept the pattern ^[a-zA-Z0-9_.-]+$. Lowercase a-z0-9- is still the recommended convention for consistency with box and host naming.

List snapshots

4kr snapshot list web-1
This prints a table with NAME, SIZE, CREATED, and DESCRIPTION columns. The created timestamp is RFC3339.

Restore a snapshot

4kr snapshot restore web-1 before-upgrade
Restore is destructive. It scales the box’s deployment to zero, deletes the live root filesystem, recreates a fresh writable filesystem from the snapshot, and scales back up. The box restarts, and the ephemeral /tmp and /run directories are wiped.
You can only restore a snapshot onto the box it was created from.

Diffing against a snapshot

Use 4kr diff to see what has changed in a box’s root filesystem since a snapshot. Diffs are root-only by construction.

Status

4kr diff status web-1
Without --against, the diff compares against the most recent snapshot. If the box has no snapshots, the command reports that you must specify one:
4kr diff status web-1 --against before-upgrade
The output lists added (+), modified (~), and deleted (-) paths, or No changes when the trees match.

A single file

4kr diff file web-1 /etc/nginx/nginx.conf
The path must be absolute. The status is one of added, deleted, modified, or unchanged; for a modified file, a unified diff is included.
File diffs are limited to 1 MB. Diffing a file larger than that returns an error. Use --against here too to pick a specific snapshot.

Bases

A base is a read-only template filesystem. Every box you create is a writable btrfs clone of a base:
4kr create new-box --base my-base
The default base is the box-base alias. Bases are read-only, so cloning never modifies the template.

List and inspect bases

4kr base list
This shows NAME, VERSION, SIZE, and CREATED. To inspect one base, including its versions and the build script of each:
4kr base show my-base
The output reports the name, the latest version, the version count, and a table with VERSION, KIND, TAG, BUILDER, PARENT, SIZE, and CREATED. The TAG column holds the build script’s sha256. You can filter versions by that sha256 with --tag:
4kr base show my-base --tag 3b1f9c2a8d4e5f60718293a4b5c6d7e8f9011223344556677889900aabbccddee

Building a base from a Dockerfile

4kr base build builds a base image from a Dockerfile in your current directory:
4kr base build dev-base
The build platform is fixed to linux/amd64, and the image is tagged <name>:latest (lowercased). Forkr auto-detects a container engine in order: docker, then podman, then nerdctl. On a non-x86_64 host using Docker, docker buildx is required to cross-build for linux/amd64. With buildx, Forkr runs docker buildx build --platform linux/amd64 ... --load; otherwise it runs a plain build --platform linux/amd64. After building, Forkr verifies the image architecture is amd64 and fails on a mismatch. Once built, Forkr exports the image’s root filesystem as a .tar.gz and uploads it as a new base.

Saving a base from a box

To turn a box’s current root filesystem into a reusable base, use 4kr base save with the new base name first and the source box second:
4kr base save my-base web-1
The server takes a read-only btrfs snapshot of the box’s on-disk root filesystem into a new base subvolume. The box’s root subvolume only needs to exist on disk — the box does not need to be running or ready, since the save reads the persistent filesystem directly.

Importing a base from a tarball

You can import a base directly from a .tar.gz of a root filesystem:
4kr base import my-base --file ./rootfs.tar.gz
The --file flag is required. To layer the tarball on top of an existing base, pass a parent:
4kr base import my-base --file ./rootfs.tar.gz --parent box-base
--parent is also available as -p. With a parent, Forkr snapshots that parent and extracts the tarball on top of it; without one, it extracts into a fresh empty filesystem. Either way, Forkr verifies the base architecture and sets the new base read-only.
On base import, -p means --parent, not --project. This command has no --project flag.

Versioning and aliases

Base names are versioned automatically. The first time you save or import a given name, Forkr writes a subvolume under that exact name and registers an alias pointing at it. Each later write of the same name gets a timestamp suffix like -v20260101120000, and the alias is updated to point at the newest version. When you run 4kr create --base my-base, Forkr resolves the alias to its latest version and clones that. To pin a box to a specific older version, pass the exact version name as --base.

Where to go next

Boxes

How boxes are created, cloned, and torn down.

Data volumes

Snapshot and back up volume data, which root snapshots and bases do not capture.

Environment

The runtime layout inside a box’s root filesystem.

API reference

The snapshot, diff, and base HTTP endpoints.