Command reference

Every command and option of nspawn 1.3.1.

nspawn --help and nspawn COMMAND --help print the same information. Errors are printed as error: ... on standard error and the exit status is 1; exec and an attached run exit with the status of the program they ran.

Every command but daemon, completions and the unit hooks is a call to the service on the system bus, which asks polkit whether the caller may take the action: the listings (images ls, ps, machines ls, inspect, top, stats, events, network ls, network inspect, volume ls, secret ls, secret inspect) ask for org.nspawn.inspect; everything else, search and hub included, asks for org.nspawn.manage. Both are for administrators by default, and root is never asked.

Global options

These are accepted by every command and can also come from the environment:

OptionEnvironmentMeaning
--registry REGISTRYNSPAWN_REGISTRYRegistry (hub) for image references without a host part.
--ca-cert FILENSPAWN_CA_CERTExtra CA certificate (PEM) to trust when talking to the registry.
--config FILENSPAWN_CONFIGConfiguration file; see Configuration.
-h, --helpHelp.

login and logout take the registry as their argument, so there --registry has to come before the subcommand: nspawn --registry hub.example login -u me. -V, --version belongs to nspawn itself, not to the subcommands.

hub

Query the hub (an OCI registry).

hub ls

nspawn hub ls [FILTER] [--no-tags]

Lists the repositories of the registry with their tags. FILTER keeps the repositories whose name contains that text; --no-tags skips the tag query of every repository, which is faster on big registries. hub list is an alias.

hub tags

nspawn hub tags REPOSITORY

Prints the tags of one repository, one per line.

nspawn search TERM [--source hub|dockerhub] [-n LIMIT]

Finds images on the hub and on Docker Hub, like docker search, and prints every hit with its source and the reference pull takes.

OptionMeaning
TERMText to look for in image names.
--source hub|dockerhubOnly one source instead of both.
-n, --limit LIMITResults per source. Default: 25.

login

nspawn login [REGISTRY] [-u USERNAME] [--password-stdin]

Checks credentials against a registry, like docker login, and keeps them in /etc/nspawn/auth.json for pull, push, search and hub.

OptionMeaning
REGISTRYRegistry host, for example docker.io or hub.nspawn.org. Default: the hub.
-u, --username USERNAMEUser name; asked for on the terminal when missing.
--password-stdinRead the password from standard input instead of the terminal.

logout

nspawn logout [REGISTRY]

Forgets the credentials stored for a registry (the hub by default).

pull

nspawn pull REFERENCE [-n NAME] [--backend BACKEND] [--mode MODE] [-f] [--no-verify]

Downloads an image from the hub or another registry, checking its signature first where the registry has a policy (the hub’s is built in; see Signed images), and makes it available to systemd-machined. On a terminal a bar shows how far each blob got, with its size, speed and time left; in a pipe or a log only the lines are written.

OptionMeaning
REFERENCE[registry/]repository[:tag|@digest], for example fedora:44 or docker.io/library/nginx.
-n, --name NAMELocal image name. Default: derived from the reference, for example fedora-44.
--backend auto|overlay|flat|mstackHow to assemble the image on this host. Default: auto, or the backend of the configuration file: overlay, or flat without overlayfs. mstack (systemd 261 or newer, managed user namespaces) is experimental. App images are assembled as overlay even when mstack is chosen.
--mode auto|boot|appWhether the image boots an init system or runs a single program. Default: auto.
-f, --forceReplace an existing image with the same name.
--no-verifySkip the signature check: the hub’s images are signed and refused without a valid signature, and the configuration can ask the same of other registries; like docker’s --disable-content-trust.

create

nspawn create SOURCE NAME [--backend BACKEND] [--network NETWORK]... [--network-alias [NETWORK=]NAME]...
              [-p [IP:]HOST:CONTAINER[/udp]]... [--entrypoint PROGRAM] [-e VAR[=VALUE]]...
              [-v SOURCE:TARGET[:ro]]... [-l KEY=VALUE]... [--restart POLICY] [-m SIZE] [--memory-swap SIZE]
              [--cpus N] [--pids-limit N] [HEALTHCHECK OPTIONS] [OTHER OPTIONS] [--interface IFACE]... [--secret SECRET]...
              [-f] [--no-verify] [-- ARGUMENTS...]

Makes another machine from a local image, like docker create, without touching the registry; a reference that is not local is pulled first, under the image’s own name, as run does. The layers are shared with the source.

OptionMeaning
SOURCELocal image to start from: its name, or the reference it was pulled from. A reference that is not local is pulled.
NAMEName of the new machine.
--backend BACKENDHow to assemble it. Default: like the source.
--network NETWORKNetworks of the new machine, as for start. Default: the source’s kind; a network made with network create is not inherited, as ports and labels are not.
--network-alias [NETWORK=]NAMEOther names of the machine on its networks, as for start.
-p, --publish [IP:]HOST:CONTAINER[/udp]Ports to publish on the host, like start -p. Not inherited from the source.
--entrypoint PROGRAMReplace the image’s entrypoint; an empty string runs the arguments alone. App images only.
-e, --env VAR[=VALUE]Environment for the program, VAR=value or VAR copied from the calling shell, like docker -e. App images only.
-v, --volume SOURCE:TARGET[:ro]Mount a host directory or a named volume, like docker -v.
-l, --label KEY=VALUELabel the machine, on top of the image’s own labels, like docker --label. Not inherited from the source.
--restart, -m, --memory-swap, --cpus, --pids-limitRestart policy and limits, as for start. Not inherited from the source.
the healthcheck options, the other options, --interface, --secretAs for start. Not inherited from the source.
-f, --forceReplace an existing machine with the same name.
--no-verifySkip the signature check of an image that has to be pulled (a local source is not checked); like docker’s --disable-content-trust.
-- ARGUMENTS...App images: replace the image’s cmd; they follow its entrypoint, as with docker.

build

nspawn build [DIRECTORY] -t TAG [-n NAME] [-d DISTRIBUTION] [-r RELEASE]
             [--profile PROFILE]... [--backend BACKEND] [--mode MODE] [-f]
             [--keep-output] [-- MKOSI_ARGS...]

Builds an image with mkosi and makes it available locally, ready to push. Needs mkosi.

OptionMeaning
DIRECTORYDirectory with the mkosi configuration (mkosi.conf, mkosi.conf.d, …). Default: ..
-t, --tag TAGReference for the result, for example myapp:1 or hub.example/team/app:2. Required.
-n, --name NAMELocal image name. Default: derived from the tag.
-d, --distribution DISTRIBUTIONDistribution to build (mkosi --distribution).
-r, --release RELEASERelease to build (mkosi --release).
--profile PROFILEmkosi profile to enable; repeatable.
--backend, --mode, -fAs for pull.
--keep-outputKeep the mkosi output directory instead of deleting it after the import.
-- MKOSI_ARGS...Extra arguments passed to mkosi verbatim.

push

nspawn push IMAGE [--to REFERENCE]

Uploads a local image to the hub or another registry, with the credentials stored for it. IMAGE is a local image name, or the reference it was pulled from or built as. --to pushes it under a different reference than the one recorded for the image. The destination needs a tag, not a digest. On a terminal a bar shows how far each blob got, as with pull.

images

Manage local images.

images ls

nspawn images ls [--json]

Lists the local images known to systemd-machined: name, type, and for the ones nspawn installed the backend, origin (pull, build or create), source reference, size and whether the image is read-only. --json prints the list as the service returns it. images list is an alias.

images rm

nspawn images rm NAME...

Removes local images and the layers and blobs nobody uses any more. Refuses the image of a running machine, or of one its restart policy is bringing back, and a name nothing is behind. Named volumes are kept. A pulled image is a machine too, so this is the same as rm without --force.

rm

nspawn rm [-f] NAME...

Removes machines, like docker rm: the record, the tree, the unit files, the boot link a restart policy made, and the layers and blobs nobody else uses. Every name is tried; one that cannot be removed, or that nothing is behind (no machine or image named NAME), is reported at the end. Named volumes are kept, and each one kept is mentioned.

OptionMeaning
-f, --forceStop a running (or restarting) machine first, with SIGKILL, instead of refusing it.

ps, machines ls

nspawn ps [-a] [--json]
nspawn machines ls [-a] [--json]

Lists the running machines, like docker ps: name, image, mode, command, state, uptime, leader PID, network and OS. A machine whose restart policy is bringing it back shows as restarting, even without -a. -a, --all also lists the nspawn machines that are not running: stopped, or starting and closing while their unit comes up or goes down. --json prints what the service returns for each machine, its whole record included. machines list is an alias of machines ls.

inspect

nspawn inspect NAME...

Prints everything nspawn knows about machines or images, running or not, as a JSON array with one object per name, like docker inspect: the record (image reference, digest, backend, mode, networks, addresses, aliases, ports, volumes, environment, command, labels, restart policy, limits, healthcheck, secrets, the other flags, and who signed the image and when, as the pull verified it: signed_by, signed_at), for a running machine its state, start time, leader PID, OS and health, and for a stopped one the exit code of its last run. The keys are those of the D-Bus interface.

start

nspawn start NAME [--network NETWORK]... [--network-alias [NETWORK=]NAME]... [-p [IP:]HOST:CONTAINER[/udp]]...
             [--entrypoint PROGRAM] [-e VAR[=VALUE]]... [-v SOURCE:TARGET[:ro]]... [-l KEY=VALUE]...
             [--restart POLICY] [-m SIZE] [--memory-swap SIZE] [--cpus N] [--pids-limit N]
             [--health-cmd COMMAND] [--health-interval D] [--health-timeout D] [--health-retries N]
             [--health-start-period D] [--health-start-interval D] [--no-healthcheck]
             [--hostname NAME] [-u USER[:GROUP]] [-w DIR] [--cap-add CAP]... [--cap-drop CAP]... [--privileged]
             [--read-only] [--tmpfs PATH[:OPTIONS]]... [--shm-size SIZE]
             [--device HOST[:CONTAINER[:PERMISSIONS]]]... [--dns ADDRESS]... [--dns-search DOMAIN]...
             [--add-host HOST:IP]... [--ulimit NAME=SOFT[:HARD]]... [--oom-score-adj N]
             [--stop-signal SIGNAL] [--stop-timeout SECONDS] [--timezone MODE] [--log-driver DRIVER] [--init] [--sysctl KEY=VALUE]...
             [--interface IFACE]... [--secret NAME[:TARGET[:MODE[:UID:GID]]]]... [--image-command] [--no-wait]
             [-- ARGUMENTS...]

Boots an image as a machine. Every option is remembered for the next start.

OptionMeaning
--network NETWORKNetwork of the machine: bridge, the default network (the default); the name of a network made with network create; veth, a veth pair configured by systemd-networkd on the host (booted images only); host, the host’s own network; none, no interface but lo; or container:NAME, the network namespace of that running machine, like docker run --network container:NAME (app images only; see container:NAME). Repeatable for several bridge networks, the first one primary: its address is where published ports lead and its gateway the default route, unless it is internal, in which case the first network that is not has the route. veth, host, none and container:NAME go alone.
--network-alias [NETWORK=]NAMEAnother name for the machine on its primary network, or on NETWORK, like docker --network-alias: every member of that network resolves it. Repeatable; none forgets them.
-p, --publish [IP:]HOST:CONTAINER[/udp]Publish a port on the host, like docker -p: on every address of the host, or on IP alone (127.0.0.1:8080:80). 8000-8010:8000-8010 publishes a range, one mapping per port. Repeatable; none forgets them all.
--entrypoint PROGRAMReplace the image’s entrypoint; an empty string runs the arguments alone. App images only.
-e, --env VAR[=VALUE]Environment for the program, VAR=value or VAR copied from the calling shell. Repeatable; none forgets them. App images only.
-v, --volume SOURCE:TARGET[:ro]Mount a host directory or a named volume, made on first use with what the image has at TARGET, as docker seeds one. Repeatable; none forgets them.
-l, --label KEY=VALUELabel the machine, on top of the image’s own labels. Repeatable; none forgets them.
--restart no|on-failure|always|unless-stoppedRestart policy, like docker --restart. always and unless-stopped also start the machine at boot; nspawn stop takes an unless-stopped machine off the boot list until the next start. Applied at the next start; update changes it at once.
-m, --memory SIZEMemory limit of the whole machine, like docker -m: 512m, 2g (at least 4m), and as much swap again unless --memory-swap says otherwise; 0 removes it. Applied at the next start; update changes it at once.
--memory-swap SIZEMemory and swap together, like docker --memory-swap: equal to --memory for no swap, larger for the difference, -1 for swap without a bound; 0 goes back to as much swap again as memory. Needs --memory. Applied at the next start; update changes it at once.
--cpus NCPU limit of the whole machine, like docker --cpus: 0.5, 2; 0 removes it. Applied at the next start; update changes it at once.
--pids-limit NMost processes and threads the machine may have (at least 16 for a booted machine); 0 removes the limit. Applied at the next start; update changes it at once.
--health-cmd COMMANDCommand that says whether the machine is healthy, run inside it through /bin/sh -c at every interval, like docker --health-cmd: exit 0 is healthy. Replaces the image’s HEALTHCHECK. update changes it at once.
--health-interval DTime between probes: 10s, 1m30s, 500ms. Default: 30s.
--health-timeout DTime a probe may take before it counts as failed. Default: 30s.
--health-retries NConsecutive failed probes that make the machine unhealthy. Default: 3.
--health-start-period DTime after the start during which failed probes do not count. Default: 0s.
--health-start-interval DTime between probes during the start period. Default: 5s.
--no-healthcheckNo probes, whatever the image says.
--hostname NAMEHostname inside the machine. Default: its name. A booted machine gets it as its /etc/hostname.
-u, --user USER[:GROUP]User the program runs as, a name or a uid (listed in the image’s passwd or not), instead of the image’s, with a group after a colon as docker takes it: a name of the image’s group file or a number, which becomes the primary and only group of the program; a name the image lacks is refused. nspawn resolves both from the image’s passwd and group files through a stand-in for getent, as docker does. App images only.
-w, --workdir DIRWorking directory of the program, instead of the image’s. App images only.
--cap-add CAPCapability to keep on top of the default set (docker’s and SYS_BOOT for an app on a bridge network, systemd-nspawn’s for a machine in a user namespace): NET_ADMIN, CAP_NET_ADMIN, ALL. Repeatable; none forgets them.
--cap-drop CAPCapability to drop from the default set. --cap-drop ALL --cap-add X keeps X, as with docker. Repeatable; none forgets them.
--privilegedEvery capability, like docker --privileged; --privileged=false takes it back.
--read-onlyMount the machine’s root read-only; --read-only=false takes it back.
--tmpfs PATH[:OPTIONS]An empty tmpfs at a path inside (/tmp:size=64m,mode=1777). One that lands on /run, a tmpfs of every machine already, is left out with a note. Repeatable; none forgets them.
--shm-size SIZESize of /dev/shm: 64m, 1g; 0 for the default.
--device HOST[:CONTAINER[:PERMISSIONS]]A device node of the host for the machine, like docker --device (/dev/ttyUSB0:/dev/ttyUSB0:rw), or a directory whose nodes are allowed one by one (/dev/dri). Repeatable; none forgets them.
--dns ADDRESSDNS server for the machine, instead of the host’s. Repeatable; none forgets them.
--dns-search DOMAINDNS search domain. Repeatable; none forgets them.
--add-host HOST:IPA line for the machine’s /etc/hosts, HOST:IP or HOST=IP (the second for an IPv6 address); host-gateway is the host’s address on the machine’s network. Repeatable; none forgets them.
--ulimit NAME=SOFT[:HARD]A resource limit of the program, like docker --ulimit (nofile=1024:4096, core=unlimited). Repeatable; none forgets them.
--oom-score-adj NOOM score adjustment of the machine, -1000 to 1000.
--stop-signal SIGNALSignal stop sends the program, instead of the image’s (SIGTERM).
--stop-timeout SECONDSSeconds stop waits after the signal before SIGKILL, unless -t says otherwise. Default: 10.
--timezone MODEHow systemd-nspawn sets the machine’s /etc/localtime at each start, its Timezone=: auto (the default, the host’s zone), off (left alone, so a zone set inside stays), copy, bind, symlink or delete. auto forgets the setting.
--log-driver DRIVERWhere the program’s output goes, like docker --log-driver: local (the default: journald’s nspawn namespace, a journal of nspawn’s own apart from the system’s, capped at 1 GiB, which logs and an attached run read), journal (the system’s journal) or none (dropped; logs refuses the machine, an attached run of an app still shows the output straight from the program, and a booted machine runs with -d).
--initAccepted for docker’s sake: nspawn’s stub init reaps orphans anyway. App images only.
--sysctl KEY=VALUEA net.* sysctl for an app machine’s network namespace. Repeatable; none forgets them.
--interface IFACEA network interface of the host, moved into the machine while it runs and given back when it stops: an ethernet one, or a wifi adapter with its whole phy (iw on the host for an app on the bridge, systemd 256 for a booted machine); the name is kept inside. Not with --network host or container:NAME; one machine at a time. See Physical interfaces. Repeatable; none forgets them.
--secret NAME[:TARGET[:MODE[:UID:GID]]]A secret made with secret create as a read-only file inside the machine, like docker’s --secret: NAME alone is /run/secrets/NAME with mode 0444, root’s. Repeatable; none forgets them. Not on mstack machines.
--image-commandForget the remembered entrypoint and arguments and run the image’s own again.
--no-waitDo not wait for a booted machine’s init to be up before returning. Its registration is still awaited, so that ports and firewall rules can be applied.
-- ARGUMENTS...App images: replace the image’s cmd; they follow its entrypoint, as with docker.

A path inside the machine, the target of -v or --secret, a --tmpfs or a --device path, must be plain: a . or .. component is refused.

run

nspawn run [-d] [--rm] [-i] [-t] [-n NAME] [--pull missing|always|never]
           [--backend BACKEND] [--mode MODE] [-f] [--no-verify] [OPTIONS OF start] [--no-wait]
           REFERENCE [COMMAND [ARGUMENT...]]

Makes a machine from an image and starts it, like docker run: pull (or create from a local image with the same reference) followed by start, whose options are remembered as after start. What pull or create report goes to standard error, so that standard output carries the program’s output alone.

Without -d, run stays attached, as docker run does. The machine’s output follows until the machine ends, a line at a time, stdout and stderr together: it is read from nspawn’s journal, so nspawn logs NAME shows it later too, and the machine goes on should run be interrupted. With --log-driver none it comes straight from the program instead, and nothing is kept. run exits with the program’s exit code, or 128 plus the signal it died of (130 after Ctrl-C, 137 after kill). Ctrl-C, SIGTERM, SIGHUP and SIGQUIT are passed on to the program; a third Ctrl-C within a second leaves the machine running and returns. A booted image shows its console until it powers off, and Ctrl-C powers it off.

OptionMeaning
REFERENCE[registry/]repository[:tag|@digest], for example nginx:1.27.
COMMAND [ARGUMENT...]App images: replace the image’s cmd and follow its entrypoint, as with docker; everything after the reference that is not an option of run, or everything after --.
-d, --detachStart the machine in the background and return, like docker run -d; nspawn logs -f NAME follows its output.
--rmRemove the machine once it ends, with or without -d; named volumes stay. An image the run had to pull is kept under the image’s local name when that name is free, as docker keeps images, and without --name the machine gets a name of its own (alpine-3-1f0c9a2e). Refused with a restart policy. A run that fails to start leaves nothing behind.
-i, --interactiveApp images: give the program this standard input, like docker run -i.
-t, --ttyApp images: give the program a terminal, like docker run -t; Ctrl-C and resizes reach it through the terminal. Closing the terminal stops the machine. With -i on a booted image: wait for it to boot, open a root shell, and power it off when the shell ends, with the shell’s exit code. Not with -d.
-n, --name NAMEName of the machine. Default: derived from the reference, for example nginx-1.27. A name that is taken is refused, with a pointer to start.
--pull missing|always|neverWhen to ask the registry. missing, the default: a local image with the same reference is made into the machine, as create does, and the registry is asked only when there is none. always: every time, for the image the tag names now. never: a local image or nothing.
--backend auto|overlay|flat|mstackHow to assemble the machine, as for pull.
--mode auto|boot|appAs for pull; a mode other than auto always pulls.
-f, --forceMake the machine anew when one of that name exists; it must be stopped.
--no-verifySkip the signature check of the image, as for pull.
the options of start--network, --network-alias, -p, --entrypoint, -e, -v, -l, --restart, -m, --cpus, --pids-limit, the healthcheck options, the other options, --interface, --secret and --no-wait (with -d only), as for start. Options may come before or after the reference, as long as they come before the command.

stop

nspawn stop NAME... [-f] [-t TIMEOUT] [--no-wait]

Powers off running machines, one after the other: the machine’s stop signal (--stop-signal, else the image’s) to the program of an app, a poweroff request to a booted machine. Stopping a machine that already ended only cleans up after it, and a paused one is thawed first. A machine with a restart policy stays stopped, and one that was waiting to be restarted is stopped too. An unless-stopped machine is also taken off the boot list until the next start; an always one stays enabled and starts again at the next boot (rm takes that away). Every name is tried; one that could not be stopped is reported at the end.

OptionMeaning
-f, --forceKill every process at once instead of asking the machine to stop.
-t, --timeout TIMEOUTApp images: seconds to wait after the stop signal before killing the machine. Default: the machine’s --stop-timeout, else 10.
--no-waitReturn right after the stop request, without waiting for the machine to be gone and without the kill after the timeout.

restart

nspawn restart NAME... [-t TIMEOUT]

Stops and starts machines, like docker restart: a stop followed by a start with everything the machine remembers, and prints each name once it runs again. A machine that is not running is started. Every name is tried; one that could not be restarted is reported at the end.

OptionMeaning
-t, --timeout TIMEOUTAs for stop.

kill

nspawn kill [-s SIGNAL] NAME...

Sends a signal to running machines, like docker kill, and prints each name once it is sent. SIGKILL, the default, stops the machine for good, as stop --force does. Any other signal goes to the program of an app or the init of a booted machine, and the machine lives on unless the signal ends it, in which case its restart policy applies; the machine’s own stop signal (an app’s, or SIGRTMIN+3 and SIGRTMIN+4 for a booted machine’s init) ends it for good, as docker does.

OptionMeaning
-s, --signal SIGNALA name (KILL, SIGHUP, RTMIN+3) or a number. Default: KILL.

pause, unpause

nspawn pause NAME...
nspawn unpause NAME...

pause freezes every process of running machines through the cgroup freezer of their units, like docker pause, and unpause thaws them; each name is printed once done. ps and inspect show a frozen machine as paused, and stop and kill thaw it first.

update

nspawn update NAME... [--restart POLICY] [-m SIZE] [--memory-swap SIZE] [--cpus N] [--pids-limit N]
              [--health-cmd COMMAND] [--health-interval D] [--health-timeout D] [--health-retries N]
              [--health-start-period D] [--health-start-interval D] [--no-healthcheck]

Changes the restart policy, the limits and the healthcheck of machines, like docker update, and prints each name once changed. A running machine gets the new limits and healthcheck at once (its probes start afresh) and the policy for its next ending; a stopped one at its next start. The options are those of start; at least one is needed.

exec

nspawn exec MACHINE [-u USER] [-e VAR[=VALUE]]... [-w DIR] [-T] [-t] [-i] [-d] COMMAND...

Runs a command inside a running machine of either kind, attached to the terminal when standard input and output are one, in the machine’s namespaces, with the image’s environment and the machine’s -e variables. The program is found on the machine’s PATH and runs with the machine’s capabilities and resource limits, like its own processes, except CAP_SYS_BOOT in an app that shares the host’s user namespace (unless --privileged), since the command does not carry the seccomp filter that keeps kexec out of the machine; right after a start it waits, a few seconds at most, until systemd-nspawn has finished confining the machine. Exits with the command’s status.

OptionMeaning
-u, --user USER[:GROUP]User inside the machine, a name or a number of its passwd file, with a group of its group file after a colon (then the only group; otherwise the user’s supplementary groups come along) and the home of the passwd entry. Default: root.
-e, --env VAR[=VALUE]A variable for the command, VAR=value or VAR copied from the calling shell, like docker exec -e. Repeatable.
-w, --workdir DIRWorking directory of the command, instead of the machine’s.
-T, --no-ttyNo terminal, even from one: pipes, as in a script. Without -t or -T, a terminal only when standard input and output are one, so redirected output is byte-exact.
-t, --ttyA terminal for the command, even without one here.
-i, --interactiveAccepted for docker’s sake: the command’s input is always this one.
-d, --detachLeave the command running in the background and return at once.
COMMAND...Command and arguments.

shell

nspawn shell MACHINE [-u USER]

Opens an interactive shell inside a running machine as USER (default root): machined’s login session for booted machines, /bin/sh in the machine’s namespaces for app machines.

top

nspawn top MACHINE

Lists the processes of a running machine, like docker top: PID as the host sees it, USER as the machine sees it, TIME of CPU and COMMAND, read from the machine’s cgroup and PID namespace.

cp

nspawn cp MACHINE:PATH DESTINATION
nspawn cp SOURCE MACHINE:PATH

Copies files and directories between the host and a machine, like docker cp. The machine may be running, or stopped if it is an overlay or flat machine; a stopped mstack machine has no tree on the host until it runs.

  • An existing directory as the destination receives the source under its own name; anything else is the name of the copy, whose parent must exist. A destination ending in / must be a directory.
  • DIR/. as the source copies the contents of DIR instead of DIR itself.
  • What goes into a machine belongs to its root, whatever user namespace the machine runs in; what comes out belongs to the user who ran cp. Modes and modification times are kept.
  • Paths inside the machine are resolved inside it: a link there, absolute or not, never leads to the host. Links are copied as links; devices, sockets and fifos are left out, and so are the kernel’s file systems mounted inside a running machine (/proc, /sys and the like).
  • A relative path after MACHINE: starts at the machine’s root. A local path with a colon is written ./a:b.

logs

nspawn logs MACHINE... [-f] [-n N] [--since WHEN] [--until WHEN] [-t] [--all] [--inside]

Shows what machines printed, like docker logs. With several machines every line carries its machine’s name (web | ...), the way docker compose shows them. The lines come from nspawn’s journal namespace (--log-driver local, the default) and from the system’s journal, which holds what a machine wrote before 1.8.0 or with --log-driver journal. A machine started with --log-driver none keeps nothing, and logs says so (a booted one’s own journal is still there with --inside).

OptionMeaning
-f, --followKeep printing new output; starts from the last 10 lines unless --lines says otherwise.
-n, --lines NOnly the last N lines.
--since WHENOnly output newer than this, in journalctl --since syntax, for example "10 min ago" or -1h.
--until WHENOnly output older than this, in journalctl --until syntax; nothing is followed then.
-t, --timestampsPrefix every line with its timestamp.
--allAlso show what systemd says about the machine’s service: start, stop, failures.
--insideBooted machines only: read the machine’s own journal instead of its console output.

stats

nspawn stats [NAME...] [--no-stream] [--json]

Shows what running machines use, like docker stats: CPU (100% is one CPU busy), memory in use against the limit (the host’s memory without one), network and disk traffic, and processes, read from the cgroup of each machine’s unit, which holds the whole machine. Without names it shows every running machine. The table is drawn again every second on a terminal.

OptionMeaning
--no-streamPrint one table, from two readings a second apart, and return.
--jsonOne JSON object per machine and reading instead of the table.

events

nspawn events [--since WHEN] [--until WHEN] [-f KEY=VALUE]... [--json]

Reports what happens to machines, networks, volumes and secrets, like docker events: for machines start, die (with its exit code), stop, restart, oom and fail, which systemd logs for every machine however it was started, health_status (with the new status) and what nspawn does, pull, build, create, push, kill, update and remove; for networks, volumes and secrets create and remove. It reads the journal, so past events can be read back.

OptionMeaning
--since WHENEvents since this time, in journalctl --since syntax ("2026-09-24 10:00", -1h, today). Without it, only new ones.
--until WHENStop at this time instead of waiting for new events; needs --since.
-f, --filter KEY=VALUEOnly matching events: name=NAME, type=machine|network|volume|secret, event=ACTION, label=KEY or label=KEY=VALUE. The same key given twice matches either value, different keys must all match.
--jsonOne JSON object per event: time, time_usec, type, action, name, attributes, labels.

network

The default network (bridge) and the ones made with network create.

network up

nspawn network up

Brings up every network’s bridge with its NAT rules and firewall exceptions, and brings the published ports in line with the machines that run. start does it for its machine’s network too; this is useful at boot and for troubleshooting.

network ls

nspawn network ls [--json]

Lists the networks, the default one first: name, bridge interface, subnet, whether it is internal, and the machines whose records name it. --json prints them as the service returns them. network list is an alias.

network create

nspawn network create NAME [--subnet CIDR] [--internal] [-l KEY=VALUE]...

Makes a network of its own, like docker network create: a bridge nsbr-NAME (hashed when the name is long) with its NAT and firewall rules, brought up at once. Machines of one network reach each other by name, and nothing of another network, the default one included, reaches them; ports they publish are reachable from everywhere through the host, as from the LAN.

OptionMeaning
NAMELetters, digits, _ and -; not bridge, host, veth, none or default.
--subnet CIDRThe network’s IPv4 subnet. Default: the next free /24 of network_pool (see Configuration), never one the host already routes.
--internalNo way out: its machines reach each other and the host, nothing beyond, and cannot publish ports.
-l, --label KEY=VALUELabel the network, like docker network create --label. Repeatable.

network inspect

nspawn network inspect NAME...

Prints networks as a JSON array, like docker network inspect: name, interface, subnet, gateway, whether it is internal, its labels, and its machines with their addresses, aliases, ports and whether they run. bridge is the default network.

network rm

nspawn network rm NAME...

Removes networks no machine uses, with their bridges and rules. A network a machine’s record names is refused, with the machines that use it; the default network cannot be removed. network remove is an alias.

network prune

nspawn network prune [-f]

Removes every network no machine uses, after asking on standard input unless -f is given.

volume

Named volumes, the directories -v NAME:/path makes under /var/lib/nspawn/volumes. Removing a machine keeps them.

volume ls

nspawn volume ls [--json]

Lists the named volumes with the machines whose records mount them, when each was made and its path. --json prints the list as the service returns it. volume list is an alias.

volume create

nspawn volume create NAME

Makes a volume ahead of its first use (start makes it otherwise): a directory owned by root, mode 0755. One that exists already is fine. Names have letters, digits, _, . and -, not starting with a dot.

volume rm

nspawn volume rm NAME...

Removes volumes no machine uses. A volume a machine still names is refused until that machine is started with other volumes (or -v none) or removed.

volume prune

nspawn volume prune [-f]

Removes every volume no machine uses once a yes comes on standard input, as docker does: from a script, whose input ends without one, nothing is removed. -f removes them without asking.

secret

Secrets, like docker’s without a swarm: kept encrypted on the host with systemd-creds, handed to machines as files by --secret on start, run and create.

secret ls

nspawn secret ls [--json]

Lists the secrets: name, when it was made, the size of its plaintext, its labels and the machines that take it; never the content. --json prints the list as the service returns it. secret list is an alias.

secret create

nspawn secret create NAME [--file FILE] [-l KEY=VALUE]...

Keeps a secret read from standard input, or from --file, encrypted for this host: bound to its TPM2 where there is one, to its credential key otherwise, under /var/lib/nspawn/secrets. A name that exists already is refused.

OptionMeaning
NAMELetters, digits, _, . and -.
--file FILERead the content from this file instead of standard input.
-l, --label KEY=VALUELabel the secret, like docker secret create --label. Repeatable.

secret inspect

nspawn secret inspect NAME...

Prints what nspawn keeps about secrets as a JSON array: name, creation time, size, labels and the machines that take them; never the content.

secret rm

nspawn secret rm NAME...

Removes secrets no machine takes. One a machine’s record names is refused, with the machines that take it, until they are started with other secrets (or --secret none) or removed. Every name is tried; one that cannot be removed is reported at the end. secret remove is an alias.

daemon

nspawn daemon [--install] [--idle-exit SECONDS]

Serves org.nspawn on the system bus. The bus starts it on demand, so this is not a command to type; --install is.

OptionMeaning
--installWrite the bus policy, the polkit actions, the activation file and the unit that let the bus start this binary on demand, then return. A package does the same.
--idle-exit SECONDSExit after this long without a call or a running job. Default: 60; 0 keeps serving.

completions

nspawn completions bash|elvish|fish|powershell|zsh

Writes the completions for that shell on standard output. Commands and flags come from the same definition the command line itself is built from; besides them, TAB completes names, asked from the service as it goes:

AfterTAB offers
stop, exec, kill, pause, unpause, top, shell, statsthe running machines
startthe images that do not run
rm, inspect, logs, restart, update, images rmevery machine and image
create, pushthe local images
runthe references of the local images
--networkthe networks, and host, none and veth
network rm, network inspectthe networks
volume rmthe volumes

The service hands those names to any user without asking polkit, so this works under sudo and without a password; secrets are not completed. The flags come once the word starts with - (- brings the short forms, -- the long ones), or where there is no name to offer. The packages install the completions, so this is for a binary you built yourself:

nspawn completions bash > ~/.local/share/bash-completion/completions/nspawn

man nspawn is the same reference as this page, generated the same way.

Unit hooks

nspawn network prepare NAME, nspawn network publish NAME and nspawn network release NAME are what the drop-in of systemd-nspawn@NAME.service runs as ExecStartPre, ExecStartPost and ExecStopPost, and nspawn health-run NAME is what nspawn-health-NAME.service runs to probe a machine’s healthcheck. They are not meant to be typed and are hidden from --help.