frostread readd
The readd extension adds readd, frostread’s daemon, to a Frostyard bootc image. It runs as lodge’s Read app, with the app id read. A server that runs the suite’s services runs Floe. frostread’s own page is frostread. Every image carries the extension’s definition, switched off. The extension itself is not in the image: Updex turns it on and downloads it.
Before you start
Section titled “Before you start”You need:
- A Frostyard bootc image built on Base.
- Root access to enable, update, and remove the extension.
- Network access to
https://repository.frostyard.org/ext/readd/. - Free space in
/varfor the image.
readd has no published test results on Frostyard images yet. Try it on a machine you can spare first.
You reach Read in a browser through lodge. Enable lodge first. The readd extension declares no dependency on lodge, so enabling readd does not enable lodge.
Enable readd
Section titled “Enable readd”See what Updex found, then enable the feature and download it now:
updex features list --component=readdsudo updex features enable readd --nowreadd appears as a component, with its feature disabled. The enable command
downloads the image, checks its checksum and signature, links it, and refreshes
the merge. With Updex v2.1.3 and later, the refresh also creates the users,
groups, and directories that the extension declares, before systemd reloads.
Upholds= then starts the units, with no reboot. updex --version shows your
version.
The lab has not yet proven this for readd: no lab run has enabled it live yet.
If a unit fails, follow the start-limit-hit steps below, or reboot.
If updex features list does not show the feature, the image is older than the
extension. Update the image first.
With an Updex older than v2.1.3, the units cannot start after the enable: their
users and groups do not exist yet. Reboot. At boot the image merges the
extensions, runs systemd-sysusers and systemd-tmpfiles --create, reloads
systemd, and Upholds= starts the units. To start them without a reboot:
sudo systemd-sysuserssudo systemd-tmpfiles --createsudo systemctl reset-failed frostread.socket frostread.servicesudo systemctl start frostread.socket frostread.serviceCheck the units and the feeds:
systemctl status frostread.socket frostread.servicesudo -u frostread readctl sourcessystemctl status shows both units active. readctl sources lists the feeds.
readctl uses /run/frostread/readctl.sock by default.
If a unit shows failed with start-limit-hit, systemd stopped starting it.
Run sudo systemctl reset-failed frostread.socket frostread.service, then
sudo systemctl start frostread.socket frostread.service, or reboot. Then run the checks again.
If enable --now exits with a refresh error (refresh_error in JSON), the
download worked, but the activation did not. If the output says
activation did not finish, the extension is merged, but its users and groups
can be missing: reboot. Otherwise the merge state is unknown: reboot. A
sudo systemd-sysext refresh by hand does not create the extension’s users
and groups. Then run the checks above again.
What runs
Section titled “What runs”frostread.socket and frostread.service run on the host. The service is
upheld because its feed poller works without a client.
The drop-in /usr/lib/systemd/system/multi-user.target.d/10-readd.conf has
Upholds= for both units, and the preset
/usr/lib/systemd/system-preset/40-readd.preset enables both. Both start at
boot. If one stops, even with exit status 0, systemd starts it again. To stop it
for longer, remove the extension or mask the unit.
extension-release.readd sets EXTENSION_RELOAD_MANAGER=1, so a merge or
refresh reloads systemd’s unit files.
frostread.service runs /usr/bin/readd --socket /run/frostread/readctl.sock
as the user frostread, with the groups lodge-apps and lodge-agents. Its
state is in /var/lib/frostread. readd reaches the public web itself, to fetch
feeds.
The configuration belongs to you, and the extension ships no file in /etc:
/etc/frostread/frostread.json.
frostread.socket listens on /run/lodge/apps/read.sock as owner frostread,
group lodge, mode 0660.
The sysusers file /usr/lib/sysusers.d/frostread.conf creates the user
frostread and the group lodge, with frostread in lodge-apps and
lodge-agents. The user is never in group lodge.
The file also creates the user lodge, with the same line as lodge’s own
sysusers file. The daemon looks up the user lodge when it starts, so it
starts without lodge’s extension. Save-as-note needs lodge’s
configuration to name frostread in agents.
The commands are /usr/bin/readd and /usr/bin/readctl. The lodge app files
are in /usr/share/lodge/apps/read/.
Update, roll back, and remove
Section titled “Update, roll back, and remove”Back up frostread’s state before you update. readd migrates its database when it starts, and an older readd refuses a database with a newer schema. A rollback does not undo a migration.
Stop frostread for the backup. Systemd starts upheld units again, so mask them while you copy. While frostread is stopped, the Read tab does not work, the poller does not run, and lodge shows the app as down. The state holds the notes token, so keep the archive root-only:
sudo systemctl mask --now frostread.socket frostread.servicesudo sh -c 'umask 077; tar -czpf /root/frostread-state-$(date -u +%Y%m%dT%H%MZ).tar.gz /var/lib/frostread'sudo systemctl unmask frostread.socket frostread.servicesudo systemctl start frostread.socket frostread.servicetar exits 0, and systemctl status frostread.socket frostread.service shows
both units active again.
Check for an update, then install it:
updex features check --component=readdsudo updex features update --component=readdBy default, the update merges the new files at once, and systemd reloads its unit files. Updex v2.1.3 and later also create new users, groups, and directories at once. An older Updex leaves them for the next boot. The running readd keeps its old binary until it restarts. A reboot applies everything.
The new files wait for the next boot when you pass --no-refresh, when the
automatic update timer installs the update, or when the output says
refresh skipped: Updex skips the refresh when it cannot refresh safely. Then
reboot. See Update.
With an Updex older than v2.1.3, run these commands first. updex --version
shows your version.
sudo systemd-sysuserssudo systemd-tmpfiles --createsudo systemctl daemon-reloadTo run the new version now, restart frostread, then let lodge read the new manifest:
sudo systemctl restart frostread.socket frostread.servicesudo lodgectl reloadCheck the version that runs:
sudo -u frostread readctl statussudo lodgectl appsreadctl status prints readd <version> with the new version. lodgectl apps
lists read up, with the new version. lodge polls each app every 15 seconds,
so if read shows down at once, run lodgectl apps again after 15 seconds.
Roll back to the previous version:
sudo updex features rollback readdThe rollback takes effect at the next boot. To apply it now, add --now, then
restart frostread as above. See Roll back.
When the older version runs, read the journal:
journalctl -u frostread.service -n 50If it shows database schema N is newer than this readd, the newer readd
migrated the database. Restore the state from your backup. Replace ARCHIVE
with the path of the archive:
sudo systemctl mask --now frostread.socket frostread.servicesudo rm -rf /var/lib/frostreadsudo tar -xzpf ARCHIVE -C / var/lib/frostreadsudo systemctl unmask frostread.socket frostread.servicesudo systemctl start frostread.socket frostread.serviceThe restore loses what changed after the backup: new items, reads, and saves.
Remove readd:
sudo updex features disable readd --now --forceUpdex unmerges all extensions on the host, deletes the image, and merges the
rest again. Reboot when the command finishes. Without --force, Updex refuses
while the image is merged.
What ships
Section titled “What ships”| Item | What you get |
|---|---|
| Package | frostyard-readd, the .deb attached to the app’s GitHub release, installed into the image with dpkg. The build checks the download against a pinned SHA-256, and checks that its dependencies are met before it installs. Its GitHub build-provenance attestation is checked when the pin is set and in every CI build, before the image is built |
| Feature | Read (frostread feed reader daemon and Lodge read app) |
| Commands | /usr/bin/readd and /usr/bin/readctl |
| Service | frostread.service, which runs /usr/bin/readd --socket /run/frostread/readctl.sock as the user frostread |
| Socket | frostread.socket on /run/lodge/apps/read.sock, owner frostread, group lodge, mode 0660 |
| Private socket | /run/frostread/readctl.sock, for readctl |
| State | /var/lib/frostread |
| User and group | frostread, group lodge, frostread in lodge-apps and lodge-agents, and the user lodge, from /usr/lib/sysusers.d/frostread.conf |
| Lodge app | /usr/share/lodge/apps/read/ |
| Activation | /usr/lib/systemd/system/multi-user.target.d/10-readd.conf with Upholds=, and /usr/lib/systemd/system-preset/40-readd.preset |
| Version | The image file name carries the frostyard-readd package version, which is the app’s release version |
| Image file | readd_<version>_13_x86-64.raw.zst, where 13 is the OS version ID; .raw.xz, .raw.gz, and .raw also work |
| Download | From https://repository.frostyard.org/ext/readd/, signature required (Verify=true), into /var/lib/extensions.d/ |
Each build checks the commands, the units, the sysusers file, the lodge app manifest and web page, and the preset, activation drop-in and extension-release files. A build that is missing one fails. Each build also checks that every upheld unit has no Condition*= line, or is a oneshot that stays active.
See also
Section titled “See also”- System extension catalog
- Manage system extensions
- lodge
- frostread
- Frostnotes notesd
- Frostmail maild
- Porter porterd
Sources
Section titled “Sources”Reviewed 2026-10-29. snosi commit
e423112908540aa3a8045fa9d8022a3742e3cd17;
core commit
cd2720e0c55d08f3ba8f28a3b55dd5796a5c425a;
frostread v0.2.0 commit
50dc179169a385714ecde0c9a45ae2046ba0295d;
Updex v2.1.3 commit
2661e987faac986f2594d1d9bbbadf1bf3053f5b.
mkosi.images/readd/mkosi.confmkosi.images/readd/mkosi.postinst.chrootmkosi.images/readd/required-paths.txtmkosi.images/readd/mkosi.extra/usr/lib/systemd/system-preset/40-readd.presetmkosi.images/readd/mkosi.extra/usr/lib/systemd/system/multi-user.target.d/10-readd.confmkosi.images/readd/mkosi.extra/usr/lib/extension-release.d/extension-release.readdmkosi.images/base/mkosi.extra/usr/lib/sysupdate.readd.d/readd.featuremkosi.images/base/mkosi.extra/usr/lib/sysupdate.readd.d/readd.transfershared/download/sysext-checksums.jsondocs/design/sysexts.md- snosi#1173 (merged 2026-10-28, merge commit
0ede646cd878f82e91b891d9c3f6eba77227573b) and snosi#1175 (merged 2026-10-28, merge commite423112908540aa3a8045fa9d8022a3742e3cd17) - core
docs/adr/0058-ship-suite-desktop-apps-as-flatpaks-and-services-as-sysexts.md - frostread
packaging/lodge/frostread.service,packaging/lodge/frostread.socket,packaging/lodge/sysusers.d-frostread.conf,cmd/readctl/main.go - frostread
README.md(Update and Roll back),docs/design/overview.md(Backup),internal/store/store.go(the schema refusal) - lodge
docs/specs/lodge-http.md(lodgectl reloadrereads the manifests),internal/apps/apps.go(PollEvery, 15 seconds) - Irulan’s review (frostyard-org#58)
- Updex v2.1.3
cmd/updex/features.go(features updaterefreshes the merge unless--no-refresh) - snosi
docs/adr/0024-verify-attestations-of-first-party-sysext-debs.md(attestation checked at pin time and in every CI build) - Murbella’s review (frostyard-org#57)
- Updex v2.1.3
README.md(accounts and paths: a live refresh runssystemd-sysusersandsystemd-tmpfiles --create; a link on an older image shows an update, andfeatures updaterepoints it) - Updex
docs/adr/0019-apply-merged-sysusers-and-tmpfiles-on-a-live-refresh.md(Updex does not restart units; a unit at its start limit stays failed untilsystemctl reset-failedor a reboot) - Updex v2.1.3
updex/features.go(activation did not finish: the images are merged, and a reboot finishes the activation) - Updex v2.1.3 release
- lodge#41 (merged 2026-10-28)
- lodge
docs/specs/app-contract.md(each app’ssysusers.dentry declares userlodge, with the line in lodge’s ownpackaging/sysusers.d/lodge.conf) - lab
docs/plans/2026-10-28-snow-sysext-probe-run.md(runjvzfn: with Updex v2.1.3 a unit can still fail in the enable boot) and lab#164 (merged 2026-10-28) src/data/extensions.json