Fedora is a Trademark of Red Hat, Inc, an operating system built by volunteers around the world. This page is provided so that independent volunteers can showcase our contributions to Fedora and Free Software in general. Official Fedora Download page.
|
|

We are happy to announce that newly purchased Private Tenant subscriptions will include raw data access as we work towards removing vendor lock-in for our SaaS customers!
IMPORTANT: Due to technical and security considerations we cannot provide real-time access to the underlying database cluster however we are working in that direction! We are also researching the technicalities behind enabling Bring Your Own Storage for file uploads!
You can find the Private Tenant subscription in the Subscriptions section on our main page!
Thank you for using Kiwi TCMS. If you like what we're doing please help us grow:
Release Candidate versions are available in the testing repository for Fedora and Enterprise Linux (RHEL / CentOS / Alma / Rocky and other clones) to allow more people to test them. They are available as Software Collections, for parallel installation, the perfect solution for such tests, and as base packages.
RPMs of PHP version 8.5.11RC1 are available
RPMs of PHP version 8.4.26RC1 are available
ℹ️ The packages are available for x86_64 and aarch64.
ℹ️ PHP version 8.3 is now in security mode only, so no more RC will be released.
ℹ️ Installation: follow the wizard instructions.
ℹ️ Announcements:
Parallel installation of version 8.5 as Software Collection:
yum --enablerepo=remi-test install php85
Parallel installation of version 8.4 as Software Collection:
yum --enablerepo=remi-test install php84
Update of system version 8.5:
dnf module switch-to php:remi-8.5 dnf --enablerepo=remi-modular-test update php\*
Update of system version 8.4:
dnf module switch-to php:remi-8.4 dnf --enablerepo=remi-modular-test update php\*
ℹ️ Notice:
Software Collections (php84, php85)
Base packages (php)
After much back and forth and hoops jumping, I can finally reveal nouveau/nvk running on a NVIDIA Spark box.
This is running on a version of nouveau[1] that has
a) ported to the 610 NVIDIA firmware
b) a bunch of display rework from Moham
c) a bunch of 0 VRAM and L2 cache handling fixes
d) spark boot support
e) spark display support
and NVK[2] with patches to handle gb10 depth/stencil differences and 0 VRAM support.
I'm not sure how best to upstream it all, it's 100 patches and a new firmware which might mean it's a wait for nova type situation, but I just wanted to see it work.
[1] https://gitlab.freedesktop.org/nouvelles/kernel/-/commits/nouveau-610-wip-spark
[2] https://gitlab.freedesktop.org/airlied/mesa/-/commits/nvk-spark-wip

We are happy to announce that private container images built on top of Red Hat Enterprise Linux are now explicitly guaranteed for Self Support subscription!
Previously only the kiwitcms/enterprise image variant was guaranteed to be built on top of
Red Hat's Universal Base Image! This guarantee is now explicitly extended to
kiwitcms/version!
There is NO such guarantee for the Kiwi TCMS Community Edition container image!
Thank you for using Kiwi TCMS. If you like what we're doing please help us grow:
Layer 2 – Ethernet Frames – Leet ARP Spoofing
ebtables -t nat -I PREROUTING -i wifi+ -p ARP --arp-opcode Reply --arp-ip-src 192.168.1.1 -s ! 00:12:34:56:78:00 -j DROPebtables -t nat -A PREROUTING -i wifi+ -p ARP --arp-opcode Reply --arp-ip-dst 192.168.1.1 -s ! 00:12:34:56:78:00 -j DROP
~
Layer 3 – Second Favorites – Lazy DHCP Snooping
ebtables -t nat -I PREROUTING -i eth0.1 -p IPv4 --ip-proto udp --ip-sport 67 -j ACCEPTebtables -t nat -A PREROUTING -i wifi+ -p IPv4 --ip-proto udp --ip-sport 67 -j DROP
~
[kmod-nft-bridge]
table bridge ethernet { chain PREROUTING { type filter hook prerouting priority filter; policy accept; iifname "wifi*" arp operation reply arp saddr ether != 00:11:22:33:44:00 arp saddr ip 192.168.1.1 counter drop iifname "wifi*" ip protocol udp udp sport 67 counter drop }}
~
Note: Most of these commands won’t work on UAP-U7-PRO APs I believe due to hardware based frame/packet routing/forwarding – I have since enabled arp-proxy and dhcp-snooping in the UI network controller application, however, I don’t see them working either, possibly because I am running a third-party gateway device. I have finally enabled client-isolation, which as tested, solves the ARP and DHCP attacks completely and forces client-to-client communication through the router instead for even further filtering!
~
Dear testers, we're happy to announce Kiwi TCMS version 16.4!
IMPORTANT:
This is a minor version release which includes critical security related updates and several improvements.
You can explore everything at https://public.tenant.kiwitcms.org!
---
Public container image (x86_64):
pub.kiwitcms.eu/kiwitcms/kiwi latest 1cefd747576b 806MB
IMPORTANT: version tagged and multi-arch container images are available only to subscribers!
hub.kiwitcms.eu/kiwitcms/version 16.4 (aarch64) d7a6828acb2c 07 Sep 2026 718MB hub.kiwitcms.eu/kiwitcms/version 16.4 (x86_64) d421c55fd66d 07 Sep 2026 698MB hub.kiwitcms.eu/kiwitcms/enterprise 16.4-mt (aarch64) 5c3cba332923 07 Sep 2026 947MB hub.kiwitcms.eu/kiwitcms/enterprise 16.4-mt (x86_64) d75c06f712d6 07 Sep 2026 926MB
IMPORTANT: version tagged, multi-arch and Enterprise container images are available only to subscribers!
Follow the Upgrading instructions from our documentation.
Happy testing!
---
If you like what we're doing please help us grow:
I have first since used a couple web based AI systems for different specific tech things and they are pretty useful if you do the extra work to verify and modify what they are telling you. I’ve found that Google Gemini AI is really good a general tech questions and configuration items (with looking it over and understanding it and modifying it of course for your specific needs) and Claude Sonnet AI is really amazing at verifying that your code is correct and other more in-depth programming related tasks (for example, memory allocation and pointer handling and file descriptor tracking).
I’ve been using these systems lightly whenever I get stuck and they are able to find the exact code snippets I was looking for to complete the rest of my projects!
Note: It’s a shame that AI resources are being used on social or political issues rather than solving technology and scientific issues to help progress humanity. I’m still amazed that I was able to feed a 1000 lines of C code to Claude as a test and it was able to determine the components purposes and the network proxy applications of it all…
Google AI seems a little more friendly and personable whereas Claude is more on task and professional ha 
~
I wanted to eventually experiment with using the AES hardware instruction but for the ARM architecture because there are ways to turn block ciphers into stream ciphers for future usage. There appears to be a C header include file that exists on both Mac and Ubuntu (arm_neon.h) and you can compile this small C program file with standard gcc options (no special arguments needed). The hardware instruction method names appear very cryptic, however, they do seem to work when I tested the hex output against other sites!
K: [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]R: [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 62 63 63 63 62 63 63 63 62 63 63 63 62 63 63 63 aa fb fb fb aa fb fb fb aa fb fb fb aa fb fb fb 6f 6c 6c cf 0d 0f 0f ac 6f 6c 6c cf 0d 0f 0f ac 7d 8d 8d 6a d7 76 76 91 7d 8d 8d 6a d7 76 76 91 53 54 ed c1 5e 5b e2 6d 31 37 8e a2 3c 38 81 0e 96 8a 81 c1 41 fc f7 50 3c 71 7a 3a eb 07 0c ab 9e aa 8f 28 c0 f1 6d 45 f1 c6 e3 e7 cd fe 62 e9 2b 31 2b df 6a cd dc 8f 56 bc a6 b5 bd bb aa 1e 64 06 fd 52 a4 f7 90 17 55 31 73 f0 98 cf 11 19 6d bb a9 0b 07 76 75 84 51 ca d3 31 ec 71 79 2f e7 b0 e8 9c 43 47 78 8b 16 76 0b 7b 8e b9 1a 62 74 ed 0b a1 73 9b 7e 25 22 51 ad 14 ce 20 d4 3b 10 f8 0a 17 53 bf 72 9c 45 c9 79 e7 cb 70 63 85 ]I: [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]O: [dc 95 c0 78 a2 40 89 89 ad 48 a2 14 92 84 20 87 ]I: [dc 95 c0 78 a2 40 89 89 ad 48 a2 14 92 84 20 87 ]O: [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]
~
Source Code: github.com/stoops/aes/blob/main/aes.c
~
This week seemed to have a lot of small irq's all around. That said, I did make some progress on a few things:
Next up on the migration train: databases. It turns out we already had one database server in staging moved to rhel10, but it was using the default postgresql 16 and since I am going to the trouble to migrate things to a new os, might as well move them to newer postgresql too.
postgresql 18 makes data page checksums default. You can disable them at startup if you really want to, but they seem like a really good idea to enable. So, I took db-koji01.stg down and added checksums and it took around 45minutes. Not super great, but not nearly as bad as it could be.
Then, the upgrade to 18 was super fast and painless.
I did some work in our ansible repo to set up rhel10 hosts with postgresql18 to start with and created a db-fas02.stg to migrate that to.
The rest of these servers will follow basically this pattern:
Setup a rhel10/postgresql18 02 vm for each server
Sync data from rhel9 one.
Stop rhel9 one (OUTAGE)
Sync data again from rhel9 one.
Enable data page checksums
Migrate from 16 to 18
Profit
I hope to get the staging ones all done next week and find any issues, then we can look at scheduling an outage after Beta freeze to do all the production ones.
My lenovo slim7x battery was getting pretty pathetic. It was 2 years old and it's max full capacity was something like 35% of design full and sometimes it was now refusing to charge without a reboot.
So, I ordered a new battery and installed it this last week.
This laptop is anoying to work on because, while there are screws on the bottom panel, it's also held on by clips. So you have to pry it off and it sounds like you are breaking it while doing so. Anoying.
Also on this laptop they routed all the cables around the battery. The battery has cable guides all around it. So, to replace the battery you have to move all those cables carefully and slide the old battery out and new one in, along with unplugging the bluetooth and wifi antennas, and disconnecting/connecting the battery connector.
I did manage to do it, but it took more time that I thought it would.
While I had the machine open I swapped the windows drive I had back in and updated the firmware (which there's no way to do from linux). It was quite a pain. windows took quite a while to notice that it was not 2024 and that it should check what _current_ updates were available. Did manage it in the end. I don't know what effect the newer firmware has, everything still works the same as far as I can tell.
We have started making rc's for beta. That sure reads weird, but if you are able, please do test and file bugs.
There's one weird auth issue I am aware of. Thats where services with keytabs are sometimes getting permission denied. It seems to be somehow some differing config on two of our ipa servers. Thats being tracked in https://forge.fedoraproject.org/infra/tickets/issues/13539
I am not aware of any other issues remaining. So, if you hit something, please do file a ticket and include enough information for us to try and fix it. ie, time/date, exactly what you were trying to login to, exactly what error message you got, etc.
As always, comment on the fediverse: https://fosstodon.org/@nirik/117219935269136120
One of the hot topics in the last months has been the use of “AI” — which usually means using LLMs (Large Language Models).
After a big push at work to adopt “AI”, it took me some time to find a good use of it in my daily workflow.
One of most popular ways of using “AI” is rewriting software. I know people having old games ported from one retro platform to another this way.
However, the low barrier to entry gave many people a way to jump in which did not end well…
As a result, countless projects have stopped accepting merge requests because so many of them were nothing more than “AI slop” (aka “worthless junk not even worth looking at”).
I have used Claude to rewrite my EDK2 ArmCpuInfo project to make it easier for me to update it. The statistics of the commit that did most of the work:
lines changed: 5630 additions & 3552 deletions
I would not send anything like that to anyone for review. Far too messy. Going through it was painful but I got what I asked for. And this was a result of several prompts and manual changes.
As you know, my work is mostly around building packages. I have worked on Arm, AArch64, ppc64le, s390x and now RISC-V. I fixed countless packages by hand, going through their source and finding out why they failed and how to get them building on target platforms.
After my last vacation I decided to check how an LLM would help with it.
I fetched the package, unpacked the sources (fedpkg prep), fetched the
build.log file from the latest failed build, and ran Claude with one, simple prompt:
Look at build.log and source and find out why it does not build on risc-v.
The amount of time I had to wait and output to read varied from package to package. Sometimes build logs from other Fedora architectures were needed, sometimes a few build attempts. At the end I had a patch which made the package buildable on the RISC-V architecture.
Some fixes were simple, like fastnetmon where a change in the link order was the only thing needed.
Some were funny, like GNU Data Language where fixing RISC-V fixed it for AArch64 as well. This made the build fail, as some tests, which were expected to fail, passed.
Others were related to differences between RISC-V (RV64GC) floating-point unit compared to other architectures. Such “simple” things like “are we dividing by zero” can be a problem.
There were also packages for which I got some patches and never sent them neither upstream nor to the package maintainer.
Those were ones I did not understand. For instance, a patch changed how the “R” language handles “NA and NaN” numbers. It was yet another issue related to how RISC-V FPU works. Also it was so cryptic that I looked at code and had no idea what I was looking at.
I understand FOSS developers who refuse to accept any “AI generated” changes. There is too much “AI slop” being submitted. At the same time I wonder where their limit is.
Would they merge patch below or not? And would presence of the “Assisted-by: LLM” line make them refuse this patch or not? Will they accept it without such line?
Subject: [PATCH] Fix abseil link order for ld.bfd
Move absl:: libraries after gRPC in fastnetmon_api_client link list.
ld.bfd (used on riscv64) is a single-pass linker and needs dependees
before dependencies.
Assisted-by: LLM
---
src/CMakeLists.txt | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 10caf4c6..5bde9fcc 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -800,10 +800,6 @@ if (ENABLE_GOBGP_SUPPORT)
add_executable(fastnetmon_api_client fastnetmon_api_client.cpp)
- if (LINK_WITH_ABSL)
- target_link_libraries(fastnetmon_api_client absl::base absl::synchronization)
- endif()
-
# We use another way to specify dependencies for Windows as our standard approach clearly does not work
# https://www.f-ax.de/dev/2020/11/08/grpc-plugin-cmake-support.html
if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
@@ -819,6 +815,10 @@ if (ENABLE_GOBGP_SUPPORT)
target_link_libraries(fastnetmon_api_client protobuf::libprotobuf)
+ if (LINK_WITH_ABSL)
+ target_link_libraries(fastnetmon_api_client absl::base absl::synchronization)
+ endif()
+
if (KAFKA_SUPPORT)
target_link_libraries(fastnetmon ${LIBKAFKA_CPP_LIBRARY_PATH})
endif()
I would accept it. Because for me, despite the origin of that patch, it is a very simple change to review.
Thanks to Google’s AI code snippets, I was able to finally implement multiple threads all reading from a singular tun interface as well as each thread performing larger batch reads/writes in one singular syscall (up to 65536 bytes per call)! Here are the parameters (IFF_MULTI_QUEUE | IFF_VNET_HDR) and calls you need to set to get it:
~
Source Code: github.com/stoops/vpn/blob/main/gtun.c
EC ElGamalpoint=f(x, y)G - point (public)k - integer (private)Q=kG - point (public)r - integer [random integer] (private)s - integer [secret integer] (private)M=sG - point [secret point] (private)C=rG - point [reference point] (public)E=rQ+M - point [encrypted point] (public)(C, E) - message [(rG, rkG+M)] (public)D=k*C - point [decryption point] (private)M=E−D - point [((rkG+M)-krG)] (private)note: must generate a unique r/M value/coordinate each time for a given keynote: encryption only works in one direction from public key to private key
~
EC DH- each side generates a secret integer (r) and multiplies with point G (rG)- each side sends their point multiplication result (rG) to the other- each side multiplies their secret integer (r) with the exchanged point r(xG)- each side can encrypt their results before sending with EC ElGamal
~
You can see point S has the same X, Y coordinates in the client as in the server and only points C and E were published!
~
Source Code: github.com/stoops/vpn/blob/main/lib/key.c
Key Generator: github.com/stoops/eckx/blob/main/ecdh.c
~
Once again, GNOME is considering participating in the Outreachy internship program. Outreachy provides internships to people subject to systemic bias and impacted by under-representation in the tech industry where they live.
Outreachy internships are funded by the participating communities. While the GNOME Foundation has not yet finalized the budget for this cohort, having a strong list of proposed projects and available mentors helps the Board decide how many slots to fund.
Project ideas will be selected based on available funding and their relevance to the overall goals of the GNOME project. Project selection will be handled by Matthias Clasen, Allan Day, and Sri Ramkrishna.
If you are a GNOME developer/maintainer available for mentoring between December 2026 and March 2027, please submit a project proposal at gitlab.gnome.org/Teams/internship/project-ideas as soon as possible (by September 11).
If you have any questions, you can contact the Internship Committee on Matrix or ask on Discourse.
It’s hard to evaluate the security of open source projects when security bug reports remain private forever. Users deserve to see security bug reports, so please remember to unset issue report confidentiality when you’re done handling an issue. There are very few good reasons to keep an issue report confidential forever. If you’re not planning to disclose the issue report within the next few months, it should probably already already be public.
For GNOME, I disclose issues whenever a merge request has been created or a fix lands in the git repo, or 30 days after the issue was reported, whichever comes first. Your project might prefer to wait until the fix is released before disclosing, especially if you fear that a vulnerability might actually be exploited during the window between the fix and release. Whatever you choose, please don’t forget about it and leave the issue report confidential forever. That’s not fair to your project’s users. Even if not many people will take the time to look, users should at least have a chance to see reported issues.
For a while now, the fingerprint management UI in GNOME Settings (gnome-control-center) has felt outdated. While it worked, the layout and enrollment flow hadn’t kept up with the rest of GNOME’s modern interface updates.
I am happy that during the GNOME 51 development cycle we managed to address that. Allan Day, Marco Trevisan, and myself worked on modernizing the interface. There’s still more work to do in the UI and in fprintd, but what we will ship in 51 is already a great step forward.
Historically, the fingerprint dialog in User Settings was stuck on a GTK3-style design. Even after being ported to GTK4, conceptually it remained unchanged. Beyond looking out of place alongside Libadwaita-based settings panels, it suffered from responsiveness and accessibility issues that made it difficult for some users to enroll their prints.

The new fingerprint management dialog uses a standard boxed list displaying your enrolled fingers. From here, each enrolled finger can be removed individually.
Clicking the “Add Fingerprint” button starts the finger enrollment process. First, you choose one of the unused finger options to enroll. From there, an assistant guides you through the scanning process. As you place your finger on the reader, the UI detects the touch and provides feedback on whether it was read correctly. You continue touching the reader until enough samples have been collected (the exact number depends on your reader’s driver). Once the progress bar fills, your finger is ready for authentication.

This is only one of the improvements that GNOME 51 is bringing. As with everything in GNOME, we will continue gathering user feedback and making iterations over time. There are already more fingerprint features in the pipeline, such as renaming enrolled fingers and verifying individual prints. Stay tuned!
Time for another saturday weekly recap in longer form.
Bunch more progress of various machines over the last week or two, and we are down to:
torrent01 (didn't manage to get this before beta freeze, will after)
mailman/lists ( https://forge.fedoraproject.org/infra/tickets/issues/13519 )
database servers ( https://forge.fedoraproject.org/infra/tickets/issues/13517 )
rabbitmq servers ( https://forge.fedoraproject.org/infra/tickets/issues/13383 )
Nice to finish this off soon.
I am hopefull that we have solved the last of our auth issues late this week. There's a lot of moving parts in our authentication stack: ipa servers on the backend, noggin on the frontend (accounts.fedoraproject.org), ipsilon for identity provider (id.fedoraproject.org). All of these have had various issues recently, but we have worked through them and I did some tuning of ipsilon on thursday that seems to have really helped.
If you are still seeing any issue, please add exactly what you were trying to login to/do and time/date to our tracking ticket. ( https://forge.fedoraproject.org/infra/tickets/issues/13482 )
We are in beta freeze now, so hopefully that will keep things a bit quieter and we can catch up on work in staging and docs and other like things.
As always, comment on the fediverse: https://fosstodon.org/@nirik/117180272072423365
RPMs of PHP version 8.5.10 are available in the remi-modular repository for Fedora ≥ 43 and Enterprise Linux ≥ 8 (RHEL, Alma, CentOS, Rocky...).
RPMs of PHP version 8.4.25 are available in the remi-modular repository for Fedora ≥ 43 and Enterprise Linux ≥ 8 (RHEL, Alma, CentOS, Rocky...).
ℹ� These versions are also available as Software Collections in the remi-safe repository.
ℹ� The packages are available for x86_64 and aarch64.
ℹ� There is no security fix this month, so no update for versions 8.2.33 and 8.3.33.
⚠� PHP version 8.1 has reached its end of life and is no longer maintained by the PHP project.
Version announcements:
ℹ� Installation: Use the Configuration Wizard and choose your version and installation mode.
Replacement of default PHP by version 8.5 installation (simplest):
On Enterprise Linux (dnf 4)
dnf module switch-to php:remi-8.5/common
On Fedora (dnf 5)
dnf module reset php dnf module enable php:remi-8.5 dnf update
Parallel installation of version 8.5 as Software Collection
yum install php85
Replacement of default PHP by version 8.4 installation (simplest):
On Enterprise Linux (dnf 4)
dnf module switch-to php:remi-8.4/common
On Fedora (dnf 5)
dnf module reset php dnf module enable php:remi-8.4 dnf update
Parallel installation of version 8.4 as Software Collection
yum install php84
And soon in the official updates:
⚠� To be noticed :
ℹ� Information:
Base packages (php)
Software Collections (php83 / php84 / php85)
In Some Changes to GNOME Security Tracking, I reported:
I will discontinue tracking newly-reported security issues on November 1, 2026. During November, I will focus only on tracking issues reported prior to November 1. By December 1, all disclosure deadlines for that set of issues will have been reached, and I will be done.
This is because I was planning to leave my job at Red Hat on December 31 due to some internal Red Hat policy changes. But this timeline has now unexpectedly moved forward two months, to October 30. Accordingly, I will now discontinue tracking newly-reported security issues on October 1, 2026. During October, I will focus only on tracking issues reported prior to October 1. By November 1, all disclosure deadlines for that set of issues will have been reached, and I will be done.

We are happy to announce the launch of 3-year plans for Kiwi TCMS! These are available for all subscription tiers; come with built-in savings and support payment by WIRE transfer.
You can find the new 3-year plans in the
Subscriptions section, near the bottom of each tier:

Happy Testing!
If you like what we're doing please help us grow:
If your agentic workload involves the agent being able to run arbitrary code (like bash or equivalent), then you should not use a “LLM as part of your app” framework like LangChain, BeeAI, OGX etc. Instead, run OpenCode, goose, or another general coding agent inside a sandbox such as OpenShell.
Sandboxing limits what the agent can access directly. For privileged effects, it is best augmented with a pattern like safe outputs: the agent emits a structured, unprivileged request that separately trusted code validates and applies.
Can it run bash or arbitrary code?
├─ Yes → Run a generic agent in a sandbox
└─ No → Are you *really* sure *all* of your tool calls (MCP or builtin) don't accidentally expose "execute arbitrary code"?
├─ Yes → OK, maybe LangChain or equivalent makes sense
└─ No → Goto start
I also think the builtin sandboxing in most agent tools (like Claude Code and Gemini CLI) is a bad idea, and it’s better to just ensure the entire thing is sandboxed.
Related to all of this, a key thing anyone making an “agent” needs to ask is “how is this different from just writing an agent skill”. From my previous post you’ll know that I think GitHub Agentic Workflows is a good reference baseline for applying agentic AI (background/task oriented) safely and effectively. And there an “agent” is almost exactly just an agent skill, but with a bit of YAML defining its integration with the outer system.
Why should it be harder than that? I just don’t see it making sense for custom agents written in frameworks like LangChain to proliferate in most use cases. Sure you can use LLMs to generate it, but it’s even more secure and understandable to not have that code at all.
Even for the use case of an interactive chat bot, do you really need a custom app versus just MCP tools for an already generic frontend? I doubt it.
I don’t think it makes sense for most organizations to have proliferation of custom bespoke agents like these LangChain-style frameworks encourage. Skills and sandboxed generic agents are just easier to understand and work with.
#
# https://github.com/rosset/myconfig/tree/master/brother-t420w-2026
#
┌───────────────────────┐
│ Brother DCP-T420W │
│ (final architecture) │
│ IPP / PWG-Raster │
└──────────▲────────────┘
│
┌──────────┴───────────┐
│ Network / IPP │
└──────────▲───────────┘
│
┌─────────────────────┴─────────────────────┐
│ │
Linux / Raspberry Pi 5 macOS 27 Golden Gate
aarch64 IPP Everywhere
│ │
CUPS + PPD CUPS
│ │
br-box64-filter driver=everywhere
│
box64
│
Brother x86_64 filter
│
HBP / PWG-Raster
│
└───────────────────────► Printer
# Linux
# Printer Brother_T420W running with Linux (aarch64) + box64 + cups filter + modified ppd
# Status: working
=> uncompress opt-brother.tar.gz to /opt - final path = /opt/brother
=> copy /opt/brother/br-box64-filter to /usr/lib/cups/filter/br-box64-filter
* make sure it is executable: chmod +x /usr/lib/cups/filter/br-box64-filter
* this filter is a wrapper for the Brother LPD filter, which is a x86_64 binary
* it uses box64 to run the x86_64 binary on aarch64 (rpi5 in my case)
* if you try to use ./lpd/x86_64/brdcpt420wfilter directly, it will fail with "wrong architecture" error
* DietPi v10.6.2 (Debian 13.6) + [BOX64] Box64 with Dynarec v0.3.4 nogit built on Apr 24 2025 09:54:47
* the "key" thing is to keep the A4 Geometry: 2480x3508 (some wrappers are changing it to 2480x3507, which is wrong)
=> key files under /opt/brother:
- /opt/brother/Printers/dcpt420w/inf/brdcpt420wrc
-changed PageSize=Letter to PageSize=A4
- /opt/brother/Printers/dcpt420w/cupswrapper/brother_dcpt420w_printer_en.ppd
- changed from *cupsFilter: "application/vnd.cups-postscript 0 brother_lpdwrapper_dcpt420w"
- to. *cupsFilter: "application/pdf 0 br-box64-filter"
- copy /opt/brother/Printers/dcpt420w/cupswrapper/brother_dcpt420w_printer_en.ppd
to /etc/cups/ppd/Brother_T420W.ppd
- finally add the printer:
lpadmin -p Brother_T420W -E -v ipp://printer-IP:631/ipp/print -P /etc/cups/ppd/Brother_T420W.ppd
# V2 => Easiest path for Linux aarch64, avoid use of box64 and Brother
# x86_64 filter, use IPP (no everywhere) driverless printing instead
#
# Brother_T420W - V1
# → Brother proprietary LPD + box64
# → maximum Brother specific compatibility
# Brother_T420W_IPP - V2
# → native CUPS driverless
# → PWG Raster over IPP
# → no x86_64 emulation
driverless \
ipp://printer-IP:631/ipp/print \
> /tmp/brother-ipp/dcp-t420w.ppd
sed -i 's/\*DefaultPageSize: Letter/*DefaultPageSize: A4/' \
/tmp/brother-ipp/dcp-t420w.ppd
lpadmin \
-p Brother_T420W_IPP \
-E \
-v ipp://printer-IP:631/ipp/print \
-P /tmp/brother-ipp/dcp-t420w.ppd
cupsenable Brother_T420W_IPP
cupsaccept Brother_T420W_IPP
lpstat -v
lpstat -p Brother_T420W_IPP -l
# macOS 27 Golden Gate
# Printer Brother_T420W with CUPS + IPP Everywhere
# Kind: DCP-T420W - IPP Everywhere
# Driver version: 2.3
# Status: working
lpadmin -p Brother_T420W -E -v "ipp://printer-IP/ipp/print" -m everywhere
By Ananya Nalavathu and Francois Gonothi Toure
Open source communities run on contribution, and contribution runs on documentation, storytelling, and knowledge sharing. At the Fedora Project, that means the Fedora Community Blog and Fedora Magazine, two publications that give contributors a voice and give the community a way to stay informed, inspired, and connected.
This year, as part of my internship with the Fedora CommOps team at Red Hat Ireland, I got to experience that firsthand. Publishing 11 articles, running editorial campaigns, and coordinating content across sprints gave me a deep appreciation for how much thought goes into keeping Fedora’s editorial standards consistent and how much easier that journey could be for new contributors with the right tool in hand.
That’s exactly what my fellow intern Gonothi built during his Outreachy internship with the Fedora Project. In our final sprint together, we decided to share it with the community because tools that make contributions more accessible deserve to be heard. With that context in mind, I’ll hand over to Gonothi to walk you through what he built and why.
My name is Gonothi, and I’m an Outreachy intern within the Fedora Project. The tool I built is called editorial-guide-ramalama, a Retrieval-Augmented Generation (RAG) assistant that reads Fedora’s actual editorial guidelines and published articles, then checks your draft against them. It tells you whether your article meets the standards and exactly what to fix if it doesn’t.
A regular chatbot would guess. RAG grounds every answer in the actual guidelines. When the tool flags a problem, it cites the specific guideline and gives you an actionable fix. Not “this looks off”- but “your article is missing the Read More tag, which is required per the Magazine guidelines.”
RamaLama is the engine behind the whole tool, and it’s a big part of why this project works the way it does. It runs open models locally as OCI containers, the same container tooling Fedora already uses, so there’s no API key, no external service, and no data leaving the machine, which keeps everything private and fully reproducible. It also has RAG built in: RamaLama handles the ingestion, chunking, and retrieval itself (running Docling internally to parse and chunk the guidelines), so I don’t have to wire together a separate vector pipeline. That combination of local inference, OCI-container packaging, and built-in RAG is what lets the tool ship as a single image that anyone can pull from Quay and run.
The tool supports both Fedora publications, Fedora Magazine and the Fedora Community Blog, each with its own editorial guidelines loaded as the primary source the model checks against. Switch publications in the sidebar, and the guidelines change accordingly.
The stack is built on RamaLama, Docling, Quay, and Streamlit, with small GPT-Generated Unified Format (GGUF) models benchmarked for quality versus size. The pipeline works like this:
Articles are pulled from both publications via the WordPress REST API; no static files are committed, and the corpus is always rebuilt from source and stays reproducible. RamaLama RAG runs Docling internally to parse and chunk the documents into a vector store, packaged as OCI images published to Quay at quay.io/fedora/editorial-guide-ramalama. To run a check, pull the relevant image and use either the Streamlit interface or the terminal; no build step required.
Paste a draft that meets the Magazine’s standards, and the model confirms compliance, citing the relevant guideline. Paste one with known issues, a missing featured image, a missing Read More tag, and it flags each problem with an actionable fix.
One honest note: small local models have limits. editorial-guide-ramalama is great for catching common issues before submission. It is not a replacement for a human editor, and it doesn’t try to be.
What strikes me most about this project is not just what it does technically, but what it represents for contributor onboarding in open source communities. One of the biggest barriers for new Fedora contributors isn’t motivation; it’s knowing the unwritten rules. Editorial guidelines, packaging standards, community norms these exist, but they’re scattered, and learning them through rejection is discouraging.
Tools like editorial-guide-ramalama lower that barrier. They don’t replace human editors or community knowledge; instead, they give new contributors a first pass, a way to self-check before they submit, and a way to learn the guidelines through doing rather than through trial and error. That’s exactly the kind of tooling that makes open source communities more accessible.
This mini-project was the proof of concept that validated the RAG approach for Fedora editorial documentation. The same architecture is now feeding into a larger project applying RAG to RPM packaging guidelines, a higher-stakes domain where grounded, local, open-model AI can help contributors get packaging right.
The code is on the Fedora Forge at ai-ml/editorial-guide-ramalama. Pull the image from Quay and try it on your next draft before you submit.
The tool is live and available now. Pull the image from Quay, paste your draft, and see what it says. If you’re a new contributor, nervous about your first article, this was built for you.
Thank you to the Fedora community, our mentors Justin Wheeler, Dominik Kawka, and Carol Chen, and Outreachy for making this internship possible.
The post Meet editorial-guide-ramalama: An AI Assistant That Checks Your Fedora CommBlog and Magazine Articles Against Editorial Guidelines appeared first on Fedora Community Blog.
Dear testers, we're happy to announce Kiwi TCMS version 16.3!
IMPORTANT:
This is a minor version release which includes critical security related updates and several improvements.
You can explore everything at https://public.tenant.kiwitcms.org!
---
Public container image (x86_64):
pub.kiwitcms.eu/kiwitcms/kiwi latest 33e301a080d4 862MB
IMPORTANT: version tagged and multi-arch container images are available only to subscribers!
hub.kiwitcms.eu/kiwitcms/version 16.3 (aarch64) f60a9c080e41 24 Aug 2026 715MB hub.kiwitcms.eu/kiwitcms/version 16.3 (x86_64) 37e2579041b9 24 Aug 2026 696MB hub.kiwitcms.eu/kiwitcms/enterprise 16.3-mt (aarch64) 349b31927cdb 24 Aug 2026 913MB hub.kiwitcms.eu/kiwitcms/enterprise 16.3-mt (x86_64) d8b365f321a8 24 Aug 2026 892MB
IMPORTANT: version tagged, multi-arch and Enterprise container images are available only to subscribers!
Follow the Upgrading instructions from our documentation.
Happy testing!
---
If you like what we're doing please help us grow:
Another week gone by, it's hard to understand that it's almost fall now.
Much of my week was handling updates/reboots/reinstalls. Got all our instances, including our openshift clusters updated to the latest and rebooted. Also I managed to move almost the last of our vmhosts over to rhel10.
We are down to just 27 rhel9 instances left.
12 are db servers
6 are rabbitmq-servers
1 logserver
2 mailman servers
1 fedorapeople
1 storinator
1 torrent server
1 straggler vmhost that needs a disk replaced before reinstall
2 zabbix servers
I'm hoping to finish up the logserver, storinator and torrent servers next week, then I will start on the db servers. Hopefully doing staging first to catch any problems and then doing the prod ones in the time after beta but before final freeze.
We have a plan for the rabbitmq servers and zabbix servers. For mailman we will need to look and see what is missing in epel10 for them.
Looking forward to finishing this up and moving on to other things.
The last bits got sorted out and now pagure.io is read-only. You can pull git repos and look at other content, but no login/push/api access is possible.
I don't know that we have a specific timeline for keeping this, but I think it should be a very long time. It's static with no auth so the attack surface is much smaller than the pagure instance.
It's already getting to be time to start the Fedora 45 Beta freeze. So, if you have anything you want to land in the Beta, you best do it asap.
My trusty Lenovo slim 7x that I have been using day to day all the time for the last 2 years (!) is finally showing some signs of wear. The battery at full is only 70% of it's orig full capacity. Some of the keys have really anoyingly been sticking for me (especially the 1 and down arrow keys). Sometimes they send 2 or 3 keypresses. Pretty anoying.
So, I have been pondering what to do.
I could try and replace the keyboard/battery in this slim7x, but not sure how easy that will be. This is not a very 'repairable' laptop. Even swapping the nvme drive was a super pain. The case uses clips instead of screws and sounds like it's going to shatter when you are trying to pry it open.
I could go back to my framework ryzen laptop. Should be perfectly usable. Not good enough for local ai playground, and would mean going back to x86, but otherwise it's just a reinstall and a bit of moving things around.
The newer snapdragon X2 version of the slim7x all models seem to only have 1024x768 screens, and thats a hard no from me.
There's a really nice looking x2ee hp laptop, the HP EliteBook X G2q. It has upstream support, but... man, you can configure one thats $7500. That is crazy. I could buy like 3 of the following laptops for that.
The asus zenbook a16 looks nice and has upstream support already, but I am not sure a 16" laptop will be very easy to carry around. I suppose it could be nice day to day. I'm not even sure my laptop bags would fit it. It would mean staying on aarch64, which I kinda like.
I could go all out and get a new framework 13 pro ( Ryzenâ„¢ AI 9 HX 370 ). That would get a nicer screen than my old framework, much faster, and possibily to play with local llm model stuff. Fair pile of money and going back to x86.
No great hurry to decide, and this is indeed a horrible time to buy new computer hardware sadly.
As always, comment on the fediverse: https://fosstodon.org/@nirik/117140830512414290
In my last post, I talked about the value GitHub provides to FOSS, while arguing that we should avoid deep dependency on it.
Now let’s talk about agentic AI (LLMs).
TL;DR: I think GitHub Agentic Workflows is a new minimum quality bar that anyone having hosted agents operate on a git repository should strive to meet. It’s FOSS (unlike the built-in Copilot stuff) and pretty well designed in my opinion especially from a security point of view.
One background opinion I have here is that agentic AI is a strong reason to go even more deeply into “git-ops” style workflows. Having the ability to audit, verify (CI) and include a rationale for changes to things that aren’t necessarily software even (like a team’s travel budget) make even more sense in a world of agents.
OK you’re using git already, now let’s say you want to use agentic AI. There are rather a lot of solutions to this =) I want to narrow in first on “hosted” workflows (as opposed to just spinning up opencode/claude/codex/whatever on your laptop).
A simple scenario here is “mostly readonly with one write output” flows, which include:
etc.
The more complex scenarios are “issue to PR” style flows, or intermixing CI and AI (e.g. having an agent run during a CI run after it fails but before the VMs/containers are torn down and being able to do some live debugging).
There’s of course plenty of third party services (mostly proprietary) that will do much of this. Today on GitHub you can assign an issue to Copilot for example, etc.
GitHub Agentic Workflows is simply a compiler that outputs GitHub Actions that run in the context of your repository. Aside from the inference endpoint, there’s no proprietary black boxes (also assuming you are using a FOSS tool inside, like Codex but not Claude Code) etc.
What the compiler takes as input is a Markdown prompt that is very much similar to an agent skill with YAML frontmatter that defines its integration with GitHub such as event triggering – but especially key is restrictions on its output.
There’s a lot to like about this. As part of my job lately I’ve had to look over what other people are doing in this space, and I have to say there’s people doing things that are worse than this. In some cases significantly worse (mostly less secure).
Let’s say you want to implement a duplicate issue detector.
A serious problem with all agentic AI is prompt injection. It’s easy for someone to encode malicious instructions in an issue they file, and an agent can easily run those. If you’re running this issue triage as e.g. an agent skill from your laptop with full credentials, you can easily get your account taken over.
But the problem is the “most obvious” way to do this stuff by e.g.
writing a GitHub Action with a GH_TOKEN and the following permissions
will allow writing to all issues:
permissions:
issues: write
If e.g. a person prompt injects an agent and says “by the way this project is archived, close all the issues” an agent might just act on that!
And for “issue to PR” style workflows, the contents: write permission to a token is very powerful.
The safe outputs portion of GH-AW is very well designed in this respect, greatly limiting the blast radius of a compromised agent (e.g. the duplicate issue detector can add at most one comment, not close other issues etc.)
For public repositories, GH-AW also has a concept of an “integrity threshold” when
reading from GitHub itself and the default is approved, so it the agent will not
even see issues from new or unaffiliated contributors. For this use case, we
have to remove that filter, but it’s balanced by restricting the output.
Prompt injection can also leak the API key you use to access the inference endpoint – definitely not something you want to be surprised by when you get the bill later that month. GH-AW runs an actions VM as normal, but the agent runs in an OpenShell-like sandbox (it’s not actually OpenShell, that’s a whole other discussion!)
Now, I’m not saying all agentic AI should be GH-AW; in addition to the advantages above, it has a whole host of downsides. In particular it’s not at all designed to be interactive and certainly there are many use cases where that’s much more efficient, especially research/planning, some types of debugging etc.
A pattern I expect to emerge is that these types of “less structured/organic/interactive/local” flows end up delegating some work to per-repository workflows. For example a weekly planning session may result in filing issues, which get driven to completion via a GH-AW style flow in each repo.
Further hybrids are possible of course, nothing truly stops one from having a GH-AW style flow send an interactive question to a human via a MCP tool or equivalent. But I don’t think I’d want to do that personally, I’d rather make it easier to turn a whole session dynamically interactive, kind of like how today one can use things like the tmate action to log into a runner.
GH-AW definitely has its issues; one thing is that it’s annoying to reproduce the sandboxing outside of a GHA run. There’s also a really high latency to each run because it involves spinning up not just a GHA runner, but also downloading and provisioning the container agent wrappers etc. That’s for good security reasons overall, and anyone doing something else should be able to justify the security tradeoffs.
Just to restate the conclusion: I think GitHub Agentic Workflows is a good reference baseline for a safe way to add agentic workflows to a GitHub hosted repository, and everyone doing something similar should include a comparison with it at least. If not, take some of the code: the “safe outputs” stuff is reasonably easy to use in other systems too.
The question of using proprietary tools to build FOSS has always been one of the tension points in our community. One of the most prominent proprietary tools is github.com and the non-FOSS parts of gitlab.com (and a longer tail of other platforms).
A while ago I came across Give Up GitHub from the Software Freedom Conservancy which is on one side of this. My opinion remains nuanced and split. One I think few people would argue with is that there’s been enormous value provided to FOSS by the $0 github.com (and gitlab.com etc) services. Just the basic hosting of git infrastructure, issue tracking and other ancillary things (discussions, etc) but especially GitHub Actions.
There are a lot of critical projects out there getting by with the $0 “free/personal organization” infrastructure. It’s actually plenty for most projects (e.g. mature language libraries).
And while GitHub hasn’t been shy about pushing into the web interface things like Copilot (a proprietary agent framework) – in my opinion the platform still generally hasn’t been subject to platform decay. I mean, there’s no advertisements (which probably wouldn’t work because people would use custom interfaces talking to the API anyways).
This could of course change literally tomorrow; or next month, etc. But my gut says that at the current time Microsoft is OK funding github.com just to provide reliable infrastructure for their own teams, and those using it at large scale on premise probably provide enough income to offset the loss-leader economics for now.
I personally believe in (and argue for at my employer) avoiding a truly deep dependency on any one (proprietary) service (which includes github.com). In particular, I think Forgejo is a nice bit of software; it’s easy to run on premise for homelabs etc. The decision to run the Fedora Forge was not an easy one – there’s real ecosystem splitting effects, but I think we’ll be OK.
The thing is though, running a $0, publicly reachable internet service where people can just store/write things is genuinely hard (and especially when paired with a service to execute arbitrary code like Github Actions). It’s under constant attack from spam, scraping, bitcoin mining and abuse in a way that probably few people outside of the administrators truly appreciate.
I have a lot of respect for people and projects choosing to self-host or use smaller-scale hosts like Codeberg, but there’s real tradeoffs there around sustainability and availability.
I don’t expect this status quo to change much in the near future. In the next post, I’ll talk about how this relates to agentic AI.
In Fedora Copr, we maintain a special tier of build machines known as High-Performance Builders (or as we call them internally, “powerful builders”).
Historically, gaining access to these machines required some manual intervention. Maintainers had to write to us, and we would enable them for specific projects or packages based on matching regular expressions. I’m happy to say those days of manual labor are over. This process is now entirely automated thanks to rpmeta (expect a dedicated blog post on this soon).
To give you an idea of the hardware: our standard builder in AWS EC2 is a c7i.xlarge, providing a respectable 4 vCPU and 8 GB of RAM. The high-performance x86_64 counterpart is the c7a.8xlarge flavor, boasting 32 vCPU and 64 GB of RAM. The real-world impact? Massive packages that typically churned for 23 hours on a standard instance are now finishing in 5 to 6 hours.
But this got me thinking. Is it possible to go even further? How much does throwing progressively heavier hardware at the problem actually accelerate an RPM build?
To test the absolute extremes, I decided to fire up the most powerful EC2 instance I could find. Finding an available datacenter for these behemoths was a challenge in itself, but I eventually managed to spin up a u-3tb1.56xlarge - the third biggest flavor in AWS EC2.
Let’s call it the Megabuilder. It packs 224 vCPUs and 3 TB of RAM.
To ensure disk I/O wouldn’t skew the results, all test builds were executed with Mock’s tmpfs plugin enabled. The entire build process happened purely in RAM, making disk speed irrelevant.
Here is what happened when I fed it some of Fedora’s most notoriously heavy packages.
python3-torch (The Socket Trap)When I first ran python3-torch on the Megabuilder, it finished faster than the 5-hour mark, but something was off. Monitoring the system revealed that it was utilizing a maximum of 28 out of the 224 available CPUs.
After digging into the SPEC file, I found the culprit. The maintainer’s parallelism detection logic was correctly counting cores, but it forgot to multiply them by the number of CPU sockets. The Megabuilder has a 4-socket architecture. After submitting a quick pull request to fix the detection logic, CPU utilization spiked (though it still didn’t max out the machine) and the build time dropped to an impressive 1h 19m.
The Cost Equation: The Megabuilder run cost $35. On the powerful builder, this same build costs only $8. That is a steep premium for speed.
Sidenote: At the very end of the build process, rpmbuild hung in a single-threaded state doing “something” for quite a while. My educated guess is that it was churning through a brp (BuildRoot Policy) script hook.
gcc (The ./configure Bottleneck)GCC rarely managed to take advantage of the Megabuilder’s massive core count. If you watch the process tree, the vast majority of the time is spent running one or two ./configure scripts. A configure script will chug along single-threaded for over a minute, followed by a brief 15-second burst where all cores light up during actual compilation, only to immediately drop back down to a single-threaded ./configure process.
Paying $151 to watch a single CPU core parse autotools macros is a tough pill to swallow.
rust (The Optimization Trade-off)Rust was the most resilient to parallelization, but this time, it’s not exactly a bug. As I understand it, this is a deliberate choice by Fedora engineering. If you force highly parallelized Rust builds, the resulting binary ends up being roughly 2–5% slower. Fedora consciously trades longer build times on the infrastructure side to guarantee faster runtime performance for end users.
So, does monstrous hardware solve long RPM build times? Only marginally, and at an astronomical cost.
The reality is that sheer hardware scale is fundamentally bottlenecked by the software architecture. Neither rpmbuild itself nor the maintainer code inside %build sections can efficiently map to extreme, massive parallelism. You hit Amdahl’s Law incredibly fast.
A final funny observation: Knowing that even on this 224-core monster the builds would take hours, I fired them up fully intending to go watch a movie on Netflix. Instead, I found myself completely mesmerized by btop and the output of ps axf. Watching process trees expand and collapse across 224 cores turned out to be far more entertaining than a Hollywood blockbuster. :)
Injection vulnerabilities, like cross-site scripting (XSS) or command injection, occur when we fail to properly encode untrusted output when inserting it into a trusted context. Before injecting uncontrolled or untrusted data, it’s essential to encode, escape, or quote the data to prevent it from breaking out of its intended context.
Some security folks previously used to like to talk about “input sanitization.” In practice, input sanitization is hopeless. Instead, nowadays we do the opposite and think about “output encoding.” When you inject untrusted data into a new context, assume the data is always malicious, and encode, escape, or quote it to make it safe for use in that context. Let’s look at some examples.
Here’s a low-stakes example of Pango markup injection:
markup = g_strdup_printf ("<b>%s</b>,
my_user_provided_data);
gtk_label_set_markup (GTK_LABEL (label), markup);
The untrusted data is not escaped and may decide to inject its own Pango markup, or break out of any markup that you used yourself. For example, if the data is </b><span foreground="blue" size="x-large">Hello world!</span><b> then it can decide to be blue and extra large instead of the intended bold. That’s not especially serious and probably not likely to be a security issue, but surely it’s an unintended bug. If you’re injecting an uncontrolled string into a Pango markup context, like a GtkLabel, then use g_markup_escape_text() first. (Pango markup can do other interesting things like hide characters or capitalize them. I’m not sufficiently creative to claim that’s definitely a security problem, but perhaps attackers will be more clever than me.)
A real-world example: in this GNOME Shell issue report, the title of a desktop notification is able to use Pango markup to manipulate its own formatting. (At least, probably, because the issue report is unconfirmed. Looks plausible, though!)
Another good example is the Evince command injection vulnerability from a few months ago, where a malicious filesystem path is able to trick Evince/Atril/Xreader into executing arbitrary code. Evince expects the path of a file to open to be something like /home/foo/hello.pdf, but a malicious PDF instead provides the evil input --gtk-module=/home/foo/evil.so /home/foo/hello.pdf. If not quoted properly, we have a command injection vulnerability where --gtk-module is interpreted as a command line flag rather than as a path:
Incorrect: /usr/bin/evince --named-dest= --gtk-module=/home/foo/evil.so /home/foo/hello.pdf
Correct: /usr/bin/evince --named-dest=' --gtk-module=/home/foo/evil.so /home/foo/hello.pdf'
If you’re constructing a Unix command line, as in the Evince example above, then use g_shell_quote(). Failure to do so is ruinous. (But beware: this isn’t necessarily safe if you’re using an actual Unix shell.)
With that primer out of the way, let’s consider what happens when you inject untrusted content into HTML (or CSS, or JavaScript).
I used to think XSS matters only for websites, and is surely not something that desktop app developers need to know about, right? Wrong, as I discovered five years ago when, to my surprise, Prakash (@1lastBr3ath) reported that websites could inject scripts into Epiphany’s new tab page (about:overview) via malicious page titles. This on its own is not especially serious, but it’s surely not supposed to be possible.
If your desktop app uses WebKitGTK or another web engine, you probably do need to think carefully about XSS. For example, before injecting untrusted data into HTML, we need to HTML-encode it, which Epiphany didn’t do anywhere. In the simplest case, that looks like this:
char *
ephy_encode_for_html (const char *input)
{
GString *str = g_string_new (input);
g_string_replace (str, "&", "&", 0);
g_string_replace (str, "<", "<", 0);
g_string_replace (str, ">", ">", 0);
g_string_replace (str, "\"", """, 0);
g_string_replace (str, "'", "'", 0);
g_string_replace (str, "/", "/", 0);
return g_string_free_and_steal (str);
}
Simply replace the few dangerous characters with HTML entities, and you’re good to go. That doesn’t work for HTML attributes, though, where the rules are slightly different. And it definitely doesn’t work for CSS or JavaScript. Carefully review the OWASP Cross Site Scripting Preventing Cheat Sheet to understand what you can and cannot do.
Anyway, back to the old about:overview bug report. Turns out, Epiphany had many similar vulnerabilities. I attempted to fix them all, but in fact, I had missed a spot. In this old commit, I recognized that a URL is untrusted data that must be encoded before I inject the URL into the error message. But I treated the error message of the GError returned by WebKit as if it’s trusted and does not need to be encoded. In fact, the error message itself may contain a URL! Oops. Fernando Munoz recently noticed and reported several example URLs that could inject content into Epiphany error pages. I’m unable to share my favorite example URL here on WordPress, because WordPress is sanitizing it (yes, that is indeed ironic, considering my above recommendation to not do that). But the result of the injection looks like this:
So an evil URL can mess up the Epiphany network error page. That’s not particularly serious, but Fernando found a second injection that is much worse, an XSS vulnerability in Epiphany’s autofill implementation. Here, selector is formed using an untrusted DOM element ID provided by the web page itself. Notice that no output encoding is performed before the untrusted value is injected into the JavaScript command:
page_id = webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view));
world_name = ephy_embed_shell_get_guid (ephy_embed_shell_get_default ());
script = g_strdup_printf ("EphyAutofill.fill(%lu, '%s', %i);",
page_id,
selector,
fill_choice);
webkit_web_view_evaluate_javascript (WEBKIT_WEB_VIEW (view),
script,
-1,
world_name,
NULL,
view->cancellable,
autofill_cb,
NULL);
Because the untrusted data here is already used as a quoted data value, one of very few cases where it is safe to inject untrusted data into JavaScript, this would actually have been safe if only Epiphany had JavaScript-encoded the value first, following the OWASP rules for JavaScript encoding: “Encode all characters using the Unicode \uXXXX encoding format, where XXXX represents the hexadecimal Unicode code point. For example, A becomes \u0041. All alphanumeric characters (letters A to Z, a to z, and digits 0 to 9) remain unencoded.” But Epiphany did not do so. (I got confused by the OWASP rules and didn’t realize how easy it was to make this safe, so I fixed it in a more complicated way instead, by removing the need for injecting the form ID.)
So how bad is this mistake? In Fernando’s example, the ID of the evil form element is "a'); alert('XSS in private world'); var _=('", allowing the malicious website to run any script it wants. That might not seem so serious, because websites don’t need to exploit any vulnerabilities to execute JavaScript… right?
Websites are only supposed to be able to execute JavaScript in the default script world. Think of a script world as basically just a big namespace for all of your JavaScript: the default world is what the website itself uses, but desktop applications can create their own private script worlds in order to run their own scripts. In a private script world, you can manipulate the page’s DOM as usual, but you have a separate environment for executing JavaScript code, so you don’t have to worry about name clashes or scripts conflicting with each other. Also, website scripts cannot access your scripts.
In practice, web browsers inject their own scripts into every web page in order to implement various browser features. Epiphany uses a script to find the best web app icon for a web page, for example. These scripts use a private script world that websites should never themselves have access to. But in this XSS attack on Epiphany’s form autofill implementation, the malicious website has managed to execute its script in the private script world. Now it can access whatever internal web browser features are available in that script world.
Unfortunately, there’s one more relevant Epiphany feature implemented using scripts: the password manager. Epiphany’s password manager is necessarily exposed to its private script world because Epiphany needs to execute JavaScript code in the web page in order to autofill passwords. Although there were no relevant bugs in Epiphany’s password autofill code (which is totally unrelated to its vulnerable generic form autofill feature), this did not matter: if an XSS bug in any Epiphany feature can be abused to execute code in Epiphany’s private script world, that code can access the password manager and exfiltrate all the user’s saved Epiphany passwords for every website. (At least, probably, because I have not set up an attack website to test this. But I don’t see why it wouldn’t work!) So that’s pretty serious.
I requested a CVE for the autofill vulnerability earlier today, but nowadays CVE requests usually take a couple of weeks, so I don’t have one yet. It is fixed in Epiphany 50.6 and 49.9. If you don’t have those versions yet, don’t panic. To be exploited, you have to manually trigger form autofill by right clicking on a form and then selecting either “Autofill Personal Fields” or “Fill This Field,” so that makes it much less scary. Even more fortunately, users probably won’t ever do that, because selecting either option always causes Epiphany to reject all further mouse input, becoming unusable. Nobody has reported this bug before, so it seems safe to conclude zero people are using Epiphany’s form autofill feature!
Update: I said it would take a couple of weeks, but a few hours later I received CVE-2026-77682. Red Hat has improved its response time!
A Letter of Claim has been sent to Nigel Farage, leader of Reform UK in relation to the widely quoted defamation on the night of the Clacton-on-Sea by-election in 2026.
One of the key remedies sought is a sum of compensation of five million pounds to be paid to each of the rival candidates disparaged in news reports about "nobodies".
We are currently looking for a defamation lawyer to advance the claim on our behalf.
A graphic from the SBS News report.
Here is a full copy of the Letter of Claim:
From: Daniel Pocock <daniel@pocock.pro>
To: Nigel Farage <clacton@reformuk.com>
CC: [ other candidates ]
Subject: Nigel Farage / Letter of Claim / defamation, 13/14 August 2026
Attn: Nigel Farage, leader of Reform UK
Dear Mr Farage,
This letter of claim is being sent to you as part of the pre-trial protocol for defamation proceedings in the High Court.
On the night of 13/14 August 2026, you gave a speech to Reform UK supporters claiming your rival candidates are "nobodies".
In the speech, you thanked your own supporters. You thanked the staff from Tendring District Council who administered the by-election. You did not thank your opponents or give us any acknowledgement except the assertion that we are "nobodies".
Your act of bad sportsmanship and the defamation carried more weight because you are the leader of a political party and you have been in the public eye for many years.
Your act of bad sportsmanship and the defamation was more severe due to the asymmetrical nature of your campaign budget and advantages you held as the incumbent member compared to our own campaigns. These advantages you hold are exacerbated by the first-past-the-post voting system in the UK.
While some candidates competed against you on a novelty theme, many of us competed on serious themes. Even novelty candidates raised some serious issues. Many of us showed up to campaign each day just as the community expects an elected MP to show up for work each day. Nobody, absolutely nobody, is a nobody.
In the same speech, you ask people to remember those who fought in world wars. My great grandfather came to the UK and France in World War 1. My great uncle served in the pacific in World War 2. My peers in the fellowship elected me to represent them before the German FSFE on ANZAC Day, 25 April 2017. I bravely did my job as a representative and exposed the FSFE as an example of Nigerian fraud. When I came to Clacton, you told the local community and the rest of the world I am a nobody.
Your act of bad sportsmanship and the defamation was reported in news stories the world over, from the BBC in the UK to the ABC in Australia and everything in between. The news stories typically included a list of all of our names and the word "nobodies".
I kindly request you rectify this matter within 14 days or sooner. I propose the following list of corrective measures and I invite my fellow candidates to add to this list:
- each week, Reform UK will conduct at least one Town Hall-style event on one of the policies raised by a rival candidate in the campaign. At least two of your MPs will attend each of these events and will be on stage with at least one of the candidates who raised the relevant policy issue. These events do not necessarily have to be in the same constituency.
- for 90 days, the Reform UK web site, main page, is to be replaced with an apology, the names, professions and faces of the so-called "nobodies" and links to our web sites
- up until voting closes at the next General Election, an apology will continue to be present in a prominent position on every page of the Reform UK web site
- for a period of five years, all of the rival candidates will be added to the list of unaccompanied guests / lobbyists sponsored by one of your MPs to come and go as we please in Westminster
- each rival candidate will be awarded £5 million compensation for the global embarrassment your bad sportsmanship has inflicted on us
- all of these measures will be announced to the public by way of your social media, a Reform press release and a dedicated Reform media conference where the rival candidates can share the stage with you
- you will pay for the cost of a public relations consultant to liaise with the press and have corrections added to all the stories containing the "nobodies" quote.
- resolve the pledge you made on 7 July 2026 to pay election expenses before the deadline for the rest of us to complete our election returns
- produce "nobody is a nobody" hats, t-shirts and stickers and distribute them to every home in Clacton
- use the "nobody is a nobody" phrase in all the apologies, social media and press communications about the apology
Should you fail to resolve the matter amicably within 14 days, I invite fellow candidates to join me in a class action for defamation before the King's Bench Division, Media and Communications List in the High Court.
Sincerely,
Daniel Pocock
-- https://danielpocock.com Follow with RSS: https://danielpocock.com/rss.xml
This is a short story of how thanks to AI agents, I am again passionate about my open source projects, namely pretty-git-prompt (p-g-p in short).
Earlier this month, I published a post about the future of Boxes where I detailed the huge technical rewrite I have been doing, porting to GTK4, Libadwaita, and replacing our SPICE display widget with Libmks. Today, I want to share a structural decision that aligns with that vision and sets up the project for long-term health/sustainability.
I have formally submitted a proposal to remove Boxes from the core-developer-tools set in gnome-build-meta and transition it towards becoming an independent application (with the ultimate goal of applying for GNOME Circle once all criteria are met).
I want to dive into why I am making this move, what it means for users and maintainers, and why I believe this is the right path forward.
First off, let’s get this out of the way: there is zero drama between Boxes and the GNOME project.
Boxes continues to be built by the same core set of contributors, fully committed to the GNOME Human Interface Guidelines (HIG) and deeply integrated into our ecosystem. We aren’t stepping away from GNOME. We are simply right-sizing how Boxes is categorized, distributed, and maintained.
The desktop Linux landscape is shifting toward image-based operating systems with atomic updates and immutability. In this model, the underlying operating system provides a slim, reliable base, while applications live on top and update independently at their own pace.
Tying a complex application like Boxes to the biannual GNOME release schedule is not useful anymore. It forces us to hold back features and bug fixes for months just to align with the OS cadence, when users should simply get updates when they are ready and stable.
Furthermore, virtualization isn’t an essential utility that needs to be pre-installed on every single user’s machine by default. Boxes fits much better as a targeted application users explicitly choose to install when they need it.
As a maintainer, maintaining separate code paths and stable branches for dozens of traditional distribution packages is simply not sustainable long-term. I can no longer afford to maintain multiple stable branches. Moving forward, I am simplifying maintenance down to one stable branch and one development/nightly branch. To make this sustainable, Flathub is our primary and only officially supported distribution method.
By bundling the virtualization stack in our Flatpak, we ensure that users get a much more tested, consistent, and working virtualization backend regardless of what operating system they are running.
Moving out of Core allows us to heavily discourage downstreams from individually packaging Boxes. Instead, distros should defer their users to the official Flatpak on Flathub. If you are filing bug reports or seeking support, the Flathub build will be the baseline.
To reflect this independent status, a few logistical changes are happening alongside this move. We are dropping “GNOME” from the user-facing app branding. Going forward, it will simply be named “Boxes”, and we will soon be moving to a new website domain (which is currently being finalized). Importantly, our Flatpak application ID will remain org.gnome.Boxes for full continuity and compatibility. This means existing installations, user settings, and Flatpak configurations won’t break, and users won’t need to reinstall anything.
This change gives us the flexibility to release updates whenever features are ready, iterate faster, and dramatically reduce maintainer burnout, all while delivering a more reliable and consistent user experience via Flathub. Once we settle into this new cadence and finalize our transition, we plan to apply for GNOME Circle.
To set clear expectations on timing: since Boxes currently uses GTK3 in its stable releases, we will soon submit an application for GNOME Circle review following our GTK4/Libadwaita rewrite.
If the Circle application is approved before the GNOME 52 Alpha deadline, the plan is to proceed with the removal from core-developer-tools and transition to Circle in time for the GNOME 52 release in March 2027.
For distribution maintainers wondering about upcoming distro releases: distros targeting GNOME 51 can continue to package the GNOME 50 release of Boxes, which will remain supported for the standard lifecycle of that release. If everything goes according to plan, GNOME 52 won’t include Boxes in the core set anymore. At this point, please don’t package Boxes anymore.
If you use Copr a lot, your project list grows fast. Personal experiments, scratch builds, one-off test repos, they all pile up next to the number of projects you actually care about. Pinned projects already assist with that; you can keep up to four projects visible in your profile by pinning them. But four is a hard limit, and a handful of icons at the top of the page is the only way it can highlight it.
Now you can go further. Copr profiles support a custom Markdown description, similar to a GitHub profile README, and there is no limitation on what you put there.
It can be used in many ways, like:
These aren’t the only options; you can further customize your profile based on your requirements.
If you are logged in, go to your profile page and click Customize Profile. Groups have the same button, visible to any member of the group.
https://copr.fedorainfracloud.org/user/customize-profile/
For a group, the URL takes the group name:
https://copr.fedorainfracloud.org/user/customize-profile/<group_name>
Happy customizing!
Most of GNOME 51 is now packaged for Fedora 45. Starting today and running through the end of the week, we will be running our traditional Fedora Test Day for GNOME. If you are a Fedora user, you can help us find last-minute integration issues and iron out what’s going to become the stable Fedora 45 release.
You can either boot the latest Fedora 45 image (nightly) in a virtual machine or update an existing test setup. Follow our guided test matrix, try out different features, and record your results. Even testing for 15 minutes and reporting a single issue makes a huge difference.
Visit https://fedoraproject.org/wiki/Test_Day:2026-08-17_GNOME_51_Desktop for more info. You can join the Fedora Workstation Matrix chat channel if you have more questions.
Another week gone by, hard to understand that it's almost fall here now. Here's a recap of things from this last week:
Fedora 45 has branched off of rawhide. rawhide is now marching toward Fedora 46. Overall the actual branching went pretty reasonably, a few minor issues. There was a lot of issues with the last minute dnf repos move change that landed hours before branching. This caused a lot of work to try and get a compose with it, without reverting. Perhaps we should make sure all changes that affect the compose process have to land a week or so before branching or will just be reverted.
Some minor things:
The new rawhide release in bodhi had 'f46' as it's branch name, but it was supposed to be 'rawhide' because this is used to match against the git branch. Easily fixed, but hopefully not something that happens next time.
The openh264 repo is a bit of a problem at branching time. We need things setup for the new rawhide before we can build it and sign it with the new key and send it out to cisco. The choice then becomes if we want it to just 404 (not be there) or redirect it to the fedora-45 one (which is signed by the fedora-45 key). I've done the latter for now and we are syncing the new rawhide build out. Hopefully updated early next week.
noarch_arches wasn't set on the new rawhide build tag in koji. I submitted a pr to fix the branching script for this case and it's corrected for f46-build
eln composes were not fully resigned by the new rawhide key, the docs around this process were not very clear, we should fix them for next time. However, eln is going to just move to their own seperate key, so we just don't have to worry about this next time.
Somehow fedora 44 base repos got their permissions messed up. I can only assume it was a script failing somewhere, but I've not been able to track it down. This meant that some mirrors deleted their f44 trees and then had to sync it again. Lots of unwanted churn when there's already a bunch of mirror churn due to the new branched compose and newly resigned rawhide.
It was suggested to me by John 'Warthog9' Hawley that we might want to look at moving our download servers to BBR. Bottleneck Bandwidth and Round-trip propagation time (BBR), is a tcp congestion control algorithm developed by Google. It's used by them at youtube and other places.
So, I switched our download servers over and... it seems to have resulted in a nice performance increase for mirrors syncing from the master mirrors.
We will see how it goes moving forward.
Managed to get in a few migrations this last week. There are now just 33 hosts left. Of those:
I am hoping to do the last 5 vmhosts next thursday (see below)
We have a plan for rabbitmq clusters (6).
zabbix is planned soon (2)
The last bastion server and logs server I also plan to do thursday.
The database servers ( 12 ) I plan to start on once we are in beta freeze for staging, then prod after we are out.
A few oddball ones will be hard to do now due to resource constraints (fedorapeople and torrent), so might defer them for now.
We will be doing a mass update/reboot/reinstall fest next week. Monday I am out on PTO (it's my b-day!). Tuesday will be staging, Wed a bunch of non outage causing things, and thursday the main event. Everything will get updated/rebooted, then I will reinstall the last 5 vmhosts and our last bastion server. Friday will be openshift clusters (but those should just not cause much notice).
The week after next we go into beta freeze. I have to say I have thought about doing away with them, but I find them a nice time to focus on other work and relax a bit. Faster is not always better.
So, of course I can't post one of these these days without talking about the scrapers. (Whats the collective noun for scrapers? :)
We were getting hit really hard last weekend and early this week, but... Ryan thought to fight ai with ai and had a LLM dig through a bunch of our logs for any patterns. It managed to come up with some patterns that we likely wouldn't have seen, but blocking those things has made a MASSIVE improvement. Basically it's like they aren't even there right now.
Load on the backend for src.fedoraproject.org that had started hovering at 180 or so is down under 1 pretty much all the time now. I know that this will not last and they will change their patterns, but it's nice to have some respite at least for a little while.
As always, comment on the fediverse: https://fosstodon.org/@nirik/117101412562880287
Yesterday I released replyfast version 0.4.0, which is a Python module to receive and send messages on Signal
You can install it via
python3 -m pip install replyfast
or
uv pip install replyfast
I have a script to help you to register as a device, and then you can send and receive messages. You can use the same script to re-register.
I also have a demo bot which shows both sending and rreceiving messages, and also how to schedule work following the crontab syntaxt.
scheduler.register(
"*/5 * * * *",
send_disk_usage,
args=(client,),
name="disk-usage",
)
replyfast is written using presage library, which does the actual work of communication via Signal protocol.
In the final week of the Clacton-on-Sea by-election, I had to make two calls to 999 about two separate incidents. 999 is the British equivalent of 911 in the US, 112 in Europe and 000 in Australia. On the day before voting, I revealed after the Fellowship elected me on ANZAC Day in 2017 and Diana von Bidder entered the Basel parliament, a group promoting a registered sex offender spent over $120,000 to have me molested. So far, that group has largely failed. Among other things, after the misfits stole fourteen domain names from me for the purpose of censorship, other people have registered four hundred more Debian domain names.
On 13 August 2026, the count night, it was clear by midnight that Nigel Farage, the guy who resigned was going to win.
By about 3am, it was clear that a novelty candidate, Count Binface, had gained a lot more votes than he achieved in the recent Makerfield by-election in June. Here are the real statistics from general elections and by-elections for Westminster contested by Count Binface:
| Contest | Votes for Binface | |
|---|---|---|
| 2019 General election | 69 | |
| 2023 Uxbridge by-election | 190 | |
| 2024 General election | 308 | |
| 2026 Makerfield by-election | 95 | |
| 2026 Clacton by-election | 9,455 |
Prior to Clacton-on-Sea, the results for Count Binface were often similar to the Official Monster Raving Loony Party and other fringe candidates. How did he suddenly get so many votes?
Presumably, if every novelty candidate and every independent candidate received equal media coverage, the results would be far different.
On 19 June 2026, at the count night for the recent Makerfield by-election, when results were read out, Count Binface managed to stand right beside the winner, Andy Burnham. Photographs show them together, even though there is no alleged relation between them.
Later that same day, the BBC published a report Why candidates dress up to run in major UK elections where they have a tightly cropped photo of Count Binface next to Andy Burnham. This was free publicity for Count Binface before anybody knew there would be an election in Clacton-on-Sea.
On 7 July 2026, Nigel Farage resigned. Count Binface immediately announced he would contest the by-election. Other major parties immediately announced they would not contest the by-election. The leader of one major party commented that Nigel Farage would spend the summer arguing with a bin. While she had referred to Count Binface, it was not an endorsement. No major party appeared to endorse anybody. All these facts were reported together without Count Binface having said anything more about policy than a few weeks prior when he got 95 votes in Makerfield.
From that point on, even as other candidates put our names forward, most of the media continued to run stories about a two-way Farage-vs-Binface contest.
The free publicity given to Count Binface in the first few days of media reporting allowed him to raise GBP 15,000 in donations while most candidates didn't receive any donations at all.
On 17 July 2026 it was confirmed 34 candidates had submitted a valid nomination before the deadline. This was the new record for the most candidates in a British election.
On the same day, 17 July, it was confirmed Andy Burnham, who had been in the BBC's June report about Count Binface, had been chosen as the new Prime Minister. This added to a sense of prestige around Count Binface without him actually having done anything of substance to earn it.
Nonetheless, the media continued to emphasize a contest between Nigel Farage and Count Binface.
The Survation telephone poll was conducted between 16 July and 24 July. Participants called by the survey were only given the names of three candidates, Nigel Farage, Laurence Fox and Count Binface. Everybody else was classified under a single category, "Another party or candidate". The process of calling voters to ask them this question adds bias to their vote.
On 3 August, the results of the Survation poll were published, telling people that seventy three percent of people faced with a rigged question would vote for Nigel Farage and twenty percent of people faced with the same rigged question would vote for Count Binface. Based on the 502 responses to the poll, the media continued producing stories about a two-way contest between Nigel Farage and Count Binface.
Many voters I met in person were very angry about this. They felt the BBC and other media were telling them to make a tactical vote for Count Binface. Word got around that Count Binface was an Oxford educated comedian who was also doing paid work for the BBC. This added to the perception the elites of west London were having a joke at Clacton's expense while news reports told us nothing about candidates with real policies and real connections to the community.
On Thursday, 6 August, there was a hustings / debate event at the Clacton-on-Sea Town Hall. Nigel Farage and Count Binface did not attend at all. There were less than fifteen local residents who attended. I suspect some of them were undercover members of political parties or supporters of the candidates on stage. In any case, the local residents at the meeting were outnumbered by the journalists. Ironically, imbalance between journalists and residents at the event may have been a result of the media failing to promote the hustings event in advance.
There were 34 candidates in the election and I saw less than half of them actively campaigning in the district. Only a third of the candidates attended the hustings event. The same group of us attended the count night while most stayed home.
In 2024 General Election, 43% of people in Clacton didn't vote at all. In the by-election, 56% of people didn't vote. If the media gave more attention to serious candidates, I suspect more of those people who stayed home would have come out to vote.
It is worth comparing Count Binface's performance to Howling Laud Hope, a co-founder of the Official Monster Raving Looney Party. Mr Hope's party is known all around the world as a champion of novelty candidates. Mr Hope was competing in his 38th election, another British record. He is Britain's longest serving leader of a political party. Yet Howling Laud Hope only received 18 votes, that is two more than me.
In fact, everybody could see this disaster unfolding well before the official voting day. I published my report about media bias four days before polling day. The report demonstrates how even the church newsletter ignored other candidates and gave the impression Nigel Farage had already won.
Not only did media bias help Count Binface get a lot more votes but it also prevented any other candidate from having a credible chance of winning. This, in turn, seems to have resulted in many residents not casting a vote at all.
Despite having demanded the election to prove his support from the community, Nigel Farage refused to attend the declaration of results. There were mixed messages about whether he refused to come due to a plot to humiliate him or due to a "credible threat" of some kind. If he feels the police were not able to protect him in this highly secured environment then it makes me wonder how he will be able to do the job of working within his constituency for the next three years.
There was intense interest in my reports about corruption in Switzerland & Debian. The Reform UK officials present at the vote counting appeared to be aware of this and I felt they were going out of their way to avoid me. In hindsight, it made me feel this may be the reason Nigel Farage didn't want to be photographed with people like Count Binface and I in the same room. Here is the photo created by the journalists at SBS in Australia:
Was Nigel Farage afraid of an Australian? The police didn't seem to be afraid. They didn't seem to be too interested either. We can thank them for their night out protecting the candidates who dared to show up, despite the odds against us.
In conclusion, the media changed the result of the election. If the media had backed a serious candidate instead of a novelty candidate, we may have had a lot more people come out to vote. We may have been able to win the argument that Farage doesn't do any work for Clacton. The media push for Count Binface had the opposite effect: they promoted a candidate who could never get enough support from every side to actually win. The fear about a joke on Clacton may have encouraged more votes for Farage and justified his warnings about the Establishment.
To see all the leaked messages from debian-private, including the history of Decklin Foster and the Democrats ActBlue scandal, please see my crowdfunding campaign video.
Release Candidate versions are available in the testing repository for Fedora and Enterprise Linux (RHEL / CentOS / Alma / Rocky and other clones) to allow more people to test them. They are available as Software Collections, for parallel installation, the perfect solution for such tests, and as base packages.
RPMs of PHP version 8.5.10RC1 are available
RPMs of PHP version 8.4.25RC1 are available
ℹ️ The packages are available for x86_64 and aarch64.
ℹ️ PHP version 8.3 is now in security mode only, so no more RC will be released.
ℹ️ Installation: follow the wizard instructions.
ℹ️ Announcements:
Parallel installation of version 8.5 as Software Collection:
yum --enablerepo=remi-test install php85
Parallel installation of version 8.4 as Software Collection:
yum --enablerepo=remi-test install php84
Update of system version 8.5:
dnf module switch-to php:remi-8.5 dnf --enablerepo=remi-modular-test update php\*
Update of system version 8.4:
dnf module switch-to php:remi-8.4 dnf --enablerepo=remi-modular-test update php\*
ℹ️ Notice:
Software Collections (php84, php85)
Base packages (php)
On 6 May 2024, I published a screenshot from the DNSlytics web site demonstrating 2,564 domain names contain the Debian trademark.
On 4 February 2025, I published another screenshot from DNSlytics demonstrating 2,655 domain names contain the Debian trademark.
Today, I made a fresh query for the Debian trademark using DNSlytics. There are now 2,928 domain names using the Debian trademark.
The rogue Debianists spent $120,000 in kill money to steal 14 domain names from me in 2024. They lied to people and said this was about protecting the Debian trademark. So far they did not spend any money on any of the other 2,900 domain names. Therefore, we know this was not about trademarks at all. The trademark was just an excuse for the total obsession some of these people have with my family and I.
Earlier this week, there was another incident of aggression in a public place. These incidents have not been random. Every time I have one of these negative experiences with an acquaintance or a stranger, I feel the hatred of the Swiss racists and rogue Debianists who commit murder-by-proxy.
Dr Schestowitz has written about similar phenomena on Techrights. He claims these bastards tried to use British police as a tool to molest him and his wife.
In a specific case, I demonstrated how another one of my co-authors, Raphael Hertzog has been using the Debian trademark in a domain name for many years. He promotes his domain name and business on the Debian.org web site and mailing lists but there has been no effort to protect the Debian trademark from Raphael Hertzog.
Notice how in Switzerland, a gay employee of the ETH Zurich has tried to use the police to molest me. This reduces Axel Beckert to the same level as the registered sex offender enthusiastically invited to so many community conferences, that is, Jeremy Bicha.
Essentially, Switzerland is not a very big country and there are only two of these prestigious engineering schools in the country. When people graduate from these schools or even work for these schools it gets to their head. They act like members of a cult.
Personally, I never said anything about the Debian suicide cluster for many years. I understood this was a particularly sensitive subject for people in Switzerland. After some of these people started indulging their racist obsession on my family and I, since 2018, they have no right to demand that I stay silent about the people they killed with their toxic personalities and their toxic culture.
Not only is Diana von Bidder-Senn a graduate of the elite ETH Zurich but she also boasts about her PhD qualifications from ETH Zurich when she ran for public office in 2021 and subsequent elections.
Her husband, who died on our wedding day, was leader of the student organisation VIS at ETH Zurich, among other things.
Therefore, both of these people have a much higher profile among the alumni of ETH Zurich. Is it simply coincidence they spend $120,000 on a crusade to "protect the trademark" at exactly the same time Diana von Bidder-Senn ran for public office?
On 14 March 2022, a legal panel confirmed that I am a victim of harassment and abuse by IBM Red Hat. The main European research and engineering centers for both IBM and Google are situated in Zurich, in close proximity to ETH Zurich.
On 11 September 2022, six months after the public confirmation that I am one of the real victims of this cult, Axel Beckert, a gay man associated with a registered sex offender through their collaboration on Debianism, signed the document begging the police to molest me.
Was this attempt to molest me a reprisal for the earlier finding that IBM Red Hat abused me?
Another key feature of the scandal: when Axel Beckert conspired to use the police to molest me, they submitted close to 20 pages of social media gossip but they hid the fact that it involves the death on our wedding day, they didn't tell the police about the connection to a politician, Diana von Bidder and they didn't tell the police that Beckert sleeps with one of my former colleagues. These are obviously the most significant facts in the case so why did they hide them and try to bamboozle the police with other rumours?
Having spent many years in Switzerland and even become a citizen of the country, it is easier for me to see the cult-like nature of this behaviour. Whether it is men in robes, men in uniforms or men who continue to wear their ETH Zurich badges and lanyards on public transport after leaving work, when they start working together to pick off a lone volunteer and humiliate that person, we need to look at the police and the employees of ETH Zurich the same way we look at the rogue priests who picked off children at Corpus Christi seminary:
How a Melbourne seminary became the breeding ground for paedophile rings
Corpus Christi was where sexually repressed men could “act out” with each other, living double lives, then transfer their attentions to the most innocent in their flocks.
...
According to a civil lawsuit due to be filed in court this week, Father Russell Vears guided the 14-year-old boy, [redacted], into the building, down a corridor with rooms on both sides, and to a communal area where four or five other boys were already sitting, waiting on a couch.
If you question the credibility of any one ETH Zurich graduate or employee, all the rest of them suddenly develop a rash. In cybersecurity, however, if we want to keep Switzerland secure we need to be able to comply with international best practice. That means the public disclosure of data breaches, vulnerabilities, censorship and social engineering attacks in open source software.
Switzerland operates a number of nuclear facilities and complies with international standards for the public disclosure of any nuclear incidents on Swiss territory. Why is there such an irrational and medieval obsession with covering up cybersecurity incidents, even in cases where there was an analogous and pre-existing duty of disclosure?
Read more about the evils of the cult behaviour.
Cockpit is the modern Linux admin interface. We release regularly.
Here are the release notes from Cockpit 366:
Previously Cockpit would automatically activate a new VLAN interface without allowing an administrator to configure it first. All new connections are now disabled by default.
After adding a VLAN or other virtual network device, Cockpit now shows the interface detail page instead of the networking overview page, allowing the user to further configure the newly created interface directly.
Cockpit 366 is available now:
The end of my campaign in the Clacton-on-Sea by-election is close. The guy who resigned in July admits hitching his wagon to the high priests of social control media and cryptocurrency. If the much-anticipated Bitcoin market implosion were to occur before polling commences on Thursday, Reform UK supporters could very quickly abandon their party. The manifestos published by rival candidates will be vital reading for voters making up their mind at the last minute.
Here is the video about police from Switzerland being used as a weapon against unpaid volunteers to try and destroy evidence about the Debian suicide cluster. This is contrary to UK law on gross negligence manslaughter:
Say there is a Python package on PyPI that you would like to build in Copr. And the project itself is not packaged in Copr or in the Fedora repositories, and neither are all of its dependencies. So the manual way of doing it would be to check which of its dependencies are not yet packaged in Fedora and build them in the right order. Miss a dependency and you only find out several minutes later, from a build log.
The --with-deps option does all of that work for you. It finds the dependencies that are missing, works out the order they have to be built in, and submits them:
copr-cli buildpypi <project_name> --packagename <package_name> \
--with-deps --chroot <chroot>
All of it happens on the client side, in copr-cli itself.
The coprtree library reads the dependency metadata from ecosyste.ms, prunes everything that is already available in the official Fedora repositories or your Copr project and topologically sorts what is left into build levels.
The pruning is what keeps the tree small. Most of a package’s dependency graph is usually already in Fedora, and there is no reason to rebuild it.
The idea of teaching copr-cli to build a whole dependency tree at once came
from Jakub Kadlčík.
--chroot has to be specified for now. Support for multiple
chroots will come later.--with-deps needs the coprtree library, which is an optional dependency of
copr-cli. Install it with dnf install python3-coprtree.The dependency resolution is still in its early stages, so expect some rough edges. If a resolved tree looks wrong, please report it to coprtree.
Even if Nigel Farage, who resigned on 7 July 2026 did not technically break rules about foreign money in the politics of the UK, there remains a big question about his competence in accepting money from the cryptocurrency industry. Some people feel that Bitcoin and other forms of cryptocurrency are an elaborate, high-tech ponzi scheme that runs across the global Internet, twenty four hours per day, seven days per week, until it it reaches the point where they run out of new victims. When new victims stop putting money into the system, the people who are already part of it will find they can't get their money back. The whole thing will come crashing down like a house of cards.
The collapse of the Bitcoin could have a knock-on effect on the Reform UK party. The party grew very quickly to become the biggest in the UK. The type of person who joins Reform UK is the type of person who will quit just as quickly if the party leader becomes embroiled in the imminent cryptocurrency industry reckoning.
Remember, pop superstar Taylor Swift was offered $100 million to endorse a cryptocurrency company. She refused to accept the money.
Jeffrey Epstein, who achieved notoriety for the exploitation of women and children, expressed the same concerns as Taylor Swift. He didn't want to be too close to the cryptocurrency industry because it might undermine high-level relationships he cultivated in the Establishment.
Ordinary mums and dads in the UK and other countries have been using cryptocurrency to try and save the deposit for their first home purchase. This is the very type of person Reform UK claims to be trying to help. When the day comes that all these people suddenly lose their money in the blink of an eye, some of them will come knocking on Nigel Farage's front door and asking him for a share of the five million pounds he ferreted out of the pyramid scheme before the upcoming collapse.
Nigel Farage told us he needed the money for security. Remember the former president of France, François Hollande, making secret visits to the home of a popular actress? He disguised himself in a motorcycle helmet and rode around Paris on the back of a scooter undetected for years. Ten years after the scandal, François Hollande auctioned the scooter and raised EUR 25,420, more than the original price.
George Clooney is also known for making incognito sorties in the countryside on a motorbike.
Read more about the perils of cryptocurrency speculation.
Another saturday spent dealing with scrapers, so now time for a recap of the previous weeks events.
I am not sure if they have some reason for hitting on saturday mornings, but they did so again this week. Once again targeting src.fedoraproject.org, which is unfortunate in that it's a single backend server without much ability to scale horizontally, running rhel8 and since we are moving away from it someday soon we don't want to spend too much time on it.
So, the two approaches left for me here are:
Block/filter/delay/cache at the proxy level to keep traffic managable
make the single backend process requests better/faster to keep up
I tried a number of things this time and ended up with a combo. Some things increased and blocked on proxies and the backend tweaked and given more cpu/memory. I'm not sure if this is going to last, but for now things seem to be back to 'normal'.
I am hopeful we can scale forgejo much better here. It's running in openshift and we have a lot more options there.
A bunch more hosts done this last week. I have about 3 more 'easy' ones to finish up and then we will get to ones that will need an outage. (database servers, vmhosts that host important services, etc).
Next week is Fedora 45 branching, so will keep things quiet, but I am tenatively thinking about a mass update/reboot cycle + rhel10 migrating things the week after. Will see how much I can line up next week. It would be good to get as much done as we can before we head into freeze the week after.
The rest of the week has been a blur. :)
As always, comment on the fediverse: https://fosstodon.org/@nirik/117061938567047801
Imagine you are someone who has played with performance co-pilot and its ?web applications. You've grown beyond the default dashboards, and want something more.
You've come to the right place: the Custom Metrics Web Emporium!
Let's presume you already have basic PCP up and running on a Fedora/RHEL-like system. If you need a non-default PMDA, you may need to:
# yum install pcp-pmda-FOOBAR
# cd /var/lib/pcp/pmdas/FOOBAR
# ./Install < /dev/null
If the PMDA is self-configuring, that's enough to fetch live data from it. If you also want
the data archived, which you do, you may need to edit the appropriate pmlogger configuration.
You could run pmlogconf against a config.pmlogger file you're already using, or edit it,
assuming you know where to find it. If you're avant-garde enough to let pmmgr run your
logging, and you want it to simply work for your whole network dammit,
# cd /var/lib/pcp/config/pmlogconf
# cat > MY_FAIR_METRICS.conf
ident MY FAIR METRICS
probe FOOBAR.ONE exists ? include : exclude
FOOBAR.ONE
FOOBAR.TWO
FOOBAR.THREE
^D
# /sbin/service pmmgr restart
The FOOBAR.ONE metric is any metric you know is contained in the PMDA, if it's working
correctly; the other FOOBAR.* ones are metrics or whole hierarchy prefixes of metrics
that you want future pmloggers to archive. You can confirm that any new archives get
the FOOBAR metrics stored in them via pmdumplog /var/log/pcp/.../archive*.meta,
or by looking at the pmlogger.log files.
If you agree that this is rather too many steps, consider adding your voice to this enhancement request.
Once your fancy new metrics start being logged to a file, it's time to check them out on
the web. You'll need to run a pmwebd server and have its pcp-webapps package(s)
installed, so that its web page http://localhost:44323/ pops up.
Then comes finding the metrics. Since there are approximately one gazillion of them, and
possibly stored over one mazillion separate pcp archive files, pmwebd needs a notation
to identify the one(s) of interest. It does this via the graphite webapi subset
it implements. The gist of it is that metrics get named something like archive.met.ric, where the
first component identifies the archive file or host name, the middle components identify the
pcp metric names, and the optional last component identifies the instance within that metric.
It's harder to explain than to show, so go and hit the graphite top level link.
Hit the little plus sign beside the "Graphite" folder, wait for the first level (archive-file/host-name) of the metric hierarchy to be populated. Find the most recent archive for your host, and keep clickin on the little pluses until you get to a real live FOOBAR metric.
If you click on the "Graph Data" button in the little composer/graph
subwindow, you will see the full graphite name for your FOOBAR metric.
Note it down. The you will probably want to replace the first component
with one with a wildcard such as *HOSTNAME*, in order to let pmwebd
search for all archives for the same host. You may want to replace the
last component with * too, if it's a metric with an instance domain,
in order to draw all instances.
If you click on the graph image itself, and get your web browser to spit out its URL, you will see something like
http://localhost:44323/graphite/render/?width=249&height=98&_salt=1497559426.608&target=vm-rhel7q64.network.ip.fragfails
If you play around with the time interval buttons at the top of the subwindow, extra fields will appear in the URL querystring:
?from=1497473484&until=1497559884
to specify the time interval. In this example, these are UNIX-style
epoch-seconds, but other syntaxes such as -2day for "two days ago"
or now for now, or HH:MM_YYYYMMDD for, well, it's obvious. All
times/dates are interpreted in UTC.
Other parameters are available to specify rendering parameters like colors, to add or subtract a legend, add other metrics. Experiment with the graphite compose window's interactive options to see their behaviour.
OK, now that you have a URL for an image, you can keep it, pass it around. But that's not good enough, is it? Otherwise you wouldn't still be reading this.
But you are. So let's get to making a dashboard. There are at least two basic
approaches: roll-your-own HTML, or grafana. In the roll-your-own HTML case,
you already have everything you need: make an HTML file with a set of IMG tags,
with each SRC pointing to one of the above graphite image URLs. Format it as
you like, publish it, done!
Grafana is another way. This is another webapp we bundle with pcp, and it is oriented toward building sets of related graphs. Normal grafana includes a dashboard storage/management server, which pcp's version doesn't, so we have to work a little harder. See this blog post for details about how the grafana dashboards may be constructed as explicit JSON files, or synthesized on the fly from a URL that includes metric/host names as querystring elements. Just use the compound graphite metric names you found for your FOOBAR metrics. Add any others of interest. Use wildcards liberally.
(warning - results not guaranteed)
Because artificial intelligence competes with humans, especially for our planet’s resources, I’ve chosen my side: the human.
I also think that AI is terribly bad for what should be our priorities:
Everything on my website, in my repository, in my personal work, and my contributions to the Open Source community is the result of my skills and my experience. No AI is used; no AI will be used.
Yes, I'm aware that AI may help in some projects (e.g., medical diagnostics, live translation), but I don't think the benefits outweigh the costs.
![]()
Yes, this is very political.
You can read Artificial Intelligence Controversies or Why No AI?
On the right of British politics, there is some argument about which group is closest to the Nazi party. Socialist Worker recently published an article alleging Reform UK is willing to share a stage with Nazis.
On the evening of 6 August 2026, candidates in the Clacton by-election gathered for a hustings-style debate at the Clacton Town Hall.
There were tense moments when Kai Stephens (Barkley Walsh) expressed concerns about another candidate, Attieh Fard, who was born in Iran but acquired British citizenship. There are thirty four candidates contesting the by-election and at least one of the Australian candidates does not hold British citizenship at all as it is not required to hold a seat in Westminster.
Stephens elaborated on his comments, explaining that it is about race. The Australians and anybody with English, Scottish, Welsh or Irish ancestry are considered, by the British Democrats, to be a superior race. Never mind the fact that Iranians have invented low cost drones that have brought superpowers to their knees in various conflicts around the world.
Stephens himself admitted being twenty percent German. Then again, the British royal family have a lot of German cousins too.
One of the Australian candidates simply asked if anybody remembered where the late Prince Philip was born.
In the Nazi era, the hyper-focus on race was equivalent to the arguments put forward by Kai Stephens.
Germans were expected to apply for an Aryan Certificate (Abstammungsnachweis) to provide proof of their ancestry. To work in the public service, it was necessary to prove at least three generations of Aryan blood. To join the Nazi party or be part of the fearsome SS, it was necessary to provide proof of Aryan blood back to at least the year 1800.
Kai Stephens' concern about Attieh Fard's birthplace, as he explained it to us on stage on 6 August 2026, appears to be analogous to the motivation behind the Aryan Certificate.
On 25 April 2017, the Fellowship elected Daniel Pocock to represent them to the FSFE (fake FSF) in Berlin. When the Germans realised that 25 April is ANZAC Day and Mr Pocock's great-grandfather was an ANZAC, they decided to remove elections from the FSFE constitution. Mr Pocock pointed out that Germans had behaved like this before. The Germans asked Berlin Police to prevent Mr Pocock calling them Nazis. German police prosecute approximately 20,000 people for criminal speech each year. In the case of Mr Pocock's uncannily accurate Nazi comparisons, Berlin police wrote to Mr Pocock, in German, and told him they will not stop him calling the FSFE Nazis.
Mr Pocock's birthday, 9 November, is the anniversary of the Kristallnacht.
Read more about Mr Pocock's work for tolerance and inclusion.
Read more about Mr Pocock's work for tolerance and inclusion.
I’m pleased to announce that NVIDIA is now supporting the LVFS as a premier sponsor.
The rollout of the NVIDIA DGX Spark firmware using fwupd is going very well indeed, with downloads continuing to increase every day.
This now takes us to 4 OEMs sponsoring LVFS, which means we’ve successfully reached the funding target we set for ourselves last year. More exciting announcements coming soon!
I have spent the last two years rebuilding GNOME Boxes from the ground up, driven by three main factors. I spoke extensively about this effort in my recent Linux App Summit, GUADEC 2025 and 2026 talks, but today I am excited to share the result for general testing.
First, shifting to a Flatpak-first (and only) model. As a solo developer, maintaining code paths for countless distributions isn’t sustainable. Since Boxes acts as a frontend for libvirt/qemu, its functionality relies heavily on the backend configuration. Flatpak lets me bundle the entire virtualization stack, giving me the control I need to fine-tune it for our specific use cases.
Second, migrating Boxes to GTK4 and Libadwaita. Beyond the obvious benefits (a modern UI, better responsiveness, and tighter desktop integration) this makes the codebase significantly easier to maintain. This transition required moving away from the GTK3-based SPICE display widget, which was too tightly coupled to older input and drawing methods. We’ve replaced it with Libmks, which has proven to be a solid alternative.
Lastly, modernizing the codebase to make it sustainable for new contributors. That meant adopting modern GNOME app design patterns and rethinking our underlying architecture.
I am now ready to share this work with a wider audience. However, please keep in mind that this is a Beta release meant for testing, not for production environments. If you plan to try it out, make sure to back up any important data in your virtual machines first.
If you want to test this new implementation of GNOME Boxes, you can set up the GNOME Nightly Flatpak Repository and install it with:
flatpak install org.gnome.Boxes.Devel
This new version already covers most of what the classic Boxes could do: creating virtual machines from ISO media and disk images (qcow2), configuring VM resources, sharing clipboard content, sending files to the guest, and more.
It can install Windows 11 without any manual workarounds. Boxes configures Secure Boot and a virtual TPM device automatically. Everything required to pass the Windows 11 hardware compatibility checks out of the box. This was the most requested feature for the classic version, so I am particularly glad it is fully functional in this rewrite.
As distributions shift toward image-based OSes, this Flatpak-only approach becomes even more valuable. Most other virtual machine managers rely on host services or privileged daemons that are difficult to configure on immutable systems. While hardware and host combinations vary, bundling the backend stack directly inside the Flatpak gives us a controlled baseline that we can actively support, configure, and refine over time.
Accessing VM contents used to be tricky due to Flatpak sandboxing. This version addresses that by introducing a VSOCK device to the box, allowing guests with systemd v256 or newer to be accessed directly over SSH. It also adds initial support for port forwarding, letting you reach services running inside the VM from your host.

All of this and more is detailed on our new website, nightly.gnomeboxes.org, where you can also learn how to help by testing and reporting issues.
Please keep in mind that I am working on this in my free time alongside maintaining GNOME Settings and my day-job responsibilities at Red Hat. I ask for your patience with issue responses, but I will do my best to address bugs and keep pushing feature development forward as time allows.
I love building GNOME Boxes, and I am constantly motivated by the positive feedback from our community. People appreciate Boxes because it lets them set up a VM quickly and get straight to work without needing deep knowledge of virtualization or operating system internals. That remains the core mission, and that is the user experience I want to continue building for.
A lot of this implementation will still change as I gather feedback and it matures. I have also drafted a series of follow-up blog posts to this one, which will describe and elaborate a bit more on the new features, explaining how to use them and how they have been implemented. Stay tuned!
RPMs of Redis version 8.10 are available in the remi-modular repository for Fedora ≥ 43 and Enterprise Linux ≥ 8 (RHEL, Alma, CentOS, Rocky...).
Packages are available in the redis:remi-8.8 module stream.
# dnf install https://rpms.remirepo.net/enterprise/remi-release-$(rpm -E %rhel).rpm # dnf module switch-to redis:remi-8.10/common
# dnf install https://rpms.remirepo.net/fedora/remi-release-$(rpm -E %fedora).rpm # dnf module reset redis # dnf module enable redis:remi-8.10 # dnf install redis --allowerasing
You may have to remove the valkey-compat-redis compatibility package.
Some optional modules are also available:
These packages are weak dependencies of Redis, so they are installed by default (if install_weak_deps is not disabled in the dnf configuration).
The modules are automatically loaded after installation and service (re)start.
The modules are not available for Enterprise Linux 8.
redis
redis-bloom
redis-json
redis-timeseries
After extensive review and discussion on the ticket request and in recent council meetings (see meetbot for 29 July and 15 July 2026), the Fedora Council would like to initiate the policy change policy process for ratifying the Fedora Forge Usage policy. This document is open to public feedback (if any) for a minimum of two weeks. If there are no significant changes to be made to the policy based on community feedback after Thursday, 13 August 2026, this policy will go to a formal ticket vote for Council to approve or reject.
If there are significant changes to be made to the document, Council will review the policy and, if necessary, extend the feedback period before calling for an official vote. Please provide feedback on the discussion post.
The policy can be found on the Council wiki page in Fedora Forge, posted on discourse, and pasted below here for convenience.
Thank you everyone for your contributions to this policy so far, and on behalf of the Council, we look forward to working with you all to ratify this policy soon.
Welcome to the Fedora Forge. This Forgejo instance is provided by the Fedora Infrastructure team to support the daily operations, development, and collaboration of the Fedora Project.
To ensure this service remains reliable, secure, and useful for everyone in the Fedora community, all users must adhere to the following usage policy.
The Fedora Forge is a dedicated workspace for the Fedora Project. Historically, the Fedora Project utilized pagure.io, which operated as a general-use public forge where Fedora repositories coexisted alongside personal projects, unrelated upstream software, and individual portfolios.
The Fedora Forge (powered by Forgejo) intentionally adopts a narrower scope. It is not a public, general-use Git hosting provider. It is an internal piece of project infrastructure, explicitly provisioned to host the code, documentation, and tooling that directly build, manage, and govern the Fedora Project.
To qualify for hosting on the Fedora Forge, a repository must meet at least one of the following criteria:
While general upstream development should happen on public forges (like GitHub, GitLab, or Codeberg), the Fedora Project recognizes that certain large-scale upstream projects are so deeply intertwined with Fedora’s infrastructure and history that they qualify as exceptions.
Recognized Exceptions:
Note: Being packaged in the Fedora repository does not automatically grant a project exception status to use the Fedora Forge as its upstream host.
If a community member is unsure whether their project fits the scope or qualifies as an ecosystem exception, the following process applies:
Access to the Fedora Forge is integrated with our central identity systems to ensure secure and accountable access.
The Fedora Forge is a collaborative space. All activity on this platform is strictly governed by the Fedora Code of Conduct.
To ensure the Fedora Forge remains performant, secure, and legally compliant, the following activities and content are strictly prohibited:
We want to empower Fedora teams with the tools they need, but we must also manage our infrastructure costs and storage effectively.
The post Fedora Forge Usage Policy appeared first on Fedora Community Blog.
A Caesar cipher is a letter for letter exchange from a clear text to a encrypted text by shifting a set distance in the alphabet. Thus, if your set distance is 2, the letter A becomes C, the letter X becomes Z. To encrypt the last letters of the alphabet, you wrap around to the beginning, so Y becomes A and Z becomes B.
Caesar is commonly respelled to Ceasar, which I have done for this article. Use the spelling of your choice.
This is a fairly easy algorithm to code, and makes for a decent early class in python. Here are the steps I would go through to teach someone:
I would do this on Linux, of course, using vim, but that is my problem. I won’t go into editor usage.
Start by writing and executing a hello_world program:
vim ceasar.py:
#!/bin/python3
print("OK")
Make the file executable.
chmod +x ceasar.py
Run the program.
./ceasar.py
OK
Always work from success. Don’t try to do more until you can get this far. Make sure you understand what you have done.
The Line !/bin/python3 tells the you that this a script to be executed by the python interpreter. The #! will be read by the Linux Kernel when you execute the program. There are lots of magic numbers for different file types. This one tells Linux to treat the file as text, to start reading until a newline, and to execute the program named by that string, with the rest of the file contents fed into that interpreter. This is pretty complex stuff, and expect people to either zone out or ask lots of questions. You could, if necessary show a different scripting language, such as bash or ruby.
The print(“OK”) is a function. That function is responsible for the OK you see on the screen after running the program.
Once you get this far, you might want to have the students change the text from OK to Hello or something, so they can see how they affect change, and get feedback from coding.
Now run
git init.
git add ceasar.py
git commit -m "Hello World"
Yeah, git. This will allow them to reset themselves later. Answering questions about this will probably kill the rest of the class session. But using git is fundamental to not losing your mind as a developer.
Next we are going to give them an input text. For this example, I will use the opening line from Pride and Prejudice:
“is, “It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife.”
Jane Austen from PRide and PRejudice
The code should now look like this:
!/bin/python3
plain_text=”It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife.”
print(plain_text)
This introduces the concept of variables. plain_text is a variable that uses the snake_case naming convention. The underscore allows you to separate words while telling python that the whole collection of characters is one variable name.
Run it.
./ceasar.py
It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife.
Add to git and commit:
git add ceasar.py
git commit -m "plain text"
Now lets uppercase the whole thing.
The code will look like this:
#!/bin/python3
plain_text="It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife."
print(plain_text.upper())
And the difference from the previous code can be shown with git diff
git diff
diff --git a/ceasar.py b/ceasar.py
index 76c6294..388e25f 100755
--- a/ceasar.py
+++ b/ceasar.py
@@ -3,4 +3,4 @@
plain_text="It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife."
-print(plain_text)
+print(plain_text.upper())
The output looks like this:
$ ./ceasar.py
IT IS A TRUTH UNIVERSALLY ACKNOWLEDGED, THAT A SINGLE MAN IN POSSESSION OF A GOOD FORTUNE, MUST BE IN WANT OF A WIFE.
Add to git and commit:
git add ceasar.py
git commit -m "to upper"
We are trying to establish the good habit of capturing your successes.
Lets go through the plain text letter by letter, now.
#!/bin/python3
plain_text="It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife."
encrypted_text = ""
for letter in plain_text.upper():
encrypted_text += letter
print(encrypted_text)
Which will look like this when executed:
/ceasar.py
IT IS A TRUTH UNIVERSALLY ACKNOWLEDGED, THAT A SINGLE MAN IN POSSESSION OF A GOOD FORTUNE, MUST BE IN WANT OF A WIFE.
i.e. exactly the same as before. We might have fooled ourselves. But the next change is going to be an important step in the understanding of coding Lets do a change that shows we actually made things work. Commit to git before continuing.
Lets strip out all characters that are not A-Z.
git add ceasar.py
git commit -m "letter by letter"
Now we will strip out all non-Alphabet characters. Make the following change. The - at the start of the line means match and remove that line, replacing it with the lines below it that start with +. Do not include the + or - characters that are at the start of the line.
- encrypted_text += letter
+ if (letter >= 'A' and letter <= 'Z'):
+ encrypted_text += letter
Now your code should look like this:
#!/bin/python3
plain_text="It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife."
encrypted_text = ""
for letter in plain_text.upper():
if (letter >= 'A' and letter <= 'Z'):
encrypted_text += letter
print(encrypted_text)
And a run of the program looks like this
./ceasar.py
ITISATRUTHUNIVERSALLYACKNOWLEDGEDTHATASINGLEMANINPOSSESSIONOFAGOODFORTUNEMUSTBEINWANTOFAWIFE
Note that now we need to mentally put the spaces back in to read it. This is a shortcoming of the Ceasar cipher, and it is something we can address with more complex cpihers in the future.
Add to git in a similar manner to how I wrote earlier.
adam@standard:~/devel/letterfreq$ git add ceasar.py
adam@standard:~/devel/letterfreq$ git commit -m "letters only"
Note how the only thing that differs on each of these commits is the message. At this point, we should have a few. We can see them (from newest to oldest) using git log:
git log
commit 422eed0a5e0c5a0b30855a3a84ae7c77fbe3945b (HEAD -> main)
Author: Adam Young <adam@younglogic.com>
Date: Mon Jul 27 15:15:52 2026 -0400
letters only
commit af884dcb08921deddfca70bcde548762310c3dc0
Author: Adam Young <adam@younglogic.com>
Date: Mon Jul 27 15:05:14 2026 -0400
letter by letter
commit 6156eaeafcaf7054044aca41aebf8f8bfe456172
Author: Adam Young <adam@younglogic.com>
Date: Mon Jul 27 14:57:21 2026 -0400
to upper
commit d739450b2c89f7e566d36f5ff201d2807bd72346
Author: Adam Young <adam@younglogic.com>
Date: Mon Jul 27 14:54:16 2026 -0400
plain text
commit 58477d16f983d2d2a32c6e4ba9769313d774b644
Author: Adam Young <adam@younglogic.com>
Date: Mon Jul 27 14:49:01 2026 -0400
hello world
Now we will convert from the letters A to Z to their numerical equivalent. We are using an encoding scheme called ASCII (American Standard Code for Information Interchange) that maps 'A' to the number 65. The rest of the alphabet follows in standard order: B=66, C=67 and so on. So to convert, we use the ord function (short for ordinal).
To convert 'A' to 65, we would write
val = ord('A')
Lets do only that and see what we get. Yeah, this is going to corrupt our output, but it will be illuminating. After the line
encrypted_text += letter
add these lines
val = ord(letter)
print(f"ordinal = {val}")
This will print out a lot of output, so much that it will scroll off the screen. The last few lines look like this:
ordinal = 87
ordinal = 73
ordinal = 70
ordinal = 69
ITISATRUTHUNIVERSALLYACKNOWLEDGEDTHATASINGLEMANINPOSSESSIONOFAGOODFORTUNEMUSTBEINWANTOFAWIFE
We won't commit this to git, as it is a broken stage. Lets instead do some arithmatic.
In order to perform the portion of the Ceasar cipher that wraps around, we want to use the arithmetic operation of modulus. This is the remainder function of division. Since there are 26 letters, the number 0 through 25 are returned unchanged, but any number larger than 25 will instead return a number 0-25. In python, this is the % operator. You might want to show this in a stand alone fashion.
Note that I am going to run the python interpreter from the command line to show this.
$ python3
Python 3.14.4 (main, Jun 18 2026, 14:25:02) [GCC 15.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> ord('A')
65
>>> 25 % 26
25
>>> 27 % 26
1
>>> ord('A') % 26
13
However, we don't want to convert 'A' to 13. So, we are going to convert 'A" from 65 to 0, B to 1, and so on. We do this by subtracting the ord value of 'A' from each letter:
>>> ord('A') % 26
13
>>> ord ('A') - ord('A')
0
>>> ord ('B') - ord('A')
1
>>> ord ('C') - ord('A')
2
>>> ord ('Z') - ord('A')
Now we can perform cipher change. For example, if we wanted to encrypt Z by 13:
>>> (ord ('Z') - ord('A') + 13) % 26
12
To convert this back to a character, add the ord value of 'A" and use the chr function.
>>> chr(12 + ord ('A'))
'M'
To exit the interpreter, run the quit function like this
quit()
Lets add this logic to our code. IT should look like this.
#!/bin/python3
#!/bin/python3
plain_text="It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife."
encrypted_text = ""
key = 13
for letter in plain_text.upper():
if (letter >= 'A' and letter <= 'Z'):
plain_val = ord(letter) - ord('A')
encrypted_val = (plain_val + key) % 26
encrypted_text += chr(encrypted_val + ord('A'))
print(encrypted_text)
~
Note that the function is chr, and not char. char is a key word in python, and the error message might be a bit hard to debug if you accidentally type that instead.
Note also the use of parenthesis to handle the order of operations. You want the modulus of the value after you subtract 65. If you were to try and execute
encrypted_val = plain_val + key % 26
Python would first perform key % 26 and then add plain_val which would not be correct.
Running the above code should look like this:
./ceasar.py
VGVFNGEHGUHAVIREFNYYLNPXABJYRQTRQGUNGNFVATYRZNAVACBFFRFFVBABSNTBBQSBEGHARZHFGORVAJNAGBSNJVSR
adam@standard:~/devel/letterfreq$ git add ceasar.py
adam@standard:~/devel/letterfreq$ git commit -m "encrypt"
Now we want to make it easier to encrypt text without changing our program. We will read from standard input instead of a constant string. To do this, we first need to import the standard library called sys.
import sys
We can remove our Jane Austen quote and add an outer loop
for line in sys.stdin:
# Use .rstrip() to remove the trailing newline character
plain_text = line.rstrip()
One of the biggest pains in python is that white space, especially tab characters, are significant. We need to move all of the internal loop code one more indentation to the left
Now the overall code should look like this:
#!/bin/python3
import sys
plain_text="It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife."
encrypted_text = ""
key = 13
for line in sys.stdin:
# Use .rstrip() to remove the trailing newline character
plain_text = line.rstrip()
for letter in plain_text.upper():
if (letter >= 'A' and letter <= 'Z'):
plain_val = ord(letter) - ord('A')
encrypted_val = (plain_val + key) % 26
encrypted_text += chr(encrypted_val + ord('A'))
print(encrypted_text)
You can now use the Linux cat utility to test your program. I have a couple paragraphs from the start of "Zen and the Art of Motorcycle Maintenance" that I can encrypt like this:
cat zen.txt | ./ceasar.py
VPNAFRROLZLJNGPUJVGUBHGGNXVATZLUNAQSEBZGURYRSGTEVCBSGURPLPYRGUNGVGVFRVTUGGUVEGLVAGURZBEAVATGURJVAQRIRANGFVKGLZVYRFNAUBHEVFJNEZNAQUHZVQJURAVGFGUVFUBGNAQZHTTLNGRVTUGGUVEGLVZJBAQREVATJUNGVGFTBVATGBORYVXRVAGURNSGREABBAVAGURJVAQNERCHATRAGBQBEFSEBZGURZNEFURFOLGUREBNQJRNERVANANERNBSGURPRAGENYCYNVAFSVYYRQJVGUGUBHFNAQFBSQHPXUHAGVATFYBHTUFURNQVATABEGUJRFGSEBZZVAARNCBYVFGBJNEQGURQNXBGNFGUVFUVTUJNLVFNABYQPBAPERGRGJBYNAREGUNGUNFAGUNQZHPUGENSSVPFVAPRNSBHEYNAREJRAGVACNENYYRYGBVGFRIRENYLRNEFNTBJURAJRCNFFNZNEFUGURNVEFHQQRAYLORPBZRFPBBYREGURAJURAJRNERCNFGVGFHQQRAYLJNEZFHCNTNVAVZUNCCLGBOREVQVATONPXVAGBGUVFPBHAGELVGVFNXVAQBSABJURERSNZBHFSBEABGUVATNGNYYNAQUNFNANCCRNYORPNHFRBSWHFGGUNGGRAFVBAFQVFNCCRNENYBATBYQEBNQFYVXRGUVFJROHZCNYBATGURORNGHCPBAPERGRORGJRRAGURPNGGNVYFNAQFGERGPURFBSZRNQBJNAQGURAZBERPNGGNVYFNAQZNEFUTENFFURERNAQGURERVFNFGERGPUBSBCRAJNGRENAQVSLBHYBBXPYBFRYLLBHPNAFRRJVYQQHPXFNGGURRQTRBSGURPNGGNVYFNAQGHEGYRFGURERFNERQJVATRQOYNPXOVEQ
One thing about using a key of 13 is that it can decrypt just by encrypting a second time. Thus, if I run my encrypted text through the cipher, I should get my clear text:
$ cat zen.txt | ./ceasar.py | ./ceasar.py
ICANSEEBYMYWATCHWITHOUTTAKINGMYHANDFROMTHELEFTGRIPOFTHECYCLETHATITISEIGHTTHIRTYINTHEMORNINGTHEWINDEVENATSIXTYMILESANHOURISWARMANDHUMIDWHENITSTHISHOTANDMUGGYATEIGHTTHIRTYIMWONDERINGWHATITSGOINGTOBELIKEINTHEAFTERNOONINTHEWINDAREPUNGENTODORSFROMTHEMARSHESBYTHEROADWEAREINANAREAOFTHECENTRALPLAINSFILLEDWITHTHOUSANDSOFDUCKHUNTINGSLOUGHSHEADINGNORTHWESTFROMMINNEAPOLISTOWARDTHEDAKOTASTHISHIGHWAYISANOLDCONCRETETWOLANERTHATHASNTHADMUCHTRAFFICSINCEAFOURLANERWENTINPARALLELTOITSEVERALYEARSAGOWHENWEPASSAMARSHTHEAIRSUDDENLYBECOMESCOOLERTHENWHENWEAREPASTITSUDDENLYWARMSUPAGAINIMHAPPYTOBERIDINGBACKINTOTHISCOUNTRYITISAKINDOFNOWHEREFAMOUSFORNOTHINGATALLANDHASANAPPEALBECAUSEOFJUSTTHATTENSIONSDISAPPEARALONGOLDROADSLIKETHISWEBUMPALONGTHEBEATUPCONCRETEBETWEENTHECATTAILSANDSTRETCHESOFMEADOWANDTHENMORECATTAILSANDMARSHGRASSHEREANDTHEREISASTRETCHOFOPENWATERANDIFYOULOOKCLOSELYYOUCANSEEWILDDUCKSATTHEEDGEOFTHECATTAILSANDTURTLESTHERESAREDWINGEDBLACKBIRD
Or if we use Pride and Prejudice:
cat pride-prejudice.txt | ./ceasar.py | ./ceasar.py
ITISATRUTHUNIVERSALLYACKNOWLEDGEDTHATASINGLEMANINPOSSESSIONOFAGOODFORTUNEMUSTBEINWANTOFAWIFE
git add ceasar.py
git commit -m "encrypt from the command line"
Last few years a small team of people in the CLE Team were working each week to prepare a Community update for you. First one published on October 21st 2021. We were starting with only Infrastructure and Release Engineering teams (+ initiatives we did in CPE Team at the time), but later added more teams to our weekly reports to bring people a better picture what is being worked on. We thank to everyone who read our updates and found some value in them.
But as life is going forward even this updates are evolving. Last few weeks @abompard worked together with us to improve his weekly report to include the sources we are using for this weekly reports. So I introduce to you This Week in Fedora as a replacement for Community weekly updates. I’m glad that this initiative I started few years ago was able to live for that long and hopefully helped a few people to find information they were looking for.
I would like to thank people who helped me working on Community weekly updates:
The post End of Community update appeared first on Fedora Community Blog.
If you look at the bottom of the site now you'll see I have published a privacy document. Normally I expect updates like this to explain how somebody is actively trying to track me harder. This is actually the opposite of that and I hope it can be useful to other folks who want to get better signal to noise ratio with still respecting their readers privacy wishes.
It's simple. A tiny bit of unessential javascript loads on each page load. The javascript checks about 4 different ways to see if you are asking not to be tracked:
(function () {
// If you have asked not to be tracked, stop here. Fire nothing.
var dnt = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
if (dnt === "1" || dnt === "yes" || navigator.globalPrivacyControl) { return; }
If that's your wish, it skips. If you leave that open, then it loads a small invisible svg:
new Image().src = "/assets/turnstile.svg?" + Date.now();
})();
The privacy page explains in much greater detail how all of this works.
You won't appear in those either.
Requests for turnstile.svg are sent to a different log file, and that's only if apache does not detect the do not track header from your browser.
If that isn't set then an item is logged in the turnstile log. For example:
2026-07-24 "https://blog.lnx.cx/privacy/"
That's it. It says on that day, July 24th, a request was made from (in this example) the privacy page. No time component, only a date stamp. No IP address. Just a date and a referral page. I can't use this to line up anything with the other logs to build a profile. I don't want to.
While you (yes, you! no, not you, the one behind you) have been sweltering in the heatwaves of the northern hemispheres (Assisted-by: AI), I've been busy adding graphics tablet support to libei. This is scheduled for the soon to be released libei 1.7.0.
The initial work was done by Jason Gerecke and Josh Dickens from Wacom, I've been extending, polishing and testing it for the last few weeks.
Also, upfront: this only covers the stylus part of a tablet, we do not yet have an implementation for the "pad" part (the buttons, dials, rings, strips).
libei is, of course, the library for Emulated Input, a good-enough transport layer for sending logical input events between processes. We're already using libei as part of the XDG Portal Remote Desktop and Input Capture portals where we've been busy hurtling key and pointer events between the participating parties (and soon gesture events and text).
In the next release of libei, we will now also have "ei stylus" capabilities, i.e. the ability to send tablet stylus events. Getting pointer, keyboard and touch events supported was a long undertaking, everything was new and shiny and needed to be added everywhere in the stack. Now that all this is in place, scuffed and scratched, adding tablet events will be quite simple.
Here's a short outline of how libei handles tablet events because it is, of course, different to how libinput handles them. Logical events are much nicer after all than physical hardware events.
First: we have a new interface: "ei_stylus". An EIS implementation (e.g. your compositor) may provide you, the libei client, with a device that supports this interface and one or more associated regions (typically representing the available screen areas). Typically this will be a separate device to the pointer devices or the keyboard devices but it's not a requirement. The ei_stylus interface comes with a bunch of capabilities you'd expect from a stylus (tilt, pressure, distance, ...) that you can selectively enable to emulate the stylus you want to. So basically, EIS will say "here's a stylus device, I support pressure, tilt, rotation, ..." and then the libei client says "This stylus should have pressure and tilt but nothing else". And then you do the normal thing: send proximity events, send tip down/up events, send data for the various capabilities you've enabled.
Happily for the EIS implementation, libei forces the client to take the guesswork out of everything: if you select the pressure capability, you must send a pressure value when coming into proximity. Where libei is used to forward data from a physical stylus (e.g. via some remoting protocol) it is up to the client to deal with firmware bugs that e.g. won't send data until a few frames in.
Note that there is no "tablet" anywhere. The tablet is represented by the region that the device may interact with. So in some ways every tablet is an on-screen tablet (which makes sense since we have logical events).
The only quirky thing is how to request multiple styli[1]: libei 1.5.0 has added a "request device" request that allows a client to say "hey, EIS, I want a new device with capabilities pointer, keyboard, ...". And, if you've been a nice client, minding your own business, the EIS implementation may just create such a device for you.
So for the case of multiple styli: if the default stylus (if any) isn't good enough, you can now tell EIS that you want a(nother) device with stylus capability, configure the stylus capabilities once the device shows up and voila, you now have a normal pen, an art pen and maybe even an airbrush represented as logical device in libei. And since they're all separate devices in the protocol, they can be individually tracked and used, much like libinput tracks individual styli.
[1] For the "lots" of users that actually use multiple styli...
/me gestures vaguely at everything
Oh, hey, this works now? Great!
libei 1.7.0 (to be released soon) comes with a new interface: "ei_gestures" which, creatively, will allow for gestures to be sent between a libei client and an EIS implementation (typically: a Wayland compositor).I'm not going to go too deeply into how pinch, swipe and hold gestures work, suffice to say we've had those in libinput (for touchpads) for years now so compositors and toolkits should already support those. And since libei and libinput have vaguely equivalent API layers integrating gestures for libei devices in compositors should be fairly straightforward.
The plumbing layers in the portals exist already too, so adding gestures to libei means that - once the compositors support it - we can have gestures support in remote desktop and input capture implementations without needing to update anything else. Hooray! Join in with me. Hooray! Louder! HOORAY!
For testing I had a (vibe-coded and thus immediately abandoned once testing was complete) gesturemouse utility which translates input events from a mouse into gesture events (depending which button is down). But don't let my lack of be a limit to your imagination, I'm sure you can come up with good use-cases for this.
If you've been paying attention (and I know you have, because it'd be embarrassing for you if you didn't) you'd have noticed that libei 1.6 (May 2026) added support for keysym and text events.
libei sends logical events between a libei client and an EIS implementation (typically: a Wayland compositor) but the keyboard interface it had was designed like real keyboards: key codes together with an (XKB) key map. You press one key, the keymap decides what that key means on the compositor side and off we go. This is easy but not always useful.
As of 1.6.0 libei now also supports an "ei_text" interface. A compositor may choose to provide you[0] with a device that supports this interface and that gives you two really nice opportunities.
First, you can now send a key sym. Instead of sending the KEY_Q
key code and hoping it actually translates to 'q' (and if there's e.g. a
frenchman^Wfrenchperson lurking behind the keyboard it may mean 'a'), you can
now send 'q' as actual keysym. Or 'Q' instead of sending shift+q and
hoping for no french influence in the process. It becomes the EIS
implementation's job to handle that keysym - if it's a shortcut it may handle
it directly, otherwise it may pass it on via Wayland to an application[1]. This
centralises the keysym to keycode handling in the EIS implementation which is a
pain for compositor authors (though they likely have that code already for e.g.
RDP support) but reduces the variety of differently-wrong implementations in
clients and of course makes it so much simpler to write clients.
Second, a client can send UTF-8 text to the compositor. So instead of emulating shift, keycodes, etc. you can literally send "Hello World" and expect the EIS implementation to pass that one. Again, makes a bunch of utilities a lot simpler to write and I mostly leave it up to your imagination to figure out what to do with that.
Notably for both cases: libei is about logical events that have a specific meaning that do not need further interpretation. If a client sends 'Q' that means it is supposed to be an uppercase Q. Sending keysym Shift_L and Q makes little sense. And for the utf8 text events: how the text comes to be matters doesn't matter for libei so you may use an IM to make up the text to begin with and send it, once committed, to EIS. It's not for sending partial strings.
As mentioned in the previous post: the plumbing for this is already in place so both clients and compositors can add support for this new interface without having to bother the rest of the stack (e.g. portals). So, hooray I guess.
The text/keysym support is relatively recent so expect this to hit the next compositor version (or the one after that).
[0]: the EIS implementation decides which devices are available and arguing about
this is even less useful than arguing with a world cup ref
[1]: after converting it to a key code with possible keymap changes... but hey, such is life
Turns out it's been years since I've talked about eggs, so let's change this. libei is, of course, the library for Emulated Input[1].
This post is mostly a refresher because it's been so long and a short summary of some of the work we've done so far, in preparation for some more posts that come soon.
libei is a transport layer for logical input events, unlike libinput which is a hardware abstraction layer. In libinput's case the device's firmare/kernel pass events that are somewhere on the sanity spectrum, libinput tries to make sense of those and then we convert those to logical events to be consumed by the next layer (typically the Wayland compositor or Xorg). This is how e.g. "touch down at position x1/y1, touch up at position x1/y2" is converted into a button click event if touchpad tapping is enabled. Or maybe into nothing if we find it was an accidental palm touch.
libei works purely on the logical level - you as the libei client pass logical events to the EIS (Emulated Input Server) implementation (typically the compositor). No guesswork, you say button click, EIS gets a button click. libei supports a "sender" and "receiver" mode, depending on whether events are sent to the EIS implementation (input emulation) or receive from the EIS implementation (input capture). libei is designed for the Wayland stack but there are zero requirements for Wayland on either the client or the EIS implementation.
Core to libei's design is that the EIS implementation is in control of virtually everything, it decides which devices are available to the client, when those devices can send events, etc. Much like the compositor is in charge when it comes to physical devices - if a compositor decides a physical device doesn't exist, a Wayland client cannot get events from it.
Since the original proposal (again, [1]!) we've been busy bees and libei is now a part of the XDG Remote Desktop portal and the XDG Input Capture (both since version 1.17, mid 2023). In both cases the portal is for the negotiation and initial agreement of what should happen, libei is then used as the transport layer between the two processes [2].
More recently we also added session persistence support so you don't have to allow access on every connecton. Much of the work enabling this was done by Jonas Ã…dahl, it is now in the portals since version 1.21.0 and should be in the major compositors in the current or next versions.
Getting all this into place was a huge amount of work across several pieces of the stack. This isn't exciting in the same way as laying plumbing pipes isn't particularly exciting but much like regular plumbing: once it's in place you can change your diet without severely impacting everyone again. Try get that analogy out of your head now. You're welcome.
In libei's case this means three things:
An example for such a case where we can now abuse the piping is Xwayland support for XTEST. XTEST is the protocol that everyone uses to emulate input under X but in Wayland it's not hooked up to anything so those APIs simply won't work.
But what we can do in Xwayland is translate XTEST to libei events and facilitate the portal interaction. This means our stack looks roughly like this:
+--------------------+ +------------------+
| Wayland compositor |---wayland---| Wayland client B |
+--------------------+\ +------------------+
| libinput | EIS | \_wayland______
+----------+---------+ \
| | +-------+------------------+
/dev/input/ +-----------| libei | XWayland |
+-------+------------------+
|
| XTEST
|
+-----------+
| X client |
+-----------+
And if said X client uses XTEST to try to emulate devices, Xwayland will
ask the Remote Desktop portal for permission and set up the session, then pass
the XTEST events on as libei events and voila - your 20 year old X client can
send pointer and keyboard events through an XDG Portal without knowing about
it (and the user can prohibit this and even gets some information on who is
sending events which is not possible with normal XTEST at all). This has now
been supported since Xwayland 23.2.0. Compositors don't need extra support for
this.
So we have a lot of the plumbing in place, or in another anology: we have a hammer, let's go looking for nails. And right now the nails we can see are sending text, gestures, and tablet support. And those will be the subject of the next few posts.
[1]: 6 years ago?! whoah...
[2]: in Remote Desktop's case replacing the DBus emulation APIs which were a Newton's Cradle of wakeups for at least 4 processes per event