Which method to choose, what each one installs, and
what is left to do afterwards. For the commands alone, without the
explanations: INSTALL-quick-guide.md.
Marionnet is published in three ready-to-use forms: an apt
repository, a dnf/zypper repository and a precompiled archive. All three
come from the same publication directory, on
www.marionnet.org, and contain the same program. The choice
therefore depends only on the package manager of your machine.
Whatever the method, two steps follow: fetching the images and the kernels (§ 2), then granting the sudoers rule (§ 3). This page also explains why each precaution exists, and what to do when something does not work (§ 6).
linux-6.12.95 (64-bit) and linux-6.12.95-i386
(32-bit).
.tar.xz file (a
tarball), for the distributions that have no Marionnet
repository.
/etc/sudoers.d/,
blocks (a), (b) and (c) of § 3.
ip or iptables commands. It checks its
arguments before acting.
1. the application § 1.A apt repository
│ § 1.B dnf/zypper repository
│ § 1.C precompiled archive
│ § 1.D from source
▼
2. images, kernels § 2 marionnet-get-images
│
▼
3. sudoers rule § 3 marionnet-sudoers.sh install
│
▼
4. launch § 4 marionnet
At step 1, the four methods are alternatives: only one concerns you. Steps 2, 3 and 4 then apply to all of them.
Without images or kernels, Marionnet starts, but it says so and cannot run any virtual machine. They weigh several gibibytes and change at their own pace: that is why they are fetched separately (§ 2).
Marionnet is a graphical program. It needs an X display
(DISPLAY), and opens access to it for the virtual machines
with xhost (§ 3.2).
On this page, a relative path starts from the directory of this file:
doc-src/ in the source tree,
<prefix>/share/doc/marionnet/ on a machine where
Marionnet is installed.
Each line of the table was measured by test benches: scripts that
install Marionnet in a bare container of the distribution, then
ask the machine what it got. They are in the source repository, under
Makefile.d/*.bench/ and
bin/scripts/marionnet-install.sh.bench/.
| System | glibc | archive (§ 1.C) | apt (§ 1.A) | dnf/zypper (§ 1.B) |
|---|---|---|---|---|
| Ubuntu 20.04 LTS (focal) | 2.31 | 49 / 0 | 41 / 0 | — |
| Ubuntu 22.04 LTS (jammy) | 2.35 | 49 / 0 | 41 / 0 | — |
| Ubuntu 24.04 LTS (noble) | 2.39 | 49 / 0 | 41 / 0 | — |
| Ubuntu 26.04 LTS | 2.41 | 49 / 0 | 41 / 0 | — |
| Debian 11 (bullseye) | 2.31 | 49 / 0 | 41 / 0 | — |
| Debian 12 (bookworm) | 2.36 | 49 / 0 | 41 / 0 | — |
| Debian 13 (trixie) | 2.41 | 49 / 0 | 41 / 0 | — |
| Rocky Linux 9 | 2.34 | — | — | 60 / 0 |
| AlmaLinux 9 | 2.34 | — | — | 58 / 0 |
| Rocky Linux 10 | 2.39 | — | — | 61 / 0 |
| AlmaLinux 10 | 2.39 | — | — | 59 / 0 |
| Fedora 42 | 2.41 | — | — | 60 / 0 |
| openSUSE Leap 15.6 | 2.38 | — | — | 56 / 0 |
| openSUSE Leap 16.0 | 2.40 | — | — | 58 / 0 |
Each cell reads cases passed / cases failed. The installer
marionnet-install.sh is measured separately, on the seven
Debian and Ubuntu systems: 504 cases, no failure.
On the RHEL 10 family, the full score includes no router: there is none yet on this family (§ 1.B).
What the table means for your machine. Marionnet and its UML kernels are dynamically linked programs. They require a glibc at least as recent as that of the system they were compiled on, never the other way round. The release is therefore compiled on the oldest system served in each family: Debian 11 (glibc 2.31) for the Debian packages and the archive, Rocky Linux 9 (glibc 2.34) for the RPM packages. Every more recent distribution receives the same files, and you have no variant to choose.
The precompiled archive carries this minimum glibc in its file name
(marionnet_<version>-r<rev>_<arch>_glibc<x.y>.tar.xz).
marionnet-install.sh reads it there: on a machine that is
too old, it refuses and says so, instead of installing a program that
would not start. The packages say the same thing in the language of
their package manager (libc6 (>= ...),
libc.so.6(GLIBC_...)), and apt or dnf refuse them on their
own.
openSUSE Leap 15.6. It is served only since the
release of 2026-09-13. Before, Marionnet depended on the
uml-utilities package, compiled by the project against
readline 8, whereas Leap 15.x provides readline 7: zypper refused the
package. The two programs that were needed from that package, the
mconsole client and the UML kernel's port-helper, are now compiled with
Marionnet, without readline, under the names
marionnet_uml_mconsole and
marionnet_uml_port_helper.
Older than the table. Ubuntu 18.04 and Debian 10 have a glibc that is too old and are not served. You can still compile Marionnet from source there (§ 1.D), provided their packages are enough.
Choose one of the four methods 1.A to 1.D, according to your machine; the others do not concern you. Sections 2, 3 and 4 then apply to every method.
| Your machine | Take | § |
|---|---|---|
| Debian, Ubuntu and derivatives | the apt repository | § 1.A |
| Fedora, RHEL family (Rocky, AlmaLinux), openSUSE | the dnf/zypper repository | § 1.B |
| any other distribution, or no package manager wanted | the precompiled archive | § 1.C |
| you want to modify Marionnet | the source | § 1.D |
A minimal installation has neither certificates nor
curl. Install them first, otherwise nothing can read the
site.
The three methods read the site over https. But a minimal Debian or Ubuntu, a container image for instance, has no certificate store at all (measured on Debian 12 and 13, Ubuntu 24.04 and 26.04; the RPM images have one). Without it, apt does not read the repository and the installer does not read the list of published files, although the server answers.
sudo apt update && sudo apt install ca-certificates curlcurl is in the same command because a slim
image has nothing to download with either, and § 1.A needs it to fetch
the key (wget -O works just as well as
curl -o).
marionnet-install.sh recognises this case and names it,
rather than blaming the network. It cannot repair it by itself: that
would take the very package manager that does not work yet.
Fetch the project's key and check its fingerprint, declare the
repository, install marionnet. Measured on Debian 12 and
13, Ubuntu 24.04 and 26.04.
# 1. the key: fetched, looked at (see "The key"), and only then trusted
sudo install -d /etc/apt/keyrings
sudo curl -o /etc/apt/keyrings/marionnet.asc \
https://git.launchpad.net/marionnet/plain/marionnet-archive-keyring.asc
sudo apt install gnupg
# must print the fingerprint below
gpg --show-keys /etc/apt/keyrings/marionnet.asc
# 2. the repository, then the application
echo 'deb [signed-by=/etc/apt/keyrings/marionnet.asc] https://www.marionnet.org/download/apt/ ./' \
| sudo tee /etc/apt/sources.list.d/marionnet.list
sudo apt update
sudo apt install marionnetThe address download/apt always follows the current
release series: you will not have to change this line when the series
changes.
The repository is signed, and signed-by= tells apt to
check the signature with this key:
Marionnet Archive Signing Key <loddo@lipn.univ-paris13.fr>
4A65 3434 0BF9 7733 E74C 9DFC 12E4 6000 225F 0E56
It is fetched from git.launchpad.net, and not from
www.marionnet.org. https only proves that you are talking
to the right server; whoever took control of that server could rewrite
the packages and the fingerprints published next to them. The
signature depends on a private key that is not on that server.
apt upgrade, they check with the key on
their own disk. A booby-trapped update, pushed by someone who had taken
the server, would be refused; this matters on machines where Marionnet
sets a sudoers rule.In a computer lab, the teacher reads the fingerprint aloud at the start of the semester: the question is settled for everyone.
Check the key before the repository line, as on the
RPM side (§ 1.B). As soon as signed-by= names the file, apt
believes what it contains.
git.launchpad.net usually answers 200, but
about one time in six it redirects (302) to its login page,
and curl then saves that answer in the file. Do not add
-L: it would follow the redirect and save the login page, a
failure that looks like a success.
If gpg --show-keys prints something else, or nothing,
fetch the key again. In a deployment script, repeat the
curl until gpg --show-keys prints the
fingerprint. apt does not need gnupg to check the
repository; you need it, to read what you fetched.
apt install marionnet installs the application and the
64-bit kernel: marionnet-kernels is a recommendation
(Recommends:), which apt follows by default.
--no-install-recommends lets you do without it. The images
remain suggestions (Suggests:): several gibibytes are a
choice.
On the RPM side (§ 1.B), dnf install marionnet brings
only the application. dnf silently skips the weak dependency on the
kernel (which pulls in glibc.i686): that channel therefore
leaves it as a suggestion, and says so after the installation. In both
cases, the message shown after the installation measures what is still
missing and names it.
Without an image, no virtual machine starts. Guignol is the only packaged image; the Debian images (wheezy, trixie) come from § 2. A virtual machine needs an image and a kernel that this image declares it accepts.
An image for which no accepted kernel is installed does not appear in Marionnet. Nothing fails, no message is shown: it is simply missing from the list.
| Package | What it contains, and what is missing without it |
|---|---|
marionnet-kernels |
the 64-bit UML kernel linux-6.12.95. Without it, the
recent images (Debian trixie, fetched in § 2) are not offered |
marionnet-fs-guignol |
the small image, machine and router, the only router image published. Without it, no router |
marionnet-kernels-i386 |
the 32-bit UML kernel linux-6.12.95-i386. Without it,
neither guignol nor wheezy is offered, nor any .mar project
older than 2026 |
A router needs two packages. Guignol's
.conf file declares
SUPPORTED_KERNELS='/3.2.[6-9]/ /-i386$/', which
linux-6.12.95 does not satisfy.
marionnet-fs-guignol therefore needs
marionnet-kernels-i386.
This 32-bit kernel in turn needs a foreign architecture enabled on
your machine: its interpreter is /lib/ld-linux.so.2, and
only libc6:i386 provides that file. For the router, both
packages:
sudo dpkg --add-architecture i386 && sudo apt update
sudo apt install marionnet-kernels-i386 marionnet-fs-guignolWithout the foreign architecture, apt refuses the package, naming
libc6:i386. Enabling it is a decision you make: that is why
the 32-bit kernel is a separate package.
If a precompiled archive (§ 1.C) was already installed on
this machine, /etc/marionnet/marionnet.conf
already exists, and dpkg asks what to do with it. A
non-interactive installation fails at that question:
DEBIAN_FRONTEND=noninteractive only concerns debconf, not
this dpkg question. To keep your configuration:
sudo apt install -o Dpkg::Options::=--force-confold marionnetThe package's version is then left next to it, as
marionnet.conf.dpkg-dist. The two files differ on one point
that matters: a package installs under /usr, an archive
under /usr/local.
Whatever the method, go on to § 2 (images and kernels), then § 3 (sudoers rule) and § 4 (launch).
On the RHEL family, enable EPEL. Then fetch the key, check its
fingerprint and import it, declare the repository, install
marionnet and the data packages. Measured on Fedora 42,
Rocky Linux 10, AlmaLinux 10 and openSUSE Leap 16.
On the RHEL family, enable EPEL first: one of Marionnet's
dependencies, gtksourceview3, lives there and not in the
base repositories.
sudo dnf install epel-releaseThe test benches also enable CRB
(sudo dnf config-manager --set-enabled crb). If dnf reports
a dependency it cannot resolve, that is the next thing to enable. Then,
on any system of this family:
# 1. the key: fetched, looked at, and only then imported
sudo install -d /etc/pki/rpm-gpg
sudo curl -o /etc/pki/rpm-gpg/RPM-GPG-KEY-marionnet \
https://git.launchpad.net/marionnet/plain/marionnet-archive-keyring.asc
# must print the fingerprint of § 1.A
gpg --show-keys /etc/pki/rpm-gpg/RPM-GPG-KEY-marionnet
sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-marionnet
# 2. the repository, then the application (Fedora and RHEL family)
sudo curl -o /etc/yum.repos.d/marionnet.repo \
https://www.marionnet.org/download/rpm/marionnet.repo
sudo dnf install marionnetOn openSUSE, zypper does not read
/etc/yum.repos.d/. After the same key step, give it the
address of the repository instead of the .repo file:
sudo zypper addrepo --gpgcheck https://www.marionnet.org/download/rpm/ marionnet
sudo zypper install marionnetLike download/apt in § 1.A, the address
download/rpm always follows the current series.
The key is the same as in § 1.A, in the same place, with the same
precautions: the redirect to the login page one time in six, and the
repeated curl in a script.
The key is looked at before
rpm --import: importing is already trusting, and looking
afterwards would be too late. If gpg is missing, install
gnupg2 (gpg2 on openSUSE); neither
dnf nor rpm needs it.
The check has another form here, not another strength. apt checks one
signature on the index, which covers every package by its digest. rpm
has two mechanisms, and the .repo file asks for both:
| Setting | What it checks |
|---|---|
gpgcheck=1 |
each package, by a signature written into the package itself |
repo_gpgcheck=1 |
the index, by the file repodata/repomd.xml.asc next to
it |
The .repo file names the key by a local file
(gpgkey=file:///etc/pki/rpm-gpg/…), not by an address: that
is why you fetch it yourself. With an address, dnf would download the
key following redirects, with no way to stop it. One time in six it
would get the login page, and the installation would stop on
Failed to import OpenPGP keys, after downloading every
package.
dnf may still show a fingerprint and ask you to accept the key: for
repo_gpgcheck it keeps a keyring of its own, which
rpm --import does not fill. Compare the fingerprint shown
with that of § 1.A before answering yes.
The repository also provides vde2, without which
Marionnet does not work and which no RPM distribution offers (checked on
Rocky 9 with EPEL, CRB and epel-next, and on Fedora 42 and 44). The
project compiles it from the Debian source package, and dnf finds it in
the same repository: you have nothing to do. openSUSE provides its own
vde2, and that is the one installed.
The data packages are the three of § 1.A, under the same names and for the same reasons. dnf installs none of them by itself:
# on openSUSE: sudo zypper install ...
sudo dnf install marionnet-kernels marionnet-fs-guignol
# not on RHEL 10, see below
sudo dnf install marionnet-kernels-i386The 32-bit kernel needs no equivalent of
dpkg --add-architecture here: these distributions install
32-bit libraries next to 64-bit ones without prior setup.
RHEL 10 has removed all 32-bit libraries:
marionnet-kernels-i386 cannot be installed there. Without a
32-bit kernel, neither guignol nor wheezy, hence no
router on the RHEL 10 family. This is temporary: a 64-bit
router image is planned. It is also why this kernel is a separate
package: its refusal does not prevent installing the rest.
Whatever the method, go on to § 2 (images and kernels), then § 3 (sudoers rule) and § 4 (launch).
An archive that installs anywhere, without a package manager.
marionnet-install.sh picks the right one and installs it
for you.
The archive is named
marionnet_<version>-r<rev>_<arch>_glibc<x.y>.tar.xz.
The last two fields decide everything: it runs on a machine of
architecture <arch> whose glibc is at least
<x.y>. It is compiled on the oldest system served
(today Debian 11, glibc 2.31, as its name says); Ubuntu 18.04 and Debian
10 therefore refuse it, naming the glibc.
This form is not signed. The SHA256SUMS
file, which the installer checks while downloading, proves that the
archive arrived whole, not who wrote it: it comes from the same server.
If that difference matters to you, take § 1.A or § 1.B.
The simplest is to let the installer pick the archive and install it:
wget https://www.marionnet.org/download/marionnet-install.sh/marionnet-install.sh
bash marionnet-install.sh --binary --with-deps--binary needs root, and calls sudo if you
are not root. To see what is published before installing anything,
including what your machine would refuse and why:
bash marionnet-install.sh --binary --fetch-only --list--list comes with a mode (--binary here):
the mode says whether the application, the images, or both interest you,
and the script does not guess it. Under its other name,
marionnet-get-images, the mode is implicit (§ 2).
You can also install the archive by hand:
xz -dc -T0 marionnet_<...>.tar.xz | tar xf -
cd marionnet_<...>/ && sudo ./install.sh --prefix /usr/localinstall.sh is the same script in both cases: the
installer only runs the one that travels in the archive. It copies
bin/ and share/ under the prefix, writes
/etc/marionnet/marionnet.conf (which is what lets the
archive live anywhere) and grants the sudoers rule (§ 3). By default it
names the missing apt packages without installing anything;
--with-deps installs them, --no-deps does not
even look. Its --help lists the rest.
The list of packages Marionnet needs to run is in the archive, one
name per line, in the file REQUIRED-PACKAGES-RUNTIME. They
are Debian names, the only ones --with-deps can install. On
another family, install their equivalents yourself; on Fedora and the
RHEL family, prefer § 1.B, since vde2 is only found in
Marionnet's own dnf repository. On a system of the Debian family, by
hand:
sudo apt install $(tr '\n' ' ' < REQUIRED-PACKAGES-RUNTIME)Whatever the method, go on to § 2 (images and kernels), then § 3 (sudoers rule) and § 4 (launch).
For whoever wants to modify Marionnet. It takes OCaml 5.4.1 (through opam) and camlp4; the images and the kernels still come from § 2.
Beforehand, only git and make are needed:
on Debian or Ubuntu, make dependencies installs the rest
(opam, the C compiler, the GTK libraries).
git clone https://git.launchpad.net/marionnet && cd marionnet
# apt packages (build and run time), opam environment and packages
make dependencies
# in every new shell: put the opam environment in the PATH
eval $(opam env)
# a fresh clone needs nothing else
dune build
# the target calls sudo itself, for the one step that needs it
make install-final-as-rootTo see the steps of make dependencies one by one, run
them separately: make apt-dependencies,
make opam-switch, make opam-dependencies.
Two things to know:
dune build does not check the whole project: for an
executable, dune only compiles what marionnet.ml uses.
make check compiles every module.make install-for-testing. When
you switch from one installation to the other,
make rebuild-for-final or
make rebuild-for-testing recompile: the prefix is written
into the program.make install-for-testing also grants the sudoers rule to
your account. The doors (§ 3) cannot stay in your opam environment,
which belongs to you: the target therefore copies them, as root, into
/usr/local/bin, then grants block (a). It asks for your
sudo password to do so.
make install-for-testing WITH_SUDOERS=no installs nothing
privileged.
Whatever the method, go on to § 2 (images and kernels), then § 3 (sudoers rule) and § 4 (launch).
marionnet-get-images shows the published images and
kernels as a checklist, and installs what you check, where the
application looks for them.
Whatever the method that installed the application:
marionnet-get-imagesIt is another name of marionnet-install.sh (§ 1.C),
installed with the application. You need it for the Debian images; if
guignol is enough for you and you installed the data packages (§ 1.A, §
1.B), you can skip it.
Run it under your own account (it calls sudo when the
destination is not writable) or as root.
For a whole lab, or in a deployment script,
marionnet-get-images --yes takes the whole selection
without asking anything. --only <pattern> and
--exclude <pattern> narrow it.
An image already installed appears checked and greyed out. The
command recognises it by its modification time, which must be the one
its .conf file records (the MTIME field): it
is also what the UML kernel checks on the base image of a virtual
machine.
Do not give --prefix after a package
installation. Without --prefix, the images go
where the installed Marionnet looks for them, which the command asks
marionnet --paths: /usr/share/marionnet/...
for a package, /usr/local/share/marionnet/... for an
archive. A --prefix typed by hand puts the images in a
directory the application never reads. Nothing fails, and the images do
not appear.
The two large images, Debian wheezy and Debian trixie, are kept out of apt and dnf on purpose: they weigh several gibibytes. The small guignol image and the kernels also exist as packages (§ 1.A, § 1.B), if you prefer your package manager to take care of them.
A computer lab without Internet access. Make a copy
(a mirror) of the publication directory once. The file
SHA256SUMS lists everything it contains, and serves the
installer as a catalogue:
# once, on a machine that has Internet access (about 1.5 GiB, compressed)
U=https://www.marionnet.org/download/marionnet-install.sh/1.0.x
mkdir -p /srv/marionnet-mirror && cd /srv/marionnet-mirror
wget "$U/SHA256SUMS"
awk -v u="$U" '{ print u "/" $2 }' SHA256SUMS | wget -i -
sha256sum -c SHA256SUMSThen point every machine at that copy: the installer accepts a local
directory as it does an address. --fetch-only installs
every published kernel and image (about 7 GiB once unpacked), and
marionnet-install.sh is installed with the application,
whatever the method:
# --yes: no confirmation asked, for a deployment script
marionnet-install.sh --fetch-only --from /srv/marionnet-mirror --yesMarionnet creates its network interfaces with iproute2,
which needs a sudoers rule. No package sets it: a package cannot know
which accounts the machine is meant for. The administrator grants it
once.
As administrator:
sudo marionnet-sudoers.sh install <login>...This command grants block (a), without which Marionnet cannot create
any network interface. The install.sh of the precompiled
archive grants it for you (unless given --no-sudoers), as
does make install-for-testing (§ 1.D). To remove
everything: sudo marionnet-sudoers.sh uninstall.
The rule allows doors, not commands. None of the
three blocks names ip, iptables or
sysctl. Each names a door, which accepts only a closed list
of actions, and which checks its arguments as root before acting.
| Block | Door | Actions allowed |
|---|---|---|
| (a) | marionnet-tap.sh, and
marionnet-tun-device.sh (which makes
/dev/net/tun usable on a host where it is not) |
4, plus 1 |
| (b) | marionnet-natbridge.sh priv, plus
marionnet-dnsmasq.sh (the DHCP and DNS service) and
marionnet-ipv6.sh |
24, plus 3 and 2 |
| (c) | marionnet-lanbridge.sh priv |
12 |
Marionnet's interfaces and bridges carry a process number in their
name. The former rules therefore had to put a * inside an
argument. But sudo-rs, the sudo of Ubuntu
26.04, rejects the whole file as soon as it meets one: measured on
ubuntu:26.04, each of those rules refused, nothing
installed. The doors solved the problem.
A door must belong to root, and so must every directory above
it. A NOPASSWD rule naming a script its owner can
replace gives a root shell to that owner. install therefore
refuses in that case, naming the faulty path and the chown
or chmod that would fix it.
A precompiled archive installed in your home directory cannot receive
the rule as it is: its doors are under a directory that belongs to you.
print and check still work there, and show the
rules with the refusal written into them.
Each install adds to the permissions already given:
granting a second person takes nothing away from the first.
sudo marionnet-sudoers.sh uninstall <login> removes
one permission and leaves the others. An account that does not exist is
refused: sudoers would accept it, and the right would go to the first
account later created under that name.
You can grant an account, or a group, written as in
sudoers (%group). That is what a computer lab needs:
whoever prepares it does not yet know the students' accounts.
# if the site has no group of its own yet
sudo groupadd marionnet
# each account (or use the existing LDAP/AD group)
sudo gpasswd -a <login> marionnet
sudo marionnet-sudoers.sh install %marionnetEvery member of the group is then allowed, including whoever joins next week. Students without sudo rights will also need the NAT bridge, granted in advance (§ 3.3).
ALL (everyone) is refused: it would include the system
accounts, and what a file grants must have been decided by someone. Up
to version 1.0.423, a member of an allowed group could also create an
interface belonging to someone else. That is no longer possible: the
owner of the interface is the account that sudo names as
the caller.
Checking a permission.
sudo -l -U <login> gives the effective rights of an
account. marionnet-sudoers.sh check only knows the accounts
and groups the file names: a member of an allowed group is not one of
them. Without arguments, check answers about the file
through its exit code:
| Code | What it means |
|---|---|
| 0 | the file is up to date for the accounts it names |
| 1 | nothing is granted |
| 4 | granted, but written by an older version of Marionnet;
check --explain lists the commands an update would gain and
lose, and marionnet-sudoers.sh install updates without
removing anyone's right |
| 5 | the file is right, but sudo does not apply it (below) |
Code 5. In sudoers, the last rule that matches wins.
A broader rule read after ours cancels every one of our
NOPASSWD lines without changing a byte of our file.
A file /etc/sudoers.d/student contains
student ALL=(ALL:ALL) ALL. It is read after
marionnet (alphabetical order), and sudo asks for a
password at each of Marionnet's actions. Reinstalling changes nothing;
renaming the broad file so that it is read first solves the problem,
since our rules then come last and win:
# find the broad rule
sudo -ll ; ls /etc/sudoers.d/
sudo mv /etc/sudoers.d/student /etc/sudoers.d/00-studentcheck asks sudo itself, once per block, because the
winning rule is decided file by file: a neighbour read after
marionnet-lanbridge cancels the LAN bridge and nothing
else. It does so by running a harmless action of that block's door.
sudo -l would not do: it says whether an account may run
the command, not whether it may without a password.
To read before granting anything beyond block (a). The three blocks
are three files in /etc/sudoers.d/, granted at different
times, and they do not have the same effects on the host machine.
| Block | Granted | What it allows doing to the host machine |
|---|---|---|
| (a) interfaces of the virtual machines | at installation, by the administrator | Create and destroy mtap* interfaces, give them the
address 172.23.0.254/32 and route 172.23.* to
them. |
| (b) NAT bridge | when used, from Marionnet | Build a private bridge mnbr*, and translate the
addresses (NAT) of the virtual machines behind it. |
| (c) LAN bridge | when used, from Marionnet | Put the network card of the host machine into a bridge, to place the virtual machines on the real local network. |
(a), in detail. The block only touches
mtap* interfaces, and the door checks it, as root: the four
actions of marionnet-tap.sh check the name they are given,
and the owner of the interface is the account that sudo
names as the caller, not an argument. These interfaces are also the path
of the graphical applications of the virtual machines: an
xterm, or above all a wireshark started inside
a virtual machine to watch its own traffic, shows up on the host's
screen through this path. Marionnet opens it with
xhost +172.23.0.254. Without this block, no graphical
application opens from the virtual machines. Routers have no graphical
applications: traffic is watched there with tcpdump.
(b), in detail. The block:
mnbr* carrying the .1/24
address of a private network;net.ipv4.ip_forward to 1, which applies to the
whole machine (Marionnet sets it back to 0 on teardown only if it had
set it to 1 itself);MASQUERADE rule and two FORWARD
rules with iptables, all marked with the comment
marionnet-natbridge:mnbr*. The door writes that marker,
from a bridge name it has just checked: no existing rule of your
firewall can be added, changed or deleted by this block;dnsmasq bound to that bridge
alone, for the DHCP (.100 to .200) and the DNS
of the virtual machines (hence the dependency on
dnsmasq-base, which the packages install with
Marionnet);/64 address, Router
Advertisements sent by the same dnsmasq, and NAT66 with
ip6tables.IPv6 forwarding is not set interface by interface: enabling it turns
the whole host machine into a router, and a router ignores the
advertisements it receives. A tiny door without arguments,
marionnet-ipv6.sh, therefore saves the value of
accept_ra and restores it.
The host's card, its addresses and its routes are never named in this block: it cannot touch them.
(c), in detail: it is the network of the host machine, and it
cannot be fenced in. A LAN bridge enslaves the host's card to
the bridge mnlan0. The host's IPv4 address and default
route move onto the bridge, which also takes the card's MAC address.
There is a single one per machine (a card has only one master bridge),
and two Marionnet sessions share it.
To weigh before granting (c):
marionnet-lanbridge.sh priv,
which decides as root which card it may touch: the one a Marionnet LAN
bridge names in its alias, and no other.In plain words, this block lets an account move the machine's IPv4
address and default route onto a bridge, one card at a time, as long as
that bridge claims it. There is no iptables, no NAT, and no
IPv6 (not handled at all).
Wi-Fi is refused: an access point does not answer several MAC addresses behind a single association. Also refused: a card already enslaved to someone else's bridge, and an ambiguous default route.
This is the default, and there is nothing to do to get it. An
install without options grants only (a), and the bridge
blocks are never granted at installation. When a user starts a NAT
bridge or a LAN bridge, Marionnet asks for their own
sudo password, and installs the block. Block (c) is therefore reserved
to the accounts that have sudo rights.
To give a lab the NAT bridge in advance, without a password and without ever granting (c):
sudo marionnet-sudoers.sh install --enable-natbridge %marionnetThis command also grants (a): it is the only one needed. To remove a block and keep (a):
# for every account
sudo marionnet-sudoers.sh uninstall --disable-natbridge
# for one account
sudo marionnet-sudoers.sh uninstall --disable-natbridge <login>Removing a permission does not stop the next user from asking for it again from Marionnet, with their own password. An administrator who wants no LAN bridge on this machine, ever and for anyone, says so once:
sudo marionnet-sudoers.sh deny --lanbridge # or --natbridge, or --bridgesAs long as this ban is in place:
sudo marionnet-sudoers.sh allow --lanbridge lifts the
ban, without granting anything: a user must still ask. Anyone can check
the state, without privileges:
# exit code 0 if the block is allowed, 3 if it is forbidden; it says which
marionnet-sudoers.sh policyThe ban is a file in /etc/marionnet/, readable by
everyone on purpose: Marionnet must know the answer before
asking for a password, and the files in /etc/sudoers.d/ are
readable by root only.
Block (a) has no ban: the administrator grants it by hand, and not
typing the command is enough. A ban stops a mistake, not a determined
administrator, who can always edit /etc/sudoers.d/. It is
useful in the usual setup of a lab, with a teacher who has sudo rights
and students who do not: that is where a LAN bridge gets built by
accident.
marionnet # or: marionnet -r lab.mar, marionnet --exam, marionnet --helpmarionnet is the name all the pages of this
documentation use. It is a symbolic link to
marionnet.native, the name dune install gives
the executable: the same program.
To know whether this installation is the one you think it is, whatever the method:
marionnet -v # version and revision
marionnet --paths # where this installation looks for images, kernels and scriptsIf the images do not appear, --paths shows the
directories where the installation really looks for them (§ 2).
To know whether anything is left to do, the command is the one the apt and dnf packages run after installation; you may already have read its output:
# as root, so that the sudoers file is examined too
marionnet-setup-check.shIt says nothing when nothing is missing. Otherwise it names what is missing: the state of the sudoers rule (§ 3.1), the missing images and kernels, the command that would fetch them. On an outdated permission, it shows the commands an update would gain and lose, on this machine.
sudo apt purge marionnet marionnet-kernels marionnet-kernels-i386 marionnet-fs-guignolsudo dnf remove marionnet marionnet-kernels marionnet-kernels-i386 marionnet-fs-guignol
(sudo zypper remove ... on openSUSE)README file
it contains lists what to delete, prefix by prefix.In all three cases, removal leaves in place:
sudo marionnet-sudoers.sh uninstall;marionnet-get-images (§ 2), which
belong to no package. Before removing, marionnet --paths
tells where they are.| What you see | What it is |
|---|---|
server down, no route, wrong URL?, while the site
answers |
no certificates: § 1 |
apt says the repository is ignored, and apt-get update
still returns 0 |
same cause, or the repository line was edited; apt only reports it as a warning |
Missing key <fingerprint>, or
signature verification failed |
the file in /etc/apt/keyrings/ is not the archive key:
fetch it again (§ 1.A) and compare the fingerprint |
| apt still offers the package although it just refused the repository | it reuses the old index:
sudo rm -rf /var/lib/apt/lists/* then
sudo apt update |
Failed to import OpenPGP keys, or dnf announces a
repository without packages |
the key file of § 1.B is missing, was not accepted, or is not a key: fetch it again and check the fingerprint before importing it |
| the precompiled archive is refused, naming a glibc | your distribution is older than the build system: § 1.C |
marionnet-kernels-i386 is refused, naming
libc6:i386 |
dpkg --add-architecture i386: § 1.A |
| Marionnet starts, but the images do not appear | they are under a prefix the application does not read: § 2, then
marionnet --paths |
| Unsatisfied dependency at startup | vde2 or graphviz is missing; the archive's
install.sh names what is missing, --with-deps
installs it |
| a virtual machine refuses to start, the interfaces cannot be created | the sudoers rule: § 3 |
nothing opens when wireshark or xterm is
started inside a virtual machine |
block (a) is not granted (§ 3.2), or the host has no X display |
marionnet-sudoers.sh install refuses, naming a path and
an owner |
a door must belong to root, with all its parent directories: § 3. Typical of an installation in a directory that belongs to you |
| the rule is installed, and sudo still asks for a password | a broader rule in /etc/sudoers.d/ is read after ours
and wins: § 3.1, code 5 |
visudo or sudo rejects the whole file on
Ubuntu 26.04 |
rules written by a Marionnet older than the doors:
sudo marionnet-sudoers.sh install <login> rewrites
them (§ 3) |
| the check keeps saying the permission is outdated, whatever you do | a Marionnet older than the one of this page, on an RPM distribution:
its check needed diff, absent from those systems. Update
Marionnet |
These pages are installed next to this one. They are in the
doc-src/ directory of the source repository, which also
publishes the archive key of § 1.A and § 1.B:
git clone https://git.launchpad.net/marionnet| Page | Read it to |
|---|---|
INSTALL.FR.md |
read this page in French |
teacher-guide.md |
prepare a lab, run the session, grade it |
scripting/README.md |
drive Marionnet from a script |
exam-mode.md |
see what an exam session records |
project-format-v3.md |
know the format of .mar projects |