persistence: move stores behind a byStore attr to support disabling persistence altogether (for e.g. rescue image)

This commit is contained in:
Colin 2023-11-08 15:32:50 +00:00
parent 7c5f5bd604
commit 28d4a4b065
78 changed files with 134 additions and 135 deletions

View File

@ -36,7 +36,7 @@
};
sane.fs."/mnt/persist/ext".mount = {};
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: this is overly broad; only need media and share directories to be persisted
{ user = "colin"; group = "users"; path = "/var/lib/uninsane"; }
];

View File

@ -12,7 +12,7 @@ in
# > AttributeError: 'NoneType' object has no attribute 'query'
lib.mkIf false
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ inherit user group; mode = "0700"; path = svc-dir; }
];

View File

@ -44,7 +44,7 @@ in
# everything configured below was fine: used ejabberd for several months.
lib.mkIf false
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "ejabberd"; group = "ejabberd"; path = "/var/lib/ejabberd"; }
];
sane.ports.ports = lib.mkMerge ([

View File

@ -18,7 +18,7 @@ let
};
in
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode? could be more granular
{ user = "opendkim"; group = "opendkim"; path = "/var/lib/opendkim"; }
{ user = "root"; group = "root"; path = "/var/lib/postfix"; }

View File

@ -15,7 +15,7 @@
owner = config.users.users.freshrss.name;
mode = "0400";
};
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "freshrss"; group = "freshrss"; path = "/var/lib/freshrss"; }
];

View File

@ -2,7 +2,7 @@
{ config, pkgs, lib, ... }:
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode? could be more granular
{ user = "git"; group = "gitea"; path = "/var/lib/gitea"; }
];

View File

@ -10,7 +10,7 @@
lib.mkIf false # i don't actively use ipfs anymore
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode? could be more granular
{ user = "261"; group = "261"; path = "/var/lib/ipfs"; }
];

View File

@ -1,7 +1,7 @@
{ ... }:
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode? we only need this to save Indexer creds ==> migrate to config?
{ user = "root"; group = "root"; path = "/var/lib/jackett"; }
];

View File

@ -40,7 +40,7 @@
description = "colin-jellyfin-https-lan";
};
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin"; }
];
sane.fs."/var/lib/jellyfin/config/logging.json" = {

View File

@ -4,7 +4,7 @@ let
inherit (svc-cfg) user group port stateDir;
in
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ inherit user group; mode = "0700"; path = stateDir; }
];

View File

@ -20,7 +20,7 @@
./signal.nix
];
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "matrix-synapse"; group = "matrix-synapse"; path = "/var/lib/matrix-synapse"; }
];
services.matrix-synapse.enable = true;

View File

@ -5,7 +5,7 @@
# - recommended to use mautrix-discord: <https://github.com/NixOS/nixpkgs/pull/200462>
lib.mkIf false
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "matrix-synapse"; group = "matrix-synapse"; path = "/var/lib/mx-puppet-discord"; }
];

View File

@ -101,7 +101,7 @@ in
})
];
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode?
{ user = "matrix-appservice-irc"; group = "matrix-appservice-irc"; path = "/var/lib/matrix-appservice-irc"; }
];

View File

@ -2,7 +2,7 @@
# - <https://github.com/mautrix/signal/blob/master/mautrix_signal/example-config.yaml>
{ config, pkgs, ... }:
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "mautrix-signal"; group = "mautrix-signal"; path = "/var/lib/mautrix-signal"; }
{ user = "signald"; group = "signald"; path = "/var/lib/signald"; }
];

View File

@ -1,7 +1,7 @@
{ lib, ... }:
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "navidrome"; group = "navidrome"; path = "/var/lib/navidrome"; }
];
services.navidrome.enable = true;

View File

@ -134,7 +134,7 @@ in
security.acme.acceptTerms = true;
security.acme.defaults.email = "admin.acme@uninsane.org";
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode?
{ user = "acme"; group = "acme"; path = "/var/lib/acme"; }
{ user = "colin"; group = "users"; path = "/var/www/sites"; }

View File

@ -30,7 +30,7 @@ let
altPort = 2587;
in
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# not 100% necessary to persist this, but ntfy does keep a 12hr (by default) cache
# for pushing notifications to users who become offline.
# ACLs also live here.

View File

@ -5,7 +5,7 @@ let
cfg = config.services.pict-rs;
in
{
sane.persist.sys.plaintext = lib.mkIf cfg.enable [
sane.persist.sys.byStore.plaintext = lib.mkIf cfg.enable [
{ user = "pict-rs"; group = "pict-rs"; path = cfg.dataDir; }
];

View File

@ -14,7 +14,7 @@ let
# logLevel = "debug";
in
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "pleroma"; group = "pleroma"; path = "/var/lib/pleroma"; }
];
services.pleroma.enable = true;

View File

@ -6,7 +6,7 @@ let
KiB = n: 1024*n;
in
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode?
{ user = "postgres"; group = "postgres"; path = "/var/lib/postgresql"; }
];

View File

@ -56,7 +56,7 @@ let
enableDebug = false;
in
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "prosody"; group = "prosody"; path = "/var/lib/prosody"; }
];
sane.ports.ports."5000" = {

View File

@ -1,7 +1,7 @@
{ config, pkgs, ... }:
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode? we need this specifically for the stats tracking in .config/
{ user = "transmission"; group = config.users.users.transmission.group; path = "/var/lib/transmission"; }
];

View File

@ -7,7 +7,7 @@ let
};
in
{
sane.user.persist.private = [ ".local/share/keyrings" ];
sane.user.persist.byStore.private = [ ".local/share/keyrings" ];
sane.user.fs."private/.local/share/keyrings/default" = {
generated.command = [ "${init-keyring}/bin/init-keyring" ];

View File

@ -13,7 +13,7 @@ let
in
{
# ssh key is stored in private storage
sane.user.persist.private = [
sane.user.persist.byStore.private = [
{ type = "file"; path = ".ssh/id_ed25519"; }
];
sane.user.fs.".ssh/id_ed25519.pub" = lib.mkIf (user-pubkey != null) {

View File

@ -5,12 +5,12 @@
# store /home/colin/a/b in /home/private/a/b instead of /home/private/home/colin/a/b
sane.persist.stores.private.prefix = "/home/colin";
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: these should be private.. somehow
"/var/log"
"/var/backup" # for e.g. postgres dumps
];
sane.persist.sys.cryptClearOnBoot = [
sane.persist.sys.byStore.cryptClearOnBoot = [
"/var/lib/systemd/coredump"
];
}

View File

@ -216,17 +216,17 @@ in
# INDIVIDUAL PACKAGE DEFINITIONS
cargo.persist.plaintext = [ ".cargo" ];
cargo.persist.byStore.plaintext = [ ".cargo" ];
# creds, but also 200 MB of node modules, etc
discord.persist.private = [ ".config/discord" ];
discord.persist.byStore.private = [ ".config/discord" ];
# `emote` will show a first-run dialog based on what's in this directory.
# mostly, it just keeps a LRU of previously-used emotes to optimize display order.
# TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
emote.persist.plaintext = [ ".local/share/Emote" ];
emote.persist.byStore.plaintext = [ ".local/share/Emote" ];
fluffychat-moby.persist.plaintext = [ ".local/share/chat.fluffy.fluffychat" ];
fluffychat-moby.persist.byStore.plaintext = [ ".local/share/chat.fluffy.fluffychat" ];
font-manager.package = pkgs.font-manager.override {
# build without the "Google Fonts" integration feature, to save closure / avoid webkitgtk_4_0
@ -235,40 +235,40 @@ in
# MS GitHub stores auth token in .config
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
gh.persist.private = [ ".config/gh" ];
gh.persist.byStore.private = [ ".config/gh" ];
"gnome.gnome-maps".persist.plaintext = [ ".cache/shumate" ];
"gnome.gnome-maps".persist.private = [ ".local/share/maps-places.json" ];
"gnome.gnome-maps".persist.byStore.plaintext = [ ".cache/shumate" ];
"gnome.gnome-maps".persist.byStore.private = [ ".local/share/maps-places.json" ];
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
monero-gui.persist.plaintext = [ ".bitmonero" ];
monero-gui.persist.byStore.plaintext = [ ".bitmonero" ];
mumble.persist.private = [ ".local/share/Mumble" ];
mumble.persist.byStore.private = [ ".local/share/Mumble" ];
# settings (electron app)
obsidian.persist.plaintext = [ ".config/obsidian" ];
obsidian.persist.byStore.plaintext = [ ".config/obsidian" ];
python3-repl.package = pkgs.python3.withPackages (ps: with ps; [
requests
]);
# creds, media
signal-desktop.persist.private = [ ".config/Signal" ];
signal-desktop.persist.byStore.private = [ ".config/Signal" ];
# printer/filament settings
slic3r.persist.plaintext = [ ".Slic3r" ];
slic3r.persist.byStore.plaintext = [ ".Slic3r" ];
tdesktop.persist.private = [ ".local/share/TelegramDesktop" ];
tdesktop.persist.byStore.private = [ ".local/share/TelegramDesktop" ];
tokodon.persist.private = [ ".cache/KDE/tokodon" ];
tokodon.persist.byStore.private = [ ".cache/KDE/tokodon" ];
whalebird.persist.private = [ ".config/Whalebird" ];
whalebird.persist.byStore.private = [ ".config/Whalebird" ];
yarn.persist.plaintext = [ ".cache/yarn" ];
yarn.persist.byStore.plaintext = [ ".cache/yarn" ];
# zcash coins. safe to delete, just slow to regenerate (10-60 minutes)
zecwallet-lite.persist.private = [ ".zcash" ];
zecwallet-lite.persist.byStore.private = [ ".zcash" ];
};
programs.feedbackd = lib.mkIf config.sane.programs.feedbackd.enabled {

View File

@ -1,7 +1,7 @@
{ ... }:
{
sane.programs.brave = {
persist.cryptClearOnBoot = [
persist.byStore.cryptClearOnBoot = [
".cache/BraveSoftware"
".config/BraveSoftware"
];

View File

@ -30,7 +30,7 @@ in
};
};
persist.private = [
persist.byStore.private = [
# ".cache/folks" # contact avatars?
# ".config/calls"
".local/share/calls" # call "records"

View File

@ -4,7 +4,7 @@
{ ... }:
{
sane.programs.cantata = {
persist.plaintext = [
persist.byStore.plaintext = [
".cache/cantata" # album art
".local/share/cantata/library" # library index (?)
];

View File

@ -36,7 +36,7 @@ in
# package = chattyNoOauth;
package = chatty-latest;
suggestedPrograms = [ "gnome-keyring" ];
persist.private = [
persist.byStore.private = [
".local/share/chatty" # matrix avatars and files
# not just XMPP; without this Chatty will regenerate its device-id every boot.
# .purple/ contains XMPP *and* Matrix auth, logs, avatar cache, and a bit more

View File

@ -3,7 +3,7 @@
{
sane.programs.cozy = {
# cozy uses a sqlite db for its config and exposes no CLI options other than --help and --debug
persist.plaintext = [
persist.byStore.plaintext = [
".local/share/cozy" # sqlite db (config & index?)
".cache/cozy" # offline cache
];

View File

@ -45,7 +45,7 @@ in
};
};
persist.private = [ ".local/share/dino" ];
persist.byStore.private = [ ".local/share/dino" ];
services.dino = {
description = "auto-start and maintain dino XMPP connection";

View File

@ -8,7 +8,7 @@
{
sane.programs.element-desktop = {
# creds/session keys, etc
persist.private = [ ".config/Element" ];
persist.byStore.private = [ ".config/Element" ];
suggestedPrograms = [ "gnome-keyring" ];
};

View File

@ -29,7 +29,7 @@
);
'' + (upstream.preFixup or "");
});
persist.private = [
persist.byStore.private = [
".cache/epiphany"
".local/share/epiphany"
# also .config/epiphany, but appears empty

View File

@ -34,7 +34,7 @@
sane.programs.flare-signal = {
package = pkgs.flare-signal-nixified;
# package = pkgs.flare-signal;
persist.private = [
persist.byStore.private = [
# everything: conf, state, files, all opaque
".local/share/flare"
# also persists a secret in ~/.local/share/keyrings. reset with:

View File

@ -37,7 +37,7 @@ in
};
};
persist.private = [
persist.byStore.private = [
# XXX by default fractal stores its state in ~/.local/share/<build-profile>/<UUID>.
".local/share/hack" # for debug-like builds
".local/share/stable" # for normal releases

View File

@ -8,7 +8,7 @@
{ ... }:
{
sane.programs.g4music = {
persist.plaintext = [
persist.byStore.plaintext = [
# index?
".cache/com.github.neithern.g4music"
];

View File

@ -1,7 +1,7 @@
{ ... }:
{
sane.programs.gajim = {
persist.private = [
persist.byStore.private = [
# avatars, thumbnails...
".cache/gajim"
# sqlite database labeled "settings". definitely includes UI theming

View File

@ -6,7 +6,7 @@
{ ... }:
{
sane.programs."gnome.geary" = {
persist.private = [
persist.byStore.private = [
# attachments, and email -- contained in a sqlite db
".local/share/geary"
# also `.cache/geary/web-resources`, which tends to stay << 1 MiB

View File

@ -3,7 +3,7 @@
{ ... }:
{
sane.programs.gnome-weather = {
persist.plaintext = [
persist.byStore.plaintext = [
".cache/libgweather"
];
};

View File

@ -24,6 +24,6 @@ in {
# XXX: we preserve the whole thing because if we only preserve gPodder/Downloads
# then startup is SLOW during feed import, and we might end up with zombie eps in the dl dir.
persist.plaintext = [ ".local/share/gPodder" ];
persist.byStore.plaintext = [ ".local/share/gPodder" ];
};
}

View File

@ -7,7 +7,7 @@
# grammars need to be persisted when developing them
# - `hx --grammar fetch` and `hx --grammar build`
# but otherwise, they ship as part of HELIX_RUNTIME, in the nix store
# persist.plaintext = [ ".config/helix/runtime/grammars" ];
# persist.byStore.plaintext = [ ".config/helix/runtime/grammars" ];
fs.".config/helix/config.toml".symlink.text = ''
# docs: <https://docs.helix-editor.com/configuration.html>
[editor.soft-wrap]

View File

@ -10,6 +10,6 @@
# jellyfin stores things in a bunch of directories: this one persists auth info.
# it *might* be possible to populate this externally (it's Qt stuff), but likely to
# be fragile and take an hour+ to figure out.
persist.plaintext = [ ".local/share/Jellyfin Media Player" ];
persist.byStore.plaintext = [ ".local/share/Jellyfin Media Player" ];
};
}

View File

@ -3,6 +3,6 @@
sane.programs.komikku = {
secrets.".local/share/komikku/keyrings/plaintext.keyring" = ../../../secrets/common/komikku_accounts.json.bin;
# downloads end up here, and without the toplevel database komikku doesn't know they exist.
persist.plaintext = [ ".local/share/komikku" ];
persist.byStore.plaintext = [ ".local/share/komikku" ];
};
}

View File

@ -44,6 +44,6 @@ in {
# history, cache, dictionaries...
# could be more explicit if i symlinked the history.lua file to somewhere it can persist better.
persist.plaintext = [ ".config/koreader" ];
persist.byStore.plaintext = [ ".config/koreader" ];
};
}

View File

@ -2,6 +2,6 @@
{
sane.programs.lemoa = {
# creds
persist.private = [ ".local/share/io.github.lemmygtk.lemoa" ];
persist.byStore.private = [ ".local/share/io.github.lemmygtk.lemoa" ];
};
}

View File

@ -4,9 +4,9 @@
{
sane.programs.mepo = {
persist.plaintext = [ ".cache/mepo/tiles" ];
persist.byStore.plaintext = [ ".cache/mepo/tiles" ];
# ~/.cache/mepo/savestate has precise coordinates and pins: keep those private
persist.private = [
persist.byStore.private = [
{ type = "file"; path = ".cache/mepo/savestate"; }
];

View File

@ -42,10 +42,10 @@ in
# mopidy-moped: <https://github.com/martijnboland/moped>
# mopidy-muse: <https://github.com/cristianpb/muse>
]);
persist.plaintext = [
persist.byStore.plaintext = [
".local/share/mopidy/local" # thumbs, library db
];
persist.private = [
persist.byStore.private = [
".local/share/mopidy/http" # cookie
];
secrets.".config/mopidy/mopidy.conf" = ../../../secrets/common/mopidy.conf.bin;

View File

@ -53,7 +53,7 @@ in
"--add-flags" "--vo=${cfg.config.vo}"
];
};
persist.plaintext = [ ".local/state/mpv/watch_later" ];
persist.byStore.plaintext = [ ".local/state/mpv/watch_later" ];
fs.".config/mpv/input.conf".symlink.text = ''
# let volume/power keys be interpreted by the system.
# this is important for sxmo.

View File

@ -87,7 +87,7 @@ in
{
# private because there could be sensitive things in the swap
sane.programs.neovim = {
persist.private = [ ".cache/vim-swap" ];
persist.byStore.private = [ ".cache/vim-swap" ];
env.EDITOR = "vim";
# git claims it should use EDITOR, but it doesn't!
env.GIT_EDITOR = "vim";

View File

@ -7,7 +7,7 @@ let
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
in {
sane.programs.newsflash = {
persist.plaintext = [ ".local/share/news-flash" ];
persist.byStore.plaintext = [ ".local/share/news-flash" ];
fs.".config/newsflashFeeds.opml".symlink.text =
feeds.feedsToOpml wanted-feeds
;

View File

@ -1,9 +1,11 @@
{ ... }:
{
# not strictly necessary, but allows caching articles; offline use, etc.
sane.programs.nheko.persist.private = [
".config/nheko" # config file (including client token)
".cache/nheko" # media cache
".local/share/nheko" # per-account state database
];
sane.programs.nheko = {
# not strictly necessary, but allows caching articles; offline use, etc.
persist.byStore.private = [
".config/nheko" # config file (including client token)
".cache/nheko" # media cache
".local/share/nheko" # per-account state database
];
};
}

View File

@ -2,6 +2,6 @@
{
# provides `nix-locate`, backed by the manually run `nix-index`
sane.programs.nix-index = {
persist.plaintext = [ ".cache/nix-index" ];
persist.byStore.plaintext = [ ".cache/nix-index" ];
};
}

View File

@ -1,7 +1,7 @@
{ ... }:
{
sane.programs.rhythmbox = {
persist.plaintext = [
persist.byStore.plaintext = [
# playlists; index
".local/share/rhythmbox"
# album art

View File

@ -23,6 +23,6 @@ in {
'';
# this is where the parsed feed items go
persist.plaintext = [ ".sfeed/feeds" ];
persist.byStore.plaintext = [ ".sfeed/feeds" ];
};
}

View File

@ -5,7 +5,7 @@
{
sane.programs.splatmoji = {
persist.plaintext = [ ".local/state/splatmoji" ];
persist.byStore.plaintext = [ ".local/state/splatmoji" ];
fs.".config/splatmoji/splatmoji.config".symlink.text = ''
# XXX doesn't seem to understand ~ as shorthand for `$HOME`
history_file=/home/colin/.local/state/splatmoji/history

View File

@ -1,11 +1,11 @@
{ ... }:
{
sane.programs.spotify = {
persist.plaintext = [
persist.byStore.plaintext = [
# probably just songs and such (haven't checked)
".cache/spotify"
];
persist.private = [
persist.byStore.private = [
# creds, widevine .so download. TODO: could easily manage these statically.
".config/spotify"
];

View File

@ -1,7 +1,7 @@
{ config, lib, ...}:
{
sane.programs.steam = {
persist.plaintext = [
persist.byStore.plaintext = [
".steam"
".local/share/Steam"
];

View File

@ -16,7 +16,7 @@
{ ... }:
{
sane.programs.stepmania = {
persist.plaintext = [
persist.byStore.plaintext = [
".stepmania-5.1/Cache" #< otherwise gotta index all the songs every launch
".stepmania-5.1/Save"
];

View File

@ -7,7 +7,7 @@
# it doesn't obey a conventional ~/Music/{Artist}/{Album}/{Track} notation, so no symlinking
# config (e.g. server connection details) is persisted in ~/.config/sublime-music/config.json
# possible to pass config as a CLI arg (sublime-music -c config.json)
persist.plaintext = [ ".local/share/sublime-music" ];
persist.byStore.plaintext = [ ".local/share/sublime-music" ];
secrets.".config/sublime-music/config.json" = ../../../secrets/common/sublime_music_config.json.bin;
};

View File

@ -27,7 +27,7 @@ in
'' + (upstream.preFixup or "");
});
persist.private = [
persist.byStore.private = [
".cache/Tangram"
".local/share/Tangram"
# dconf achieves atomic writes via `mv`, so a symlink doesn't work

View File

@ -6,7 +6,7 @@
# - still required as of 2023/07/14
useHardenedMalloc = false;
};
persist.cryptClearOnBoot = [
persist.byStore.cryptClearOnBoot = [
".local/share/tor-browser"
];
};

View File

@ -10,7 +10,7 @@ let
in
{
sane.programs.vlc = {
persist.private = [
persist.byStore.private = [
# vlc remembers play position in ~/.config/vlc/vlc-qt-interface.conf
# filenames are stored in plaintext (unlike mpv, which i think hashes them)
".config/vlc"

View File

@ -15,7 +15,7 @@ in {
sane.programs.zeal = {
# package = pkgs.zeal-qt6; #< TODO: upgrade system to qt6 versions of everything (i.e. jellyfin-media-player, nheko)
package = pkgs.zeal-qt5;
persist.plaintext = [
persist.byStore.plaintext = [
".cache/Zeal"
".local/share/Zeal"
];

View File

@ -53,7 +53,7 @@ in
config = mkMerge [
({
sane.programs.zsh = {
persist.private = [
persist.byStore.private = [
# we don't need to full zsh dir -- just the history file --
# but zsh will sometimes backup the history file and symlinking just the file messes things up
".local/share/zsh"

View File

@ -42,8 +42,9 @@
# - <https://github.com/lourkeur/distro/blob/11173454c6bb50f7ccab28cc2c757dca21446d1d/nixos/profiles/users/louis-full.nix>
# - <https://github.com/dnr/sample-nix-code/blob/03494480c1fae550c033aa54fd96aeb3827761c5/nixos/laptop.nix>
pamMount = let
hasPrivate = config.fileSystems ? "/home/colin/private";
priv = config.fileSystems."/home/colin/private";
in {
in lib.mkIf hasPrivate {
fstype = priv.fsType;
path = priv.device;
mountpoint = priv.mountPoint;
@ -56,7 +57,7 @@
sane.users.colin = {
default = true;
persist.plaintext = [
persist.byStore.plaintext = [
"archive"
"dev"
# TODO: records should be private

View File

@ -25,7 +25,7 @@ in
sane.users.guest.fs.".ssh/authorized_keys".symlink.target = config.sops.secrets."guest/authorized_keys".path or "/dev/null";
sane.persist.sys.plaintext = lib.mkIf cfg.enable [
sane.persist.sys.byStore.plaintext = lib.mkIf cfg.enable [
# intentionally allow other users to write to the guest folder
{ path = "/home/guest"; user = "guest"; group = "users"; mode = "0775"; }
];

View File

@ -1,6 +1,6 @@
{ ... }:
{
sane.persist.sys.cryptClearOnBoot = [
sane.persist.sys.byStore.cryptClearOnBoot = [
# when running commands as root, some things may create ~/.cache entries.
# notably:
# - `/root/.cache/nix/` takes up ~10 MB on lappy/desko/servo

View File

@ -132,7 +132,7 @@
];
};
sane.persist.sys.plaintext = lib.mkIf config.sane.programs.guiApps.enabled [
sane.persist.sys.byStore.plaintext = lib.mkIf config.sane.programs.guiApps.enabled [
"/var/lib/alsa" # preserve output levels, default devices
"/var/lib/colord" # preserve color calibrations (?)
"/var/lib/systemd/backlight" # backlight brightness

View File

@ -119,7 +119,7 @@ in
# persisting fontconfig & mesa_shader_cache improves start time by ~5x
users.users.greeter.home = "/var/lib/greeter";
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "greeter"; group = "greeter"; path = "/var/lib/greeter/.cache/fontconfig"; }
{ user = "greeter"; group = "greeter"; path = "/var/lib/greeter/.cache/mesa_shader_cache"; }
];

View File

@ -236,7 +236,7 @@ in
# XXX(2023/10/12): rtkit does not play well on moby. any application sending audio out dies after 10s.
# security.rtkit.enable = true;
# persist per-device volume levels
sane.user.persist.plaintext = [ ".local/state/wireplumber" ];
sane.user.persist.byStore.plaintext = [ ".local/state/wireplumber" ];
# persist per-device volume settings across power cycles.
# pipewire sits atop the kernel ALSA API, so alsa-utils knows about device volumes.
@ -252,7 +252,7 @@ in
# ExecStop = "${pkgs.alsa-utils}/sbin/alsactl store --ignore";
# };
# };
# sane.persist.sys.plaintext = [ "/var/lib/alsa" ];
# sane.persist.sys.byStore.plaintext = [ "/var/lib/alsa" ];
networking.useDHCP = false;
networking.networkmanager.enable = true;

View File

@ -261,7 +261,7 @@ in
# "superd" # make superctl (used by sxmo) be on PATH
];
persist.cryptClearOnBoot = [
persist.byStore.cryptClearOnBoot = [
# builds to be 10's of MB per day
# ".local/state/superd/logs"
];
@ -550,7 +550,7 @@ in
}
(lib.mkIf (cfg.greeter == "lightdm-mobile") {
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# this takes up 4-5 MB of fontconfig and mesa shader caches.
# it could optionally be cleared on boot.
{ path = "/var/lib/lightdm"; user = "lightdm"; group = "lightdm"; mode = "0770"; }

View File

@ -73,7 +73,7 @@ in
# TODO: configure without compression (leverage fs-level compression), and enable file-clone (i.e. hardlinks)
programs.ccache.enable = true;
nix.settings.extra-sandbox-paths = [ cacheDir ];
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ group = "nixbld"; mode = "0775"; path = config.programs.ccache.cacheDir; }
];
sane.fs."${cacheDir}/ccache.conf" = sane-lib.fs.wantedText ''

View File

@ -10,7 +10,7 @@ in
{
config = lib.mkIf config.sane.roles.client {
# persist external pairings by default
sane.persist.sys.plaintext = [ "/var/lib/bluetooth" ];
sane.persist.sys.byStore.plaintext = [ "/var/lib/bluetooth" ];
sane.fs."/var/lib/bluetooth".generated.acl.mode = "0700";
sane.fs."/var/lib/bluetooth/.secrets.stamp" = {

View File

@ -15,7 +15,7 @@ in
config = mkIf cfg.enable {
# we need this mostly because of the size of duplicity's cache
sane.persist.sys.cryptClearOnBoot = [{
sane.persist.sys.byStore.cryptClearOnBoot = [{
path = "/var/lib/duplicity";
user = "root";
group = "root";

View File

@ -128,35 +128,28 @@ let
}
];
# this submodule creates one attr per store, so that the user can specify something like:
# <option>.private.".cache/vim" = { mode = "0700"; };
# to place ".cache/vim" into the private store and create with the appropriate mode
# this submodule converts store-based access to path-based access so that the user can specify e.g.:
# <top>.byStore.private = [ ".cache/vim" ];
# <top>.byStore.private = [ { path=".cache/vim"; mode = "0700"; } ];
# to place ".cache/vim" into the private store and/or create with the appropriate mode
entrySubmodule = types.submodule ({ config, ... }: {
# TODO: this should be a plain-old `attrsOf (convertInlineAcl entryInStoreOrShorthand)` with downstream checks,
# rather than being filled in based on *other* settings.
# otherwise, it behaves poorly when `sane.persist.enable = false`
options = lib.attrsets.unionOfDisjoint
# create one option per store:
(mapAttrs (store: store-cfg: mkOption {
default = [];
type = types.listOf (convertInlineAcl entryInStoreOrShorthand);
description = let
suffix = if store-cfg.storeDescription != null then
": ${store-cfg.storeDescription}"
else "";
in "directories/files to persist in ${store}${suffix}";
}) cfg.stores)
# or allow direct access by path
{
byPath = mkOption {
type = types.attrsOf (convertInlineAcl entryAtPath);
default = {};
description = ''
map of <path> => <path config> for all paths to be persisted.
this is computed from the other options, but users can also set it explicitly (useful for overriding)
'';
};
options = {
byStore = mkOption {
type = types.attrsOf (types.listOf (convertInlineAcl entryInStoreOrShorthand));
default = {};
description = ''
directories/files to persist within a specific store (e.g. "plaintext" or "private").
'';
};
byPath = mkOption {
type = types.attrsOf (convertInlineAcl entryAtPath);
default = {};
description = ''
map of <path> => <path config> for all paths to be persisted.
this is computed from the other options, but users can also set it explicitly (useful for overriding)
'';
};
};
config = let
# set the `store` attribute on one dir attrset
annotateWithStore = store: dir: {
@ -168,13 +161,16 @@ let
};
store-names = attrNames cfg.stores;
# :: (store -> entry -> AttrSet) -> [AttrSet]
# applyToAllStores = f: lib.concatMap
# (store: map (f store) config.byStore."${store}")
# store-names;
applyToAllStores = f: lib.concatMap
(store: map (f store) config."${store}")
store-names;
(store: map (f store) config.byStore."${store}")
(builtins.attrNames config.byStore);
in {
byPath = lib.mkMerge (concatLists [
# convert the list-style per-store entries into attrsOf entries
(applyToAllStores (store: dirToAttrs))
(applyToAllStores (_store: dirToAttrs))
# add the `store` attr to everything we ingested
(applyToAllStores annotateWithStore)
]);

View File

@ -22,7 +22,7 @@ in
"networkmanager" # required to authenticate with mmcli
];
};
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "eg25-control"; group = "eg25-control"; path = "/var/lib/eg25-control"; }
];

View File

@ -69,7 +69,7 @@ in
# prefer specifying it via environment.etc since although it is generated per-host,
# it's made to be immutable after generation. hence, a `persist`-style mount wouldn't be as great.
environment.etc."ssh/host_keys".source = "/nix/persist/etc/ssh/host_keys";
# sane.persist.sys.plaintext = [ "/etc/ssh/host_keys" ];
# sane.persist.sys.byStore.plaintext = [ "/etc/ssh/host_keys" ];
# let openssh find our host keys
services.openssh.hostKeys = [