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

Determine support path for RPMs that install into `/opt`, `/usr/local` etc #233

Closed
cgwalters opened this issue Mar 14, 2016 · 71 comments
Closed

Comments

@cgwalters
Copy link
Member

@cgwalters cgwalters commented Mar 14, 2016

RPMs like Puppet and Google Chrome go in /opt.

For the package layering case, in this PR we made it an obvious error.

The core problem here is: OSTree defines /opt (really /var/opt) as system administrator territory - it's never rolled forward/backwards etc. Content in there isn't protected by the ro bind mount covering /usr right now.

One approach would be to - for these RPMs, automatically rewrite the content into /usr. Chrome I don't believe actually stores any persistent state in /var, so simply rewriting /opt/google/chrome -> /usr/lib/opt/google/chrome with a compatibility symlink would likely work.

Puppet probably stores state in /var and hence would be harder.

@copumpkin
Copy link
Contributor

@copumpkin copumpkin commented Mar 29, 2016

I'd support the /usr/lib/opt approach!

@cgwalters cgwalters changed the title Determine support path for RPMs that install into `/opt` Determine support path for RPMs that install into `/opt`, `/usr/local` etc Apr 1, 2016
@copumpkin
Copy link
Contributor

@copumpkin copumpkin commented Apr 4, 2016

@cgwalters any hints about what I can do in the meantime to get a sensible /opt to work? I was thinking of manually putting things into /usr/lib/opt during my install script, and then setting up a bind mount to /opt in my /etc/fstab, but I don't know if that'll be incompatible with the existing mount mechanism under OSTree. Is there a better way to weasel my way into the standard OSTree mount mechanism?

@copumpkin
Copy link
Contributor

@copumpkin copumpkin commented Apr 4, 2016

(the issue here is proprietary software with hardcoded assumptions about being in /opt, by the way; otherwise I'd just patch it)

@cgwalters
Copy link
Member Author

@cgwalters cgwalters commented Apr 4, 2016

We can change rpm-ostree to do this postprocessing automatically.

@copumpkin
Copy link
Contributor

@copumpkin copumpkin commented Apr 4, 2016

@cgwalters yeah, sorry, I realize that; was just asking about what to do between now and having native support for /opt in rpm-ostree

@cgwalters
Copy link
Member Author

@cgwalters cgwalters commented Apr 4, 2016

The only thing I can think of is to postprocess the RPM outside of rpm-ostree, basically RPMs are just cpio blobs with metadata and scripts. One could rpm2cpio foo.rpm to unpack it, then mv opt/foo usr/lib/foo, then turn it into a "source" tarball and make a binary-only RPM from that.

It might sound complex at first but it'd probably be a 4 line script + 15 line spec file.

@copumpkin
Copy link
Contributor

@copumpkin copumpkin commented Apr 4, 2016

@cgwalters but then I also need something to add an /opt bind mount back at runtime, right? The RPMs are still hardcoded to think they're in /opt. Would I have my RPM-wrangler add an entry to fstab as well?

@cgwalters
Copy link
Member Author

@cgwalters cgwalters commented Apr 4, 2016

Add a systemd tmpfiles.d file which creates the symlink /opt/foo -> /usr/lib/foo. This is pretty similar to what rpm-ostree automatically generates for directories in /var. See also https://github.com/projectatomic/rpm-ostree/blob/master/src/app/tmpfiles-ostree-integration.conf#L18

@copumpkin
Copy link
Contributor

@copumpkin copumpkin commented Apr 4, 2016

Oh, excellent, thanks!

@copumpkin
Copy link
Contributor

@copumpkin copumpkin commented Apr 12, 2016

Ah, it looks like https://github.com/projectatomic/rpm-ostree/blob/master/src/libpriv/rpmostree-postprocess.c#L102 is already putting a symlink for /opt -> /var/opt, so I think I need to use an L+ tmpfiles entry.

@copumpkin
Copy link
Contributor

@copumpkin copumpkin commented Apr 12, 2016

Turns out even with L+, systemd-tmpfiles-setup.service doesn't have the power to unlink /opt. Not does root. I'm confused what kind of thing /opt is to prevent me from changing it like this, given that it's on a RW filesystem and isn't a special mount point or anything weird.

@cgwalters
Copy link
Member Author

@cgwalters cgwalters commented Apr 12, 2016

I don't think you want to replace the full /opt symlink, just create a sub-symlink inside it, no? I.e your tmpfiles.d snippet should be

L /opt/appname - - - - ../usr/share/appname

or so.

In the current model, the /opt -> /var/opt symlink is part of the ostree commit (see the init_rootfs() function), it isn't created on boot. The reason you're getting EPERM is because of the immutable bit.

@copumpkin
Copy link
Contributor

@copumpkin copumpkin commented Apr 12, 2016

Ah yes, I just figured out the immutable bit on /. The reason I was trying to redirect all of /opt, rather than just subdirectories within it is that I have a few different packages that want to put things into /opt, and I was just going to have a general purpose "/opt fixer" in my postprocessing script rather than teaching my individual RPMs how to add to tmpfiles.

So my postprocess script currently just copies /opt into /usr/lib/opt and adds a tmpfiles.d entry that (tries to) symlink /opt to /usr/lib/opt.

I can do it for individual packages, but that starts putting a lot more burden on different subprojects, so I was hoping to avoid that 😔

@copumpkin
Copy link
Contributor

@copumpkin copumpkin commented Apr 12, 2016

Interesting effect of having /opt -> /var/opt and then using tmpfiles.d to populate /opt: I need to ensure that my tmpfiles.d conf file sorts lexicographically later than rpm-ostree-autovar.conf (or tmpfiles-ostree-integration.conf, which also defines the same entry) because otherwise tmpfiles.d tries to create my /opt/myapp while /opt is still a broken link, before /var/opt has been created.

@cgwalters
Copy link
Member Author

@cgwalters cgwalters commented Apr 12, 2016

Yeah, this would all be better if rpm-ostree handled it internally. I'll get around to this at some point if no one else does.

@copumpkin
Copy link
Contributor

@copumpkin copumpkin commented Apr 21, 2016

How would you envision the "ostree-native" version of this working? My concern with the obvious thing is that a lot of programs use it to store all their files, including ones they expect to mutate. Simply making a symlink from /opt/foo to /usr/lib/opt/foo will work until the program tries to mutate one of those, and then we'll run into other issues. What I'm doing today with my horrible hack is copying stuff from /usr/lib/opt into /opt, which ostree sets up to point to /var/opt so it's mutable anyway. This leads to some duplication and more runtime mutability than I'd like, but I don't have a cleaner solution in mind other than handling /opt entries on a case-by-case basis.

@tobiashochguertel
Copy link

@tobiashochguertel tobiashochguertel commented Apr 24, 2016

@cgwalters I would suggest an migration of /opt to /usr/lib/opt 233#issue-140670748. From treefile we can set remove-from-packages to remove files.

I'm not sure if the way to say we drop all files from /opt/ except for the following files and directories which are definied from treefile option include-from-opt (Array)*.The Entries from include-from-opt are moved to /usr/lib/opt. The previous behavior of rpm-ostree does not change (version compatibility).

*New treefile option introduction: include-from-opt (Array).

What do you think?

@tobiashochguertel
Copy link

@tobiashochguertel tobiashochguertel commented Apr 24, 2016

I hope this will help others to workaround until there is an solution, thanks to @cgwalters and @copumpkin

Rebuild puppet-agent rpm with new path

Regular Expression to change /opt/ -to-> /var/opt:

:%s/"\/opt/"\/var\/opt/g

Copy Conent from /opt/ to the new location: /var/opt/

cp -rfa /opt/puppetlabs /var/opt/puppetlabs
rpmrebuild -e puppet-agent

   opens vi/vim, run the regular expression... and write close the change ( !wq ).

ls -lha /root/rpmbuild/RPMS/x86_64/puppet-agent-1.4.1-1.el7.x86_64.rpm
yum install createrepo
createrepo --database /root/customrpms

File: sig-atomic-buildscripts/puppetlabs-pc1.repo

[puppetlabs-pc1]
name=Puppet Labs PC1 Repository el 7 - $basearch
#baseurl=http://yum.puppetlabs.com/el/7/PC1/$basearch
baseurl=http://192.168.99.102:6060
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs-PC1

Start Custom Yum repository:

  • http-server: ( npm install -g http-server )
cd /root/customrpms/
http-server -p 6060

via rpm-ostree upgrade I've got the changes in ostree and /opt/puppetlabs -> /var/opt/puppetlabs e.g. I can run now puppet agent on centos-atomic host. The above documented solution is upgradeable. I have no blog or website where I can put this and link from here.

HTH
Tobias

@tobiashochguertel
Copy link

@tobiashochguertel tobiashochguertel commented Apr 25, 2016

by the way this does not work with rpm-ostree -> I get the following log error: https://nopaste.me/view/dd563d20

A test installation of my rpmrebuild rpm on my ostree-build system was just fine, files & binaries are located in /var/opt/puppetlabs/. With sudo rpm-ostree-toolbox treecompose -c ~/sig-atomic-buildscripts/config.ini --ostreerepo /srv/repo/ -p hochguertel.local and testing the custom ostree via virtualmachine shows me that there something went wrong. /var/opt/puppetlabs and directory structure and even some files are there - but also files are missing, binaries are missing.

Can someone help?

@tobiashochguertel
Copy link

@tobiashochguertel tobiashochguertel commented Apr 26, 2016

After some research I was able to understand that I have to modify my custom rpm so that is will be located under /usr/ instead /var/. /var stays empty in ostree. After changing the location to /usr/opt things went fine and I was able to get the complete content of the custom rpm on my custom ostree.

I changed the regular expression from above to: :%s/"\/opt/"\/var\/opt/g.

As next I have to add or change the tmpfiles.d file (system.d tmpfiles.d) of puppet-agent rpm (my custom rpm) before rpmrebuild it.

cat <<EOF > /usr/lib/tmpfiles.d/puppet-agent.conf
d /var/run/puppetlabs 0755 root root -
d /tmp/puppetlabs 0755 root root -
d /tmp/puppetlabs/puppet 755 root root -
d /tmp/puppetlabs/puppet/cache 755 root root -
L+ /usr/opt/puppetlabs/puppet/cache - - - - /tmp/puppetlabs/puppet/cache
L+ /opt/puppetlabs - - - - /usr/opt/puppetlabs
EOF

On my testing centos-atomic-host it is now possible to start the puppet-agent systemd service, the original location of /opt/puppetlabs is a symLink to /usr/opt/puppetlabs.

There are some addtional adjustments todo at the custom rpm - which are not yet done by me, but the informations here are already useful so I hope.

HTH
Tobias

@cgwalters
Copy link
Member Author

@cgwalters cgwalters commented May 28, 2016

Thanks for providing the workarounds. I would like to support this better, however, it would touch a lot of code that is in flux for other work (e.g. the just-landed package layering).

cgwalters added a commit to cgwalters/rpm-ostree that referenced this issue Feb 13, 2017
See coreos#233 - for RPMs which
place files in e.g. `/opt`, we have different behavior in the treecompose case
(silently drop it) versus package layering (does the wrong thing).

Since the unpacker right now is only used in the layering case, this just
ensures we'll get a consistent error there.
@cgwalters
Copy link
Member Author

@cgwalters cgwalters commented Oct 4, 2018

FWIW, if anyone is like "Just make Chrome work on Silverblue", you can do:

rpm-ostree install libXScrnSaver

(Then optionally rpm-ostree ex livefs, or reboot)

Then:

rpm2cpio /path/to/google-chrome.rpm | (cd / && cpio -div)

It will fail to write files to /usr which breaks desktop integration (like the app launcher), but you can run Chrome directly from the command line by executing /opt/google/chrome/google-chrome.

With this path you won't get updates though without redownloading the RPM.

This could be scripted, but any effort here is probably better put into flatpak'ing it.

@dustymabe
Copy link
Member

@dustymabe dustymabe commented Oct 4, 2018

FWIW, if anyone is like "Just make Chrome work on Silverblue", you can do

I've been telling people to try out rpm-ostree install chromium, but I'm sure in some cases they want chrome and not just chromium. chromium works pretty well for me so it depends on what you need it for.

@meltingrobot
Copy link

@meltingrobot meltingrobot commented Oct 4, 2018

FWIW, if anyone is like "Just make Chrome work on Silverblue", you can do

I've been telling people to try out rpm-ostree install chromium, but I'm sure in some cases they want chrome and not just chromium. chromium works pretty well for me so it depends on what you need it for.

Yeah, I am currently using Chromium, but I would really like regular Chrome to have the flash support and other features.

@dustymabe
Copy link
Member

@dustymabe dustymabe commented Nov 2, 2018

marking this as difficulty/hard. Please let me know if that needs to be adjusted.

@jurf
Copy link

@jurf jurf commented Nov 5, 2018

Ah, ULD also requires /opt:

error: Importing uld: Unsupported path: /opt/samsung/scanner/share/oem.conf; See https://github.com/projectatomic/rpm-ostree/issues/233
@soulofmischief
Copy link

@soulofmischief soulofmischief commented Nov 7, 2018

Does anyone have a workaround for Keybase in the meantime?

@miabbott
Copy link
Collaborator

@miabbott miabbott commented Nov 8, 2018

Does anyone have a workaround for Keybase in the meantime?

I was able to run keybase from inside a container

@cjao
Copy link

@cjao cjao commented Nov 16, 2018

Chrome also seems to work in a container (tested in Fedora Toolbox ), albeit with limited desktop integration.

@cjao
Copy link

@cjao cjao commented Dec 2, 2018

The core problem here is: OSTree defines /opt (really /var/opt) as system administrator territory - it's never rolled forward/backwards etc.

Is this set in stone? What would happen if one treats /opt like /usr?

@vtolstov
Copy link

@vtolstov vtolstov commented Dec 3, 2018

Does is issue relevant to my problem - after i'm build my new ostree with fedora 29 and install it so system i have old chrome browser. Package systems says tha i have google-chrome-stable-70.0.3538.102-1.x86_64 but about says: Version 63.0.3239.84

also rpmverify says that md5 of files does not match.

@vtolstov
Copy link

@vtolstov vtolstov commented Dec 23, 2018

any chance to get this fixed?

@tobstarr
Copy link

@tobstarr tobstarr commented Jan 7, 2019

I ran into this issue twice in the previous week. First a printer driver would not install and second Enpass 6 is now distributed as an rpm package (they used a custom installer before which worked without any problems), both issues were due not being able to write to /opt.

One can install chromium but chromecasting does not work (a feature I actually would like to use from time to time). Being able to use Google Chrome would solve this issue for me as well I guess.

@vtolstov
Copy link

@vtolstov vtolstov commented Jan 10, 2019

@cgwalters @dustymabe any change to fix this really old issue? I need to use google chrome and printer drivers.

@dustymabe
Copy link
Member

@dustymabe dustymabe commented Jan 10, 2019

@vtolstov sorry - unfortunately we are busy with other commitments right now

@cgwalters @jlebon - out of the possible solutions to this problem what do you think is the most attractive?

  • seal opt (or other directories), allow package layering - conversation around #233 (comment)
  • have a readonly /usr/opt and a read/write /opt where copies of files in /usr/opt get shadowed and made immutable over in /opt - suggested in #233 (comment)

others? If we can clearly identify which way we want to go then we can maybe get a volunteer to work on it.

@matthiasclasen
Copy link

@matthiasclasen matthiasclasen commented Jan 10, 2019

Yes, please identify the preferred approach, then I'll look for somebody to dispatch here

@vtolstov
Copy link

@vtolstov vtolstov commented Jan 12, 2019

i'm happy with any workaround that can be applied in tree compose before deployed to end-user hardware.

@jlebon
Copy link
Member

@jlebon jlebon commented Jan 14, 2019

add the bluejeans app to the /opt -out list :)

FWIW, there's a BlueJeans flatpak available now: https://flathub.org/apps/details/com.bluejeans.BlueJeans

@vtolstov
Copy link

@vtolstov vtolstov commented Feb 9, 2019

does anybody can provide workaround? slack already says that my chrome is too old (72 in rpm and 63 on my system, that can't upgrade it).

fwilhe added a commit to fwilhe2/silverblue-system-config that referenced this issue Feb 27, 2019
alexlarsson added a commit to alexlarsson/rpm-ostree that referenced this issue Mar 21, 2019
This adds support for layering rpms with files in /opt. The way we
do this is that when importing the rpms we rewrite any files in /opt
into /usr/lib/opt, and then we add back a symlink from the toplevels
of /opt into /usr/lib/opt via the per-package tmpfiles.d.

Also, in order for this to work with the %post script we bind /opt
to usr/lib/opt during the script execution.

This is enough to make layering chrome work.

This fixes coreos#233
alexlarsson added a commit to alexlarsson/rpm-ostree that referenced this issue Mar 22, 2019
This adds support for layering rpms with files in /opt. The way we
do this is that when importing the rpms we rewrite any files in /opt
into /usr/lib/opt, and then we add back a symlink from the toplevels
of /opt into /usr/lib/opt via the per-package tmpfiles.d.

Also, in order for this to work with the %post script we bind /opt
to usr/lib/opt during the script execution.

This is enough to make layering chrome work.

This fixes coreos#233
jlebon added a commit to alexlarsson/rpm-ostree that referenced this issue Mar 26, 2019
This adds support for layering rpms with files in /opt. The way we
do this is that when importing the rpms we rewrite any files in /opt
into /usr/lib/opt, and then we add back a symlink from the toplevels
of /opt into /usr/lib/opt via the per-package tmpfiles.d.

Also, in order for this to work with the %post script we bind /opt
to usr/lib/opt during the script execution.

This fixes coreos#233 at least for Google Chrome.
@steffansluis
Copy link

@steffansluis steffansluis commented Jul 17, 2019

Ran into this today, with Chrome not being able to install plugins (presumably) because of read-only /opt. Specifically, I installed google-chrome-stable from the Google Chrome repositories after enabling them on both SilverBlue and regular Fedora 30, using rpm-ostree install google-chrome-stable and sudo dnf install google-chrome-stable). In SilverBlue, opening a flash application fails with download failed, and in regular Fedora everything works after restarting Chrome because the flash plugin is installed automatically succesfully. Chrome is installed into /opt, and based on what I've read the plugin is downloaded there, so it breaking with download failed (because of the read-only fs) makes sense.

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

Successfully merging a pull request may close this issue.

You can’t perform that action at this time.