mirror of
https://github.com/ostreedev/ostree.git
synced 2025-01-25 10:04:14 +03:00
261 lines
11 KiB
XML
261 lines
11 KiB
XML
<?xml version="1.0"?>
|
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
|
|
<!ENTITY version SYSTEM "../version.xml">
|
|
]>
|
|
<part id="adapting-existing">
|
|
<title>Adapting existing mainstream distributions</title>
|
|
<chapter id="layout">
|
|
<title>System layout</title>
|
|
<para>
|
|
First, OSTree encourages systems to implement <ulink
|
|
url="http://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/">UsrMove</ulink>.
|
|
This is simply to avoid the need for more bind mounts. By
|
|
default OSTree's dracut hook creates a read-only bind mount over
|
|
<filename class='directory'>/usr</filename>; you can of course
|
|
generate individual bind-mounts for <filename
|
|
class='directory'>/bin</filename>, all the <filename
|
|
class='directory'>/lib</filename> variants, etc. So it is not
|
|
intended to be a hard requirement.
|
|
</para>
|
|
|
|
<para>
|
|
Remember, because by default the system is booted into a
|
|
<literal>chroot</literal> equivalent, there has to be some way
|
|
to refer to the actual physical root filesystem. Therefore,
|
|
your operating system tree should contain an empty <filename
|
|
class='directory'>/sysroot</filename> directory; at boot time,
|
|
OSTree will make this a bind mount to the physical / root
|
|
directory. There is precedent for this name in the initramfs
|
|
context. You should furthermore make a toplevel symbolic link
|
|
<filename class='directory'>/ostree</filename> which points to
|
|
<filename class='directory'>/sysroot/ostree</filename>, so that
|
|
the OSTree tool at runtime can consistently find the system data
|
|
regardless of whether it's operating on a physical root or
|
|
inside a deployment.
|
|
</para>
|
|
|
|
<para>
|
|
Because OSTree only preserves <filename
|
|
class='directory'>/var</filename> across upgrades (each
|
|
deployment's chroot directory will be garbage collected
|
|
eventually), you will need to choose how to handle other
|
|
toplevel writable directories specified by the <ulink
|
|
url="http://www.pathname.com/fhs/">Filesystem Hierarchy
|
|
Standard</ulink>. Your operating system may of course choose
|
|
not to support some of these such as <filename
|
|
class='directory'>/usr/local</filename>, but following is the
|
|
recommended set:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<filename class='directory'>/home</filename> to <filename class='directory'>/var/home</filename>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<filename class='directory'>/opt</filename> to <filename class='directory'>/var/opt</filename>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<filename class='directory'>/srv</filename> to <filename class='directory'>/var/srv</filename>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<filename class='directory'>/root</filename> to <filename class='directory'>/var/roothome</filename>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<filename class='directory'>/usr/local</filename> to <filename class='directory'>/var/local</filename>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<filename class='directory'>/mnt</filename> to <filename class='directory'>/var/mnt</filename>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<filename class='directory'>/tmp</filename> to <filename class='directory'>/sysroot/tmp</filename>
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
|
|
<para>
|
|
Furthermore, since <filename class='directory'>/var</filename>
|
|
is empty by default, your operating system will need to
|
|
dynamically create the <emphasis>targets</emphasis> of these at
|
|
boot. A good way to do this is using
|
|
<command>systemd-tmpfiles</command>, if your OS uses systemd.
|
|
For example:
|
|
</para>
|
|
|
|
<programlisting>
|
|
<![CDATA[
|
|
d /var/log/journal 0755 root root -
|
|
L /var/home - - - - ../sysroot/home
|
|
d /var/opt 0755 root root -
|
|
d /var/srv 0755 root root -
|
|
d /var/roothome 0700 root root -
|
|
d /var/usrlocal 0755 root root -
|
|
d /var/usrlocal/bin 0755 root root -
|
|
d /var/usrlocal/etc 0755 root root -
|
|
d /var/usrlocal/games 0755 root root -
|
|
d /var/usrlocal/include 0755 root root -
|
|
d /var/usrlocal/lib 0755 root root -
|
|
d /var/usrlocal/man 0755 root root -
|
|
d /var/usrlocal/sbin 0755 root root -
|
|
d /var/usrlocal/share 0755 root root -
|
|
d /var/usrlocal/src 0755 root root -
|
|
d /var/mnt 0755 root root -
|
|
d /run/media 0755 root root -
|
|
]]>
|
|
</programlisting>
|
|
|
|
<para>
|
|
Particularly note here the double indirection of <filename
|
|
class='directory'>/home</filename>. By default, each
|
|
deployment will share the global toplevel <filename
|
|
class='directory'>/home</filename> directory on the physical
|
|
root filesystem. It is then up to higher levels of management
|
|
tools to keep <filename>/etc/passwd</filename> or equivalent
|
|
synchronized between operating systems.
|
|
</para>
|
|
<para>
|
|
Each deployment can easily be reconfigured to have its own home
|
|
directory set simply by making <filename
|
|
class='directory'>/var/home</filename> a real directory.
|
|
</para>
|
|
</chapter>
|
|
|
|
<chapter id="booting">
|
|
<title>Booting and initramfs technology</title>
|
|
<para>
|
|
OSTree comes with optional dracut+systemd integration code that
|
|
parses the <literal>ostree=</literal> kernel command line
|
|
argument in the initramfs, and then sets up the read-only bind
|
|
mount on <filename class='directory'>/usr</filename>, a bind
|
|
mount on the deployment's <filename
|
|
class='directory'>/sysroot</filename> to the physical <filename
|
|
class='directory'>/</filename>, and then finally uses
|
|
<literal>mount(MS_MOVE)</literal> to make the deployment root appear to be the
|
|
root filesystem before telling systemd to switch root.
|
|
</para>
|
|
|
|
<para>
|
|
If you are not using dracut or systemd, using OSTree should still
|
|
be possible, but you will have to write the integration code. Patches
|
|
to support other initramfs technologies and init systems, if sufficiently
|
|
clean, will likely be accepted upstream.
|
|
</para>
|
|
|
|
<para>
|
|
A further specific note regarding <command>sysvinit</command>:
|
|
OSTree used to support recording device files such the
|
|
<filename>/dev/initctl</filename> FIFO, but no longer does.
|
|
It's recommended to just patch your initramfs to create this at
|
|
boot.
|
|
</para>
|
|
</chapter>
|
|
|
|
<chapter id="lib-passwd">
|
|
<title>/lib/passwd</title>
|
|
<para>
|
|
In order to ship an OS that contains both system users and users
|
|
dynamically created on client machines, you will need to choose
|
|
a solution for <filename>/etc/passwd</filename>. The core
|
|
problem is that if you add a user to the system for a daemon,
|
|
the OSTree upgrade process for <filename
|
|
class='directory'>/etc</filename> will simply notice that
|
|
because <filename>/etc/passwd</filename> differs from the
|
|
previous default, it will keep the modified config file, and
|
|
your new OS user will not be visible.
|
|
</para>
|
|
<para>
|
|
The solution chosen for the <ulink
|
|
url="https://wiki.gnome.org/GnomeOSTree">gnome-ostree</ulink>
|
|
operating system is to create <filename>/lib/passwd</filename>,
|
|
and to include a NSS module <ulink
|
|
url="https://github.com/aperezdc/nss-altfiles">nss-altfiles</ulink>
|
|
which instructs glibc to read from it. Then, the build system places
|
|
all system users there, freeing up <filename>/etc/passwd</filename>
|
|
to be purely a database of local users.
|
|
</para>
|
|
</chapter>
|
|
|
|
<chapter id="adapting-package-manager">
|
|
<title>Adapting existing package managers</title>
|
|
<para>
|
|
The largest endeavor is likely to be redesigning your
|
|
distribution's package manager to be on top of OSTree,
|
|
particularly if you want to keep compatibility with the "old
|
|
way" of installing into the physical <filename
|
|
class='directory'>/</filename>. This section will use examples
|
|
from both <command>dpkg</command> and <command>rpm</command> as
|
|
the author has familiarity with both; but the abstract concepts
|
|
should apply to most traditional package managers.
|
|
</para>
|
|
|
|
<para>
|
|
There are many levels of possible integration; initially, we
|
|
will describe the most naive implementation which is the
|
|
simplest but also the least efficient. We will assume here that
|
|
the admin is booted into an OSTree-enabled system, and wants to
|
|
add a set of packages.
|
|
</para>
|
|
|
|
<para>
|
|
Many package managers store their state in <filename
|
|
class='directory'>/var</filename>; but since in the OSTree model
|
|
that directory is shared between independent versions, the
|
|
package database must first be found in the per-deployment
|
|
<filename class='directory'>/usr</filename> directory. It
|
|
becomes read-only; remember, all upgrades involve constructing a
|
|
new filesystem tree, so your package manager will also need to
|
|
create a copy of its database. Most likely, if you want to
|
|
continue supporting non-OSTree deployments, simply have your
|
|
package manager fall back to the legacy <filename
|
|
class='directory'>/var</filename> location if the one in
|
|
<filename class='directory'>/usr</filename> is not found.
|
|
</para>
|
|
|
|
<para>
|
|
To install a set of new packages (without removing any existing
|
|
ones), enumerate the set of packages in the currently booted
|
|
deployment, and perform dependency resolution to compute the
|
|
complete set of new packages. Download and unpack these new
|
|
packages to a temporary directory.
|
|
</para>
|
|
|
|
<para>
|
|
Now, because we are merely installing new packages and not
|
|
removing anything, we can make the major optimization of reusing
|
|
our existing filesystem tree, and merely
|
|
<emphasis>layering</emphasis> the composed filesystem tree of
|
|
these new packages on top. A command lke this: <command>ostree
|
|
commit -b osname/releasename/description
|
|
--tree=ref=<replaceable>osname/releasenamename/description</replaceable>
|
|
--tree=dir=/var/tmp/newpackages.13A8D0/</command> will create a
|
|
new commit in the
|
|
<replaceable>osname/releasename/description</replaceable>
|
|
branch. The OSTree SHA256 checksum of all the files in
|
|
/var/tmp/newpackages.13A8D0/ will be computed, but we will not
|
|
re-checksum the present existing tree. In this layering model,
|
|
earlier directories will take precedence, but files in later
|
|
layers will silently override earlier layers.
|
|
</para>
|
|
|
|
<para>
|
|
Then to actually deploy this tree for the next boot:
|
|
<command>ostree admin deploy
|
|
<replaceable>osname/releasenamename/description</replaceable></command>
|
|
</para>
|
|
|
|
</chapter>
|
|
|
|
</part>
|