Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Support /etc/ostree/config.d/ and use it to support user-configured top-level symlinks #2681

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

jlebon
Copy link
Member

@jlebon jlebon commented Jul 29, 2022

The first commit adds support for users to drop configs in /etc/ostree/config.d. The second commit makes use of it to support users configuring top-level symbolic links. See individual commit messages for details.

Example using Fedora CoreOS:

$ cat config-toplevel-symlinks.bu
variant: fcos
version: 1.4.0
storage:
  disks:
    - device: /dev/disk/by-id/coreos-boot-disk
      partitions:
        - start_mib: 8000
          label: foobar
  filesystems:
    - device: /dev/disk/by-partlabel/foobar
      format: xfs
      with_mount_unit: true
      path: /var/foobar
  files:
    - path: /etc/ostree/config.d/01-foobar.conf
      contents:
        inline: |
          [toplevel-links]
          foobar=/var/foobar

$ cosa run -B config-toplevel-symlinks.bu -x 'sudo touch /foobar/bazboo && ls -l /foobar /foobar/'
lrwxrwxrwx. 1 root root 11 Jul 29 22:37 /foobar -> /var/foobar

/foobar/:
total 0
-rw-r--r--. 1 root root 0 Jul 29 22:37 bazboo

The sysroot handling of libostree supports multiple knobs specified in
the system repo keyfile. E.g. `sysroot.bootloader`, `sysroot.readonly`,
etc...

One issue is that all the knobs so far have been "vendor-oriented". I.e.
they're not necessarily something we expect users to directly modify.

I'd like to add more sysroot configurable knobs which we *do* expect
users to modify, but I don't want them to modify the main config
directly and mix with knobs they really shouldn't touch. It's also not
convenient to modify in a provisioning flow.

Add a new concept of a "user config" which is a config obtained by
merging all the configs in `/etc/ostree/config.d`. Now, there's no
official API for merging `GKeyFile` objects, but the parser has the
right semantics if we simply concatenate all the configs and parse the
resulting final config: keys are merged into the same group and later
keys override earlier keys. Appending to a string list is not supported,
but we can design our knobs so that this is not an issue.

We don't want user configs to be able to override e.g. `core.mode`. We
only want to support specific keys in those configs (but for
consistency, also in the primary config). So keep it as a separate
`user_config` object.
A semi-common topic that comes up with libostree is the lack of support
for top-level entries. The main reason for this is that OSTree cycles
deployments all the time and so we don't want users to store data there.
But we do want to be nice to e.g. applications which expect a specific
top-level path to exist or users who are used to mounting things at the
root.

Add support for user-configurable symlinks provided via the new user
configs. The configuration looks like this:

```
[toplevel-links]
foobar=/var/foobar
```

OSTree will create the symlinks everytime a new deployment is created.

Add a hidden `ostree admin create-toplevel-user-links` command which can
be used by provisioning code to create the symlinks on first boot so
that it takes effect on the pre-existing deployment.

I initially also supported configuring empty immutable directories
(which would only be useful as mountpoints), but this becomes much
harder to support in a provisioning flow via Ignition. We can still
support it in libostree if wanted, and just not expose it in
Ignition-based downstreams. The nice thing with symlinks is that it
matches all the other default symlinks pointing into `/var` to reinforce
that all user data must remain there.

Closes: coreos/rpm-ostree#337
@openshift-ci
Copy link

openshift-ci bot commented Jul 29, 2022

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

jlebon added a commit to jlebon/fedora-coreos-config that referenced this pull request Jul 29, 2022
With this, users can specify an Ignition config like

```yaml
variant: fcos
version: 1.4.0
storage:
  files:
    - path: /etc/ostree/config.d/01-foobar.conf
      contents:
        inline: |
          [toplevel-links]
          foobar=/var/foobar
```

and on first boot, a `/foobar` symlink will be created.

Requires: ostreedev/ostree#2681
jlebon added a commit to jlebon/fedora-coreos-config that referenced this pull request Jul 29, 2022
With this, users can specify an Ignition config like

```yaml
variant: fcos
version: 1.4.0
storage:
  files:
    - path: /etc/ostree/config.d/01-foobar.conf
      contents:
        inline: |
          [toplevel-links]
          foobar=/var/foobar
```

and on first boot, a `/foobar` symlink will be created.

Requires: ostreedev/ostree#2681
Related: coreos/rpm-ostree#337
@jlebon
Copy link
Member Author

jlebon commented Jul 29, 2022

I encountered https://gitlab.gnome.org/GNOME/libglnx/-/merge_requests/41 while hacking on this, which took me some time to figure out!

@cgwalters
Copy link
Member

Today, the ostree-ext container logic discards everything not in /usr (or /etc). But, we could choose to make it as easy to do this as:

FROM quay.io/coreos-assembler/fcos:testing-devel
RUN mkdir /nix

@cgwalters
Copy link
Member

(hmm also really need to fix ostree container commit to warn about content outside of /usr and /etc, not just special case /var)

@jlebon
Copy link
Member Author

jlebon commented Aug 2, 2022

Today, the ostree-ext container logic discards everything not in /usr (or /etc). But, we could choose to make it as easy to do this as:

Sure, I think this could make sense to support in the container flow. Do you think it obviates native support for it in libostree? The UX described in the demo above is quite streamlined in comparison. (There's also the question of whether other downstreams not planning to ship their OS as a container would be interested in this.)

@cgwalters
Copy link
Member

Do you think it obviates native support for it in libostree?

I'd say there's clearly room for both.

The UX described in the demo above is quite streamlined in comparison.

I find this a bit more debatable 😄

(There's also the question of whether other downstreams not planning to ship their OS as a container would be interested in this.)

True!

Basically I'm roughly 👍 if you want to drive this in.


self->user_config = g_key_file_new ();

/* we want g_key_file_load_from_fd() but that's private */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm...I think I would say it's simpler to read the configs into e.g. a GString or a GMemoryOutputStream.

@jlebon
Copy link
Member Author

jlebon commented Aug 4, 2022

The UX described in the demo above is quite streamlined in comparison.

I find this a bit more debatable 😄

Heh fair. The mkdir is definitely nicer. Just the barrier to entry to get there is higher.

Basically I'm roughly 👍 if you want to drive this in.

OK cool! In that case, I'll enhance it to support directories too. It'd be good to support anyway, but also I think I've ironed out a not-too-hacky way to support it on first boot via Ignition.

@cgwalters
Copy link
Member

I know I wrote this somewhere else but I can't find it right now:

Another approach that would work both client and server side is to support e.g. /etc/ostree/toplevel and /usr/lib/ostree/toplevel.

Then the UX flow (instead of frobbing a config file) for making a toplevel dir is just:
mkdir -p /etc/ostree/toplevel/nix

(OK and...hm, we'd need a command to re-reconcile this, might as well support it live; don't want to wait to do an upgrade to process it)

A key idea here is that the description of the root directory is captured in /usr.

@cgwalters
Copy link
Member

cgwalters commented Mar 23, 2023

I'm still increasingly thinking we should relax the "content in /usr" restriction in ostree and just allow people to put at least empty directories wherever (except /var).

That said, today one can do this via a systemd unit with ExecStart e.g. in a systemd unit:

[Service]
Type=oneshot
ExecStart=chattr -i / && mkdir /afs && chattr +i /
RemainAfterExit=yes

Then one can have a regular mount unit mount it that's ordered After= that unit (or just also run mount from the service unit).

@openshift-ci
Copy link

openshift-ci bot commented Jun 29, 2023

@jlebon: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/images 746e342 link true /test images
ci/prow/fcos-e2e 746e342 link true /test fcos-e2e

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants