Skip to content

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.

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 /var for 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.

See what Updex found, then enable the feature and download it now:

Terminal window
updex features list --component=readd
sudo updex features enable readd --now

readd 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:

Terminal window
sudo systemd-sysusers
sudo systemd-tmpfiles --create
sudo systemctl reset-failed frostread.socket frostread.service
sudo systemctl start frostread.socket frostread.service

Check the units and the feeds:

Terminal window
systemctl status frostread.socket frostread.service
sudo -u frostread readctl sources

systemctl 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.

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/.

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:

Terminal window
sudo systemctl mask --now frostread.socket frostread.service
sudo 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.service
sudo systemctl start frostread.socket frostread.service

tar exits 0, and systemctl status frostread.socket frostread.service shows both units active again.

Check for an update, then install it:

Terminal window
updex features check --component=readd
sudo updex features update --component=readd

By 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.

Terminal window
sudo systemd-sysusers
sudo systemd-tmpfiles --create
sudo systemctl daemon-reload

To run the new version now, restart frostread, then let lodge read the new manifest:

Terminal window
sudo systemctl restart frostread.socket frostread.service
sudo lodgectl reload

Check the version that runs:

Terminal window
sudo -u frostread readctl status
sudo lodgectl apps

readctl 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:

Terminal window
sudo updex features rollback readd

The 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:

Terminal window
journalctl -u frostread.service -n 50

If 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:

Terminal window
sudo systemctl mask --now frostread.socket frostread.service
sudo rm -rf /var/lib/frostread
sudo tar -xzpf ARCHIVE -C / var/lib/frostread
sudo systemctl unmask frostread.socket frostread.service
sudo systemctl start frostread.socket frostread.service

The restore loses what changed after the backup: new items, reads, and saves.

Remove readd:

Terminal window
sudo updex features disable readd --now --force

Updex 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.

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.

Reviewed 2026-10-29. snosi commit e423112908540aa3a8045fa9d8022a3742e3cd17; core commit cd2720e0c55d08f3ba8f28a3b55dd5796a5c425a; frostread v0.2.0 commit 50dc179169a385714ecde0c9a45ae2046ba0295d; Updex v2.1.3 commit 2661e987faac986f2594d1d9bbbadf1bf3053f5b.