• Pl chevron_right

      Aryan Kaushik: Open Forms is now 0.4.0 - and the GUI Builder is here

      news.movim.eu / PlanetGnome • 1 month from now • 3 minutes

    Open Forms is now 0.4.0 - and the GUI Builder is here

    A quick recap for the newcomers

    Ever been to a conference where you set up a booth or tried to collect quick feedback and experienced the joy of:

    • Captive portal logout
    • Timeouts
    • Flaky Wi-Fi drivers on Linux devices
    • Poor bandwidth or dead zones

    Meme showcasing wifi fails when using forms

    This is exactly what happened while setting up a booth at GUADEC. The Wi-Fi on the Linux tablet worked, we logged into the captive portal, the chip failed, Wi-Fi gone. Restart. Repeat.

    Meme showing a person giving their child a book on 'Wifi drivers on linux' as something to cry about

    We eventually worked around it with a phone hotspot, but that locked the phone to the booth. A one-off inconvenience? Maybe. But at any conference, summit, or community event, at least one of these happens reliably.

    So I looked for a native, offline form collection tool. Nothing existed without a web dependency. So I built one.

    Open Forms is a native GNOME app that collects form inputs locally, stores responses in CSV, works completely offline, and never touches an external service. Your data stays on your device. Full stop.

    Open Forms pages

    What's new in 0.4.0 - the GUI Form Builder

    The original version shipped with one acknowledged limitation: you had to write JSON configs by hand to define your forms.

    Now, I know what you're thinking. "Writing JSON to set up a form? That's totally normal and not at all a terrible first impression for non-technical users." And you'd be completely wrong, to me it was normal and then my sis had this to say "who even thought JSON for such a basic thing is a good idea, who'd even write one" which was true. I knew it and hence it was always on the roadmap to fix, which 0.4.0 finally fixes.

    Open Forms now ships a full visual form builder.

    Design a form entirely from the UI - add fields, set labels, reorder things, tweak options, and hit Save. That's it. The builder writes a standard JSON config to disk, same schema as always, so nothing downstream changes.

    It also works as an editor. Open an existing config, click Edit, and the whole form loads up ready to tweak. Save goes back to the original file. No more JSON editing required.

    Open forms builder page

    Libadwaita is genuinely great

    The builder needed to work well on both a regular desktop and a Linux phone without me maintaining two separate layouts or sprinkling breakpoints everywhere. Libadwaita just... handles that.

    The result is that Open Forms feels native on GNOME and equally at home on a Linux phone, and I genuinely didn't have to think hard about either. That's the kind of toolkit win that's hard to overstate when you're building something solo over weekends.


    The JSON schema is unchanged

    If you already have configs, they work exactly as before. The builder is purely additive, it reads and writes the same format. If you like editing JSON directly, nothing stops you. I'm not going to judge, but my sister might.

    Also thanks to Felipe and all others who gave great ideas about increasing maintainability. JSON might become a technical debt in future, and I appreciate the insights about the same. Let's see how it goes.

    Install

    Snap Store

    snap install open-forms
    

    Flatpak / Build from source

    See the GitHub repository for build instructions. There is also a Flatpak release available .

    What's next

    • A11y improvements
    • Maybe and just maybe an optional sync feature
    • Hosting on Flathub - if you've been through that process and have advice, please reach out

    Open Forms is still a small, focused project doing one thing. If you've ever dealt with Wi-Fi pain while collecting data at an event, give it a try. Bug reports, feature requests, and feedback are all very welcome.

    And if you find it useful - a star on GitHub goes a long way for a solo project. 🙂

    Open Forms on GitHub

    • Pl chevron_right

      Christian Hergert: ((lib)Re)bonjour

      news.movim.eu / PlanetGnome • 2 days ago • 4 minutes

    I made another weird side project while unemployed. In fact I’ve wanted it for a while but once I learned that “Rebonjour” is the word for “hello again” I just had to finish the library.

    librebonjour is an asynchronous DNS-SD and mDNS client library for GLib applications. Or, more practically, it is a small GObject API over the two local service-discovery providers you are likely to find on a Linux system: Avahi and systemd-resolved.

    It does not link against either of them. It only talks to them over D-Bus.

    The reason for that is mostly boring, which is usually where the useful things are. Applications should not need to care if a machine has Avahi running, or if it is using systemd-resolved for mDNS. They should be able to discover a service, resolve it, maybe advertise something, and get on with whatever they were actually trying to do.

    So RebonjourClient selects a backend internally. If org.freedesktop.Avahi is available on the system bus, it uses Avahi. If not, it falls back to systemd-resolved’s org.freedesktop.resolve1 API. If neither is around, availability checks fail like you would expect.

    The public API stays the same either way.

    What It Does

    There are three common things I wanted to make pleasant.

    First, one-shot discovery. Ask for the service types in local , ask for instances of something like _ipp._tcp , then resolve one of those instances into addresses and TXT metadata.

    Second, browser-style discovery. A RebonjourBrowser owns a stable GListModel of RebonjourService objects. That fits nicely into GTK code because the model object can stay the same while the contents change underneath it.

    Third, registration. You can describe a local service with RebonjourServiceDescription , register it, and keep the returned RebonjourRegistration alive for as long as the service should be advertised.

    Resolving a service gives you a RebonjourResolvedService . That contains the SRV result, TXT data, priority, weight, and a model of RebonjourEndpoint objects. The endpoints hold the GSocketAddress you would actually use to connect.

    Why Two Backends

    Avahi is the nicer backend for browsing. Its D-Bus API gives you long-lived browser objects and emits signals when services appear and disappear. That maps very naturally to GListModel changes.

    systemd-resolved is different. It has useful DNS-SD and mDNS operations over D-Bus, but the browsing side is lookup-based. That means you can ask what is there, but you do not get the same live add/remove signal stream that Avahi provides.

    I did not want applications to have to care about that distinction unless they really want to. So the browser has auto-refresh and refresh-interval properties. With Avahi, auto-refresh is effectively harmless because the model is already live. With systemd-resolved, it starts an internal refresh loop and updates the model for you.

    It is not magic. It is just putting the backend-shaped unpleasantness in one place so application code can stay boring.

    Asynchronous with libdex

    The whole thing is built on libdex . Anything that might touch D-Bus or the network returns a DexFuture .

    That means construction, availability checks, service-type lookup, instance lookup, resolving, registration, browser refresh, and unregistering are all future-based. If you are already writing fiber-style code with libdex, the API fits into that directly:

    g_autoptr(RebonjourClient) client = NULL;
    g_autoptr(GListModel) services = NULL;
    g_autoptr(GError) error = NULL;
    
    if (!(client = dex_await_object (rebonjour_client_new (), &error)))
      g_error ("%s", error->message);
    
    services = dex_await_object (rebonjour_client_lookup_instances (client,
                                                                    0,
                                                                    "_ipp._tcp",
                                                                    NULL,
                                                                    REBONJOUR_LOOKUP_FLAGS_NONE),
                                 &error);
    

    The 0 there means any interface. Passing NULL for the domain uses local . The common case should not require looking up interface indexes which I’m pretty sure most people reading this have never even done before.

    Advertising

    Advertising is where things get more system-policy-oriented.

    With Avahi, registration goes through Avahi’s D-Bus API. With systemd-resolved, registration uses RegisterService and UnregisterService , which are polkit-protected. Also, resolved needs full mDNS enabled with MulticastDNS=yes ; MulticastDNS=resolve is enough to browse and resolve, but not enough to respond as a service.

    So librebonjour can expose one API for registration, but it cannot make host policy disappear. Applications still need to handle authorization failure, missing mDNS responder support, sandbox boundaries, or whatever policy the system administrator has decided is appropriate.

    That seems like the right way to demarcate things. The library should hide the provider mechanics, not the permissions of the platform.

    Why

    Mostly because I wanted this to exist.

    DNS-SD is handy. Local-network service discovery is still useful. But using it from a GLib application means either caring too much about the provider or writing just enough glue that every application gets to have its own slightly different version of the same code.

    And even worse is having to bundle things to build projects like Avahi for Flatpak when you only use the library which calls into D-Bus anyway.

    This is not a grand platform initiative. It is not something I am employed to maintain. So you know, use wisely.

    • Pl chevron_right

      Michael Meeks: 2026-05-22 Friday

      news.movim.eu / PlanetGnome • 2 days ago

    • Early interview & job offer for a support role, catch up with Anna, sync with Dave, catch up with a partner, 1:1 with Naomi.
    • Sync with Thorsten, Skyler, Pedro, poked at slides.
    • Dave, Emily, Jake, Pete & Eli arrived - played in the garden somewhat, enjoyed company, tried to cook a meal; caught up happily after a decade+ gap. Bed early.
    • Pl chevron_right

      This Week in GNOME: #250 Sideloading

      news.movim.eu / PlanetGnome • 2 days ago • 5 minutes

    Update on what happened across the GNOME project in the week from May 15 to May 22.

    Third Party Projects

    Alexander Vanhee reports

    Last Saturday, Bazaar was updated to 0.8.0 with the ability to install .flatpak bundles. We created a fancy new dialog so people can better understand what happens when they install one. We also added the ability to remove app caches directly from within the sizes dialog and reworked the app install animations.

    Feel free to leave your feedback on the GitHub repo !

    bazaar_bundle.BKRpfvv5_cHJ1M.webp

    bazaar_cache.BfwwHb7S_Z2iEV8y.webp

    Luiggi R. Cardoso says

    Draft v1.3 has been released!

    You know those text snippets you need to save, that quick idea you want to write down, or a link you need to hold onto but don’t want to open a heavy app for? This is Draft.

    This new version brings:

    • Estonian and Brazilian Portuguese Translations (thanks to our community!).
    • Keyboard shortcuts for formatting options.
    • Under-the-hood performance fixes and minimal spellchecking support.

    Download it on Flathub | Contribute on GitLab | Help with Translations

    draft-screenshot.BUjBAXZH_ZJArlS.webp

    Bilal Elmoussaoui reports

    I have released a new version of gobject-linter . The release includes:

    • Parse custom types using g_type_register_static directly
    • Add a new unused vfuncs rule
    • Add a new missing_g_begin_decls rule
    • Generate fixes for g_object_virtual_methods_chain_up , missing_autoptr_cleanup
    • gi_missing_since rule now validates that enum members don’t include inlined Since: annotations
    • Improvements to various existing rules

    francescocaracciolo says

    Newelle 1.4.0 Released! Newelle (AI Assistant and Agent for Gnome) has received a new major update!

    🔗 Added Interfaces: alternative way external applications can interact with Newelle! Featuring Telegram support, APIs, WebUI and more!

    👷 Support for directly download pre-compiled binaries for llama.cpp instead of compiling

    🔐 Better Command permissions

    💬 Better Prompt Editing

    📝 Better Font rendering and customization

    Get it on Flathub: https://flathub.org/it/apps/io.github.qwersyk.Newelle

    Wladimir Palant reports

    Gnome Commander 2.0 has been released! Many changes:

    • Rewritten in Rust, with better performance and stability.
    • Added embedded terminal to display output of commands run in Gnome Commander.
    • Redesigned Quick Search can now be used to filter the file list as well.
    • Far better search performance and many more improvements to the Search dialog.
    • Consistent handling of file encodings in the internal viewer along with lots of other improvements.
    • Improved accessibility of the application, screen readers should be able to recognize the context everywhere now.
    • More tab state is being restored on restart – selected file, column sizes and ordering, hidden columns.
    • Tons of fixed bugs and more .

    commander.DZi49Kc3_Z1cLSkU.webp

    Anil reports

    Codd 0.5.0 has been released!

    Since the first Flathub release, several new features and improvements have been added:

    • Secure password storage using the system keyring
    • SQL script generation for tables
    • A Table Inspector for inspecting columns, data types, defaults, constraints, indexes, foreign keys and triggers
    • Additional table action options

    Spanish translations have also been added recently, thanks to fvtronics.

    Codd is a lightweight PostgreSQL client for GNOME, available on Flathub. Feedback, bug reports, and feature ideas from PostgreSQL users are very welcome.

    Get it on Flathub or check out the source code .

    codd_1.l0YU6Bk2_10frGv.webp

    codd_2.0NemD-O__1rTnKN.webp

    Gitte

    A simple Git GUI for GNOME

    Christian announces

    🎉 Gitte 0.4.0 released!

    Gitte is a GTK4/libadwaita Git interface for the GNOME desktop, written in Rust.

    This version introduces a mainline concept: you can now mark a branch as your project’s mainline and use it as a reference for merged-checks, filtering, and a brand-new “Sync with mainline” action that rebases your branch and fast-forwards it in one step. The commit log also gained a filter to only show commits not yet in the mainline.

    Working with changes got more flexible: you can now revert commits straight from Gitte, partially stage untracked files, toggle an additive selection mode in the changed files list, and ignore whitespace in diffs. Staging and unstaging are now available via context menu, Enter, and double-click, and you can create a branch directly from any commit in the log.

    The UI received a lot of polish. The push and pull dialogs are now visually distinguishable and show their targets in tooltips, “ahead/behind” is rendered as text instead of arrows, popovers no longer claim unnecessary width, and several diff styling glitches are gone. Checking out a branch now creates a detached HEAD, with switching as a separate, explicit action.

    This release also brings a long list of fixes around macOS shutdown and keyboard shortcuts, keyboard navigation, files without trailing newlines, now respects fetch.prune = true in the pull dialog, and various small papercuts.

    Get it on Flathub , for macOS or have a look at the Code .

    gitte_1.DyzkWrbO_2d1LFM.webp

    gitte_2.C8oexdPP_Zpbqph.webp

    gitte_3.D5Ve8sB2_Jtaev.webp

    Fractal

    Matrix messaging app for GNOME written in Rust.

    Kévin Commaille reports

    Here comes Fractal 14.rc. This release candidate comes with a fair amount of quality of life improvements:

    • The sidebar room filter has been improved: Enter goes to first room result, and there’s an empty state when no results match the term.
    • The performance of the room list has also been improved, it should be mostly noticeable for accounts that have joined a lot of rooms.
    • Informative events ( Unable to decrypt , server notices…) are now styled differently to reflect their special nature and differentiate them from regular text messages that anyone can send.
    • Calls are rendered in the timeline and incoming calls trigger a notification. We still don’t support calls, but at least now you know when someone is calling and can open another client to answer.

    As usual, this release includes other improvements, fixes and new translations thanks to all our contributors, and our upstream projects.

    It is available to install via Flathub Beta, see the instructions in our README .

    As the version implies, it should be mostly stable and we expect to only include minor improvements until the release of Fractal 14.

    If you want to join the fun, you can try to fix one of our newcomers issues . We are always looking for new contributors!

    fractal-utds-and-calls.BUaXhMyF_1WUEfz.webp

    Miscellaneous

    Damned Lies

    The internal application to manage localization of GNOME & friends modules

    Guillaume Bernard says

    GNOME Damned Lies has received a few improvements this week! Focusing on the issues identified for the next GNOME 51 release, we implemented the auto-closing feature for translations pushed through a merge request. This way, a background job regularly checks the status of the merge request (GitLab instances and Github.com are supported) to auto-close workflows.

    We also updated the look and feel of the vertimus workflows to use more native Boostrap base style and removed the custom CSS that was used to render the action history, easing the maintenance.

    In addition to that, we added support for Codeberg.org projects. Only direct pushes are supported at this time, because we need to implement the plugin to open/check merge requests on Forgejo software. We are on our way to also support Freedesktop’s GitLab instance soon.

    That’s all for this week!

    See you next week, and be sure to stop by #thisweek:gnome.org with updates on your own projects!

    • Pl chevron_right

      Thibault Martin: I realized that A cheap VPS is a good front

      news.movim.eu / PlanetGnome • 3 days ago • 1 minute

    I have a server at home. It runs a Kubernetes cluster and a few services. I want to expose them to the Internet, so I can e.g. share public links from my Nextcloud, or synchronize my Kobo reader with Grimmory . But I don't want to expose my home IP to the world, and I want to have some reasonable protection against unsophisticated DoS attacks.

    I realized that I can achieve that with a cheap VPS that acts as a front, HAProxy , and Wireguard .

    I rented a tiny VPS for €4/month at Infrawire (1 vCPU, 2 GB RAM, 25 GB NVMe). I installed a Debian 13 on it, because I want that front server to be as stable and low maintenance as possible, and installed the Debian-packaged HAProxy onto it. I also installed Wireguard. The VPS has a publicly accessible IP, so it will be my Wireguard server: my server at home can reach the VPS to establish a tunnel, the opposite is not true.

    On my k3s node, I've installed Wireguard as well. I configured Wireguard on the VPS and my k3s node to establish a tunnel between the two. I've also bound the sshd on my VPS to the wireguard address. Infrawire offers a console so I can unstick myself if I locked me out of my own server (e.g. by misconfiguring Wireguard on any side, or if my server at home had any failure).

    I pointed all my DNS records to the VPS. The HAProxy is a "dumb" tcp forwarder, so I can keep operating like before on my cluster. In particular, HAProxy doesn't do TLS termination. My certificates are fetched on my cluster by cert-manager like before, using the http-01 challenge and Let's Encrypt. I could also move to dns-01 challenges, but http-01 just works and lets me switch to a registrar without an API if need be.

    That way, I don't need a fixed IP at home, and I don't have to do any port-forwarding from my home router to my k3s cluster. Even better: the VPS has an anti-DDoS protection included, and I can also configure HAProxy to refuse too many connections from a same IP, I can make it close TCP connections that take too long to establish, and more. If my VPS gets hammered, I can still access my services from within my home network.

    • Pl chevron_right

      Michael Catanzaro: Single-Click Code Execution Exploit for Evince, Atril, and Xreader

      news.movim.eu / PlanetGnome • 3 days ago • 7 minutes

    CVE-2026-46529 is an argument injection vulnerability in Evince, Atril, and Xreader caused by missing shell quoting when composing a command line. The reporter, João Medeiros, has published a GitHub repo for the CVE and a blog post with the story of how he discovered the flaw and developed the exploit. He also created an Atril security advisory and an Evince issue report .

    The vulnerability is fixed in:

    • Evince 48.4 ( fix commit ) (I originally reported that it is fixed in 48.2, but there was no successful release for that tag)
    • Atril 1.28.4 and 1.26.3 ( fix commit )
    • Xreader 4.6.4 and 3.6.7 ( fix commit )

    If you use one of these PDF readers, update immediately. Or at least please be seriously paranoid about clicking on links in PDFs until you do update.

    This vulnerability also affects Papers , but it’s probably not urgent to update Papers. (No, not because it uses Rust. Keep reading!)

    The Flatpak sandbox could have drastically reduced the danger of this attack, limiting the compromise to only files that you had previously opened in the PDF reader. Sadly, Evince and Papers both use sandbox holes that render the sandbox totally meaningless. (Atril and Xreader are not available on Flathub.)

    The Vulnerability

    When you click on a link in a PDF, Evince may execute itself to display the link. Normally the command line used would look something like this:

    /usr/bin/evince --named-dest=/home/foo/hello.pdf

    But an evil PDF may trick Evince into executing a command that is quite different than expected:

    /usr/bin/evince --named-dest= --gtk-module=/home/foo/evil.so /home/foo/hello.pdf

    Oops. The first part of the command is always going to be /usr/bin/evince , but the evil PDF is nevertheless able to unexpectedly load a GTK module into Evince. The fix is to quote the untrusted input using g_shell_quote() to ensure it cannot “break out” of its intended context:

    /usr/bin/evince --named-dest='/home/foo/hello.pdf'

    Or:

    /usr/bin/evince --named-dest=' --gtk-module=/home/foo/evil.so /home/foo/hello.pdf'

    Much better: now the threat is neutralized. g_shell_quote() is safe to use even if the untrusted input itself contains quotes. (However, beware: this only works because GLib is parsing the command line itself, and GLib is not a real Unix shell. It’s not safe if the input is going to be passed to an actual Unix shell. It might not even be theoretically possible to do that safely, because it’s valid for filenames to contain entirely arbitrary characters!)

    All GTK 3 apps support the --gtk-module command line argument for injecting a shared library into the application. The library may of course then execute whatever code it wants via its library constructor. But GTK 4 no longer has standard GTK command line flags, so this does not work for GTK 4 applications like Papers. It’s still possible to tell a GTK 4 app to load a GTK module, but only via environment variables, not via command line flags, and I don’t see any opportunity for the malicious command to set environment variables. It’s probably not possible to exploit this vulnerability in Papers: although it has the exact same vulnerability as the other PDF readers, the impact is different.

    The Exploit

    So far this looks like a pretty typical security bug. OK, so if you trick the user into downloading an archive (or perhaps a git repo) that contains both a malicious PDF and also a malicious shared library, then you can trick the PDF reader into loading the shared library and thereby execute arbitrary code. That’s a pretty bad foreseeable exploit, sure, but at least the attacker is at considerable risk of arousing suspicion if the user is trying to download a PDF and also receives a shared library. You’d have to try pretty hard to hide the library in a forest of other boring files if you want the attack to look convincing and unsuspicious. Right?

    Nope.

    João used Claude Opus 4.7 to develop a sophisticated script for building malicious polyglot PDFs that are simultaneously both valid PDF files and also valid ELF binaries, so the attacker only needs to trick the victim into downloading one evil PDF file. When the victim clicks on a link in that PDF, the PDF reader will dlopen the PDF itself. The PDF/ELF polyglot’s library constructor will then execute arbitrary code. Much less suspicious, and much scarier. Polyglot files are not entirely novel , but I’d still say this required substantial creativity and expertise from the AI, and substantial persistence from the human. Needless to say, very nice job to both Claude and João.

    You can easily build your own malicious PDF using the provided script and sample GTK module. The script in the Evince and Atril issue reports requires that the attacker predict the absolute path that the malicious PDF file will be saved to; however, João’s blog post and GitHub repo refine the exploit to remove that requirement.

    Some Thoughts on AI Vulnerability Reports

    A human inspecting this code should have been able to find the parameter injection vulnerability, but that requires considerable time and effort, so unsurprisingly nobody did. We’re probably in for a rough time in the short term as the volume of AI-generated vulnerability findings remains temporarily very high and attackers have a much easier time crafting working exploits. But in the long term, I expect we are going to be much more secure than we were before, so this will be worth it.

    A human working alone would have almost certainly stopped and moved on after finding the vulnerability. Claude allowed taking the investigation much farther. It’s highly unusual for a GNOME vulnerability report to come with a working exploit. This is a dangerous change. Perhaps it will be a one-time event, but I suspect we will be seeing more frequent exploits in the future.

    Silver lining: the exploit helps us better appreciate the severity of the issue. It’s often hard to assess how bad a vulnerability is. If not for the weaponized exploit, I would have thought this bug was not very scary, and would have treated it as not a big deal. We would have fixed it, perhaps or perhaps not with a CVE ID, surely without any blog post or fanfare, and probably without distro security updates. But since there is an exploit, we instead had no doubt that this vulnerability was dangerous, and were able to handle it accordingly.

    Several GNOME projects have begun outright prohibiting all AI-generated contributions, including issue reports, with no exception for vulnerability reports. Such policies are misguided and unacceptable. I can sort of understand why some projects might (misguidedly) wish to prohibit AI-generated code contributions. OK, fine. But blocking AI vulnerability reports will make GNOME less safe. AI-assisted vulnerability reporting is the new industry standard for good reason: it is highly effective.

    Some humans are not good at preparing AI-assisted vulnerability reports and will spam maintainers with low-quality reports. Sometimes they will be outright bogus, although more often there may be valid underlying bugs with exaggerated severity claims or bad proof of concept demos. This is annoying, but bad issue reports are a cost we are just going to have to accept and deal with.

    The quality level of AI vulnerability reports reviewed by conscientious humans — as well as AI assessments of AI vulnerability reports — is now often quite encouraging. But just like humans, AIs may also miss things, especially subtle distinctions that may be highly relevant. Although I’m quite impressed with these AIs, we still need experienced humans to review and manage reports. Please don’t abuse the technology by submitting vulnerability reports that you do not understand or have not validated. And certainly please do not allow an AI agent to interact with an issue tracker on your behalf!

    For Security Geeks

    This was my first time scoring a vulnerability using CVSS 4.0 rather than CVSS 3.1. It’s also the first time I wasn’t terribly confused about how to set the parameters, because the scoring guide contained answers to all of my questions. Nice. My CVSS vector for CVE-2026-46529 is CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N, the base score is 8.4, and I’m pretty sure my choices for each parameter are good. By comparison, using CVSS 3.1 I came up with CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H and base score 7.8.

    • Pl chevron_right

      Bart Piotrowski: Why are Flathub downloads so slow sometimes?

      news.movim.eu / PlanetGnome • 4 days ago • 3 minutes

    It's probably not your fault.

    On a cache miss, there are two things a reverse proxy (which Fastly is to us) can do. It can make the client wait until the proxy itself fetches the requested content and then serve it, with subsequent requests being served from the cache. From a user's perspective, it means staring at "hung" process, and people tend not to be understanding when a program is stuck seemingly doing nothing.

    Instead, the proxy can stream the response from the origin, caching it at the end. This makes the client receive the data right away, although it's not without drawbacks.

    In a streaming setup like Flathub's, an all-MISS path adds some upstream latency before the first byte, but also limits the download speed to what the slowest link can deliver. As we don't run servers in the same datacenter or on a single backbone network, the hop from Fastly through the caching proxy to the master server incurs a penalty that may affect how quickly the data gets back.

    In order to cache files larger than 20MB, Fastly expects customers who use streaming misses to use segmented caching. Anything larger than that gets broken down into smaller chunks. When Fastly wants the data from us, it will add a Range header specifying which bytes we should respond with. Fastly will then serve the request after reconstructing the file from various chunks. Our caching proxies also use the value of the Range header in the caching key to avoid requesting the full file over and over again from the master server as well.

    While great for caching, many concurrent range MISSes can turn what would be a sequential file read into scattered, random reads. It wouldn't matter with SSD or NVMe, but as the repository is stored on HDDs, when combined with streaming misses, it can turn cold transfer speed into min(network bottleneck, ZFS random-read bottleneck) .

    Counterintuitively, you may improve your download speeds by aborting the ongoing Flatpak operation and starting it again. While the initial request was slow, there's a non-zero chance it went through all the caching layers and it will become a cache hit in the meantime.

    Flatpak

    Let's talk Flatpak. When installing or upgrading applications, Flatpak will try to use delta files. A typical delta is an update file that contains only the difference between versions. There are also from-scratch deltas, which effectively are an archive with all files required to install an app from scratch, thus the name.

    Flathub generates a single upgrade delta and a from-scratch delta for the latest version. Delta generation is an expensive process in terms of disk reads and writes, but also disk space. Because our ZFS setup isn't exactly the fastest, generating more delta files also affects how quickly we can publish an update. Yes, in theory we could be doing this out of band but we don't. In hindsight, Titanic wasn't unsinkable after all.

    What happens if you are not updating often enough? A lot of suffering. Flatpak will download each missing file between the version you are on and the one you want to upgrade to, separately. This is an almost certain cache miss causing even more random seeks on the master server. At this point Flatpak would be better off downloading the from-scratch delta but it can't. The behaviour is controlled by OSTree, which doesn't offer any knobs to affect it . It is the right choice if the goal is to limit the bandwidth used by the client to fetch updates, but an incredibly bad one for anyone on a reliable connection; downloading a single large file is almost always faster than fetching multiple smaller ones.

    What do? Some brave soul could fix OSTree to apply a better heuristic on when to use from-scratch deltas for upgrades, or at least make it expose an API that lets Flatpak choose. For the rest of us mere mortals, we can only update regularly or wait patiently for the update to finish.

    • Pl chevron_right

      Sam Thursfield: Status update, 21st May 2026

      news.movim.eu / PlanetGnome • 4 days ago • 4 minutes

    I often write about how when stuff works well, you take it for granted.

    It’s true for technology: when’s the last time you hit a compiler bug in GCC? Once upon a time these were a common thing and you had to choose your C compiler wisely. Yet I haven’t recently seen an article that says “GCC is going great” .

    It’s true for people too. When someone does an excellent job maintaining an open source project then, they do occasionally get some gratitude, but — if you do a bad job, it’s amazing how quickly the negative comments pile up in the issue tracker, many of which taking subtle or not-so-subtle digs at the project owners. Maybe we created this situation for ourselves by having a prominent “report issue” button but no corresponding “send flowers to the maintainer” button.

    On that note, a hat tip to Carlos Garnacho for all his work on the Localsearch extractor sandbox which recently got a shout out its “extremely strong” design.

    (It’s worth noting that Localsearch also stopped using GStreamer to parse media files altogether, which the discussion in that thread missed. We love GStreamer but it isn’t the right tool for metadata scanning. The 3.9 and 3.10 series use libav/ffmpeg instead, but given that US software patent laws make it tricky for USA folk to distribute that, the plan is to move to using MediaInfoLib )

    Fairphone 5

    It’s coming up to two years since I switched to a Fairphone 5 . The real proof of this device will be in 2033 when I manage ten years of using the same phone.

    Meanwhile, I recently had some issues with it not charging via the USB-C port. I thought it might be a bit tricky to fix, but it really is easy: buy the replacement part (about 20€), take off the back cover, remove a few small screws and switch over the whole USB port + speaker unit.

    I hear some fellow Android users complaining about Alphabet/Google’s intrusive AI integration. Apparently the power button is now the AI button? I use the stock Android, and I know vendors have their hands tied somewhat by Alphabet/Google, so its worth noting that disabling the AI integration on the Fairphone 5 is a single config setting .

    I’d be interested to know more about the kernel version as it is old as hell. I guess this is a vendor/Android thing, and hopefully most of the many known vulnerabilities in this old version of Linux are mitigated by sandboxing higher up in Android. If you’re a high risk cybercrime target then I would definitely not recommend using the vendor Android OS on this device. (Probably best to avoid Android altogether if this is your situation!)

    So its not perfect, but I just wanted to shout out again that there are some good people doing good work here. If only all smartphones were built like this one.

    Korg Minilogue XD

    One reason I’m not writing much about open source software is that I’m spending a lot of my time outside work making music in various guises, these days mainly as part of soon to be huge Galician disco revival group Muaré. This band needs a website, so in future I don’t have to link you to Instagram , but you know how the world is at the moment. We do at least have a Bandcamp page .

    When it comes to music gear, I seem to be a Yamaha guy. It’s amazing actually that the same company that made my trombone also makes excellent digital pianos, and if and when I need a motorbike, Yamaha also sells those .

    When it comes to synths though I’ve been really enjoying the Korg Minilogue XD . It’s cheap, built like a tank and its ten years old so there are plenty of second hand models around. It’s not fucking Behringer (please don’t give money to Behringer ). It’s simple and sounds great.

    But most impressively, it support plugins via a freely available SDK . You can develop your own custom digital oscillators and effects for this thing and deploy them over USB. Of all major pro audio manufacturers, Korg are the only company I know to support this. So even though the hardware is now 10 years old, it can still learn new tricks, and there is an active scene of both free and commercial plugins for the platform. Perhaps the most active commercial outfit is Sinevibes . There is, of course, reddit . The SDK is not truly open source (and few things in pro audio ever are) but it’s free from any licensing fees, and the whole thing is sat here in a Git repo . Pretty good.

    If I’d had more time to prepare I might have a video here of some cool Minilogue XD tunes I made. But I guess you’ll have to wait til next month for that. Until then!

    • Pl chevron_right

      Christian Hergert: Asynchronous Varlink with varlink-glib

      news.movim.eu / PlanetGnome • 5 days ago • 2 minutes

    I’ve been putting together varlink-glib , which is a library for writing Varlink clients and services in C. The basic idea is to keep the transport policy out of the library. You get a connected GIOStream however you want, whether that is GLib networking, socket activation, or something more specialized, and then wrap it in a VarlinkClientProtocol or VarlinkServerProtocol .

    The API is built around DexFuture , which makes the async parts feel a lot nicer in C than the usual callback layering. Client calls return a future, server replies return a future, and internally the protocol can use fibers for the work that wants to look sequential while still integrating with the GLib main context. This is very much the style of API I want for system services: explicit enough that you can debug it, but not so painfully manual that every call site becomes a state machine.

    future = example_calc_add_call_invoke (proxy,
                                           call,
                                           VARLINK_METHOD_CALL_DEFAULT,
                                           add_reply_cb,
                                           NULL,
                                           NULL);
    

    There is also a varlink-codegen tool which takes a .varlink interface and generates typed C wrappers for it. That gives you proxy objects, server skeletons, call objects, reply objects, and error constants instead of making every application hand-roll JSON. You can still drop down to VarlinkMessage , VarlinkMessageBuilder , and VarlinkMessageReader for forwarding or weird infrastructure cases, but most code should get to stay typed.

    File descriptor passing works when the transport is a Unix socket connection. This follows the same general model as systemd’s Varlink support: the JSON payload contains an integer index, while the actual descriptors are sent out-of-band with SCM_RIGHTS and attached to the containing message as a GUnixFDList . Generated code can continue to treat the field as an integer, while the actual descriptor list stays attached to the underlying VarlinkMessage .

    fd_list = g_unix_fd_list_new ();
    fd_index = g_unix_fd_list_append (fd_list, fd, &error);
    
    varlink_message_set_unix_fd_list (parameters, fd_list);
    

    Protocol upgrades are supported too. A method call can ask to upgrade the connection, and once the final successful reply is sent, Varlink stops being valid on that connection. The VarlinkProtocol is still a GIOStream , so the next protocol can continue reading and writing through the same object. That keeps the handoff explicit without requiring a separate transport abstraction.

    I also wired in optional Sysprof capture support. When enabled, client and server RPCs can show up as Sysprof marks with useful bits like method name, result, reply count, one-way, multi-reply, upgrade, Varlink error, and GError details. That matters because once you have concurrent calls, generated dispatch through VarlinkServerRegistry , and services doing real work, “it got slow somewhere” is not enough information.

    A screenshot of Sysprof showing captured varlink calls over time with the RPC and message metadata inline.

    There is still more polish to do, but the shape is there: typed generated APIs for normal users, low-level message APIs for infrastructure, DexFuture for async flow, Unix FD passing for the system service cases, protocol upgrades for handoff cases, and profiler hooks so it can be debugged when the happy path stops being happy.

    A small personal note: as I wrote in my recent update from France , I am no longer employed by Red Hat. Work like this is currently self-funded, out of pocket, while my family and I settle into a new chapter. If you find it useful, a note of encouragement or a contribution means a lot right now. It helps make it possible to keep improving the free software infrastructure many of us rely on.