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

This commit is contained in:
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.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 # TODO: this is overly broad; only need media and share directories to be persisted
{ user = "colin"; group = "users"; path = "/var/lib/uninsane"; } { user = "colin"; group = "users"; path = "/var/lib/uninsane"; }
]; ];

View File

@@ -12,7 +12,7 @@ in
# > AttributeError: 'NoneType' object has no attribute 'query' # > AttributeError: 'NoneType' object has no attribute 'query'
lib.mkIf false lib.mkIf false
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.byStore.plaintext = [
{ inherit user group; mode = "0700"; path = svc-dir; } { 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. # everything configured below was fine: used ejabberd for several months.
lib.mkIf false lib.mkIf false
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.byStore.plaintext = [
{ user = "ejabberd"; group = "ejabberd"; path = "/var/lib/ejabberd"; } { user = "ejabberd"; group = "ejabberd"; path = "/var/lib/ejabberd"; }
]; ];
sane.ports.ports = lib.mkMerge ([ sane.ports.ports = lib.mkMerge ([

View File

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

View File

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

View File

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

View File

@@ -10,7 +10,7 @@
lib.mkIf false # i don't actively use ipfs anymore 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 # TODO: mode? could be more granular
{ user = "261"; group = "261"; path = "/var/lib/ipfs"; } { 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? # TODO: mode? we only need this to save Indexer creds ==> migrate to config?
{ user = "root"; group = "root"; path = "/var/lib/jackett"; } { user = "root"; group = "root"; path = "/var/lib/jackett"; }
]; ];

View File

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

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
# - recommended to use mautrix-discord: <https://github.com/NixOS/nixpkgs/pull/200462> # - recommended to use mautrix-discord: <https://github.com/NixOS/nixpkgs/pull/200462>
lib.mkIf false lib.mkIf false
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.byStore.plaintext = [
{ user = "matrix-synapse"; group = "matrix-synapse"; path = "/var/lib/mx-puppet-discord"; } { 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? # TODO: mode?
{ user = "matrix-appservice-irc"; group = "matrix-appservice-irc"; path = "/var/lib/matrix-appservice-irc"; } { 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> # - <https://github.com/mautrix/signal/blob/master/mautrix_signal/example-config.yaml>
{ config, pkgs, ... }: { config, pkgs, ... }:
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.byStore.plaintext = [
{ user = "mautrix-signal"; group = "mautrix-signal"; path = "/var/lib/mautrix-signal"; } { user = "mautrix-signal"; group = "mautrix-signal"; path = "/var/lib/mautrix-signal"; }
{ user = "signald"; group = "signald"; path = "/var/lib/signald"; } { user = "signald"; group = "signald"; path = "/var/lib/signald"; }
]; ];

View File

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

View File

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

View File

@@ -30,7 +30,7 @@ let
altPort = 2587; altPort = 2587;
in 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 # not 100% necessary to persist this, but ntfy does keep a 12hr (by default) cache
# for pushing notifications to users who become offline. # for pushing notifications to users who become offline.
# ACLs also live here. # ACLs also live here.

View File

@@ -5,7 +5,7 @@ let
cfg = config.services.pict-rs; cfg = config.services.pict-rs;
in 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; } { user = "pict-rs"; group = "pict-rs"; path = cfg.dataDir; }
]; ];

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -13,7 +13,7 @@ let
in in
{ {
# ssh key is stored in private storage # ssh key is stored in private storage
sane.user.persist.private = [ sane.user.persist.byStore.private = [
{ type = "file"; path = ".ssh/id_ed25519"; } { type = "file"; path = ".ssh/id_ed25519"; }
]; ];
sane.user.fs.".ssh/id_ed25519.pub" = lib.mkIf (user-pubkey != null) { 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 # 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.stores.private.prefix = "/home/colin";
sane.persist.sys.plaintext = [ sane.persist.sys.byStore.plaintext = [
# TODO: these should be private.. somehow # TODO: these should be private.. somehow
"/var/log" "/var/log"
"/var/backup" # for e.g. postgres dumps "/var/backup" # for e.g. postgres dumps
]; ];
sane.persist.sys.cryptClearOnBoot = [ sane.persist.sys.byStore.cryptClearOnBoot = [
"/var/lib/systemd/coredump" "/var/lib/systemd/coredump"
]; ];
} }

View File

@@ -216,17 +216,17 @@ in
# INDIVIDUAL PACKAGE DEFINITIONS # INDIVIDUAL PACKAGE DEFINITIONS
cargo.persist.plaintext = [ ".cargo" ]; cargo.persist.byStore.plaintext = [ ".cargo" ];
# creds, but also 200 MB of node modules, etc # 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. # `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. # 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. # 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 { font-manager.package = pkgs.font-manager.override {
# build without the "Google Fonts" integration feature, to save closure / avoid webkitgtk_4_0 # 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 # 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 # 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.byStore.plaintext = [ ".cache/shumate" ];
"gnome.gnome-maps".persist.private = [ ".local/share/maps-places.json" ]; "gnome.gnome-maps".persist.byStore.private = [ ".local/share/maps-places.json" ];
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate) # 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? # 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) # settings (electron app)
obsidian.persist.plaintext = [ ".config/obsidian" ]; obsidian.persist.byStore.plaintext = [ ".config/obsidian" ];
python3-repl.package = pkgs.python3.withPackages (ps: with ps; [ python3-repl.package = pkgs.python3.withPackages (ps: with ps; [
requests requests
]); ]);
# creds, media # creds, media
signal-desktop.persist.private = [ ".config/Signal" ]; signal-desktop.persist.byStore.private = [ ".config/Signal" ];
# printer/filament settings # 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) # 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 { programs.feedbackd = lib.mkIf config.sane.programs.feedbackd.enabled {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -34,7 +34,7 @@
sane.programs.flare-signal = { sane.programs.flare-signal = {
package = pkgs.flare-signal-nixified; package = pkgs.flare-signal-nixified;
# package = pkgs.flare-signal; # package = pkgs.flare-signal;
persist.private = [ persist.byStore.private = [
# everything: conf, state, files, all opaque # everything: conf, state, files, all opaque
".local/share/flare" ".local/share/flare"
# also persists a secret in ~/.local/share/keyrings. reset with: # 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>. # XXX by default fractal stores its state in ~/.local/share/<build-profile>/<UUID>.
".local/share/hack" # for debug-like builds ".local/share/hack" # for debug-like builds
".local/share/stable" # for normal releases ".local/share/stable" # for normal releases

View File

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

View File

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

View File

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

View File

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

View File

@@ -24,6 +24,6 @@ in {
# XXX: we preserve the whole thing because if we only preserve gPodder/Downloads # 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. # 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 # grammars need to be persisted when developing them
# - `hx --grammar fetch` and `hx --grammar build` # - `hx --grammar fetch` and `hx --grammar build`
# but otherwise, they ship as part of HELIX_RUNTIME, in the nix store # 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 = '' fs.".config/helix/config.toml".symlink.text = ''
# docs: <https://docs.helix-editor.com/configuration.html> # docs: <https://docs.helix-editor.com/configuration.html>
[editor.soft-wrap] [editor.soft-wrap]

View File

@@ -10,6 +10,6 @@
# jellyfin stores things in a bunch of directories: this one persists auth info. # 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 # it *might* be possible to populate this externally (it's Qt stuff), but likely to
# be fragile and take an hour+ to figure out. # 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 = { sane.programs.komikku = {
secrets.".local/share/komikku/keyrings/plaintext.keyring" = ../../../secrets/common/komikku_accounts.json.bin; 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. # 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... # history, cache, dictionaries...
# could be more explicit if i symlinked the history.lua file to somewhere it can persist better. # 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 = { sane.programs.lemoa = {
# creds # 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 = { 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 # ~/.cache/mepo/savestate has precise coordinates and pins: keep those private
persist.private = [ persist.byStore.private = [
{ type = "file"; path = ".cache/mepo/savestate"; } { type = "file"; path = ".cache/mepo/savestate"; }
]; ];

View File

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

View File

@@ -53,7 +53,7 @@ in
"--add-flags" "--vo=${cfg.config.vo}" "--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 = '' fs.".config/mpv/input.conf".symlink.text = ''
# let volume/power keys be interpreted by the system. # let volume/power keys be interpreted by the system.
# this is important for sxmo. # this is important for sxmo.

View File

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

View File

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

View File

@@ -1,9 +1,11 @@
{ ... }: { ... }:
{ {
# not strictly necessary, but allows caching articles; offline use, etc. sane.programs.nheko = {
sane.programs.nheko.persist.private = [ # not strictly necessary, but allows caching articles; offline use, etc.
".config/nheko" # config file (including client token) persist.byStore.private = [
".cache/nheko" # media cache ".config/nheko" # config file (including client token)
".local/share/nheko" # per-account state database ".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` # provides `nix-locate`, backed by the manually run `nix-index`
sane.programs.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 = { sane.programs.rhythmbox = {
persist.plaintext = [ persist.byStore.plaintext = [
# playlists; index # playlists; index
".local/share/rhythmbox" ".local/share/rhythmbox"
# album art # album art

View File

@@ -23,6 +23,6 @@ in {
''; '';
# this is where the parsed feed items go # 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 = { sane.programs.splatmoji = {
persist.plaintext = [ ".local/state/splatmoji" ]; persist.byStore.plaintext = [ ".local/state/splatmoji" ];
fs.".config/splatmoji/splatmoji.config".symlink.text = '' fs.".config/splatmoji/splatmoji.config".symlink.text = ''
# XXX doesn't seem to understand ~ as shorthand for `$HOME` # XXX doesn't seem to understand ~ as shorthand for `$HOME`
history_file=/home/colin/.local/state/splatmoji/history history_file=/home/colin/.local/state/splatmoji/history

View File

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

View File

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

View File

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

View File

@@ -7,7 +7,7 @@
# it doesn't obey a conventional ~/Music/{Artist}/{Album}/{Track} notation, so no symlinking # 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 # 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) # 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; secrets.".config/sublime-music/config.json" = ../../../secrets/common/sublime_music_config.json.bin;
}; };

View File

@@ -27,7 +27,7 @@ in
'' + (upstream.preFixup or ""); '' + (upstream.preFixup or "");
}); });
persist.private = [ persist.byStore.private = [
".cache/Tangram" ".cache/Tangram"
".local/share/Tangram" ".local/share/Tangram"
# dconf achieves atomic writes via `mv`, so a symlink doesn't work # 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 # - still required as of 2023/07/14
useHardenedMalloc = false; useHardenedMalloc = false;
}; };
persist.cryptClearOnBoot = [ persist.byStore.cryptClearOnBoot = [
".local/share/tor-browser" ".local/share/tor-browser"
]; ];
}; };

View File

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

View File

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

View File

@@ -53,7 +53,7 @@ in
config = mkMerge [ config = mkMerge [
({ ({
sane.programs.zsh = { sane.programs.zsh = {
persist.private = [ persist.byStore.private = [
# we don't need to full zsh dir -- just the history file -- # 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 # but zsh will sometimes backup the history file and symlinking just the file messes things up
".local/share/zsh" ".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/lourkeur/distro/blob/11173454c6bb50f7ccab28cc2c757dca21446d1d/nixos/profiles/users/louis-full.nix>
# - <https://github.com/dnr/sample-nix-code/blob/03494480c1fae550c033aa54fd96aeb3827761c5/nixos/laptop.nix> # - <https://github.com/dnr/sample-nix-code/blob/03494480c1fae550c033aa54fd96aeb3827761c5/nixos/laptop.nix>
pamMount = let pamMount = let
hasPrivate = config.fileSystems ? "/home/colin/private";
priv = config.fileSystems."/home/colin/private"; priv = config.fileSystems."/home/colin/private";
in { in lib.mkIf hasPrivate {
fstype = priv.fsType; fstype = priv.fsType;
path = priv.device; path = priv.device;
mountpoint = priv.mountPoint; mountpoint = priv.mountPoint;
@@ -56,7 +57,7 @@
sane.users.colin = { sane.users.colin = {
default = true; default = true;
persist.plaintext = [ persist.byStore.plaintext = [
"archive" "archive"
"dev" "dev"
# TODO: records should be private # 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.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 # intentionally allow other users to write to the guest folder
{ path = "/home/guest"; user = "guest"; group = "users"; mode = "0775"; } { 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. # when running commands as root, some things may create ~/.cache entries.
# notably: # notably:
# - `/root/.cache/nix/` takes up ~10 MB on lappy/desko/servo # - `/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/alsa" # preserve output levels, default devices
"/var/lib/colord" # preserve color calibrations (?) "/var/lib/colord" # preserve color calibrations (?)
"/var/lib/systemd/backlight" # backlight brightness "/var/lib/systemd/backlight" # backlight brightness

View File

@@ -119,7 +119,7 @@ in
# persisting fontconfig & mesa_shader_cache improves start time by ~5x # persisting fontconfig & mesa_shader_cache improves start time by ~5x
users.users.greeter.home = "/var/lib/greeter"; 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/fontconfig"; }
{ user = "greeter"; group = "greeter"; path = "/var/lib/greeter/.cache/mesa_shader_cache"; } { 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. # XXX(2023/10/12): rtkit does not play well on moby. any application sending audio out dies after 10s.
# security.rtkit.enable = true; # security.rtkit.enable = true;
# persist per-device volume levels # 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. # persist per-device volume settings across power cycles.
# pipewire sits atop the kernel ALSA API, so alsa-utils knows about device volumes. # 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"; # 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.useDHCP = false;
networking.networkmanager.enable = true; networking.networkmanager.enable = true;

View File

@@ -261,7 +261,7 @@ in
# "superd" # make superctl (used by sxmo) be on PATH # "superd" # make superctl (used by sxmo) be on PATH
]; ];
persist.cryptClearOnBoot = [ persist.byStore.cryptClearOnBoot = [
# builds to be 10's of MB per day # builds to be 10's of MB per day
# ".local/state/superd/logs" # ".local/state/superd/logs"
]; ];
@@ -550,7 +550,7 @@ in
} }
(lib.mkIf (cfg.greeter == "lightdm-mobile") { (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. # this takes up 4-5 MB of fontconfig and mesa shader caches.
# it could optionally be cleared on boot. # it could optionally be cleared on boot.
{ path = "/var/lib/lightdm"; user = "lightdm"; group = "lightdm"; mode = "0770"; } { 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) # TODO: configure without compression (leverage fs-level compression), and enable file-clone (i.e. hardlinks)
programs.ccache.enable = true; programs.ccache.enable = true;
nix.settings.extra-sandbox-paths = [ cacheDir ]; nix.settings.extra-sandbox-paths = [ cacheDir ];
sane.persist.sys.plaintext = [ sane.persist.sys.byStore.plaintext = [
{ group = "nixbld"; mode = "0775"; path = config.programs.ccache.cacheDir; } { group = "nixbld"; mode = "0775"; path = config.programs.ccache.cacheDir; }
]; ];
sane.fs."${cacheDir}/ccache.conf" = sane-lib.fs.wantedText '' sane.fs."${cacheDir}/ccache.conf" = sane-lib.fs.wantedText ''

View File

@@ -10,7 +10,7 @@ in
{ {
config = lib.mkIf config.sane.roles.client { config = lib.mkIf config.sane.roles.client {
# persist external pairings by default # 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".generated.acl.mode = "0700";
sane.fs."/var/lib/bluetooth/.secrets.stamp" = { sane.fs."/var/lib/bluetooth/.secrets.stamp" = {

View File

@@ -15,7 +15,7 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
# we need this mostly because of the size of duplicity's cache # 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"; path = "/var/lib/duplicity";
user = "root"; user = "root";
group = "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: # this submodule converts store-based access to path-based access so that the user can specify e.g.:
# <option>.private.".cache/vim" = { mode = "0700"; }; # <top>.byStore.private = [ ".cache/vim" ];
# to place ".cache/vim" into the private store and create with the appropriate mode # <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, ... }: { entrySubmodule = types.submodule ({ config, ... }: {
# TODO: this should be a plain-old `attrsOf (convertInlineAcl entryInStoreOrShorthand)` with downstream checks, options = {
# rather than being filled in based on *other* settings. byStore = mkOption {
# otherwise, it behaves poorly when `sane.persist.enable = false` type = types.attrsOf (types.listOf (convertInlineAcl entryInStoreOrShorthand));
options = lib.attrsets.unionOfDisjoint default = {};
# create one option per store: description = ''
(mapAttrs (store: store-cfg: mkOption { directories/files to persist within a specific store (e.g. "plaintext" or "private").
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)
'';
};
}; };
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 config = let
# set the `store` attribute on one dir attrset # set the `store` attribute on one dir attrset
annotateWithStore = store: dir: { annotateWithStore = store: dir: {
@@ -168,13 +161,16 @@ let
}; };
store-names = attrNames cfg.stores; store-names = attrNames cfg.stores;
# :: (store -> entry -> AttrSet) -> [AttrSet] # :: (store -> entry -> AttrSet) -> [AttrSet]
# applyToAllStores = f: lib.concatMap
# (store: map (f store) config.byStore."${store}")
# store-names;
applyToAllStores = f: lib.concatMap applyToAllStores = f: lib.concatMap
(store: map (f store) config."${store}") (store: map (f store) config.byStore."${store}")
store-names; (builtins.attrNames config.byStore);
in { in {
byPath = lib.mkMerge (concatLists [ byPath = lib.mkMerge (concatLists [
# convert the list-style per-store entries into attrsOf entries # convert the list-style per-store entries into attrsOf entries
(applyToAllStores (store: dirToAttrs)) (applyToAllStores (_store: dirToAttrs))
# add the `store` attr to everything we ingested # add the `store` attr to everything we ingested
(applyToAllStores annotateWithStore) (applyToAllStores annotateWithStore)
]); ]);

View File

@@ -22,7 +22,7 @@ in
"networkmanager" # required to authenticate with mmcli "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"; } { 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, # 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. # 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"; 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 # let openssh find our host keys
services.openssh.hostKeys = [ services.openssh.hostKeys = [