tauri-apps/tauri

[feat] Bundle Tauri apps as Flatpak

puyoxyz opened this issue ยท 27 comments

Describe the problem

According to this page, Tauri apps can only be bundled as .deb or AppImage.

Describe the solution you'd like

An option to bundle Tauri apps as Flatpaks.

Alternatives considered

No response

Additional context

No response

fwiw, flatpak and rpm support is on my todo list, but i won't start working on it until after v1 stable is released (if nobody beats me to it by then)

Hi! I'm interested in taking a stab at this.

There's two ways this could be accomplished:

  1. Generating installable Flatpak single-file bundles (similar to APKs on Android.)
  2. Creating a Flatpak manifest that can be used with flatpak-builder to build an app into a repo or uploaded to Flathub for distribution.

The first requires the second, but is ultimately easier to accomplish as the build process could access the internet (Flathub disallows internet access during builds on their runners). The first is also more in line with how the other bundlers work.

In my WIP, I've named the first method flatpak in BundleTarget in tauri.conf.json. Would it be better to call this flatpak-bundle to allow for the second method in the future or is the second way not really a goal?

Great to hear you're interested in working on it!

With method 1, is there then any way of publishing to flathub or similar? I would imagine that's what most people would be looking for in a flatpak target.

AFAIK, you can't publish a Flatpak bundle directly to Flathub, you have to submit a manifest. However, I think the best course of action is to:

  1. Create a Flatpak manifest that can create the Flatpak without network access (declaring the crates and other dependencies as sources), then
  2. building the app and exporting a bundle.

This gives the user a bundle that they can host themselves and a manifest that could be submitted to Flathub with minimal changes (likely just changing where the app's sources are downloaded from).

This has a slight downside in that the app will have to be compiled twice (once on the host for the other bundlers, and once in the sandbox by flatpak-builder, but ultimately I think this is a good thing since the app will be built in the same environment that it will run in, and the generated manifest contains everything necessary to build the Flatpak on it's own.)

There could also be an option to disable generating the Flatpak bundle and only generate the manifest, skipping the building phase and preventing compilation from happening twice.

Happy to report that I made quite a bit of progress towards this!

It's definitely still a work in progress, but for now it can:

  1. Generate a Flatpak manifest that can build the app without network access
  2. Build and export the app as a .flatpak bundle

From here, I think it needs to be made a bit more reliable, and will definitely need documentation added.

Should I open a draft PR?

With method 1, is there then any way of publishing to flathub or similar? I would imagine that's what most people would be looking for in a flatpak target.

Yep, that's a really important part of flatpak, [in my opinion] adding just flatpak single-file bundles isn't enough

@owendaprile beat me to it there ๐Ÿ˜„
That said I've not built flatpaks before so glad you're looking into it. Let me see where I can help out.
This is the branch you're working in right? https://github.com/owendaprile/tauri/tree/feat/bundler/flatpak

@Beanow Yeah, that's where I'm working from. I haven't been able to work on it in the past few days, but I can explain my strategy. Currently, it compiles and installs the app inside the sandbox, which overall is better since it means the library versions on the host don't matter and there won't be any dependency issues (unlike the AppImage, where the host library versions matter). However, this is a lot more difficult because flatpak-builder disables network access during the build process, and all sources need to be declared in the manifest. I was having trouble copying sidecar binaries in and getting the correct path to install them. After thinking about it, I think there's only really two paths forward for building the Flatpak:

  1. Building the Debian package on the host, specifying that as the source in the manifest, then extracting the data archive and copying all those files to /app. This is the easiest method, but means there can be library incompatibilities depending on which distro builds the Debian package.
  2. Specifying the entire project tree as the source for the Flatpak, installing cargo-tauri as a build dependency, use that to build only the Debian package (or make another bundle target that generates a tarball and use that) and extract those files and copy them to /app. This avoids the library compatibilities. (However, now that I think about it, this would require the app to have the source code public if submitted to Flathub.)

In either case, some extra settings will have to be added to the bundle settings for specifying extra permissions past the required ones.

When I have more time, I'll join the Discord and try to figure out which path is best and what other requirements there are.

@owendaprile I've been poking around and trying your branch, and that approach is what I wonder about as well.
I'm still learning about flatpak though so I don't know how people tend to approach this yet. Consider my comments mainly questions as I look into it ๐Ÿ˜„

Currently, as you mentioned for the AppImage, the "host" already needs to be a controlled environment (we do this with Github Actions) when making releases. And both the Deb and AppImage are created by compiling on the 'host', then the bundler copies build artifacts, assets and libraries as needed.

This is similar to what you would do with a multi-stage docker image.

FROM some-image as builder
...

FROM scratch
COPY --from=builder ...

Where GH Actions handle this "builder" stage, and "copy from builder" is what the bundler does for you.

While I can see where you're coming from wanting to build inside the target sandbox, the issue I see is build dependencies for people's Tauri projects may vary wildly. And now you'd end up maintaining two parallel build environments. The one for flatpak builds and the existing build environment / GH actions.

I think if we're going to depend on / unpack the deb package, we'd essentially be leaning on the existing approach. Wouldn't it make more sense to generate a manifest which sources directly from the compiled src-tauri/target/release/...?

If it's already expected that the bundler is running in a controlled environment, then I think it's okay to build on the host and copy all the required files into the sandbox.

I still think it's better to use the deb package (or some equivalent archive) because that's just one archive that can be pointed to as a source for all the applications files. Reducing the number of sources listed in the manifest is better because when submitting the manifest to Flathub, all the sources have to be publicly available for their builders to download. (Flathub doesn't allow you to upload a Flatpak bundle, only a manifest). The AppImage bundler also starts from the deb package as a base. This would also reduce code duplication as only one bundler (the debian one) does all the real work and the other just work from that as a base.

I think it's important for the generated manifest to be as easy as possible to modify for submission to Flathub, as that's where most people will want to distribute their Flatpaks.

Maybe we could ask some Flathub reviewers/maintainers what would be the best approach for easy submission?

Flathub doesn't allow you to upload a Flatpak bundle, only a manifest

Well that puts us into a chicken-or-egg problem. None of the build artifacts would be published on a public URL known to the bundler at that time. Because it's in the middle of the job of creating them ๐Ÿ˜…

And I agree, not having a Flathub option is a no-go in my opinion.

Maybe we could ask some Flathub reviewers/maintainers what would be the best approach for easy submission?

In the long run, I think that makes sense. For several reasons, such as if we could save people hassle and bandwidth with a runtime/base app, like they use for Electron https://docs.flatpak.org/en/latest/dependencies.html#base-apps.

For the moment though, I feel like I just need to do the homework xD
There's a good amount of reference manifests on https://github.com/flathub
Plus the docs at https://github.com/flathub/flathub/wiki/App-Requirements
I'll spend some time on that, see where it gets me.

Well that puts us into a chicken-or-egg problem. None of the build artifacts would be published on a public URL known to the bundler at that time. Because it's in the middle of the job of creating them sweat_smile

Yeah, we can't make a manifest that works without modification on Flathub, but we can make one that is as simple as possible to modify for submission to Flathub. I think the right strategy is to generate a manifest that references the deb somewhere on the local filesystem, so the Flatpak can be built locally. The docs should then advise users to host the deb package and adjust the manifest to point towards that URL when hosting on Flathub.

The local manifest would look something like this:

"sources": [
    {
        "type": "archive",
        "path": "tauri-app.deb"
    }
],

and you'd only have to change it to this for submission to Flathub:

"sources": [
    {
        "type": "archive",
        "url": "https://example.com/dl/tauri-app.deb",
        "sha256": "..."
    }
],

I don't think a base app is necessary because the GNOME platform has the required dependencies already (GTK 3 and webkit2gtk) and as far as I know that's all that's required for a Tauri app to run. I guess webkit2gtk and some other dependencies could be put in a base app but that's much more maintenance effort than just using the GNOME platform.

@owendaprile I opened #4426, let's brainstorm there to limit notifications for others here.

This is flatpak's cargo template/script: https://github.com/flatpak/flatpak-builder-tools/tree/master/cargo
I feel like there should be a cargo-flatpak or something already but there's none.
We could probably provide such tool in the end. Or if anyone is interested, this could be an excellent opportunity for side project.

https://github.com/flathub/in.cinny.Cinny is an example of an app using tauri that's Flatpak'ed, and I'm working on packaging the above referenced pocket-sync.

https://github.com/flathub/in.cinny.Cinny is an example of an app using tauri that's Flatpak'ed, and I'm working on packaging the above referenced pocket-sync.

pocket-sync review for Flathub: flathub/flathub#3688

Looks really good @hadess!
I've not had time to work on it, but I know it comes up with the team regularly as something we still want to do.

In #4426 I got to the point where I could tauri build a .flatpak single file while using networking locally or in GitHub Actions. With the idea being, to use the build artifacts as input for FlatHub manifests. Because not all applications built with Tauri are necessarily Open Source, so rather than compiling on FlatHub with offline packages, it would extract pre-compiled assets.

Either way, if you're able to help think about good approaches, or with implementation that would be great ๐Ÿ™

I'm sure @wusyong and @FabianLars have thought about it more, since my last work on it too.

In #4426 I got to the point where I could tauri build a .flatpak single file while using networking locally or in GitHub Actions. With the idea being, to use the build artifacts as input for FlatHub manifests. Because not all applications built with Tauri are necessarily Open Source, so rather than compiling on FlatHub with offline packages, it would extract pre-compiled assets.

The fact that I'm using Flathub is completely tangential to the fact that, by default, flatpaks require offlines sources. Requiring offline sources means that apps are reproducible, which is important even for proprietary apps, to limit unwanted changes, whether for sources "bill of materials", following the terms of software licenses, or just making it easier to debug something!

You can obviously build your apps locally, or on a private servers for Flatpak, just like you were able to compile debs and RPMs targets for your apps.

Doing online builds, whether it's for Flatpak, debs or appimages, doesn't give you any way to check what sources were actually used, and verify them, to make sure they didn't have a particular bug, or backdoor. Rebuilding the app with the same sources might give you a different result.

But that's not any different to the other binary target you currently have. Just make sure that the "right" way with offline source generators is mentioned.

any update?

Would like support for this please! Flatpak is my favourite package manager ;)

any update?

I added support for arch and rpm via github actions

https://github.com/don-cryptus/clippy/blob/master/.github/workflows/release.yml

any progress for debian?

I added support for arch and rpm via github actions
https://github.com/don-cryptus/clippy/blob/master/.github/workflows/release.yml

any progress for debian?

tauri already bundles .deb thats how I am creating the arch and rpm packages

I added support for arch and rpm via github actions
https://github.com/don-cryptus/clippy/blob/master/.github/workflows/release.yml

any progress for debian?

tauri already bundles .deb thats how I am creating the arch and rpm packages

so after this will this issue be resolved?

I'd like to share my learnings around converting a v1 tuari app from AppImage to flatpak.

I could not get the AppImage to run, it would segfault, see repro. Instead I had to use a the .deb build but I don't really know if there are implications to that as I'm not a linux user.

https://github.com/Hacksore/flatpak-tauri/tree/appimage

At Axolotl we just build the Flatpak with cargo.
You can find the manifest here and the cargo invocation here.

It would be great if we could just cargo tauri build for Flatpak as we do for deb and appimage already.