CRIU(8)

โœจ CRIU โœจ

okay bestie, welcome to the CRIU Manual, section 8 โ€” yes, criu(8), the one and only. this is the tool that checkpoints and restores running applications, and i'm gonna walk you through it like we're texting at 2am. ๐Ÿซถ


๐ŸŒธ NAME ๐ŸŒธ

criu โ€” checkpoint/restore in userspace ๐Ÿ’…


๐Ÿฆ‹ SYNOPSIS ๐Ÿฆ‹

criu command [option ...]

๐Ÿ’– DESCRIPTION ๐Ÿ’–

so like, criu is a tool for checkpointing and restoring running applications. it does this by saving their state as a collection of files (see the dump command) and creating equivalent processes from those files (see the restore command). the restore operation can be performed at a later time, on a different system, or both. literally time travel but for processes, no cap. โณโœจ


๐Ÿ”ฅ OPTIONS ๐Ÿ”ฅ

most of the long flags can be prefixed with no- to negate the option (example: --display-stats and --no-display-stats). so if you wanna be a hater, just add no-. ๐Ÿ’€

๐ŸŽ€ Common options ๐ŸŽ€

these ones are applicable to any command. universal besties. ๐Ÿซถ

  • -v[v...], --verbosity โ€” bump verbosity up from the default level. with the short option you can stack multiple vs, and each one cranks verbosity up by one. so -vvv is you screaming "tell me EVERYTHING". ๐Ÿ˜ญ
  • -vnum, --verbosity=num โ€” set the verbosity level to num directly. the higher the level, the more output is produced.

the following levels are available:

  • -v0 no output;
  • -v1 only errors;
  • -v2 above plus warnings (this is the default level);
  • -v3 above plus information messages and timestamps;
  • -v4 above plus lots of debug.
  • --config file โ€” pass a specific configuration file to criu. your own personal config, main character energy. ๐Ÿ‘‘
  • --no-default-config โ€” disable parsing of default configuration files. don't come for the defaults, they're doing their best. ๐Ÿ™ˆ
  • --pidfile file โ€” write root task, service or page-server pid into a file.
  • -o, --log-file file โ€” write logging messages to a file.
  • --display-stats โ€” during dump, as well as during restore, criu collects some statistics, like the time required to dump or restore the process, or the number of pages dumped or restored. this information is always saved to the stats-dump and stats-restore files, and can be shown using crit(1). the --display-stats option prints out this information on the console at the end of a dump or restore operation. numbers on the screen at the end = the lil dopamine hit. ๐Ÿ“Š
  • -D, --images-dir path โ€” use path as a base directory where to look for sets of image files.
  • --stream โ€” dump/restore images using criu-image-streamer. see https://github.com/checkpoint-restore/criu-image-streamer for detailed usage.
  • --prev-images-dir path โ€” use path as a parent directory where to look for sets of image files. this option makes sense in case of incremental dumps. (incremental? we love a glow-up arc. โœจ)
  • -W, --work-dir dir โ€” use directory dir for putting logs, pidfiles and statistics. if not specified, path from the -D option is taken.
  • --close fd โ€” close file descriptor fd before performing any actions.
  • -L, --libdir path โ€” path to plugins directory.
  • --enable-fs [fs[,fs...]] โ€” specify a comma-separated list of filesystem names that should be auto-detected. the value all enables auto-detection for all filesystems.
Note: this option is not safe, use at your own risk. auto-detecting a filesystem mount assumes that the mountpoint can be restored with mount(src, mountpoint, flags, options). when used, dump is expected to always succeed if a mountpoint is to be auto-detected, however restore may fail (or do something wrong) if the assumption for restore logic is incorrect. this option is not compatible with --external dev. โš ๏ธ
  • --action-script script โ€” add an external action script to be executed at certain stages. the environment variable CRTOOLS_SCRIPT_ACTION is available to the script to find out which action is being executed, and its value can be one of the following:
    • pre-dump โ€” run prior to beginning a dump
    • post-dump โ€” run upon dump completion
    • pre-restore โ€” run prior to beginning a restore
    • post-restore โ€” run upon restore completion
    • pre-resume โ€” run when all processes and resources are restored but tasks are stopped waiting for final kick to run. must not fail.
    • post-resume โ€” called at the very end, when everything is restored and processes were resumed
    • network-lock โ€” run to lock network in a target network namespace
    • network-unlock โ€” run to unlock network in a target network namespace
    • setup-namespaces โ€” run once root task has just been created with required namespaces. note it is an early stage of restore, when nothing is restored yet, except for namespaces themselves
    • post-setup-namespaces โ€” called after the namespaces are configured
    • orphan-pts-master โ€” called after master pty is opened and unlocked. this hook can be used only in the RPC mode, and the notification message contains a file descriptor for the master pty
    • query-ext-files โ€” called after the process tree is stopped and network is locked. this hook is used only in the RPC mode. the notification reply contains file ids to be added to external file list (may be empty).
  • --unprivileged โ€” this option tells criu to accept the limitations when running as non-root. running as non-root requires criu at least to have CAP_SYS_ADMIN or CAP_CHECKPOINT_RESTORE. for details about running criu as non-root please consult the NON-ROOT section. (yes you can run it without root, no it's not free, there's lore. ๐Ÿ“œ)
  • -V, --version โ€” print program version and exit.
  • -h, --help โ€” print some help and exit.

๐Ÿงš pre-dump ๐Ÿงš

performs the pre-dump procedure, during which criu creates a snapshot of memory changes since the previous pre-dump. note that during this criu also creates the fsnotify cache which speeds up the restore procedure. pre-dump requires at least -t option (see dump below). in addition, page-server options may be specified.

  • --track-mem โ€” turn on memory changes tracker in the kernel. if the option is not passed the memory tracker get turned on implicitly. sneaky lil auto-on, she's always watching. ๐Ÿ‘€
  • *--pre-dump-mode=mode* โ€” there are two mode to operate pre-dump algorithm. the splice mode is parasite based, whereas read mode is based on process_vm_readv syscall. the read mode incurs reduced frozen time and reduced memory pressure as compared to splice mode. default is splice mode.

๐Ÿ’… dump ๐Ÿ’…

performs a checkpoint procedure.

  • -t, --tree pid โ€” checkpoint the whole process tree starting from pid.
  • -R, --leave-running โ€” leave tasks in running state after checkpoint, instead of killing. this option is pretty dangerous and should be used only if you understand what you are doing.
Note: if task is about to run after been checkpointed, it can modify TCP connections, delete files and do other dangerous actions. therefore, criu can not guarantee that the next restore action will succeed. most likely if this option is used, at least the file system snapshot must be made with the help of post-dump action script.

in other words, do not use it unless really needed. bestie. i'm begging. ๐Ÿ˜ญ

  • -s, --leave-stopped โ€” leave tasks in stopped state after checkpoint, instead of killing.
  • --external type[id]:value โ€” dump an instance of an external resource. the generic syntax is type of resource, followed by resource id (enclosed in literal square brackets), and optional value (prepended by a literal colon). the following resource types are currently supported: mnt, dev, file, tty, unix. syntax depends on type. note to restore external resources, either --external or --inherit-fd is used, depending on resource type.
  • --external mnt[mountpoint]:name โ€” dump an external bind mount referenced by mountpoint, saving it to image under the identifier name.
  • --external mnt[]:flags โ€” dump all external bind mounts, autodetecting those. optional flags can contain m to also dump external master mounts, s to also dump external shared mounts (default behavior is to abort dumping if such mounts are found). if flags are not provided, colon is optional.
  • --external dev[major/minor]:name โ€” allow to dump a mount namespace having a real block device mounted. a block device is identified by its major and minor numbers, and criu saves its information to image under the identifier name.
  • --external file[mnt_id:inode] โ€” dump an external file, i.e. an opened file that is can not be resolved from the current mount namespace, which can not be dumped without using this option. the file is identified by mnt_id (a field obtained from /proc/pid/fdinfo/N) and inode (as returned by stat(2)).
  • --external tty[rdev:dev] โ€” dump an external TTY, identified by st_rdev and st_dev fields returned by stat(2).
  • --external unix[id] โ€” tell criu that one end of a pair of UNIX sockets (created by socketpair(2)) with the given id is OK to be disconnected.
  • --external net[inode]:name โ€” mark a network namespace as external and do not include it in the checkpoint. the label name can be used with --inherit-fd during restore to specify a file descriptor to a preconfigured network namespace.
  • --external pid[inode]:name โ€” mark a PID namespace as external. this can be later used to restore a process into an existing PID namespace. the label name can be used to assign another PID namespace during restore with the help of --inherit-fd.
  • --freeze-cgroup โ€” use cgroup freezer to collect processes.
  • --manage-cgroups โ€” collect cgroups into the image thus they gonna be restored then. without this option, criu will not save cgroups configuration associated with a task.
  • --cgroup-props spec โ€” specify controllers and their properties to be saved into the image file. criu predefines specifications for common controllers, but since the kernel can add new controllers and modify their properties, there should be a way to specify ones matched the kernel.

the spec argument describes the controller and properties specification in a simplified YAML form:

"c1":
 - "strategy": "merge"
 - "properties": ["a", "b"]
"c2":
 - "strategy": "replace"
 - "properties": ["c", "d"]

where c1 and c2 are controllers names, and a, b, c, d are their properties.

note the format: double quotes, spaces and new lines are required. the strategy specifies what to do if a controller specified already exists as a built-in one: criu can either merge or replace such.

for example, the command line for the above example should look like this:

--cgroup-props "\"c1\":\n - \"strategy\": \"merge\"\n - \"properties\": [\"a\", \"b\"]\n \"c2\":\n - \"strategy\": \"replace\"\n - \"properties\": [\"c\", \"d\"]"

(yes the escaping is giving unhinged, no i did not make it up, yes you have to copy it exactly. ๐Ÿ’€)

  • --cgroup-props-file file โ€” literally the same as --cgroup-props, except the spec gets read out of file instead of you typing it inline. ๐Ÿ’…
  • --cgroup-dump-controller name โ€” dump a controller by name only, and skip everything else that got auto-discovered (usually through /proc). Obsessed with this one when you just need CRIU to not touch some controllers. ๐Ÿ™ˆ
  • --cgroup-yard path โ€” instead of letting CRIU try to mount cgroups itself, you hand it a path to a directory that already has the cgroup yard built. Chef's kiss when you don't wanna grant CAP_SYS_ADMIN to CRIU. Rules of the game: for every cgroup mount there should be exactly one directory. If there's only one controller in that mount, the dir's name should just be the controller's name. If multiple controllers are comounted, the directory name should have them separated by a comma. ๐ŸŽ€

So like, if /proc/cgroups looks like this:

#subsys_name hierarchy num_cgroups enabled
cpu          1         1           1
devices      2         2           1
freezer      2         2           1

then you can create the cgroup yard with these commands:

mkdir private_yard
cd private_yard
mkdir cpu
mount -t cgroup -o cpu none cpu
mkdir devices,freezer
mount -t cgroup -o devices,freezer none devices,freezer
  • --tcp-established โ€” checkpoint established TCP connections. ๐Ÿค
  • --tcp-close โ€” don't dump the state of, or block, established tcp connections (including the connection that's once established but now closed). This is giving "we're not restoring these anyway" energy โ€” it's useful when tcp connections are not going to be restored. โœจ
  • --skip-in-flight โ€” this one skips in-flight TCP connections. If any TCP connections that are not yet completely established get found, criu ignores these connections, rather than erroring out. The TCP stack on the client side is expected to handle the re-connect gracefully. no cap, that's on the client bestie ๐Ÿ’€
  • --evasive-devices โ€” use any path to a device file if the original one is inaccessible. She's flexible like that. ๐Ÿ’…
  • --page-server โ€” send pages to a page server (see the page-server command). ๐Ÿ“ฎ
  • --force-irmap โ€” force resolving names for inotify and fsnotify watches. ๐Ÿ”
  • --auto-dedup โ€” deduplicate "old" data in pages images of a previous dump. Heads up: this option implies incremental dump mode (see the pre-dump command). โ™ป๏ธ
  • -l, --file-locks โ€” dump file locks. But bestie, listen: it is necessary to make sure that all file lock users are taken into dump, so it is only safe to use this for enclosed containers where locks are not held by any processes outside of the dumped process tree. โš ๏ธ
  • --link-remap โ€” allows linking unlinked files back, if possible. Note that this modifies filesystem during restore, so know what you're doing. ๐Ÿซฃ
  • --timeout number โ€” set a time limit in seconds for collecting tasks during the dump operation. The timeout is 10 seconds by default. โฐ
  • --ghost-limit size โ€” set the maximum size of deleted file to be carried inside image. By default, up to 1M file is allowed. Using this option lets you not put big deleted files inside images. The size argument may be postfixed with a K, M or G, which stands for kilo-, mega, and gigabytes, accordingly. ๐Ÿ‘ป
  • --ghost-fiemap โ€” enable an optimization based on fiemap ioctl that can reduce the number of system calls used when checkpointing highly sparse ghost files. This option is enabled by default, and it can be disabled with --no-ghost-fiemap. An automatic fallback to SEEK_HOLE/SEEK_DATA is used when fiemap is not supported. ๐ŸŒธ
  • -j, --shell-job โ€” allow one to dump shell jobs. This implies the restored task will inherit session and process group ID from the criu itself. This option also allows to migrate a single external tty connection, to migrate applications like top. If used with dump command, it must be specified with restore as well. ๐Ÿš
  • --cpu-cap [cap[,cap...]] โ€” specify CPU capabilities to write to an image file. The argument is a comma-separated list of:
    • none to ignore capabilities at all; the image will not be produced on dump, neither any check performed on restore;
    • fpu to check if FPU module is compatible;
    • ins to check if CPU supports all instructions required;
    • cpu to check if CPU capabilities are exactly matching;
    • all for all above set.

By default the option is set to fpu and ins. ๐Ÿง 

  • --cgroup-root [controller:]/newroot โ€” change the root for the controller that will be dumped. By default, criu simply dumps everything below where any of the tasks live. However, if a container moves all of its tasks into a cgroup directory below the container engine's default directory for tasks, permissions will not be preserved on the upper directories with no tasks in them, which may cause problems. ๐Ÿ™ƒ
  • --lazy-pages โ€” perform the dump procedure without writing memory pages into the image files and prepare to service page requests over the network. When dump runs in this mode it presumes that lazy-pages daemon will connect to it and fetch memory pages to lazily inject them into the restored process address space. This option is intended for post-copy (lazy) migration and should be used in conjunction with restore with appropriate options. ๐Ÿฆ‹
  • --file-validation [mode] โ€” set the method to be used to validate open files. Validation is done to ensure that the version of the file being restored is the same version when it was dumped. The mode may be one of the following:
    • filesize โ€” to explicitly use only the file size check all the time. This is the fastest and least intensive check. ๐ŸŽ๏ธ
    • buildid โ€” to validate ELF files with their build-ID. If the build-ID cannot be obtained, chksm-first method will be used. This is the default if mode is unspecified. ๐Ÿ†”
  • --network-lock [mode] โ€” set the method to be used for network locking/unlocking. Locking is done to ensure that tcp packets are dropped between dump and restore. This is done to avoid the kernel sending RST when a packet arrives destined for the dumped process. The mode may be one of the following:
    • iptables โ€” use iptables rules to drop the packets. This is the default if mode is not specified. ๐Ÿ”’
    • nftables โ€” use nftables rules to drop the packets. ๐Ÿ”—
    • skip โ€” don't lock the network. If --tcp-close is not used, the network must be locked externally to allow CRIU to dump TCP connections. โš ๏ธ
  • --allow-uprobes โ€” allow dumping when uprobes vma is present. When used on dump, this option is required on restore as well.

A uprobes vma is automatically created by the kernel once a uprobe is triggered. This mapping is not removed even once the uprobe is deleted. So, even if a process once had uprobes attached to it, and they're removed by the time the process is dumped, this option is still required because criu has no way of knowing whether there are active uprobes or not.

When using this option on restore, make sure the uprobes (if any) active on the dumped processes are still active. Otherwise, when execution reaches a uprobe'd location in any of the restored processes, that process will be sent a SIGTRAP.

As an example, say a uprobe is set at function foo in the executable of the process p_bar. Whenever execution in p_bar reaches function foo, the uprobe is triggered. If the uprobe has been triggered at least once, then the kernel will have created the uprobes vma. To dump p_bar, this option is necessary. After dumping, say the uprobe is deleted. Now, on restoring with this option, once execution reaches function foo, SIGTRAP will be sent to the restored p_bar. Unless it has a signal handler installed for SIGTRAP, it will be terminated and core dumped. ๐Ÿ’€

โœจ restore โœจ

Restores previously checkpointed processes. The glow-up moment fr fr. ๐Ÿ’–

  • --inherit-fd fd[N]:resource โ€” inherit a file descriptor. This option lets criu use an already opened file descriptor N for restoring a file identified by resource. This option can be used to restore an external resource dumped with the help of --external file, tty, pid and unix options.

The resource argument can be one of the following:

  • tty[rdev:dev]
  • pipe[inode]
  • socket[inode*]*
  • file[mnt_id:inode]
  • path/to/file
Note that square brackets used in this option arguments are literals and usually need to be escaped from shell. ๐Ÿš
  • -d, --restore-detached โ€” detach criu itself once restore is complete. bye bestie ๐Ÿ‘‹
  • -s, --leave-stopped โ€” leave tasks in stopped state after restore (rather than resuming their execution). ๐Ÿ›‘
  • -S, --restore-sibling โ€” restore root task as a sibling (makes sense only with --restore-detached). ๐Ÿ‘ฏ
  • --log-pid โ€” write separate logging files per each pid. ๐Ÿ“
  • -r, --root path โ€” change the root filesystem to path (when run in a mount namespace). This option is required to restore a mount namespace. The directory path must be a mount point and its parent must not be overmounted. ๐Ÿ—‚๏ธ
  • --external type[id]:value โ€” restore an instance of an external resource. The generic syntax is type of resource, followed by resource id (enclosed in literal square brackets), and optional value (prepended by a literal colon). The following resource types are currently supported: mnt, dev, veth, macvlan. Syntax depends on type. Note: to restore external resources dealing with opened file descriptors (such as dumped with the help of --external file, tty, and unix options), option --inherit-fd should be used. ๐Ÿ”Œ
  • --external mnt[name]:mountpoint โ€” restore an external bind mount referenced in the image by name, bind-mounting it from the host mountpoint to a proper mount point. ๐Ÿ“‚
  • --external mnt[] โ€” restore all external bind mounts (dumped with the help of --external mnt[] auto-detection). ๐ŸŒˆ
  • --external dev[name]:/dev/path โ€” restore an external mount device, identified in the image by name, using the existing block device /dev/path. ๐Ÿ’พ
  • --external veth[inner_dev]:outer_dev@bridge โ€” set the outer VETH device name (corresponding to inner_dev being restored) to outer_dev. If optional @bridge is specified, outer_dev is added to that bridge. If the option is not used, outer_dev will be autogenerated by the kernel. ๐ŸŒ‰
  • --external macvlan[inner_dev]:outer_dev โ€” restoring an image that's got a MacVLAN device inside it? Then bestie, you must use this one. It tells CRIU which outer_dev (an existing network device hanging out in the CRIU namespace) the restored inner_dev should get bound to. No option, no binding, no restore. ๐Ÿ’…
  • -J, --join-ns NS:{PID|NS_FILE}[,EXTRA_OPTS] โ€” restores the process tree inside a namespace that already exists. You can hand over the namespace as a PID or as an NS_FILE path (for example --join-ns net:12345 or --join-ns net:/foo/bar). Right now the supported values for NS are: ipc, net, time, user, and uts. This option does not do PID namespaces โ€” that's still possible, just via --external and --inheritfd. EXTRA_OPTS is optional and lets you set UID and GID for the user namespace (like --join-ns user:PID,UID,GID). ๐Ÿซถ
  • --manage-cgroups [mode] โ€” restores the cgroup configuration tied to a task, straight out of the image. Controllers are always restored in an optimistic way โ€” if it's already in the system, criu just reuses it, otherwise it creates it. โœจ

The mode can be one of these:

  • none โ€” don't restore cgroup properties at all, but the cgroup is required to already exist at the moment of the restore procedure.
  • props โ€” restore cgroup properties, and require the cgroup to pre-exist.
  • soft โ€” restore cgroup properties only if the cgroup was created by criu; otherwise don't restore properties. This is the default when mode is unspecified.
  • full โ€” always restore all cgroups and all their properties.
  • strict โ€” restore all cgroups and their properties from scratch, and require that they are not present in the system.
  • ignore โ€” don't deal with cgroups at all and just pretend they don't exist.
  • --cgroup-yard path โ€” instead of trying to mount cgroups in CRIU, you give it a path to a directory that already has a cgroup yard all set up. For more info, go look in the dump section. ๐ŸŽ€
  • --cgroup-root [controller:]/newroot โ€” changes the root cgroup the controller will be installed into. Leave the controller out and the root becomes the default for every controller you didn't specify.
  • --tcp-established โ€” restore previously dumped established TCP connections. Heads up, this implies the network was locked between the dump and restore phases, so the other side of the connection just notices a kind of lag. ๐Ÿ˜ญ
  • --tcp-close โ€” restore connected TCP sockets in the closed state.
  • --veth-pair IN=OUT โ€” the correspondence between the outside and inside names of veth devices.
  • -l, --file-locks โ€” restore file locks from the image. ๐Ÿ”ฅ
  • --lsm-profile type:name โ€” pick an LSM profile to be used during restore. The type can be either apparmor or selinux.
  • --lsm-mount-context context โ€” sets a new mount context to be used during restore.

This option will only replace existing mount context information with the one you specified. Mounts that don't have the context= option will not be changed.

So if a mountpoint was checkpointed with an option like

context="system_u:object_r:container_file_t:s0:c82,c137"

you can change it using

--lsm-mount-context "system_u:object_r:container_file_t:s0:c204,c495"

and the result is that the mountpoint gets restored with the new context=. Super handy if you're using selinux and the labels need to change on restore โ€” like when a container gets restored into an existing Pod. ๐Ÿ‘‘

  • --auto-dedup โ€” the second a page is restored, it gets punched out from the image.
  • -j, --shell-job โ€” restore shell jobs, aka inherit the session and process group ID from the criu itself.
  • --cpu-cap [cap[,cap...]] โ€” says which CPU capabilities must be present on the CPU the process is restoring on. To inverse a capability, prefix it with ^. This option implies that --cpu-cap was passed on dump as well โ€” except in the fpu option case. The cap argument can be any of these (or a set of comma-separated values):
    • all โ€” require all capabilities. This is the default mode when --cpu-cap is passed without arguments. Most safe mode.
    • cpu โ€” require the CPU to have all capabilities in the image to match the runtime CPU.
    • fpu โ€” require the CPU to have a compatible FPU. For example, the process might be dumped with xsave capability but you attempt to restore without it present on the target CPU โ€” in that case we refuse to proceed. This is the default mode if --cpu-cap is not present in the command line. Note this argument might be passed even if no --cpu-cap was specified on the dump, because FPU frames are always encoded into images.
    • ins โ€” require CPU compatibility on the instructions level.
    • none โ€” ignore capabilities. Most dangerous mode. The behaviour is implementation dependent. Try not to use it until it's really required. ๐Ÿ™ˆ

For example, this option can be used when --cpu-cap=cpu was used during dump and the images get migrated to a less capable CPU and are to be restored. By default criu shows an error that the CPU capabilities are not adequate, but you can suppress that with --cpu-cap=none.

  • --weak-sysctls โ€” silently skip restoring sysctls that aren't available. This lets you restore on an older kernel, or a kernel that was configured without some options.
  • --lazy-pages โ€” restore the processes without filling out the entire memory contents. When this option is used, restore sets up the infrastructure required to fill memory pages either on demand (when the process accesses them) or in the background, without stopping the restored process. This option requires a running lazy-pages daemon. ๐Ÿ˜ด
  • --file-validation [mode] โ€” sets the method used to validate open files. Validation is done to make sure the version of the file being restored is the same version as when it was dumped.

The mode may be one of these:

  • filesize โ€” explicitly use only the file size check, all the time. This is the fastest and least intensive check.
  • buildid โ€” validate ELF files with their build-ID. If the build-ID can't be obtained, the chksm-first method will be used. This is the default when mode is unspecified.
  • --skip-file-rwx-check โ€” skip checking file permissions (r/w/x for u/g/o) on restore. ๐Ÿ’…
  • --allow-uprobes โ€” required when it was dumped with this option. Refer to this option in the section on dumping for more details.

๐Ÿฉบ check โ€” the kernel vibe check โœจ

Checks whether the kernel supports the features criu needs to dump and restore a process tree. ๐Ÿฆ‹

There are three categories of kernel support, and they go like this. criu check always checks Category 1 features, unless --feature is specified โ€” which then only checks the one specified feature.

Category 1 ๐Ÿ’–

Absolutely required. These are features like support for /proc/PID/map_files, NETLINK_SOCK_DIAG socket monitoring, /proc/sys/kernel/ns_last_pid etc.

Category 2 ๐ŸŒธ

Required only for specific cases. These are features like AIO remap, /dev/net/tun and others that are only required if the process being dumped or restored is using them.

Category 3 ๐Ÿงช

Experimental. These are features like task-diag that are used for experimental purposes (mostly during development).


If there are no errors or warnings, criu prints "Looks good." and its exit code is 0. ๐ŸŽ‰

A missing Category 1 feature makes criu print "Does not look good." and its exit code is non-zero. ๐Ÿ’€

Missing Category 2 and 3 features make criu print "Looks good but ..." and its exit code is non-zero.

Without any options, criu check checks Category 1 features. You can change that behavior with these options:

  • --extra โ€” check kernel support for Category 2 features.
  • --experimental โ€” check kernel support for Category 3 features.
  • --all โ€” check kernel support for Category 1, 2, and 3 features.
  • --feature name โ€” check a specific feature. If name is list, a list of valid kernel feature names that can be checked will be printed. ๐Ÿ‘‘

๐Ÿ“„ page-server ๐Ÿ’Œ

Launches criu in page server mode. ๐Ÿฆ‹

  • --daemon โ€” runs the page server as a daemon (background process).
  • --status-fd โ€” write \0 to the FD and close it once page-server is ready to handle requests. The status-fd lets you not daemonize a process and still get its exit code at the end. It isn't supposed to be used with --daemon and --status-fd together. ๐Ÿซถ
  • --address address โ€” page server IP address or hostname.
  • --port number โ€” page server port number.
  • --ps-socket fd โ€” use the provided file descriptor as the socket for incoming connections. In this case --address and --port are ignored. Useful for intercepting page-server traffic, e.g. to add encryption or authentication. ๐Ÿ”
  • --lazy-pages โ€” serve a local memory dump to a remote lazy-pages daemon. In this mode the page-server reads the local memory dump and lets the remote lazy-pages daemon request memory pages in random order.
  • --tls-cacert file โ€” specifies the path to a trusted Certificate Authority (CA) certificate file used for verification of a client or server certificate. The file must be in PEM format. When this option is used, only the specified CA is used for verification. Otherwise, the system's trusted CAs and, if present, /etc/pki/CA/cacert.pem will be used.
  • --tls-cacrl file โ€” specifies a path to a Certificate Revocation List (CRL) file, which contains a list of revoked certificates that should no longer be trusted. The file must be in PEM format. When this option is not specified, the file, if present, /etc/pki/CA/cacrl.pem will be used.
  • --tls-cert file โ€” specifies a path to a file that contains an X.509 certificate to present to the remote entity. The file must be in PEM format. When this option is not specified, the default location (/etc/pki/criu/cert.pem) will be used.
  • --tls-key file โ€” specifies a path to a file that contains the TLS private key. The file must be in PEM format. When this option is not specified, the default location (/etc/pki/criu/private/key.pem) will be used.
  • --tls โ€” use TLS to secure remote connections. ๐Ÿ”ฅ

๐Ÿ˜ด lazy-pages ๐Ÿฆ‹

Launches criu in lazy-pages daemon mode.

okay so the lazy-pages daemon ๐Ÿ’ค is the girlboss in charge of user-level demand paging for the processes you just restored. She pulls everything she needs to fill in the process memory pages from the restore and from the checkpoint directory โ€” two sources, no cap. And here's the magic โœจ: the first time a restored process touches a certain memory page, she swoops in and injects its contents into the process address space. And the pages nobody's asked for yet? She injects those in the background like the multitasking queen she is. ๐Ÿ’…


โœจ exec โœจ

Runs a system call inside a destination task's context. ๐Ÿซถ

lowkey deprecated!! This functionality is deprecated โ€” please use Compel instead. periodt. ๐Ÿ’€

โœจ service โœจ

Launches criu in RPC daemon mode, where criu is sitting there listening for RPC commands over a socket so it can go do the thing. ๐ŸŽง

Why is this iconic? Because it's so convenient for the case where the daemon itself is running in a privileged (superuser) mode but the clients are not. ๐ŸŽ€

โœจ dedup โœจ

Kicks off the pagemap data deduplication procedure ๐Ÿงน โ€” criu scans over all the pagemap files and tries to minimize the number of pagemap entries by obtaining the references from a parent pagemap image. Less is more, bestie. ๐Ÿ’–

โœจ cpuinfo dump โœจ

Fetches the current CPU features and writes them into an image file. ๐Ÿ“ธ Simple. Elegant. Ate.

โœจ cpuinfo check โœจ

Fetches the current CPU features (i.e. the CPU the criu is running on) and tests if they're compatible with the ones present in an image file. ๐Ÿง Compatibility vibe check, basically.


๐ŸŒธ CONFIGURATION FILES ๐ŸŒธ

Criu supports usage of configuration files so you don't have to write every single option on the command line every single time โ€” which is so useful, especially when you're repeating the same options over and over. ๐Ÿ™ˆ

You can pass a specific config file with the "--config file" option. If you don't pass one, the default configuration files /etc/criu/default.conf and $HOME/.criu/default.conf get parsed (if they're present on the system, of course ๐Ÿซถ). And if the environment variable CRIU_CONFIG_FILE is set, that one gets parsed too.

The options passed to CRIU via CLI, RPC or configuration file are evaluated in this order, bestie โ€” don't mess it up:

  • apply_config(/etc/criu/default.conf)
  • apply_config($HOME/.criu/default.conf)
  • apply_config(CRIU_CONFIG_FILE)
  • apply_config(--config file)
  • apply_config(CLI) or apply_config(RPC)
  • apply_config(RPC configuration file) (only for RPC mode)

Default configuration file parsing can be deactivated with "--no-default-config" if you need that. And parsed configuration files get merged with command line options, which allows overriding boolean options. ๐Ÿ”ฅ

๐Ÿ’… Configuration file syntax ๐Ÿ’…

Comments are supported using the '#' sign โ€” the rest of the line is just ignored, she's not listening. ๐Ÿ™ˆ

Options are the same as command line options but without the '--' prefix, and you use one option per line (with the corresponding argument if applicable, divided by whitespaces). If needed, the argument can be provided in double quotes (this should be needed only if the argument contains whitespaces). And in case this type of argument contains a literal double quote as well, it can be escaped using the '\' sign. Usage of commands is disallowed and all other escape sequences are interpreted literally. ๐ŸŽ€

Example of configuration file to illustrate syntax:

$ cat ~/.criu/default.conf
tcp-established
work-dir "/home/USERNAME/criu/my \"work\" directory"
#this is a comment
no-restore-sibling   # this is another comment

๐ŸŒˆ Configuration files in RPC mode ๐ŸŒˆ

Not only does criu evaluate configuration files in CLI mode โ€” she also evaluates configuration files in RPC mode. Just as in CLI mode, the configuration file values are evaluated first. Which means any option set via RPC will overwrite the configuration file setting. So the user can change criu's default behavior, but it is not possible to change settings which are explicitly set by the RPC client. ๐Ÿซถ

The RPC client can, however, specify an additional configuration file which will be evaluated after the RPC options (see above for the option evaluation order ๐Ÿ‘†). The RPC client specifies this additional configuration file via req.opts.config_file = /path/to/file. The values from this configuration file will overwrite all other configuration file settings or RPC options. ๐Ÿ”ฅ

heads up bestie!! This can lead to undesired behavior of criu and should only be used carefully. Not me telling you to be careful twice. ๐Ÿ˜ญ

๐Ÿ‘‘ NON-ROOT ๐Ÿ‘‘

criu can be used as non-root with either the CAP_SYS_ADMIN capability or with the CAP_CHECKPOINT_RESTORE capability introduced in Linux kernel 5.9. And just so we're clear: CAP_CHECKPOINT_RESTORE is the minimum that is required. periodt.

criu also needs either CAP_SYS_PTRACE or a value of 0 in /proc/sys/kernel/yama/ptrace_scope (see ptrace(2)) to be able to interrupt the process for dumping. ๐Ÿ›‘

Running criu as non-root has many limitations and, depending on the process you want to checkpoint and restore, it may not be possible. ngl, that's just how it is. ๐Ÿ’€

In addition to CAP_CHECKPOINT_RESTORE it is possible to give criu additional capabilities to enable additional features in non-root mode. โœจ Currently criu can benefit from the following additional capabilities:

  • CAP_NET_ADMIN
  • CAP_SYS_CHROOT
  • CAP_SETUID
  • CAP_SYS_RESOURCE

Note that for some operations, having a capability in a namespace other than the init namespace (i.e. the default/root namespace) is not sufficient. For example, in order to read symlinks in proc/[pid]/map_files CRIU requires CAP_CHECKPOINT_RESTORE in the init namespace โ€” having CAP_CHECKPOINT_RESTORE while running in another user namespace (e.g. in a container) does not allow CRIU to read symlinks in /proc/[pid]/map_files. ๐Ÿซ 

And without access to /proc/[pid]/map_files, checkpointing/restoring processes that have mapped deleted files may not be possible. ๐Ÿ™ˆ

Independent of the capabilities, it is always necessary to use "--unprivileged" to accept criu's limitation in non-root mode. No skipping this step, bestie. ๐Ÿ’…


๐Ÿฆ‹ EXAMPLES ๐Ÿฆ‹

To checkpoint a program with pid of 1234 and write all image files into directory checkpoint:

criu dump -D checkpoint -t 1234

To restore this program detaching criu itself:

criu restore -d -D checkpoint

๐ŸŽ€ AUTHOR ๐ŸŽ€

The CRIU team. ๐Ÿซถ (icons, all of them)

Copyright (C) 2011-2016, Parallels Holdings, Inc.


okay that's the whole page bestie, we made it to the end ๐Ÿฅนโœจ this masterpiece comes from the criu source, dated 2026-07-21, and it lives in section CRIU(8) of the manual โ€” go forth and checkpoint something iconic. no cap. ๐Ÿ’…๐ŸŒˆ๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from