hello icon indicating copy to clipboard operation
hello copied to clipboard

Food for thought: Using zfs-receive for updates?

Open kraileth opened this issue 3 years ago • 26 comments

Since (unless I missed something) there has not been any final decision on how hello is going to be updated in the future, here's another take at what might be a possible solution. Instead of theorizing first, I'm going to present what it could look like first so that it's easier to get an idea.

  1. Create an ISO that does come with a live system and installer only (small image) or that + a zfs-send stream as a file (large image).
  2. When installing, only prepare the pool, then zfs-receive the stream (after either downloading the current one from the net or using the one on the installation media) to install the OS.
  3. Base system upgrade would not involve freebsd-update(8) but rather check free space, download a newer stream, zfs-receive it to make it available in the filesystem and then activate the new BE to be used after the next reboot.
  4. If that were to work well, we could experiment with a service that zfs-sends on demand and clients receiving directly from the net instead of first downloading a stream file and then receiving locally.

Such an approach would obviously work poorly in vanilla FreeBSD as packages may depend on system libraries that could introduce ABI changes on a major version upgrade, so we need /usr/local as part of the BE (as it is by default). Which then means that applications would have to be always reinstalled after the receive (which is perfectly doable but not prett).

For hello however... As an AppImage-based approach to application packaging is likely to be implemented, we'll see self-contained applications in the end that are kind of separate from the base system (according to the platform idea).

One downside would be that we lose delta diffs that freebsd-update(8) give us. But considering e.g. HardenedBSD's upgrade mechanism which also involves always distributing the whole base system (for the simple reason that providing deltas is somewhat involved and the small team decided to not put the required resources into that), it's not actually that bad. Especially since ZFS offers compressed send / receive and FreeBSD's base system is not terribly large by today's standards.

We might even go one step further and consider some traditional packages an "extended base". I'm especially thinking of Xorg + mesa + drm stuff here which could be included into the ZFS stream that's received for any update. This would create a unity between the actual FreeBSD base system and the "platform core" (or whatever to call it). We could run tests against it before releasing the stream as a new update to make sure that graphical logins never ever break during an update.

A naming convention could be something like year, month, FreeBSD version, hello revision (e.g. 2021-05-13.0-p0h0).

Just sharing a somewhat raw idea here. While I didn't see any obvious (for me) problems that are not solvable, there might be some. If anybody is interested in this topic, let's have a discussion.

kraileth avatar May 14 '21 17:05 kraileth

This sounds nice. Coming from macOS myself because its the most perfect Os out there.. how would you handle the updates itself? Im new to ZFS and all (only use Linux on my servers, everything else is macOS/iOS) but how will it handle network interuptions?

Would it be possible to install updates, keep the old situation as fallback, and once a reboot occurs and everything works, the old situation gets deleted? How should i see this?

sorry if im not making sense, its been a long time that i actually involved myself with anything other then macOS :)

jhjacobs81 avatar May 15 '21 10:05 jhjacobs81

If I was familiar with macOS, I'd compare ZFS to APFS for you, but I'm not. So here's the basics that this concept depends on: ZFS is not a filesystem in the classic meaning of the word. In fact it's a volume manager + filesystem. You're pooling storage providers (e.g. partitions, whole disks or anything else that can hold data) together. Anything you put into the pool is called a VDEV ("virtual device"). There are multiple types of VDEVs which break down to what redundancy they provide. Say you have two 2 TB drives and add both to the pool as stripe VDEVs, your pool holds 4 TB of storage capacity but has no redundancy: If one drive fails, the pool is faulty and you lost your data. If instead you add a mirror vdev, you only get 2 TB capacity but the pool can tolerate loss of one drive (this is like traditional RAID-1). There are also RAID-z VDEVS and you can combine all of those into your pool (mixing VDEV types is possible but not a good idea).

On your pool you create so-called datasets. These are the actual filesystems (i.e. moving a file from one to another means actually copying data). The nice thing about them is their flexibility: They all share the pool's remaining capacity as maximum available storage. You can use quotas and such, but the important point here is that you don't have to declare the size beforehand as you do with classical partitioning.

Datasets can be snapshot. A snapshot of the dataset that contains the system (and adheres to a special layout) is called a Boot Environment (BE). The nice thing about it is that when booting your system the bootloader will allow you to boot either the default BE or choose another one. Using this you can basically have bullet-proof updates. The user's home directories reside in separate datasets and are unaffected by the BEs: You can for example boot an older BE and NOT have the work that you did in the meantime undone.

One nice thing about ZFS is that it supports sending snapshots off - e.g. to a file or via SSH to another machine. The other pool can then receive the snapshot. That way you can transfer whole datasets (or more precise: the state of a dataset at a certain point in time). The idea described above means that a system managed like that will get (by whatever means) a stream that contains a newer snapshot of the system and makes it available in the local pool via receive. You can continue working with your system as you do the update and reboot when you're ready for it. You'll then boot into the new BE and have the new version of the system running. Let's say something doesn't work right despite being tested before, you can simply reboot into the old version and wait for a newer update that fixes the problem. Some tool should make sure that only a configurable number of BEs are kept before the oldest one gets destroyed to free space.

Network interruptions should not be a problem. If the stream was not received properly, there will be no new BE available to boot into. ZFS even supports resumable send/receive.

kraileth avatar May 15 '21 16:05 kraileth

how hello is going to be updated in the future

One of the interesting things about this project is that probonopd wants to minimise the amount helloSystem forces updates on people (intentionally not updating AppDirs and app bundles, like the AppImage idea), so system updates are an interesting thing.

In my opinion, hello should automatically install important security updates, and give users the option to update when a new major release is published, but NOT force anything on anyone, because that's one of the reasons why everybody hates Windows.

kettle-7 avatar May 15 '21 23:05 kettle-7

One of the interesting things about this project is that probonopd wants to minimise the amount helloSystem forces updates on people (intentionally not updating AppDirs and app bundles, like the AppImage idea), so system updates are an interesting thing.

Totally agree on not forcing updates on users. It's their responsibility and the system should make it as easy and convenient as possible to stay up to date without being either obtrusive or even lacking the option to not update. Since we're talking image-based system design anyway, my proposal might fit the general concept (some details will have to be worked out regarding configuration changes made to the system for example).

Some more data: Base system including lib32 takes 700 MB of space with the default lz4 compression and 1.5 GB with full Xorg included. If we'd use zstd compression we could certainly decrease this further (and as it is an asymmetric algorithm the cost for higher compression is at write time only). Since ZFS supports compressed send, this is the amount of data that would have to be received for an initial installation (where using incrementals obviously is not an option).

In my opinion, hello should automatically install important security updates, and give users the option to update when a new major release is published, but NOT force anything on anyone, because that's one of the reasons why everybody hates Windows.

Absolutely! To be fair, I think that Microsoft has another target group and with some people it might even make sense to force them since otherwise they'd never do an update. You should really be able to turn it off, though and said group probably wouldn't do that because those people don't bother messing with settings.

When the TrueOS desktop project was still alive, I tested it for a few months as my primary OS. The way they did updates both fascinated and annoyed me. It was nice as it created a new BE and installed updates into that, so I could continue working and simply reboot when I was ready. The annoying part was that it always uninstalled all packages in the new BE and then reinstalled from the online repo. So even for a small change to the system a huge amount of data had to go over the wire. This is annoying for people on slow connections and it's a real no-go for those who have to pay per gigabyte of traffic. Hello should try avoid unnecessarily huge updates IMO.

kraileth avatar May 16 '21 04:05 kraileth

I wonder if ostree would work? Or is that another redhat project that only works on Linux...

kettle-7 avatar May 16 '21 07:05 kettle-7

I agree that important security updates should be installed automaticly.

in fact, i firmly believe that, while updating should not be “in your face” it should be enabled automaticly, making it an “opt out” thing. Time and time again people have proven not to be capable or willing to handle updates responsible. Its what drove MS to the shithole update implementation it has now.

Sure, helloSystem is small and only for the nice market now. But what about down the road? I believe helloSystem could become a fairly big player (think Linux Mint or ElementaryOS) and by then, users will climb aboard who will not be so serious about updates..

Actually, could this be solved by creating a “helloStore” much like apple’s appstore? It could bring a single place where users could go for software, as well as system updates. That way, the update process isnt mandatory, while users still know where to get them. The helloStore could alert them with an icon in the taskbar (much like the windows upgrade does) so the user knows, and still can choose to upgrade at a time of their choice?

jhjacobs81 avatar May 16 '21 14:05 jhjacobs81

Let me descibe my thoughts, although I don't have a particular technical solution in mind yet:

Slow-moving Core OS

On the Mac, users have been moved to yearly "major", and users mostly are hating it. It's too frequent and there are not really that many "major" features. "Moving targets" are a pain - for developers, for users, for everyone. So I'd like to see "major" system upgrades every ~3 years (similar to Enterprise Linux distributions). In between, security patches.

Unbreakable, no questions asked Core OS upgrades

I hate upgrading the OS, especially if there is a >0.0% chance that I end up on the command line without a graphical desktop. Hence, my ideal scenario would be that the Core OS comes in pre-tested, immutable (unchangeable) image files, of which the user could have multiple ones. "Upgrading" the Core OS would be booting into a different image file, while keeping the original one around. Since the Core OS is read-only, all changes would be in some read-write space which could be carried over to the "new" system.

Android works somewhat like this. You have a (normally) read-only system parittion and a read-write data partition. When the Core OS is updated, you get a whole new, vendor-tested system partition while keeping your exsiting data partition, where apps and user data are persisted. With Android, you don't really start to mess around with packages or configuration files on the system partition. The whole partition is handled as one opaque blob.

Would zfs-receive help achieve something like this?

Fast-moving applications

Applications need to be upgradeable whenever the application author and the user feel like it, independent of system release cycles and infrastructure. FreeBSD somewhat does this by separating between the core system and Ports, although Ports contain vital elements of a desktop such as Xorg which I would rather like to see in the base system.

For applications, it must be possible to keep the old version in addition to the new version, so that users always can go back in case the new one doesn't work properly. Application bundles nicely allow one to do this.

probonopd avatar May 16 '21 19:05 probonopd

@probonopd Slow-moving core OS: Agreed. An OS needs to be reliable. Advanced users often like to play around with the exciting stuff - but that always has to be a deliberate decision. A platform that forces that on the users is only a toy.

So basically if hello had been released let's say in 2016 based on 11.0, it would have been updated to 11.0-p${whatever} during the 11.0 life cycle, then to 11.1 in 2017, 11.2 in 2018 and 11.3 in 2019 even though 12.0 would have already been available in 2019?

Unbreakable, dead simple OS upgrades: Yes, never break graphical mode should be the mantra here. What I proposed above is pretty close to what you want, I think. You basically build your system however you want it to be, snapshot zroot/ROOT/default and send that snapshot to a file which gets included in the install ISO. The installer prepares an empty pool and receives the snapshot and treats it as the default BE. If a new version is released, you create a new snapshot (an incremental one preferably) and the user receives that into his pool and activates it for next boot. Done, system updated. It's all atomic and clean and you can always go back to the previous one. This will work best if users never mess with the OS image.

There are a couple of problems, though that make me think a completely read-only system does not work. One of the exceptions to the general "let everything be immutable!" rule would be /etc/master.passwd: We need to allow for creation of new users, password changes and so on. I'm not sure if having a symlink to an rw part of the filesystem works or if there are programs that expect the file to NOT be a symlink. Overlaying may work, but I'm also not sure. We'd have to test. I would also expect that some more side effects manifest with a completely ro system dataset. We'd have to experiment with that.

Another thing is /etc/rc.conf, but we could by policy make that file immutable and relay on /etc/rc.conf.local for the user to change if necessary (need to figure out if symlinking / overlaying it works).

Fast-moving applications: I'm with you in this regard, too. The nice thing with an image-based OS upgrade approach is that we could define an "extended base" that would include packages like Xorg that applications can rely on (and rely on not breaking).

kraileth avatar May 16 '21 20:05 kraileth

What I proposed above is pretty close to what you want, I think. You basically build your system however you want it to be, snapshot zroot/ROOT/default and send that snapshot to a file which gets included in the install ISO. The installer prepares an empty pool and receives the snapshot and treats it as the default BE. If a new version is released, you create a new snapshot (an incremental one preferably) and the user receives that into his pool and activates it for next boot. Done, system updated. It's all atomic and clean and you can always go back to the previous one. This will work best if users never mess with the OS image.

Sounds very interesting indeed. (And comes exactly at a point in time where I have been working on dropping ZFS from the Live image for https://github.com/helloSystem/ISO/issues/4... oh well, maybe need to revert to ZFS...).

probonopd avatar May 16 '21 20:05 probonopd

You do not need to use ZFS for the live system. When a system booted from UFS is asked to do anything ZFS-related (like listing importable pools or creating a pool) opensolaris.ko and zfs.ko automatically get loaded and the system will be able to work with ZFS. It's not either UFS or ZFS. FreeBSD installation images also don't use ZFS but the installer is perfectly capable of creating a system that does.

kraileth avatar May 17 '21 01:05 kraileth

i believe this is much of what macOS does too these days.

All grand idea's aside, its nice to not force users to upgrade.. and for a while this might work. As most people using helloSystem in the first year will probably be developers anyway. But how about when it gets out there, and less experienced people are starting to use it? there HAS to be a way to alert users of important updates, and upgrades as well.

MS has created a shithole update system, but at least its better then the past where you could prevent updates for endless months on end. In the end, people got hacked, randsomed etc. all because they kept their systems not up to date. 9 out of 10 windows security problems we faced could have been avoided had people updated their systems. This is less so with Windows 10, because it "forces" them to upgrade. Too bad it forces them to upgrade at times they are hard at work.. and it forces malfunctioning updates as well. THATS why people hate updating.

jhjacobs81 avatar May 18 '21 10:05 jhjacobs81

Well with probonopd's os image idea, maybe we can make helloSystem check for security updates when you connect to the WiFi, download the new image (think rsync would be good here, but for now we'll probably need something like a patch file), and just use it on the next boot.

As for apps, I have something planned and underway.

kettle-7 avatar May 18 '21 20:05 kettle-7

That would work, especially if people wouldn't notice it because all the applications are self contained app bundles on their own volume.

See, most people dont care about the os. they care about the easyness of use, of the pretty looks, but they dont care about the technics. especially if it "just works"

Thats what i would like to see: The beauty, ease and security of macOS, with the stability of BSD, and the freedom of Linux. i guarantee you, with a good marketing strategy this could be bigger then ElementaryOS, and see how they handle funding? people ARE willing to pay for something good.

People dont buy mac's because it runs BSD. They buy mac's because its so easy to use, and so pretty. Apple isnt a great company because of its magnificent and renewing idea's.. half their shit is "stolen" from others. But they do excel in polishing those idea's, finishing the rough edges and then spotlight everything.

Combine it with a great website and store (yes.. respository's, i know.. but people dont like reposity's and commandlines. they want GUI's) and i see no reason why this project should remain small and for a few users only. But we'd still have a lot of thinking to do ;-)

Yes.. i think ahead, im a visionair like Steve Jobs himself ;-) But there's truth in what i say :-)

jhjacobs81 avatar May 19 '21 06:05 jhjacobs81

If what we want is people to see three folders in /, all of which they have interest in, and hide the ones they don't, like /usr, /etc and that, then how the OS is structured matters only to us, right?

kettle-7 avatar May 19 '21 20:05 kettle-7

I think this would be the best way for most users, yes. But at the same time, we should not forget the few advanced users who like to meddle, could these be catered to as well? Maybe through some advaced fiew? Or “root mode” or something?

jhjacobs81 avatar May 19 '21 21:05 jhjacobs81

Already done. Just press Ctrl+H or View->Show Hidden Files.

kettle-7 avatar May 19 '21 21:05 kettle-7

Awesome! I have to try tomorrow, im still fighting with getting it to a resolution beyond 800x600

jhjacobs81 avatar May 19 '21 22:05 jhjacobs81

Are you using a VM?

kettle-7 avatar May 19 '21 23:05 kettle-7

Are you using a VM?

yes, see this: https://github.com/helloSystem/ISO/issues/211

ProxMox, got it to work with this config :)

jhjacobs81 avatar May 20 '21 07:05 jhjacobs81

While it is recommended to try hello on real hardware, installing to your hard drive wipes everything and installing to a USB doesn't work. I manually installed it (a process that took about a week and a lot of problems) and strongly recommend you don't do the same.

kettle-7 avatar May 20 '21 08:05 kettle-7

thats the problem.. i have no device i could spare, so i run it in a VM :) are you not on IRC?

jhjacobs81 avatar May 20 '21 08:05 jhjacobs81

I still have yet to Google what irc even is.

kettle-7 avatar May 20 '21 08:05 kettle-7

maybe we should setup a discord server, makes streamlining the conversations much easier :D and then, in the future, all the app devs that make apps for hS could have their own channel!

or matrix, or whatever.

jhjacobs81 avatar May 20 '21 08:05 jhjacobs81

Sounds good. Although, when Github discussions reaches organisations, that'll be the ideal place for this. In the meantime, we should probably move this discussion to a new issue because the last page of comments have little to do with system updates...

kettle-7 avatar May 20 '21 20:05 kettle-7

github is good for developers, not for endusers ;-)

i still say we should put up a website with its own forum for everyone to join ;-) i know not a single normal user who doesnt find github complicated :)

jhjacobs81 avatar May 21 '21 09:05 jhjacobs81

are you not on IRC?

I still have yet to Google what irc even is.

Please see https://hellosystem.github.io/docs/developer/contact

probonopd avatar May 21 '21 19:05 probonopd