mirror of
https://github.com/QubesOS/qubes-doc.git
synced 2024-12-18 12:14:42 -05:00
444 lines
12 KiB
ReStructuredText
444 lines
12 KiB
ReStructuredText
================
|
||
Template manager
|
||
================
|
||
|
||
|
||
This document discusses the designs and technical details of
|
||
``qvm-template``, a template manager application. The goal of the
|
||
project is to design a new mechanism for template distribution and a
|
||
unified tool for template management.
|
||
|
||
Motivation
|
||
----------
|
||
|
||
|
||
This project was originally proposed in the 2020 Google Summer of Code
|
||
program.
|
||
|
||
Previously, templates were distributed by RPM packages and managed by
|
||
``yum``/``dnf``. However, tracking inherently dynamic VM images with a
|
||
package manager suited for static files creates some challenges. For
|
||
example, users may accidentally update the images, overriding local
|
||
changes (`#996 <https://github.com/QubesOS/qubes-issues/issues/996>`__,
|
||
`#1647 <https://github.com/QubesOS/qubes-issues/issues/1647>`__). (Or in
|
||
the case of
|
||
`#2061 <https://github.com/QubesOS/qubes-issues/issues/2061>`__, want to
|
||
specifically override the changes.) Other operations that work well on
|
||
normal VMs are also somewhat inconsistent on RPM-managed templates. This
|
||
includes actions such as renaming
|
||
(`#839 <https://github.com/QubesOS/qubes-issues/issues/839>`__), removal
|
||
(`#5509 <https://github.com/QubesOS/qubes-issues/issues/5509>`__) and
|
||
backup/restore
|
||
(`#1385 <https://github.com/QubesOS/qubes-issues/issues/1385>`__,
|
||
`#1453 <https://github.com/QubesOS/qubes-issues/issues/1453>`__,
|
||
`discussion thread 1 <https://groups.google.com/forum/#!topic/qubes-devel/rwc2_miCNNE/discussion>`__,
|
||
`discussion thread 2 <https://groups.google.com/forum/#!topic/qubes-users/uQEUpv4THsY/discussion>`__).
|
||
In turn, this creates inconveniences and confusion for users
|
||
(`#1403 <https://github.com/QubesOS/qubes-issues/issues/1403>`__,
|
||
`#4518 <https://github.com/QubesOS/qubes-issues/issues/4518>`__).
|
||
|
||
Also, the usage of RPM packages meant that installing a template results
|
||
in arbitrary code execution, which is not ideal.
|
||
|
||
Besides distribution, users may also wish to have an integrated template
|
||
management application
|
||
(`#2062 <https://github.com/QubesOS/qubes-issues/issues/2062>`__,
|
||
`#2064 <https://github.com/QubesOS/qubes-issues/issues/2064>`__,
|
||
`#2534 <https://github.com/QubesOS/qubes-issues/issues/2534>`__,
|
||
`#3040 <https://github.com/QubesOS/qubes-issues/issues/3040>`__), as
|
||
opposed to the situation where multiple programs are required for
|
||
different purposes, e.g., ``qubes-dom0-update``, ``dnf``,
|
||
``qvm-remove``, ``qubes-manager``.
|
||
|
||
To tackle these issues, ``qvm-template`` was created. It strives to
|
||
provide not only a better mechanism for handling template installation
|
||
but also a consistent user-facing interface to deal with template
|
||
management.
|
||
|
||
Features
|
||
--------
|
||
|
||
|
||
- Install/reinstall/downgrade/upgrade templates, either from local
|
||
packages or remote repositories
|
||
|
||
- Ability to install templates in alternative pools
|
||
|
||
- Possibility for the template package to specify options such as
|
||
the kernel or ``virt_mode`` used by the resulting template
|
||
|
||
|
||
|
||
- List and show information about local and available templates
|
||
|
||
- Machine-readable output for easy extension
|
||
|
||
|
||
|
||
- Search for templates
|
||
|
||
- Remove templates
|
||
|
||
- Optionally, VMs based on the template to be removed can be either
|
||
removed or “disassociated” – namely, have their templates changed
|
||
to a “dummy” one.
|
||
|
||
|
||
|
||
- Show available repositories
|
||
|
||
- Works in both dom0 and management VMs by utilizing the Admin API
|
||
|
||
- Works well with existing tools
|
||
|
||
- Command-line interface with DNF-like usage
|
||
|
||
- A graphical interface also available
|
||
|
||
|
||
|
||
Package format
|
||
--------------
|
||
|
||
|
||
The RPM package format is still used. However, the contents are manually
|
||
extracted instead of installing the whole package. This allows us to
|
||
take advantage of existing tools for things like repository management.
|
||
We can also avoid the burden of dealing with verification, reducing the
|
||
risk of issues like `QSB-028 <https://www.qubes-os.org/news/2016/12/19/qsb-28/>`__.
|
||
|
||
The package name should be in the form
|
||
``qubes-template-<TEMPLATE_NAME>``.
|
||
|
||
The package metadata (summary, description, etc.) should not contain the
|
||
``|`` character to avoid possibly cryptic errors. This is because of its
|
||
use as an internal separator. Note that as we already consider the
|
||
repository metadata untrusted. This should not result in security
|
||
issues.
|
||
|
||
The file structure should be quite similar to previous template RPMs.
|
||
Namely, there should be the following files in the package:
|
||
|
||
- ``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/root.img.part.[00,01,...]``
|
||
|
||
- Split tarball of template ``root.img``
|
||
|
||
- Note that the file is still split due to tools such as
|
||
``rpm2cpio`` not supporting large files. (Notably, the cpio format
|
||
does not support files over 4GiB.)
|
||
|
||
|
||
|
||
- ``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/template.conf``
|
||
|
||
- Stores custom package metadata (as RPM does not support custom
|
||
attributes).
|
||
|
||
- Uses ``KEY=VALUE`` format.
|
||
|
||
- Fields (corresponding to
|
||
`qvm-prefs <https://dev.qubes-os.org/projects/core-admin-client/en/stable/manpages/qvm-prefs.html#common-properties>`__
|
||
and
|
||
`qvm-features <https://dev.qubes-os.org/projects/core-admin-client/en/stable/manpages/qvm-features.html#list-of-known-features>`__
|
||
tags with the same names)
|
||
|
||
- ``virt_mode``
|
||
|
||
- Setting this to ``pv`` requires user confirmation.
|
||
|
||
- Permitted values: ``pv``, ``pvh``, ``hvm``.
|
||
|
||
|
||
|
||
- ``kernel``
|
||
|
||
- Only allowed to be set to “” (without quotes), i.e., “none”,
|
||
for PVGrub.
|
||
|
||
|
||
|
||
- Network-related flags: (Must be set to IPv4 addresses in the
|
||
form of ``x.x.x.x``.)
|
||
|
||
- ``net.fake-ip``
|
||
|
||
- ``net.fake-gateway``
|
||
|
||
- ``net.fake-netmask``
|
||
|
||
|
||
|
||
- Boolean flags: (Permitted values are “1” and “0”, denoting
|
||
“true” and “false” respectively.)
|
||
|
||
- ``no-monitor-layout``
|
||
|
||
- ``pci-e820-host``
|
||
|
||
- ``linux-stubdom``
|
||
|
||
- ``gui``
|
||
|
||
- ``gui-emulated``
|
||
|
||
- ``qrexec``
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
- ``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/whitelisted-appmenus.list``
|
||
|
||
- Contains default app menu entries of the template itself.
|
||
|
||
|
||
|
||
- ``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/vm-whitelisted-appmenus.list``
|
||
|
||
- Contains default app menu entries of VMs based on the template.
|
||
|
||
|
||
|
||
- ``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/netvm-whitelisted-appmenus.list``
|
||
|
||
- Contains default app menu entries of NetVMs based on the template.
|
||
|
||
- These three files are the same as the current format.
|
||
|
||
- Note that the contents of these files are stored in
|
||
``qvm-features`` upon installation. See the section below for
|
||
details.
|
||
|
||
|
||
|
||
|
||
|
||
Metadata storage
|
||
----------------
|
||
|
||
|
||
The template manager needs to keep metadata of installed templates such
|
||
as versions and origin. This data can be stored via ``qvm-features`` to
|
||
keep things consistent when, e.g., ``qvm-remove`` is used. Besides,
|
||
backups are also more easily handled this way.
|
||
|
||
Also, the fields can serve as an indicator of whether a template is
|
||
installed by ``qvm-template``.
|
||
|
||
Fields
|
||
^^^^^^
|
||
|
||
|
||
Most of the fields should be fairly self-explanatory.
|
||
|
||
- ``template-name``
|
||
|
||
- Note that this field needs to be consistent with the template name
|
||
to be considered valid.
|
||
|
||
|
||
|
||
- ``template-epoch``
|
||
|
||
- ``template-version``
|
||
|
||
- ``template-release``
|
||
|
||
- ``template-reponame``
|
||
|
||
- ``template-buildtime``
|
||
|
||
- ``template-installtime``
|
||
|
||
- The times are in UTC, and are of the format
|
||
``YYYY-MM-DD HH:MM:SS``.
|
||
|
||
|
||
|
||
- ``template-license``
|
||
|
||
- ``template-url``
|
||
|
||
- ``template-summary``
|
||
|
||
- ``template-description``
|
||
|
||
- Note that the newlines in this field are converted to ``|`` to
|
||
work better with existing tools like ``qvm-features``.
|
||
|
||
|
||
|
||
- ``menu-items``
|
||
|
||
- ``default-menu-items``
|
||
|
||
- ``netvm-menu-items``
|
||
|
||
- The ``*menu-items`` entries store the contents of
|
||
``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/whitelisted-appmenus.list``,
|
||
``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/vm-whitelisted-appmenus.list``,
|
||
``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/netvm-whitelisted-appmenus.list``
|
||
respectively.
|
||
|
||
- Note that newlines are converted to spaces, again for it to work
|
||
better with existing tools. This should not cause ambiguity as
|
||
`the FreeDesktop specifications <https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html>`__
|
||
forbid spaces in .desktop file names.
|
||
|
||
|
||
|
||
|
||
|
||
Repository management
|
||
---------------------
|
||
|
||
|
||
For UpdateVMs to access the repository configuration, the package
|
||
`qubes-repo-templates <https://github.com/WillyPillow/qubes-repo-templates>`__
|
||
is created with the following contents:
|
||
|
||
- ``/etc/qubes/repo-templates/*.repo``: repository configuration
|
||
|
||
- ``/etc/qubes/repo-templates/keys``: PGP keys
|
||
|
||
|
||
|
||
As template keys may be less trusted, they are *not* added to the system
|
||
RPM keychain but instead managed separately.
|
||
|
||
Qrexec protocol
|
||
---------------
|
||
|
||
|
||
Dom0 and management VMs without network access also need to interact
|
||
with template repositories. The following qrexec calls that list and
|
||
download templates are thus proposed.
|
||
|
||
- ``qubes.TemplateSearch``: wraps ``dnf repoquery``
|
||
|
||
- ``qubes.TemplateDownload``: wraps ``dnf download``
|
||
|
||
|
||
|
||
Input
|
||
^^^^^
|
||
|
||
|
||
Both calls accept the following format from standard input:
|
||
|
||
.. code:: bash
|
||
|
||
arg1
|
||
arg2
|
||
...
|
||
argN
|
||
package-file-spec
|
||
---
|
||
repo config
|
||
|
||
|
||
|
||
In other words, the input consists of two parts separated by the line
|
||
``---``. The first part contains some arguments and
|
||
``package-file-spec`` that indicates the pattern to be queried or
|
||
downloaded. The following arguments are allowed:
|
||
|
||
- ``--enablerepo=<repoid>``
|
||
|
||
- ``--disablerepo=<repoid>``
|
||
|
||
- ``--repoid=<repoid>``
|
||
|
||
- ``--releasever=<release>``
|
||
|
||
- ``--refresh``
|
||
|
||
|
||
|
||
where the usage is identical to that of DNF.
|
||
|
||
For the exact definition of ``package-file-spec``, refer to the DNF
|
||
documentation.
|
||
|
||
The second part contains the repository configurations in
|
||
``yum.repos.d`` format.
|
||
|
||
Output
|
||
^^^^^^
|
||
|
||
|
||
``qubes.TemplateSearch`` prints each package in
|
||
``%{name}|%{epoch}|%{version}|%{release}|%{reponame}|%{downloadsize}|%{buildtime}|%{license}|%{url}|%{summary}|%{description}|``
|
||
format to standard output, separated by newlines. Note that there is a
|
||
``|`` at the end of the line. This is because ``%{description}`` may
|
||
contain newlines, and doing so allows us to split the entries by
|
||
``|\n``. (As we are using ``dnf repoquery --qf``, we are unable to
|
||
escape the newlines in advance.)
|
||
|
||
``qubes.TemplateDownload``, on the other hand, directly outputs the
|
||
downloaded content to standard output.
|
||
|
||
Machine-readable output
|
||
-----------------------
|
||
|
||
|
||
The commands ``qvm-template list`` and ``qvm-template info`` provide
|
||
machine-readable output in both pipe(``|``)-separated and JSON format.
|
||
See the ``qvm-template`` man page for details.
|
||
|
||
Interactions with existing tools
|
||
--------------------------------
|
||
|
||
|
||
``qvm-remove``
|
||
^^^^^^^^^^^^^^
|
||
|
||
|
||
The existing ``qvm-remove`` tool should behave identically to
|
||
``qvm-template remove`` – albeit without fancy features like
|
||
disassociation. This is unlike the previous situation where
|
||
``qvm-remove`` cannot remove RPM-installed templates.
|
||
|
||
Notably, the metadata needs no special handling as it is stored in VM
|
||
features and thus automatically consistent.
|
||
|
||
Renaming and cloning
|
||
^^^^^^^^^^^^^^^^^^^^
|
||
|
||
|
||
A template is treated as non-manager-installed once renamed or cloned.
|
||
However, relevant metadata in the VM features is still retained for
|
||
future extension and to serve as a hint for the user.
|
||
|
||
Further reading
|
||
---------------
|
||
|
||
|
||
Initial Google Summer of Code (2020) project proposal:
|
||
|
||
- https://hackmd.io/aYauztkGR0iOIoh8fJLecw
|
||
|
||
|
||
|
||
Previous design document:
|
||
|
||
- https://gist.github.com/WillyPillow/b8a643ddbd9235a97bc187e6e44b16e4
|
||
|
||
|
||
|
||
Discussion threads:
|
||
|
||
- https://groups.google.com/forum/#!topic/qubes-devel/6Zb_WLy3GY4
|
||
|
||
- https://groups.google.com/forum/#!topic/qubes-devel/PyJogqT1TUg
|
||
|
||
- https://groups.google.com/forum/#!topic/qubes-devel/2XaMP4Us3kg
|
||
|
||
- https://groups.google.com/forum/#!topic/qubes-devel/wF_84b1BR0A
|
||
|
||
- https://groups.google.com/forum/#!topic/qubes-devel/pYHnihVCBM0
|
||
|
||
|