Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion content/en/docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ description: >-
`lowerdir+=`). Without it images are extracted as flat directories.
- **iproute2** and **nftables** (`ip` and `nft`) for the bridge network. Nothing
else: the bridge does not need systemd-networkd or NetworkManager on the host.
Only `--network veth` needs systemd-networkd.
Only `--network veth` needs systemd-networkd, and only `--interface` with a
wifi adapter needs `iw` (for an app on the bridge) or systemd 256 (for a
booted machine).
- **Root, or an administrator with polkit.** Every command is a call to the
[service](/docs/overview/#the-service) on the system bus, which asks polkit
who you are: root is never asked, an administrator is asked for a password,
Expand Down
4 changes: 4 additions & 0 deletions content/en/docs/machines.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,10 @@ its unit:
- `--sysctl KEY=VALUE`: `net.*` keys, set in the network namespace nspawn
makes for an app machine on a bridge network. Nothing else is accepted, and
a booted machine sets its own.
- `--interface IFACE`: a network interface of the host, moved into the
machine while it runs and back on the host when it stops, a wifi adapter
with its whole phy included; no docker counterpart. See [Physical
interfaces](/docs/networking/#physical-interfaces).

A list takes `none` to forget it (`--cap-drop none`, `--tmpfs none`), a value
an empty string (`--hostname ""`) or `0` (`--oom-score-adj 0`), and
Expand Down
60 changes: 60 additions & 0 deletions content/en/docs/networking.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,66 @@ sudo nspawn run -d docker.io/qmcgaw/gluetun --name vpn --cap-add NET_ADMIN --dev
sudo nspawn run -d docker.io/library/nginx:1.27 --name web --network container:vpn
```

## Physical interfaces

`--interface IFACE` on `run`, `create` and `start` gives a machine a network
interface of the host, whole: a second ethernet port, or a wifi adapter for a
machine doing wireless work. `--device` cannot do it, since a network interface
is not a node under `/dev`, and `--network host` cannot either: the machines
run in a user namespace, which may not configure the host's interfaces. The
interface is moved into the machine's network namespace before its program or
init runs and is back on the host when the machine stops or is removed, with
its name kept on both sides, as systemd-nspawn's `Interface=` and LXC's `phys`
type do it. It arrives down and unconfigured, as the kernel moves it: the
machine brings it up and configures it, with `ip` in an app or its
systemd-networkd in a booted machine. The flag is repeatable and remembered
like the rest, `--interface none` forgets them, and `inspect` lists them as
`interfaces`.

```shell
sudo nspawn run -d kali:latest --name kali --interface wlp11s0f3u2u3
sudo nspawn exec kali -- iw dev
sudo nspawn stop kali # the adapter is back on the host
```

Where systemd-nspawn makes the machine's network namespace (a booted machine,
on the bridge or with veth, and any machine with `--network none`) the
interface goes into the machine's settings file as `Interface=` and
systemd-nspawn moves it at start and back at exit. An app machine on a bridge
network gets its namespace from nspawn itself (`NamespacePath=`, which allows
no `Interface=` beside it), so the unit's hooks move the interface in with `ip`
before systemd-nspawn runs and give it back after; such an app runs without a
user namespace, so `iw reg set` and monitor mode work inside as on the host.
Either way the unit waits for the interface's device unit, so that a machine
started at boot waits for a USB adapter udev has not seen yet.

A wifi adapter cannot leave its phy, so the phy moves whole, every interface it
carries with it (nspawn says which), and a driver without namespace support
(`ath6kl`, `wilc1000`) refuses the move naming the phy. An app on the bridge
takes a wireless interface on any systemd, through `iw`, which has to be
installed on the host; `Interface=` moves a phy since systemd 256, so on an
older host a wireless interface is refused for a booted machine or one with
`--network none`, with a message that says so. The regulatory domain (`iw reg
set`) and rfkill are host-wide: they are set on the host, or from an app on
the bridge; `--device /dev/rfkill` hands the switch to such an app.

One machine at a time takes an interface: a second one naming it is refused
while the first runs (`stop` it, or start it with `--interface none`). Refused
as well: `lo`, the bridges and veth ends of nspawn's own, a port of a bridge or
bond (`ip link set IFACE nomaster` first), a name that is not on the host (a
machine that ended a moment ago may still hold it: the kernel gives interfaces
back a little after their namespace dies), a machine with `--network host`, one
with `--network container:NAME` (give the interface to `NAME`) and the mstack
backend. The interface of the host's default route is allowed with a warning,
since the host loses its route while the machine runs. When the interface
comes back, NetworkManager or systemd-networkd manage it again as before, and
a name taken on the host in the meantime makes the kernel rename it (`dev0`,
`wlan0`). `stop --force` kills the machine: an app on the bridge still gets
every interface back from its release hook, while a machine that took them
through `Interface=` may not get to give them back, and the kernel then
returns a physical interface or a wifi phy a moment later and destroys a
virtual one (a VLAN, a macvlan, a dummy) with the namespace.

Behind the scenes the service binds the name systemd-nspawn looks for
(`/run/netns/nspawn-web`) to the network namespace of `vpn`'s leader process,
the mount `ip netns attach` would make, so the settings are the ones of any
Expand Down
10 changes: 6 additions & 4 deletions content/en/docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ size, speed and time left; in a pipe or a log only the lines are written.
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] [--cpus N]
[--pids-limit N] [HEALTHCHECK OPTIONS] [OTHER OPTIONS] [--secret SECRET]...
[--pids-limit N] [HEALTHCHECK OPTIONS] [OTHER OPTIONS] [--interface IFACE]... [--secret SECRET]...
[-f] [--no-verify] [-- ARGUMENTS...]
```

Expand All @@ -142,7 +142,7 @@ the image's own name, as `run` does. The layers are shared with the source.
| `-v`, `--volume SOURCE:TARGET[:ro]` | Mount a host directory or a named volume, like `docker -v`. |
| `-l`, `--label KEY=VALUE` | Label the machine, on top of the image's own labels, like `docker --label`. Not inherited from the source. |
| `--restart`, `-m`, `--cpus`, `--pids-limit` | Restart policy and limits, as for [start](#start). Not inherited from the source. |
| the healthcheck options, the other options, `--secret` | As for [start](#start). Not inherited from the source. |
| the healthcheck options, the other options, `--interface`, `--secret` | As for [start](#start). Not inherited from the source. |
| `-f`, `--force` | Replace an existing machine with the same name. |
| `--no-verify` | Skip 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. |
Expand Down Expand Up @@ -268,7 +268,8 @@ nspawn start NAME [--network NETWORK]... [--network-alias [NETWORK=]NAME]... [-p
[--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] [--init] [--sysctl KEY=VALUE]...
[--secret NAME[:TARGET[:MODE[:UID:GID]]]]... [--image-command] [--no-wait] [-- ARGUMENTS...]
[--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.
Expand Down Expand Up @@ -312,6 +313,7 @@ Boots an image as a machine. Every option is remembered for the next start.
| `--stop-timeout SECONDS` | Seconds `stop` waits after the signal before SIGKILL, unless `-t` says otherwise. Default: 10. |
| `--init` | Accepted for docker's sake: nspawn's stub init reaps orphans anyway. App images only. |
| `--sysctl KEY=VALUE` | A `net.*` sysctl for an app machine's network namespace. Repeatable; `none` forgets them. |
| `--interface IFACE` | A 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](/docs/networking/#physical-interfaces). Repeatable; `none` forgets them. |
| `--secret NAME[:TARGET[:MODE[:UID:GID]]]` | A secret made with [secret create](#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-command` | Forget the remembered entrypoint and arguments and run the image's own again. |
| `--no-wait` | Do 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. |
Expand Down Expand Up @@ -353,7 +355,7 @@ image shows its console until it powers off, and Ctrl-C powers it off.
| `--mode auto\|boot\|app` | As for `pull`; a mode other than `auto` always pulls. |
| `-f`, `--force` | Make the machine anew when one of that name exists; it must be stopped. |
| `--no-verify` | Skip 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, `--secret` and `--no-wait` (with `-d` only), as for [start](#start). Options may come before or after the reference, as long as they come before the command. |
| 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](#start). Options may come before or after the reference, as long as they come before the command. |

## stop

Expand Down
2 changes: 1 addition & 1 deletion hugo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ params:
privacy_policy: /about/#privacy

# Version of nspawn the documentation describes.
version: 1.5.1
version: 1.6.0
archived_version: false

# In-page links to open issues and suggest changes.
Expand Down