Frostnotes notesd
The notesd extension adds notesd, the Frostnotes notes daemon, to a Frostyard bootc image. It runs as lodge’s Notes app, with the app id notes. A server that runs the suite’s services runs Floe. On a desktop, install the Frostnotes Flatpak instead. 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/notesd/. - Free space in
/varfor the image.
notesd has no published test results on Frostyard images yet. Try it on a machine you can spare first.
You reach Notes in a browser through lodge. Enable lodge first. The notesd extension declares no dependency on lodge, so enabling notesd does not enable lodge.
Enable notesd
Section titled “Enable notesd”See what Updex found, then enable the feature and download it now:
updex features list --component=notesdsudo updex features enable notesd --nownotesd 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.
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 frostnotes-lodge.socket frostnotes.servicesudo systemctl start frostnotes-lodge.socket frostnotes.serviceCheck the merge and the units:
systemd-sysext statussystemctl status frostnotes-lodge.socket frostnotes.servicesudo -u frostnotes notesctl --socket /run/frostnotes/notesd.sock vault listsystemd-sysext status lists notesd, systemctl status shows both units
active, and vault list lists the vaults and prints no error.
If a unit shows failed with start-limit-hit, systemd stopped starting it.
Run sudo systemctl reset-failed frostnotes-lodge.socket frostnotes.service, then
sudo systemctl start frostnotes-lodge.socket frostnotes.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”frostnotes-lodge.socket and frostnotes.service run on the host.
The drop-in /usr/lib/systemd/system/multi-user.target.d/10-notesd.conf has
Upholds= for both units, and the preset
/usr/lib/systemd/system-preset/40-notesd.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.notesd sets EXTENSION_RELOAD_MANAGER=1, so a merge or
refresh reloads systemd’s unit files.
frostnotes.service runs /usr/bin/notesd -lodge as the system user
frostnotes, with its data in /var/lib/frostnotes. The vault work, which is
file watching, rescans, and version pruning, runs from boot, whether lodge runs
or not. notesctl reaches notesd on the private socket
/run/frostnotes/notesd.sock.
frostnotes-lodge.socket listens on /run/lodge/apps/notes.sock as owner
frostnotes, group lodge, mode 0660. Only lodge’s group can open it.
The sysusers file /usr/lib/sysusers.d/frostnotes.conf creates the user
frostnotes, the group lodge, and the group lodge-apps, with frostnotes
in lodge-apps. 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 the
daemon and the socket start without lodge’s extension.
The lodge app files are in /usr/share/lodge/apps/notes/: app.json and
web/. The commands are /usr/bin/notesd and /usr/bin/notesctl.
Update, roll back, and remove
Section titled “Update, roll back, and remove”Before you update, back up the data directory /var/lib/frostnotes and each
vault directory.
Check for an update, then install it:
updex features check --component=notesdsudo updex features update --component=notesdBy 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 notesd 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 notesd, then let lodge read the new manifest:
sudo systemctl restart frostnotes-lodge.socket frostnotes.servicesudo lodgectl reloadCheck the version that runs:
sudo -u frostnotes notesctl --socket /run/frostnotes/notesd.sock hellosudo lodgectl appshello prints notesd <version> (protocol N) with the new version. lodgectl apps
lists notes up, with the new version. lodge polls each app every 15 seconds,
so if notes shows down at once, run lodgectl apps again after 15 seconds.
Roll back to the previous version:
sudo updex features rollback notesdThe rollback takes effect at the next boot. To apply it now, add --now, then
restart notesd as above. See Roll back.
notesd refuses a database that a newer notesd migrated, and a rollback does not undo a migration. notesd 0.3.0 adds no migration to 0.2.0, so a rollback from 0.3.0 to 0.2.0 needs no restore.
When the older version runs, read the journal:
journalctl -u frostnotes.service -n 50If it shows database schema N is newer than this notesd, go forward again.
The rollback holds back the newer version, so clear the hold first:
sudo updex features rollback --clear notesdsudo updex features update --component=notesdThe update links the newer version again without a new download. Then restart notesd and check its version as above.
Remove notesd:
sudo updex features disable notesd --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-notesd, 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 | Notes (Frostnotes notes daemon and Lodge notes app) |
| Commands | /usr/bin/notesd and /usr/bin/notesctl |
| Service | frostnotes.service, which runs /usr/bin/notesd -lodge as the system user frostnotes |
| Socket | frostnotes-lodge.socket on /run/lodge/apps/notes.sock, owner frostnotes, group lodge, mode 0660 |
| Private socket | /run/frostnotes/notesd.sock, for notesctl |
| Data | /var/lib/frostnotes |
| User and group | frostnotes, group lodge, frostnotes in group lodge-apps, and the user lodge, from /usr/lib/sysusers.d/frostnotes.conf |
| Lodge app | /usr/share/lodge/apps/notes/, with app.json and web/ |
| Activation | /usr/lib/systemd/system/multi-user.target.d/10-notesd.conf with Upholds=, and /usr/lib/systemd/system-preset/40-notesd.preset |
| Version | The image file name carries the frostyard-notesd package version, which is the app’s release version |
| Image file | notesd_<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/notesd/, 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
- Frostnotes
- The hub behind lodge: how the hub runs in lodge, and how devices move to it.
- Notes in lodge: the app contract with lodge.
Sources
Section titled “Sources”Reviewed 2026-10-29. snosi commit
e423112908540aa3a8045fa9d8022a3742e3cd17;
core commit
cd2720e0c55d08f3ba8f28a3b55dd5796a5c425a;
Frostnotes v0.3.0 commit
2d80734337b90f497c5b6f0c7e87038d2bc96b20;
Updex v2.1.3 commit
2661e987faac986f2594d1d9bbbadf1bf3053f5b.
mkosi.images/notesd/mkosi.confmkosi.images/notesd/mkosi.postinst.chrootmkosi.images/notesd/required-paths.txtmkosi.images/notesd/mkosi.extra/usr/lib/systemd/system-preset/40-notesd.presetmkosi.images/notesd/mkosi.extra/usr/lib/systemd/system/multi-user.target.d/10-notesd.confmkosi.images/notesd/mkosi.extra/usr/lib/extension-release.d/extension-release.notesdmkosi.images/base/mkosi.extra/usr/lib/sysupdate.notesd.d/notesd.featuremkosi.images/base/mkosi.extra/usr/lib/sysupdate.notesd.d/notesd.transfershared/download/sysext-checksums.jsondocs/design/sysexts.md- snosi#1169 (merged 2026-10-28), snosi#1173 (merged 2026-10-28) and snosi#1175 (merged 2026-10-28)
- core
docs/adr/0058-ship-suite-desktop-apps-as-flatpaks-and-services-as-sysexts.mdanddocs/adr/0063-uphold-notesds-service-as-well-as-its-socket.md - Frostnotes
packaging/systemd/frostnotes.service,packaging/systemd/frostnotes-lodge.socket,packaging/sysusers.d/frostnotes.conf,cmd/notesctl/root.go - 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; a rollback records the newer version as rejected, andfeatures updatelinks nothing at or below it untilfeatures rollback --clear) - 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)
- 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: before the packages declared the userlodge, a unit failed in the enable boot) and lab#164 (merged 2026-10-28) - lab run
dev-snow-bootc-lifecycle-9f8w4(2026-10-28, labmainat4250354, with the settle window of lab#166; not yet recorded in the lab repository): with notesd 0.3.0 and maild 0.3.0 and Updex v2.1.3, the userlodgeexists in the enable boot, andfrostnotes-lodge.socket,frostmail.socket,frostnotes.serviceandfrostmail.servicestay active with no restart; the reboot boot matches - 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
docs/specs/lodge-http.md(lodgectl reloadrereads the manifests),internal/apps/apps.go(PollEvery, 15 seconds) - Frostnotes
internal/store/store.go(the schema refusal),docs/design/sync.md(back up the vault and data directories),cmd/notesd/main.goandcmd/notesctl/hello.go(hellonamesnotesd <version>) src/data/extensions.json