Skip to content

Commit

Permalink
Add concept of state overlays
Browse files Browse the repository at this point in the history
In the OSTree model, executables go in `/usr`, state in `/var` and
configuration in `/etc`. Software that lives in `/opt` however messes
this up because it often mixes code *and* state, making it harder to
manage.

More generally, it's sometimes useful to have the OSTree commit contain
code under a certain path, but still allow that path to be writable by
software and the sysadmin at runtime (`/usr/local` is another instance).

Add the concept of state overlays. A state overlay is an overlayfs
mount whose upper directory, which contains unmanaged state, is carried
forward on top of a lower directory, containing OSTree-managed files.

In the example of `/usr/local`, OSTree commits can ship content there,
all while allowing users to e.g. add scripts in `/usr/local/bin` when
booted into that commit.

Some reconciliation logic is executed whenever the base is updated so
that newer files in the base are never shadowed by a copied up version
in the upper directory. This matches RPM semantics when upgrading
packages whose files may have been modified.

For ease of integration, this is exposed as a systemd template unit which
any downstream distro/user can enable. The instance name is the mountpath
in escaped systemd path notation (e.g.
`[email protected]`).

See discussions in #3113 for
more details.
  • Loading branch information
jlebon committed Jan 10, 2024
1 parent 062cf60 commit 92b1a27
Show file tree
Hide file tree
Showing 9 changed files with 588 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Makefile-boot.am
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ systemdsystemunit_DATA = src/boot/ostree-prepare-root.service \
src/boot/ostree-finalize-staged.service \
src/boot/ostree-finalize-staged.path \
src/boot/ostree-finalize-staged-hold.service \
src/boot/[email protected] \
$(NULL)
systemdtmpfilesdir = $(prefix)/lib/tmpfiles.d
dist_systemdtmpfiles_DATA = src/boot/ostree-tmpfiles.conf
Expand Down Expand Up @@ -72,6 +73,7 @@ EXTRA_DIST += src/boot/dracut/module-setup.sh \
src/boot/ostree-remount.service \
src/boot/ostree-finalize-staged.service \
src/boot/ostree-finalize-staged-hold.service \
src/boot/[email protected] \
src/boot/grub2/grub2-15_ostree \
src/boot/grub2/ostree-grub-generator \
$(NULL)
10 changes: 9 additions & 1 deletion Makefile-man.am
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,17 @@ endif

man5_files = ostree.repo.5 ostree.repo-config.5

man8_files = [email protected]

man1_MANS = $(addprefix man/,$(man1_files))
man5_MANS = $(addprefix man/,$(man5_files))
man8_MANS = $(addprefix man/,$(man8_files))

manhtml_files = \
man/html/index.html \
$(addprefix man/html/,$(man1_files:.1=.html)) \
$(addprefix man/html/,$(man5_files:.5=.html)) \
$(addprefix man/html/,$(man8_files:.8=.html)) \
$(NULL)

if ENABLE_MAN_HTML
Expand All @@ -65,7 +69,7 @@ noinst_DATA += $(manhtml_files)
manhtml: $(manhtml_files)
endif

EXTRA_DIST += man/index.xml $(man1_MANS:.1=.xml) $(man5_MANS:.5=.xml)
EXTRA_DIST += man/index.xml $(man1_MANS:.1=.xml) $(man5_MANS:.5=.xml) $(man8_MANS:.8=.xml)

XSLT_MAN_STYLESHEET = http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl
XSLT_HTML_STYLESHEET = man/html.xsl
Expand All @@ -87,13 +91,17 @@ XSLTPROC_MAN = $(XSLTPROC) $(XSLTPROC_FLAGS)
%.5: %.xml
$(AM_V_GEN) $(XSLTPROC_MAN) --output $@ $(XSLT_MAN_STYLESHEET) $<

%.8: %.xml
$(AM_V_GEN) $(XSLTPROC_MAN) --output $@ $(XSLT_MAN_STYLESHEET) $<

man/html/%.html: man/%.xml
@mkdir -p man/html
$(AM_V_GEN) $(XSLTPROC_MAN) --output $@ $(XSLT_HTML_STYLESHEET) $<

CLEANFILES += \
$(man1_MANS) \
$(man5_MANS) \
$(man8_MANS) \
$(manhtml_files) \
$(NULL)

Expand Down
1 change: 1 addition & 0 deletions Makefile-ostree.am
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ ostree_SOURCES += \
src/ostree/ot-admin-builtin-post-copy.c \
src/ostree/ot-admin-builtin-upgrade.c \
src/ostree/ot-admin-builtin-unlock.c \
src/ostree/ot-admin-builtin-state-overlay.c \
src/ostree/ot-admin-builtins.h \
src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c \
src/ostree/ot-admin-instutil-builtin-set-kargs.c \
Expand Down
107 changes: 107 additions & 0 deletions man/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<!--
Copyright 2023 Red Hat Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
-->

<refentry id="[email protected]">

<refentryinfo>
<title>ostree-state-overlay</title>
<productname>ostree</productname>

<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Jonathan</firstname>
<surname>Lebon</surname>
<email>[email protected]</email>
</author>
</authorgroup>
</refentryinfo>

<refmeta>
<refentrytitle>ostree-state-overlay</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>

<refnamediv>
<refname>[email protected]</refname>
<refpurpose>Set up state overlays</refpurpose>
</refnamediv>

<refsynopsisdiv>
<para><filename>[email protected]</filename></para>
</refsynopsisdiv>

<refsect1>
<title>Experimental</title>
<para>
<emphasis role="bold">Note this feature is currently considered
experimental.</emphasis> It may not work correctly and some of its
semantics may be subject to change. Positive or negative feedback are both
welcome and may be provided at
<ulink url="https://github.com/ostreedev/ostree/discussions"/>. If using
the feature via rpm-ostree, feedback may also be provided at
<ulink url="https://github.com/coreos/rpm-ostree/issues/233"/>.
</para>
</refsect1>

<refsect1>
<title>Description</title>
<para>
In some cases, it's useful to be able to have a directory as part of the
OSTree commit yet still have this directory be writable client-side. One
example is software that ships in <filename>/opt</filename>.
<filename>/opt</filename> is its own vendor-namespaced alternate file
hierarchy which may contain both code and state. With state overlays, it's
possible to have the code part baked in the OSTree, but still allowing the
directory to be writable so that state can be kept there.
</para>

<para>
Since it's writable, nothing prevents sufficiently privileged code to
modify or delete content that comes from the OSTree commit. This is in
sharp contrast with content in <filename>/usr</filename>, and more
closely matches a package manager-based distro.
</para>

<para>
Crucially, this state is automatically rebased during upgrades (or more
generally, anytime a different OSTree commit is booted). The semantics
of the rebase are as follows: any state file or directory that modified
OSTree content is deleted, otherwise it is kept and merged onto the new
base content (using overlayfs). This mostly matches the semantics of a
package manager.
</para>

<para>
To enable this feature, simply instantiate the unit template, using the
target path (in escaped systemd path notation) as the instance name. For
example, to enable it on <filename>/opt</filename>:
</para>

<literallayout>
$ systemctl enable --now [email protected]
</literallayout>

</refsect1>

</refentry>
36 changes: 36 additions & 0 deletions src/boot/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright (C) 2023 Red Hat Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <https://www.gnu.org/licenses/>.

[Unit]
Description=OSTree State Overlay On /%I
Documentation=man:ostree(1)
DefaultDependencies=no
ConditionKernelCommandLine=ostree
# run after /var is setup since that's where the upperdir is stored
# and after boot.mount so we can load the sysroot
After=var.mount boot.mount
# but before local-fs.target, which we consider ourselves a part of
Before=local-fs.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/ostree admin state-overlay %i /%I
StandardInput=null
StandardOutput=journal
StandardError=journal+console

[Install]
WantedBy=local-fs.target
Loading

0 comments on commit 92b1a27

Please sign in to comment.