Flatpak, a technical walkthrough
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Larsson, Alexander
Flatpak is a desktop-focused application distribution and deployment system for linux. This talk will walk through the technical details of the core functionallity and explain how it work and why it works that way. Flatpak has now had a major stable release and the rate of change is slowing down. This is a good time to take a look at how the things work behind the scenes. This talk will go through the technical details behind flatpak, explaining things like ostree, bubblewrap and how flatpak uses this to implement the sandbox and basic flatpak commands. It will also explain in high-level terms how the portals and other desktop integration features work.
 I'm with Red Hat for the last 18 years or something. I work in the desktop group. I normally work on GNOME stuff, but the last three years or something, I've been working on this project called Flatpak. I'm going to talk today about the core implementation of Flatpak and how it works and why it works that way. But first, maybe I need a short description of what Flatpak is. How many people use Flatpak? And how many people heard about it? Not everyone, but most. So it's apps for the Linux desktops. And obviously we had applications for the Linux desktop forever. So apps mean something else. It's like Apple phone apps style or Android apps. You can expect to easily install them and fearlessly do so without having them messing up the system in some way or affecting other apps or your system updating, affecting the apps. Like you want the apps to be an isolated thing from the core operating system. So there's several parts to this. There is a distribution of your app. We have a repository format that you can add this remote and you can install stuff from it. We have A, this is FlatHop, which is one source of FlatPaks. There can be many. You can configure many yourself like a jump repository or a debut repository. There can be many and they're independent. This is the website for FlatHop. But the data is all there. You can use it from the command line. You can use it from GNOME software, KDE Discover, or you just click on install on this website. They all use the same data, the same screenshot, descriptions, and whatnot. And then, and this is kind of the core, you can run the same app, the same build on any distro. These are just the distros that we have on descriptions of how to install FlatPak on. But fundamentally, it should run on anything that has not even recent kernels, but pretty ancient kernels still can run this thing. And not only can you run on any distro, you can also like distro hop while having the same apps installed. You can upgrade your distro and it will not affect the thing. And you can run a newer version on an older distro and all that kind of stuff, right? So common example is to use a really stable, rel or debu stable base, but still want to run the latest GIMP or some specific app. You can also build it anywhere, because building itself, I mean, there are many ways to build stuff, but the default way we build FlatPaks builds in a sandbox too, so you can have two people sharing a development environment, even though they're on completely different systems and they will produce essentially the same binaries. There might be some timestamps and whatnot, but the rest is shared, right? It also runs in a sandbox. We're talking about desktop apps here, so sandboxing is complicated. There are very many integration points between the desktop app and the desktop or even other apps. So sandbox is available and the default sandbox is very secure, but you can't really do a lot of stuff in it. So you can also opt out and the user gets asked, you want to grant these permissions and you can give your app file system access and whatnot. But we're also working on the other side with things like Wayland, Pywire, portals, to make it possible to have sandboxed apps that are actually useful, but that's partially in the future. But right now you can use it for any app, but it's just not as secure. So you might ask yourself, how is this different from containers? Because all of these things I talked about before, you can also do with Docker, right? A Docker image can run on anywhere, you can build it and build out or Docker build or something and ship it somewhere else. So there are two main differences. First of all, the target user of Flatpak is fundamentally non-privileged. It might be like a data entry clerk who has an IT, like IT gives him a laptop, he doesn't have sysammin on it or anything, right? He is not root, he doesn't have a root password, so we can't have any tools like Docker that requires you to be root or that implicitly grants you root rights, like if you have access to the Docker socket, that is giving you root. We can't have that. As I add on to that, none of the techniques we use in Flatpak itself can fundamentally rely on root-only features. That means certain things just cannot be used. We can't do device mapper, we can't use butterf as snapshots, or we can't do firewall setup for port forwarding, because all of these are fundamentally sysadmin level operations that are not allowed for any kind of unprivileged use. The second thing is that the goal is to run desktop apps. So we automatically integrate with the desktop in all the ways that matters. Like you install the app, it's a single click, and when it's installed, like there's a nice graphical progress thing, and when it's installed, it appears in your desktop, it has an icon, it has a description, it can install MIME type files or DBA service files, it has access to X or Wayland, it can talk to DBAs in a safe way, it has the right GPU drivers in there, if you use free desktop specs to find your stuff, you can easily find your stuff, we have interactive permissions, like the portals I talked about, it's basically a way to have low permissions, but then at run time, safely grant extra permissions, like access to a particular file or web camera or something. So to build Flatpak, there's two major parts beneath it that kind of has to be explained in detail before we can explain Flatpak, and actually once we have these, like a working knowledge of Ostr and bubble wrap, the rest of Flatpak is mostly trivial, just using these in the right way. In Ostr is like the short quote, it's like get for operating systems, and by saying it's like it, I mean that all the things you'd expect from Git are there, there is a remote repository, there's a local repository, you configure the remote, you pull from the remote, you pull refs from the remote, you can commit a ref, you can check out a ref, a ref points to a commit object, which is a checksum, and it contents address the rest of the files in the commit, it's essentially a re-implementation of Git, but where Git is made for source code, and if you ever try to commit like a large binary, it just isn't meant to handle that, whereas Ostr is all about having a on-disk file format that is useful for trees of binaries. It was originally made for committing your entire operating system into Git, basically. So we are going to look at the repository layout, which is the way that Ostr differs from Git. So we have here, kind of hard to see, but yeah, an app, it's just a directory with some files, but in the end, that's what all apps are, right? It's just a directory with files plus some metadata. So there's a bunch of normal files here, and I colored them so you can kind of follow where they appear when we commit them. So if you were to commit this, these are the Ostr operations you run, the init repository, and then we commit, whoa, we commit to a branch called master, this directory called app, and it generates a commit ID for us. And you can look at it, and it looks like it's a commit. That's basically what Git would give you, right? And it generates this repository here that if you ever looked into a.git directory, it's very, very similar, right? So there's a refs directory that contains the refs, and ref is like a more generic thing than branches, but think of it as branch. And they have a bunch of objects, and if you look at this ref file for master, it's just a, actually, I cut down all this, they're actually very much longer, but I cut them down all to 10 characters so you can read them. It's a commit ID, and if you look in the object directory, you can find the commit here, and the commit is just a small metadata file that contains the commit message, the timestamp, the previous commit ID, because that's like a history of these, and also a pointer to the root directory of the thing. And that's just also an ID, which is to check some of this. So the red thing is the root directory, so it has a pointer to this, which is also a small metadata file that basically says, this is a directory, and it has a file named bin with this commit ID, or a directory, and a file called readme with this commit. And then you can recursively look into everything, and if you eventually reach a regular.file, which is just a normal file, if you look at that file inside the repository, it's just represented as itself with a different name. And the name is a checksum of the content of the file plus some subset of the metadata, like the user that owns it, the permissions, and extended attributes, and a couple of things that are part of the identity of the file, because if you store two files in the same repository that have the same content, but different permissions or whatever, there will be two objects in the object store. And then we can modify this. So we change the readme file here, and we commit again. So we get a new commit. I don't think you can see it, but it's like a brighter version of the color when it's changed. So what happens then is that we add, we changed the master here to point to the new root commit object, which now points to the previous one, plus the new root directory, and the new version of this file here. All the other ones are left alone because they weren't modified, right? So we modified the app and the readme. And you can find both the objects at both versions in there. So the interesting thing here is that committing a new three is a purely additive operation plus an atomic switch of this file at the end, basically. So operations are very safe in that they're not destructive or changing anything. And if you were to check this out, this is just the same postory. If you check this out, check that as to a directory new, you get a directory new, which looks like the original thing, except if you look really, really careful, these file has our hardlink count of two, which they shouldn't have normally. And if you look in detail, you see that actually they're the same inode as the repository objects, these checkouts are fundamentally hardlink farms back into the repository. So they're very efficient to create. And if you have multiple checkouts of the same or slightly different things, they are like co-share inodes. So it's very efficient in that sense. And the way you're meant to use it is that you mount this thing read only. Like when OSTRI uses it for its inoestry as the whole operating system, you basically commit slash user into OSTRI and then you mount it read only. So it's safe for these hardlinks to point back into the repository because you're never able to modify it. And there's also a version that isn't meant for local store. If you put this thing on a web server, it's a similar format. The main difference is that they are. The files are compressed and the metadata of the file are in the file. Plus there's a file called summary that has all the refs in a single file because you can't naturally enumerate all the refs on a web server, right? So you can read a single file and it will tell you the name of all the refs and their current commit. So then you can recursively find anything you want. And if you have a local version of a ref and the new one or the upstream one is different, you can very efficiently calculate which objects you need to download to make your local copy the latest one. There's also GPG signatures in this commit meta file. This is basically you can add metadata to it, including a commit or a signature of the commit and you can sign the summary. So you can protect against men in the middle kind of stuff or downgrades or something. It's also, it's not listed here, but there's also an optional static deltas directory where we store basically binary diffs between specific versions. So if you're going from maybe the next to last to the current version, there might be a specific delta file you can download. And that will give you even better download performance. If a file changed, but it's just one byte that changed, you can just get a really small delta. If you don't have the delta for the particular download you want it to do, you can fall back to the regular OSTRI pull. So the reasons we use this is the automatic deduplication is very nice because fundamentally containerization and sandboxing and everything is about bundling. So we want to try to minimize the cost of bundling. So anything that accidentally gets shared because it's the same file just automatically gets shared. So if two completely different builds happens to have the same icon, so what not, they'll just automatically be shared. Even if you have reproducible builds, it's likely the most things will be shared. And they're also shared both on disk and in the page cache because page cache is per inode and inode is the same because they're all hard links. You also get very efficient updates due to the deltas and the quick way to get what's changed in a version. And updates are atomic, the way you use OSTRI is that you check out in Git, a checkout is almost always tied to a particular Git local Git repository, but in OSTRI you normally have one shared repository and multiple checkouts on the side. So it's very safe to do an update of the repository and then a new checkout that doesn't affect a running instance of a previous checkout. And they can automatically switch over. And also this needs nothing in from the kernel. It works on Unix version 7 or wherever hard links were introduced. Just isn't anything complicated or privileged here. So the other tool is MableRep. And it's an unprivileged chute on steroids. And I guess most people here know the virtual file system, but we have a bunch of physical file system that are probably stored on a device somewhere or maybe there are tempfs. And in the kernel there's a mount table that is basically a sequence of take this here and put it here that builds up the virtual file system. And nothing super exciting about this. One might notice that, I don't know if you can see here, but there's C is mounted twice here. So this file foo is available here and over here somewhere. In the kernel it's just another mount. But most people know them as bind mounts because the way you create it is if you go to the first mount and then you take the existing thing here and bind mounted here. But in the kernel it's just a list of mounts. And at some point someone added this root. It's just called because maybe it would be cool to virtualize what apps see. So instead of the root directory being a global thing, it became a per process thing. So basically a global variable was made like a member of the struct process thing. And this way apps can see different things in terms of the file system. And also a lot later, namespaces were added, which basically makes the entire mount table to be a thing that can be different in each process. So mounts can be completely different in namespaces. And in fact, some of these physical things might be visible in some but completely invisible not even mounted in other namespaces. So Shroot is really cool. And so most people like it and use it. But for me it's not very useful because you have to be root to run it. And why is that? So Unix the kernel is a very simple thing. And to create a user space operating system on top of it, it relies on certain things like set UID to increase privileges. Simple example is sudo. sudo is an app that is set UID. So anyone who ever runs it turns into root, which is not good. So the first thing sudo does is look at etsy sudoers and see are you allowed to do this. But this relies on the fact that etsy sudoers is actually the admins file. If you're in control of the file system, you can point it to something else that says, yes, I am allowed to become root. And suddenly you broke the system. So this implicit trust in things like privilege raising operations, there are many of them, set UID, set caps. I guess I haven't thought that many, but there are a couple of them. So with the introduction of unprivileged username spaces, and I think actually the username spaces themselves aren't vastly interesting, but this process control switch was added that you have to enable to make unprivileged username spaces work. And it basically means this process and all its children can never ever raise privileges using all these set UID-like operations. And that means that root operation is safe, because the sudo or whatever inside your sandbox can never actually become root. There's also like mappings of UIDs and whatnot, which is kind of nice, but not necessarily important for me at least. So I wrote this tool called bubble wrap. It was initially part of Flatpak, but it was an interest from many people, it was extracted to separate things. But it's basically a shell wrapper that uses all these kernel features, because while they are just kernel syscalls, you have to be very careful when you set them up, and it's really messy and hard. So it's a simple tool where you can create your own namespace. And it's slightly different in how it works from root. In root, you kind of from the outside build up the entire thing, and then you jump into it. Whereas bubble wrap starts with a completely empty system, with only root being a tempfs, and then you can like from the inside, but via commands from the outside, build the thing up. So this example starts with nothing, and then we create the directory in temp, and then we make a read-only bind of the host user on the user in the sandbox, and then a sim link from lib64 to use lib64, and then we run userbinls in the sandbox. And this is all it sees. Obviously, this only works if you have a lib64 style host, but on a Fedora, that will run in a super minimal sandbox that only has read-only access to user and nothing else. And other than the primary way of setting up the file system, we have a bunch of other features that enable basically all the things you can do, unprivileged, on the current Linux kernels. So you can unshare more namespaces. If you unshare the net one, you only end up with a loopback and nothing else, and you can unshare all of these, and you can mount certain kinds of file system. Well, dev isn't actually a file system, but if you say mount dev here, it will create one that has bind mounts of the host slash dev nodes, because we can't create device nodes as a user, but we can link to pre-existing ones. And if you unshare the pit file system, we have a handler for pit one, so you can read children and not get zombies and whatnot. And seccomp, there's a way to pass a binary of seccomp rules into bubble wrap that will get applied. After everything is set up, we apply the seccomp rules at the end. So you can, like, the seccomp rules doesn't have to include everything to set up the environment. There's also a set UID version of bubble wrap. The regular one works fine on Fedora and Ubuntu, but a bunch of other distros disable unprivileged username space or put them behind some kind of kernel flag or boot flag or something. And the reason is, in unprivileged username spaces, you are rude in some sense. You're rude against that username space. But there is a, I don't think anyone thinks that the general things that username spaces expose are unsafe. It's just that there might be other part of the kernels. There's this enormous syscall ABI, and not all of it is correctly namespaced. So something might process this UID zero as meaning it has access to something where it actually is just UID zero in this namespace. So we have a, well, it's the same, basically. If you take the bubble wrap binary and make it set UID, it will switch to using a set UID model of operation where it's normally mount stuff. It does all the same things. So it should theoretically not be any less unsafe than the unprivileged one. And in fact, one could argue that it's more safe because it doesn't expose the full, you know, syscall ABI to this fake use, fake root mode. So yeah, that's useful thing to make Flatback work on all distros. So I think we have now everything we need to take a very, very high level view of how Flatback work. Every installation has an OSTRI repository, a local one. And there are actually two main installations. There's a per user one in Valib Flatback, and there's a per user one in each home directory. Every app and something called runtimes are committed to this OSTRI repository in branches that looks like this, or these are refs. So this is an app ref, and this is a runtime ref. And like this is obviously the name of the app, or the runtime, and the architecture, and there's like a version thing. So those are in the repository, and we pull them from a remote, and then we check them out next to the repository. This is called deploying them in OSTRI. And then we run them with bubble wrap, where we put the files from the app, in slash app, and the runtime in user. And these are all read-only mounts, so we can't affect them. And obviously, there's a bunch of more here to set up, like we have a temp, and we have a proc, and we have a dev, and various other standard stuff. You can also request access to regular file system paths, like if you want home directory, we'll add a bind mount of the home directory to the end. But this is the basics of how we run an app. And if you look at an app that's deployed, in Barlet Flatpak, there's a directory called repo, which has the repository, but there's also a name, which is the entire ref. And in that, we have the actual thing checked out under its own commit ID, and a similar name called active that points to it. And if you look in that active directory, this is the checkout, has some metadata, the name of the thing, what's binary to run, environment variables to set, and files is like the regular file, it's like a prefix. Basically someone built into a prefix and made it into the app. So it's got bin, lib share, and whatever else you might have there. There's a subject you call export that contains special kinds of files that we want exported to the file system, or to the host file system. This currently allows icons, desafiles, mime type, service files, and I think an own shell search providers. And also, after checking out Flatpak itself, it creates this deploy file, and this ref file, which are not actually part of the upstream thing, the deploy file just says this checkout came from this remote. The ref file is actually just a file, but whenever we mount this read only, we also have the pit one of the sandbox take a non-exclusive ref, non-exclusive lock on this file. So at any point, we can look at a certain checkout and see if it's locked. And if so, something is using it, and we have to keep it around. So the typical Flatpak install command, you just give the name. So we have to figure out the entire ref, but we know it's probably for the current architecture, and you specify a remote here, and the remote has the default branch name, so we can figure out what you actually want to install. So we pull the entire ref to the lock of repository. To figure out what commit we actually ended up with, and we check this out and create these files, and then we sync everything. Up until this point, we only created new files. Nothing affected anything running in the system, or that you could run. But then we do an atomic set of this active sim link, and at this point, Flatpak run will find the new version. So we will say later in an update, there might be multiple commit here, but there's only one that is the active one, and switching between them is an atomic operation. And then at the end, we also look at all these exports and copy them into shared directory. Well, it's not a pure copy. We look at the files and rewrite some stuff and make sure it's safe and whatnot. But basically, we copy them. One update is the same, except when we're done, all the old commits are moved to this global directory called thought removed. And then for everything in that directory, we take an exclusive lock on this ref thing, and if we can't do that, then it's still in use, and we leave it be there. Moving the directory somewhere else doesn't affect the running instances. So if your Firefox is running, it will not notice anything changing until the last instance of it exits, then the lock gets unlocked, and we can take an exclusive lock on it, and then it's fine to delete, because at that point, nothing could ever refer to this old thing because it's in this sub directory, and the sim links are changed and whatnot. Obviously, if something was running and we updated it, we will not delete this thing, so it will be left around possibly forever, but generally, we run update again, and it will traverse all the removed files and eventually become garbage collected. On top of that, we have a top of the line sandbox or something. We enable a bunch of stuff. Use in namespaces is optional because it's not always available. In the set UID version of Flaphack, we might not be able to support a username space in case it was completely disabled in the kernel, but if it is, we enable it. Obviously, we use the file system namespace, but we have to. That's how we make sure we run something else. We also use the pit namespace because if you can see proc, basically all the other apps that are running on your system, at least all of your apps are visible in proc, and you can use those proc fd and whatnot to look into what those other apps are doing. We isolate that by using a pit namespace, but it also neatly gives us a pit one that controls the lifetime of the entire container. We know we can kill that to kill all of it, but we also know that when it exits, the last process in the sandbox died. Optionally, we do network and IPC namespaces. We do seccomp. It's very hard to generically do seccomp for everything. We're supposed to run arbitrary desktop apps. What can we forbid? Well, there's some really weird stuff. Like who uses X25 or whatever. We use socket ties to disable some really weird syscall. The key ring is not, the kernel key ring is not namespace aware. I think it's somewhat. But yeah, we disable that. These things, ptrace perf multilarch, are useful for development. We have modes where you can request them. If we're building stuff, we enable them by default. In a regular app, you would really not need ptrace. We disable it by default. We also disable recursive namespaces. If you actually have real, unprivileged namespaces, those can stack. But we want to avoid having the app control the way, like the layout of the file system for similar reasons to the pseudo incident before we want to be able to trust that we set up the sandbox in a specific way and it keeps being that way. Obviously, every app has its own temp, because it's just part of the root tempfs. We can't generally add C groups. We don't use C groups. Except if you have systemd user running, we create a scope for the thing on the user in the instance. This doesn't currently give us a lot, though. We can't apply any policy on the group, because that's not doable as a user. But hopefully, eventually, C group v2 will save us all and whatnot. Then we can do C group limitations and whatnot as a user. We also have something called the deepest proxy. Every app has access to the session bus, and have certain privileges on it. Everything goes via this proxy that filters calls so you can basically only be called into, plus do some very, very open system-wide calls, like talk to the bus itself and own your own name and a couple of other things. In case you're not requesting any specific permissions, this directory is created for you in various environment variables points to it. It will be the only writeable persistent directory where you can store data. Obviously, if you grant your app home to access, you can write wherever you want. The idea is that in the long run, when everything is sandboxed, we will have a directory where every app has its configure files, its cached files, its whatever. When you uninstall it, you can also easily take away all the per-user data that the app installed. Here's a couple of links to various projects and ways to reach me and the project. Anyone has any questions? Do we have a microphone? Thanks. I have my home folder still on a rotational drive. For me, OS3 is really slow to the point that the flatback update of the GNOME platform can take up to seven minutes to complete. It's R8.1. It's encrypted, so a butter FS or copy on write. It's a worst case scenario. Are there any plans to add another backend? For instance, we see a sync in place of OS3, or are there any performance improvements that can be made? I think it's more about having the download be efficient. I don't know if it actually stores in a de-duplicated way that we can use directly. It does? Fundamentally, though, should that, if it has the same layout where you explode every file as a file and then F sync and make it atomic and all that, if you do all that, isn't it still as slow, though? Because that's the problem, right? You write all these files all over the place and then you sync it and you end up in a journal or whatnot. If you're a butter FS, you're not doing that. There's a similar issue on the XE4, right, if you F sync something, you force the journal to be flushed and everything else blocks and whatnot. But I don't quite see how CS sync would not have the same issues in the end. If you want to ensure the OS3 is on this, it's going to take a while. I don't see really any way out of that. Yeah. Over the years, we've been developing Flatpak that's been talking about a file browser so that you wouldn't have to give full access to the home directory and you could basically have the file browser sort of inject files into the app. Has that moved up forward at all? Yeah. So, it's basically a file system portal, file-shooting portal. It's basically a combination of a Fuse file system where every app, every Flatpak app that runs has a bind modded in it, a subset of this Fuse file system that is called a document portal. You can register a file and create a document for it and then it's visible in the document portal mount plus there's a sub directory per app and that sub directory gets mounted into the sandbox. You can dynamically add files to target a specific app. What happens is you do a debus call to the portal and outside of the sandbox. We have full access to everything. We do a file chooser and at the end, we create a document for this file which makes it appear in the sandbox of the running app and then we pass back the document identifier and then we can access the file via that Fuse file system. What doesn't work is exposing an entire sub tree of your file system. So it's mostly for like, I can open a PDF in events in sandbox mode but it doesn't work for Emacs or an IDE or something like that. But I could run a Firefox or a... Yeah, events or something like that. Yeah, that works. In the beginning you mentioned Apple apps. They seem to be much, much simpler basically just directories on the Mac or zip files on iOS that were part of the simplicity stems from the fact that everything is either part of the operating system or part of the application. Why does it have to be so much more complicated in the Linux world? Well, there are two things. First of all, the sign of SAP HAC is meant to work on current apps. Current apps in Linux hard code the prefix and the binary. Over time people have tried to make things relocatable and some snaps for instance relies on relocatability with like, ass loads of environment variables and things. But still there are things that aren't relocatable. Get text is just a hard coded prefix. It just isn't possible to use a system that is relocatable on the current Linux apps basically. The second is that Apple has a single ABI that they maintain that you can use and given my history of like 20 years trying to keep ABI in Fedora and whatnot. It just isn't doable. It's not even doable in Fedora to keep a single ABI for between versions and sometimes not even in single version. And doing it between distribution is just, I don't think it's realistic at all. For the up question here, doesn't that mean there will be a proliferation of runtimes? For example, if I have application version one requesting runtime version one, is this same application still able to use runtime version two when it comes out or will it still require runtime version one? Well, it would still use one until you switch it. Until upstream decides that it's time for me to switch to the new one and do all the QI to verify that it's now possible. And I think, yes, there is a risk for a proliferation of runtimes. We try to make them, for instance, we have a shared free desktop runtime and the GNOME and the KITI runtimes all use that. We try to keep it down to a small amount of stuff. But fundamentally, I don't think we are going to end up in a situation where we have apps depending on really old runtimes because apps wants the newest thing too. That's part of the reason why we can't keep ABI because apps wants to use the new stuff. So I think it's in their interest as well as the users to move to the newer version. So eventually we'll be able to purge old versions of stuff. But in a broader ecosystem, they'll still be around. Like there'll be a bunch of old versions just like there's all Isis and Fedora 5 or whatever. It doesn't mean everyone uses them. Within a Flatpak, where do we look to see how bubble wrap is used if we want to learn more about it, just verify how it's wrapping the environment? I mean, you can look at the code or you can run Flatpak run dash VV. I think it will print all the bubble wrap command lines runs. Daniel? So one often stated advantage of classical package management over application images is if I have a commonly used library that's shared by many, many applications and that library has a security flaw. And that flaw is fixed upstream by the library. And I only depend on one new package update from that library. If I use application images, I would have a zoo of versions of that library spread in my system. How do I get it safe and secure? So one of the partial responses to that is that we have the runtime system where we can rev the runtime independently of the app. So even if the app is not maintained, we can rev open SSL or libpng. And in fact, when we're designing the run time, the aspect of the run time that is security sensitive, we ensure that all those libraries are in the run time. So we can also. But it's still true that some app could bundle a specific library. Maybe they need an old lib SSL or maybe just some random library they need. That could have security issues. Sandboxing partially mitigates that, but not completely. And it's a well-known issue with this kind of solution. But I think it's worth it because fundamentally the current app ecosystem for Linux just doesn't work. As an upstream author of apps, I cannot get my code into the user's hand. It's a much for me as a developer of things I think are cool and that my user thinks are cool and they want to use, they can't use them because the system is broken. And if they use them, they use an ancient version and reports bugs I fixed two years ago. It's ridiculous. And yes, there are risks with it. But it doesn't mean we can keep doing something forever that doesn't work. Okay. Thanks. As anybody looked at developing tools to be able to scan through your flat. We have a very simple CVE tracker that looks for CVE. It looks at the versions in the run times mainly. But we want to deploy it against all of the flat hub manifests also. But it's very simple. It looks at you use this module, this tarball that has this version, this reported CVE against that. We file a bug against your GitHub repo. We're not actively looking for new bugs. Has anybody done any basic Chrome apps or Android apps for Linux? In flatbacks. How do you mean? Well, I've heard, I know it's been talked about basically can I package up an Android app and put it into a flatback? Android apps. There's this an box thing. Like lets you run an Android apps. I don't think it's doable to run that as flatback because it has kernel side features. Like there are kernel specific or Android specific kernel APIs like the binder and whatnot that you might have to use. But for instance, Chrome apps, I think should work. We have a base application for electron apps that makes it really easy to package electron apps. Electron apps are basically like Chrome apps, aren't they? You mentioned the exports directory to integrate stuff with the system. Is there a multiple versions? Story to that, what happens if I have Libre Office and say five different versions on the system? So this is the concept of which one is current and only the current one wins. So you can switch which one is current. So I can't say for example open this file always with this version of the app and that other file with the other version. You can manually start any version on the command line by using flatback run. But there's only ever going to be one desktop file which is the current active one. And you can switch which one that is. But it's only one at the time. Do you think this current model of text files for MIME types and icons and so forth is really scaling or wouldn't we need something like launch services on Mac where you have a database that really can do more flexible on demand stuff? I mean my name is on half of those specs. So that was 15 years ago. So could they be better? Quite possibly. Will they? I doubt it.
 I'm with Red Hat for the last 18 years or something.  I work in the desktop group.  I normally work on GNOME stuff, but the last three years or something, I've been working  on this project called Flatpak.  I'm going to talk today about the core implementation of Flatpak and how it works and why it works  that way.  But first, maybe I need a short description of what Flatpak is.  How many people use Flatpak?  And how many people heard about it?  Not everyone, but most.  So it's apps for the Linux desktops.  And obviously we had applications for the Linux desktop forever.  So apps mean something else.  It's like Apple phone apps style or Android apps.  You can expect to easily install them and fearlessly do so without having them messing up the system  in some way or affecting other apps or your system updating, affecting the apps.  Like you want the apps to be an isolated thing from the core operating system.  So there's several parts to this.  There is a distribution of your app.  We have a repository format that you can add this remote and you can install stuff from  it.  We have A, this is FlatHop, which is one source of FlatPaks.  There can be many.  You can configure many yourself like a jump repository or a debut repository.  There can be many and they're independent.  This is the website for FlatHop.  But the data is all there.  You can use it from the command line.  You can use it from GNOME software, KDE Discover, or you just click on install on this website.  They all use the same data, the same screenshot, descriptions, and whatnot.  And then, and this is kind of the core, you can run the same app, the same build on any  distro.  These are just the distros that we have on descriptions of how to install FlatPak on.  But fundamentally, it should run on anything that has not even recent kernels, but pretty  ancient kernels still can run this thing.  And not only can you run on any distro, you can also like distro hop while having the  same apps installed.  You can upgrade your distro and it will not affect the thing.  And you can run a newer version on an older distro and all that kind of stuff, right?  So common example is to use a really stable, rel or debu stable base, but still want to  run the latest GIMP or some specific app.  You can also build it anywhere, because building itself, I mean, there are many ways to build  stuff, but the default way we build FlatPaks builds in a sandbox too, so you can have two  people sharing a development environment, even though they're on completely different  systems and they will produce essentially the same binaries.  There might be some timestamps and whatnot, but the rest is shared, right?  It also runs in a sandbox.  We're talking about desktop apps here, so sandboxing is complicated.  There are very many integration points between the desktop app and the desktop or even other  apps.  So sandbox is available and the default sandbox is very secure, but you can't really do a  lot of stuff in it.  So you can also opt out and the user gets asked, you want to grant these permissions  and you can give your app file system access and whatnot.  But we're also working on the other side with things like Wayland, Pywire, portals, to make  it possible to have sandboxed apps that are actually useful, but that's partially in the  future.  But right now you can use it for any app, but it's just not as secure.  So you might ask yourself, how is this different from containers?  Because all of these things I talked about before, you can also do with Docker, right?  A Docker image can run on anywhere, you can build it and build out or Docker build or something  and ship it somewhere else.  So there are two main differences.  First of all, the target user of Flatpak is fundamentally non-privileged.  It might be like a data entry clerk who has an IT, like IT gives him a laptop, he doesn't  have sysammin on it or anything, right?  He is not root, he doesn't have a root password, so we can't have any tools like Docker that  requires you to be root or that implicitly grants you root rights, like if you have access  to the Docker socket, that is giving you root.  We can't have that.  As I add on to that, none of the techniques we use in Flatpak itself can fundamentally  rely on root-only features.  That means certain things just cannot be used.  We can't do device mapper, we can't use butterf as snapshots, or we can't do firewall setup  for port forwarding, because all of these are fundamentally sysadmin level operations  that are not allowed for any kind of unprivileged use.  The second thing is that the goal is to run desktop apps.  So we automatically integrate with the desktop in all the ways that matters.  Like you install the app, it's a single click, and when it's installed, like there's a nice  graphical progress thing, and when it's installed, it appears in your desktop, it has an icon,  it has a description, it can install MIME type files or DBA service files, it has access  to X or Wayland, it can talk to DBAs in a safe way, it has the right GPU drivers in  there, if you use free desktop specs to find your stuff, you can easily find your stuff,  we have interactive permissions, like the portals I talked about, it's basically a way  to have low permissions, but then at run time, safely grant extra permissions, like access  to a particular file or web camera or something.  So to build Flatpak, there's two major parts beneath it that kind of has to be explained  in detail before we can explain Flatpak, and actually once we have these, like a working  knowledge of Ostr and bubble wrap, the rest of Flatpak is mostly trivial, just using these  in the right way.  In Ostr is like the short quote, it's like get for operating systems, and by saying it's  like it, I mean that all the things you'd expect from Git are there, there is a remote  repository, there's a local repository, you configure the remote, you pull from the remote,  you pull refs from the remote, you can commit a ref, you can check out a ref, a ref points  to a commit object, which is a checksum, and it contents address the rest of the files  in the commit, it's essentially a re-implementation of Git, but where Git is made for source  code, and if you ever try to commit like a large binary, it just isn't meant to handle  that, whereas Ostr is all about having a on-disk file format that is useful for trees of binaries.  It was originally made for committing your entire operating system into Git, basically.  So we are going to look at the repository layout, which is the way that Ostr differs  from Git.  So we have here, kind of hard to see, but yeah, an app, it's just a directory with some  files, but in the end, that's what all apps are, right?  It's just a directory with files plus some metadata.  So there's a bunch of normal files here, and I colored them so you can kind of follow  where they appear when we commit them.  So if you were to commit this, these are the Ostr operations you run, the init repository,  and then we commit, whoa, we commit to a branch called master, this directory called app,  and it generates a commit ID for us.  And you can look at it, and it looks like it's a commit.  That's basically what Git would give you, right?  And it generates this repository here that if you ever looked into a.git directory, it's  very, very similar, right?  So there's a refs directory that contains the refs, and ref is like a more generic thing  than branches, but think of it as branch.  And they have a bunch of objects, and if you look at this ref file for master, it's just  a, actually, I cut down all this, they're actually very much longer, but I cut them  down all to 10 characters so you can read them.  It's a commit ID, and if you look in the object directory, you can find the commit here, and  the commit is just a small metadata file that contains the commit message, the timestamp,  the previous commit ID, because that's like a history of these, and also a pointer to  the root directory of the thing.  And that's just also an ID, which is to check some of this.  So the red thing is the root directory, so it has a pointer to this, which is also a  small metadata file that basically says, this is a directory, and it has a file named bin  with this commit ID, or a directory, and a file called readme with this commit.  And then you can recursively look into everything, and if you eventually reach a regular.file,  which is just a normal file, if you look at that file inside the repository, it's just  represented as itself with a different name.  And the name is a checksum of the content of the file plus some subset of the metadata,  like the user that owns it, the permissions, and extended attributes, and a couple of things  that are part of the identity of the file, because if you store two files in the same  repository that have the same content, but different permissions or whatever, there will  be two objects in the object store.  And then we can modify this.  So we change the readme file here, and we commit again.  So we get a new commit.  I don't think you can see it, but it's like a brighter version of the color when it's  changed.  So what happens then is that we add, we changed the master here to point to the new root commit  object, which now points to the previous one, plus the new root directory, and the new version  of this file here.  All the other ones are left alone because they weren't modified, right?  So we modified the app and the readme.  And you can find both the objects at both versions in there.  So the interesting thing here is that committing a new three is a purely additive operation  plus an atomic switch of this file at the end, basically.  So operations are very safe in that they're not destructive or changing anything.  And if you were to check this out, this is just the same postory.  If you check this out, check that as to a directory new, you get a directory new, which  looks like the original thing, except if you look really, really careful, these file has  our hardlink count of two, which they shouldn't have normally.  And if you look in detail, you see that actually they're the same inode as the repository objects,  these checkouts are fundamentally hardlink farms back into the repository.  So they're very efficient to create.  And if you have multiple checkouts of the same or slightly different things, they are  like co-share inodes.  So it's very efficient in that sense.  And the way you're meant to use it is that you mount this thing read only.  Like when OSTRI uses it for its inoestry as the whole operating system, you basically  commit slash user into OSTRI and then you mount it read only.  So it's safe for these hardlinks to point back into the repository because you're never  able to modify it.  And there's also a version that isn't meant for local store.  If you put this thing on a web server, it's a similar format.  The main difference is that they are.  The files are compressed and the metadata of the file are in the file.  Plus there's a file called summary that has all the refs in a single file because you  can't naturally enumerate all the refs on a web server, right?  So you can read a single file and it will tell you the name of all the refs and their  current commit.  So then you can recursively find anything you want.  And if you have a local version of a ref and the new one or the upstream one is different,  you can very efficiently calculate which objects you need to download to make your local copy  the latest one.  There's also GPG signatures in this commit meta file.  This is basically you can add metadata to it, including a commit or a signature of the  commit and you can sign the summary.  So you can protect against men in the middle kind of stuff or downgrades or something.  It's also, it's not listed here, but there's also an optional static deltas directory where  we store basically binary diffs between specific versions.  So if you're going from maybe the next to last to the current version, there might be  a specific delta file you can download.  And that will give you even better download performance.  If a file changed, but it's just one byte that changed, you can just get a really small  delta.  If you don't have the delta for the particular download you want it to do, you can fall back  to the regular OSTRI pull.  So the reasons we use this is the automatic deduplication is very nice because fundamentally  containerization and sandboxing and everything is about bundling.  So we want to try to minimize the cost of bundling.  So anything that accidentally gets shared because it's the same file just automatically  gets shared.  So if two completely different builds happens to have the same icon, so what not, they'll  just automatically be shared.  Even if you have reproducible builds, it's likely the most things will be shared.  And they're also shared both on disk and in the page cache because page cache is per  inode and inode is the same because they're all hard links.  You also get very efficient updates due to the deltas and the quick way to get what's  changed in a version.  And updates are atomic, the way you use OSTRI is that you check out in Git, a checkout is  almost always tied to a particular Git local Git repository, but in OSTRI you normally  have one shared repository and multiple checkouts on the side.  So it's very safe to do an update of the repository and then a new checkout that doesn't affect  a running instance of a previous checkout.  And they can automatically switch over.  And also this needs nothing in from the kernel.  It works on Unix version 7 or wherever hard links were introduced.  Just isn't anything complicated or privileged here.  So the other tool is MableRep.  And it's an unprivileged chute on steroids.  And I guess most people here know the virtual file system, but we have a bunch of physical  file system that are probably stored on a device somewhere or maybe there are tempfs.  And in the kernel there's a mount table that is basically a sequence of take this here  and put it here that builds up the virtual file system.  And nothing super exciting about this.  One might notice that, I don't know if you can see here, but there's C is mounted twice  here.  So this file foo is available here and over here somewhere.  In the kernel it's just another mount.  But most people know them as bind mounts because the way you create it is if you go to the  first mount and then you take the existing thing here and bind mounted here.  But in the kernel it's just a list of mounts.  And at some point someone added this root.  It's just called because maybe it would be cool to virtualize what apps see.  So instead of the root directory being a global thing, it became a per process thing.  So basically a global variable was made like a member of the struct process thing.  And this way apps can see different things in terms of the file system.  And also a lot later, namespaces were added, which basically makes the entire mount table  to be a thing that can be different in each process.  So mounts can be completely different in namespaces.  And in fact, some of these physical things might be visible in some but completely invisible  not even mounted in other namespaces.  So Shroot is really cool.  And so most people like it and use it.  But for me it's not very useful because you have to be root to run it.  And why is that?  So Unix the kernel is a very simple thing.  And to create a user space operating system on top of it, it relies on certain things  like set UID to increase privileges.  Simple example is sudo.  sudo is an app that is set UID.  So anyone who ever runs it turns into root, which is not good.  So the first thing sudo does is look at etsy sudoers and see are you allowed to do this.  But this relies on the fact that etsy sudoers is actually the admins file.  If you're in control of the file system, you can point it to something else that says,  yes, I am allowed to become root.  And suddenly you broke the system.  So this implicit trust in things like privilege raising operations, there are many of them,  set UID, set caps.  I guess I haven't thought that many, but there are a couple of them.  So with the introduction of unprivileged username spaces, and I think actually the  username spaces themselves aren't vastly interesting, but this process control switch  was added that you have to enable to make unprivileged username spaces work.  And it basically means this process and all its children can never ever raise privileges  using all these set UID-like operations.  And that means that root operation is safe, because the sudo or whatever inside your sandbox  can never actually become root.  There's also like mappings of UIDs and whatnot, which is kind of nice, but not necessarily  important for me at least.  So I wrote this tool called bubble wrap.  It was initially part of Flatpak, but it was an interest from many people, it was extracted  to separate things.  But it's basically a shell wrapper that uses all these kernel features, because while they  are just kernel syscalls, you have to be very careful when you set them up, and it's really  messy and hard.  So it's a simple tool where you can create your own namespace.  And it's slightly different in how it works from root.  In root, you kind of from the outside build up the entire thing, and then you jump into  it.  Whereas bubble wrap starts with a completely empty system, with only root being a tempfs,  and then you can like from the inside, but via commands from the outside, build the thing  up.  So this example starts with nothing, and then we create the directory in temp, and then  we make a read-only bind of the host user on the user in the sandbox, and then a sim  link from lib64 to use lib64, and then we run userbinls in the sandbox.  And this is all it sees.  Obviously, this only works if you have a lib64 style host, but on a Fedora, that will run  in a super minimal sandbox that only has read-only access to user and nothing else.  And other than the primary way of setting up the file system, we have a bunch of other  features that enable basically all the things you can do, unprivileged, on the current Linux  kernels.  So you can unshare more namespaces.  If you unshare the net one, you only end up with a loopback and nothing else, and you  can unshare all of these, and you can mount certain kinds of file system.  Well, dev isn't actually a file system, but if you say mount dev here, it will create one  that has bind mounts of the host slash dev nodes, because we can't create device nodes  as a user, but we can link to pre-existing ones.  And if you unshare the pit file system, we have a handler for pit one, so you can read  children and not get zombies and whatnot.  And seccomp, there's a way to pass a binary of seccomp rules into bubble wrap that will  get applied.  After everything is set up, we apply the seccomp rules at the end.  So you can, like, the seccomp rules doesn't have to include everything to set up the environment.  There's also a set UID version of bubble wrap.  The regular one works fine on Fedora and Ubuntu, but a bunch of other distros disable unprivileged  username space or put them behind some kind of kernel flag or boot flag or something.  And the reason is, in unprivileged username spaces, you are rude in some sense.  You're rude against that username space.  But there is a, I don't think anyone thinks that the general things that username spaces  expose are unsafe.  It's just that there might be other part of the kernels.  There's this enormous syscall ABI, and not all of it is correctly namespaced.  So something might process this UID zero as meaning it has access to something where it  actually is just UID zero in this namespace.  So we have a, well, it's the same, basically.  If you take the bubble wrap binary and make it set UID, it will switch to using a set UID  model of operation where it's normally mount stuff.  It does all the same things.  So it should theoretically not be any less unsafe than the unprivileged one.  And in fact, one could argue that it's more safe because it doesn't expose the full, you  know, syscall ABI to this fake use, fake root mode.  So yeah, that's useful thing to make Flatback work on all distros.  So I think we have now everything we need to take a very, very high level view of how  Flatback work.  Every installation has an OSTRI repository, a local one.  And there are actually two main installations.  There's a per user one in Valib Flatback, and there's a per user one in each home directory.  Every app and something called runtimes are committed to this OSTRI repository in branches  that looks like this, or these are refs.  So this is an app ref, and this is a runtime ref.  And like this is obviously the name of the app, or the runtime, and the architecture,  and there's like a version thing.  So those are in the repository, and we pull them from a remote, and then we check them  out next to the repository.  This is called deploying them in OSTRI.  And then we run them with bubble wrap, where we put the files from the app, in slash app,  and the runtime in user.  And these are all read-only mounts, so we can't affect them.  And obviously, there's a bunch of more here to set up, like we have a temp, and we have  a proc, and we have a dev, and various other standard stuff.  You can also request access to regular file system paths, like if you want home directory,  we'll add a bind mount of the home directory to the end.  But this is the basics of how we run an app.  And if you look at an app that's deployed, in Barlet Flatpak, there's a directory called  repo, which has the repository, but there's also a name, which is the entire ref.  And in that, we have the actual thing checked out under its own commit ID, and a similar  name called active that points to it.  And if you look in that active directory, this is the checkout, has some metadata, the  name of the thing, what's binary to run, environment variables to set, and files is  like the regular file, it's like a prefix.  Basically someone built into a prefix and made it into the app.  So it's got bin, lib share, and whatever else you might have there.  There's a subject you call export that contains special kinds of files that we want exported  to the file system, or to the host file system.  This currently allows icons, desafiles, mime type, service files, and I think an own shell  search providers.  And also, after checking out Flatpak itself, it creates this deploy file, and this ref  file, which are not actually part of the upstream thing, the deploy file just says this checkout  came from this remote.  The ref file is actually just a file, but whenever we mount this read only, we also have the  pit one of the sandbox take a non-exclusive ref, non-exclusive lock on this file.  So at any point, we can look at a certain checkout and see if it's locked.  And if so, something is using it, and we have to keep it around.  So the typical Flatpak install command, you just give the name.  So we have to figure out the entire ref, but we know it's probably for the current architecture,  and you specify a remote here, and the remote has the default branch name, so we can figure  out what you actually want to install.  So we pull the entire ref to the lock of repository.  To figure out what commit we actually ended up with, and we check this out and create these  files, and then we sync everything.  Up until this point, we only created new files.  Nothing affected anything running in the system, or that you could run.  But then we do an atomic set of this active sim link, and at this point, Flatpak run will  find the new version.  So we will say later in an update, there might be multiple commit here, but there's only  one that is the active one, and switching between them is an atomic operation.  And then at the end, we also look at all these exports and copy them into shared directory.  Well, it's not a pure copy.  We look at the files and rewrite some stuff and make sure it's safe and whatnot.  But basically, we copy them.  One update is the same, except when we're done, all the old commits are moved to this  global directory called thought removed.  And then for everything in that directory, we take an exclusive lock on this ref thing,  and if we can't do that, then it's still in use, and we leave it be there.  Moving the directory somewhere else doesn't affect the running instances.  So if your Firefox is running, it will not notice anything changing until the last instance  of it exits, then the lock gets unlocked, and we can take an exclusive lock on it, and  then it's fine to delete, because at that point, nothing could ever refer to this old  thing because it's in this sub directory, and the sim links are changed and whatnot.  Obviously, if something was running and we updated it, we will not delete this thing,  so it will be left around possibly forever, but generally, we run update again, and it  will traverse all the removed files and eventually become garbage collected.  On top of that, we have a top of the line sandbox or something.  We enable a bunch of stuff.  Use in namespaces is optional because it's not always available.  In the set UID version of Flaphack, we might not be able to support a username space in  case it was completely disabled in the kernel, but if it is, we enable it.  Obviously, we use the file system namespace, but we have to.  That's how we make sure we run something else.  We also use the pit namespace because if you can see proc, basically all the other apps  that are running on your system, at least all of your apps are visible in proc, and  you can use those proc fd and whatnot to look into what those other apps are doing.  We isolate that by using a pit namespace, but it also neatly gives us a pit one that  controls the lifetime of the entire container.  We know we can kill that to kill all of it, but we also know that when it exits, the last  process in the sandbox died.  Optionally, we do network and IPC namespaces.  We do seccomp.  It's very hard to generically do seccomp for everything.  We're supposed to run arbitrary desktop apps.  What can we forbid?  Well, there's some really weird stuff.  Like who uses X25 or whatever.  We use socket ties to disable some really weird syscall.  The key ring is not, the kernel key ring is not namespace aware.  I think it's somewhat.  But yeah, we disable that.  These things, ptrace perf multilarch, are useful for development.  We have modes where you can request them.  If we're building stuff, we enable them by default.  In a regular app, you would really not need ptrace.  We disable it by default.  We also disable recursive namespaces.  If you actually have real, unprivileged namespaces, those can stack.  But we want to avoid having the app control the way, like the layout of the file system  for similar reasons to the pseudo incident before we want to be able to trust that we  set up the sandbox in a specific way and it keeps being that way.  Obviously, every app has its own temp, because it's just part of the root tempfs.  We can't generally add C groups.  We don't use C groups.  Except if you have systemd user running, we create a scope for the thing on the user  in the instance.  This doesn't currently give us a lot, though.  We can't apply any policy on the group, because that's not doable as a user.  But hopefully, eventually, C group v2 will save us all and whatnot.  Then we can do C group limitations and whatnot as a user.  We also have something called the deepest proxy.  Every app has access to the session bus, and have certain privileges on it.  Everything goes via this proxy that filters calls so you can basically only be called  into, plus do some very, very open system-wide calls, like talk to the bus itself and own  your own name and a couple of other things.  In case you're not requesting any specific permissions, this directory is created for  you in various environment variables points to it.  It will be the only writeable persistent directory where you can store data.  Obviously, if you grant your app home to access, you can write wherever you want.  The idea is that in the long run, when everything is sandboxed, we will have a directory where  every app has its configure files, its cached files, its whatever.  When you uninstall it, you can also easily take away all the per-user data that the app  installed.  Here's a couple of links to various projects and ways to reach me and the project.  Anyone has any questions?  Do we have a microphone?  Thanks.  I have my home folder still on a rotational drive.  For me, OS3 is really slow to the point that the flatback update of the GNOME platform  can take up to seven minutes to complete.  It's R8.1.  It's encrypted, so a butter FS or copy on write.  It's a worst case scenario.  Are there any plans to add another backend?  For instance, we see a sync in place of OS3, or are there any performance improvements  that can be made?  I think it's more about having the download be efficient.  I don't know if it actually stores in a de-duplicated way that we can use directly.  It does?  Fundamentally, though, should that, if it has the same layout where you explode every  file as a file and then F sync and make it atomic and all that, if you do all that, isn't  it still as slow, though?  Because that's the problem, right?  You write all these files all over the place and then you sync it and you end up in a journal  or whatnot.  If you're a butter FS, you're not doing that.  There's a similar issue on the XE4, right, if you F sync something, you force the journal  to be flushed and everything else blocks and whatnot.  But I don't quite see how CS sync would not have the same issues in the end.  If you want to ensure the OS3 is on this, it's going to take a while.  I don't see really any way out of that.  Yeah.  Over the years, we've been developing Flatpak that's been talking about a file browser so  that you wouldn't have to give full access to the home directory and you could basically  have the file browser sort of inject files into the app.  Has that moved up forward at all?  Yeah.  So, it's basically a file system portal, file-shooting portal.  It's basically a combination of a Fuse file system where every app, every Flatpak app  that runs has a bind modded in it, a subset of this Fuse file system that is called a  document portal.  You can register a file and create a document for it and then it's visible in the document  portal mount plus there's a sub directory per app and that sub directory gets mounted  into the sandbox.  You can dynamically add files to target a specific app.  What happens is you do a debus call to the portal and outside of the sandbox.  We have full access to everything.  We do a file chooser and at the end, we create a document for this file which makes it appear  in the sandbox of the running app and then we pass back the document identifier and then  we can access the file via that Fuse file system.  What doesn't work is exposing an entire sub tree of your file system.  So it's mostly for like, I can open a PDF in events in sandbox mode but it doesn't work  for Emacs or an IDE or something like that.  But I could run a Firefox or a...  Yeah, events or something like that.  Yeah, that works.  In the beginning you mentioned Apple apps.  They seem to be much, much simpler basically just directories on the Mac or zip files on  iOS that were part of the simplicity stems from the fact that everything is either part  of the operating system or part of the application.  Why does it have to be so much more complicated in the Linux world?  Well, there are two things.  First of all, the sign of SAP HAC is meant to work on current apps.  Current apps in Linux hard code the prefix and the binary.  Over time people have tried to make things relocatable and some snaps for instance relies  on relocatability with like, ass loads of environment variables and things.  But still there are things that aren't relocatable.  Get text is just a hard coded prefix.  It just isn't possible to use a system that is relocatable on the current Linux apps basically.  The second is that Apple has a single ABI that they maintain that you can use and given  my history of like 20 years trying to keep ABI in Fedora and whatnot.  It just isn't doable.  It's not even doable in Fedora to keep a single ABI for between versions and sometimes not  even in single version.  And doing it between distribution is just, I don't think it's realistic at all.  For the up question here, doesn't that mean there will be a proliferation of runtimes?  For example, if I have application version one requesting runtime version one, is this  same application still able to use runtime version two when it comes out or will it still  require runtime version one?  Well, it would still use one until you switch it.  Until upstream decides that it's time for me to switch to the new one and do all the  QI to verify that it's now possible.  And I think, yes, there is a risk for a proliferation of runtimes.  We try to make them, for instance, we have a shared free desktop runtime and the GNOME  and the KITI runtimes all use that.  We try to keep it down to a small amount of stuff.  But fundamentally, I don't think we are going to end up in a situation where we have apps  depending on really old runtimes because apps wants the newest thing too.  That's part of the reason why we can't keep ABI because apps wants to use the new stuff.  So I think it's in their interest as well as the users to move to the newer version.  So eventually we'll be able to purge old versions of stuff.  But in a broader ecosystem, they'll still be around.  Like there'll be a bunch of old versions just like there's all Isis and Fedora 5 or whatever.  It doesn't mean everyone uses them.  Within a Flatpak, where do we look to see how bubble wrap is used if we want to learn  more about it, just verify how it's wrapping the environment?  I mean, you can look at the code or you can run Flatpak run dash VV.  I think it will print all the bubble wrap command lines runs.  Daniel?  So one often stated advantage of classical package management over application images  is if I have a commonly used library that's shared by many, many applications and that  library has a security flaw.  And that flaw is fixed upstream by the library.  And I only depend on one new package update from that library.  If I use application images, I would have a zoo of versions of that library spread in  my system.  How do I get it safe and secure?  So one of the partial responses to that is that we have the runtime system where we can  rev the runtime independently of the app.  So even if the app is not maintained, we can rev open SSL or libpng.  And in fact, when we're designing the run time, the aspect of the run time that is security  sensitive, we ensure that all those libraries are in the run time.  So we can also.  But it's still true that some app could bundle a specific library.  Maybe they need an old lib SSL or maybe just some random library they need.  That could have security issues.  Sandboxing partially mitigates that, but not completely.  And it's a well-known issue with this kind of solution.  But I think it's worth it because fundamentally the current app ecosystem for Linux just doesn't  work.  As an upstream author of apps, I cannot get my code into the user's hand.  It's a much for me as a developer of things I think are cool and that my user thinks are  cool and they want to use, they can't use them because the system is broken.  And if they use them, they use an ancient version and reports bugs I fixed two years  ago.  It's ridiculous.  And yes, there are risks with it.  But it doesn't mean we can keep doing something forever that doesn't work.  Okay.  Thanks.  As anybody looked at developing tools to be able to scan through your flat.  We have a very simple CVE tracker that looks for CVE.  It looks at the versions in the run times mainly.  But we want to deploy it against all of the flat hub manifests also.  But it's very simple.  It looks at you use this module, this tarball that has this version, this reported CVE against  that.  We file a bug against your GitHub repo.  We're not actively looking for new bugs.  Has anybody done any basic Chrome apps or Android apps for Linux?  In flatbacks.  How do you mean?  Well, I've heard, I know it's been talked about basically can I package up an Android  app and put it into a flatback?  Android apps.  There's this an box thing.  Like lets you run an Android apps.  I don't think it's doable to run that as flatback because it has kernel side features.  Like there are kernel specific or Android specific kernel APIs like the binder and whatnot that  you might have to use.  But for instance, Chrome apps, I think should work.  We have a base application for electron apps that makes it really easy to package electron  apps.  Electron apps are basically like Chrome apps, aren't they?  You mentioned the exports directory to integrate stuff with the system.  Is there a multiple versions?  Story to that, what happens if I have Libre Office and say five different versions on  the system?  So this is the concept of which one is current and only the current one wins.  So you can switch which one is current.  So I can't say for example open this file always with this version of the app and that  other file with the other version.  You can manually start any version on the command line by using flatback run.  But there's only ever going to be one desktop file which is the current active one.  And you can switch which one that is.  But it's only one at the time.  Do you think this current model of text files for MIME types and icons and so forth is really  scaling or wouldn't we need something like launch services on Mac where you have a database  that really can do more flexible on demand stuff?  I mean my name is on half of those specs.  So that was 15 years ago.  So could they be better?  Quite possibly.  Will they?  I doubt it.
Flatpak__a_technical_walkthrough_K0bkapSpzzk_0_6803.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_6804_7271.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_7272_12827.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_12828_31679.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_31680_59459.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_59460_59567.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_59568_59699.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_59700_60251.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_60252_60395.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_60396_60539.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_60540_60719.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_60720_60887.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_60888_61127.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_61128_62123.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_62124_62243.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_62244_62639.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_62640_62771.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_62772_62819.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_62820_63083.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_63084_63275.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_63276_63707.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_63708_63995.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_63996_64055.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_64056_64391.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_64392_64499.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_64500_64559.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_64560_64727.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_64728_64835.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_64836_64907.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_64908_64967.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_64968_65027.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_65028_65075.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_65076_65147.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_65148_65207.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_65208_65315.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_65316_65447.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_65448_65519.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_65520_65675.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_65676_65735.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_65736_65795.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_65796_65879.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_65880_65987.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_65988_66059.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_66060_66419.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_66420_67163.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_67164_67355.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_67356_68231.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_68232_68771.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_68772_69179.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_69180_69227.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_69228_70595.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_70596_74819.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_74820_75635.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_75636_76199.png Flatpak__a_technical_walkthrough_K0bkapSpzzk_76200_76342.png