refactor hosts/common/home to use sane.programs API

This commit is contained in:
2023-04-24 07:22:33 +00:00
parent 337fb9e9d9
commit 1f2c9a9a5e
17 changed files with 103 additions and 98 deletions

View File

@@ -3,8 +3,8 @@
imports = [ imports = [
./aerc.nix ./aerc.nix
./firefox.nix ./firefox.nix
./gfeeds.nix
./git.nix ./git.nix
./gnome-feeds.nix
./gpodder.nix ./gpodder.nix
./keyring.nix ./keyring.nix
./kitty ./kitty

View File

@@ -4,7 +4,7 @@ let
mkCfg = lib.generators.toINI { }; mkCfg = lib.generators.toINI { };
in in
{ {
sane.user.fs.".config/git/config" = sane-lib.fs.wantedText (mkCfg { sane.programs.git.fs.".config/git/config" = sane-lib.fs.wantedText (mkCfg {
user.name = "Colin"; user.name = "Colin";
user.email = "colin@uninsane.org"; user.email = "colin@uninsane.org";
alias.co = "checkout"; alias.co = "checkout";

View File

@@ -6,7 +6,7 @@ let
all-feeds = config.sane.feeds; all-feeds = config.sane.feeds;
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds; wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
in { in {
sane.user.fs.".config/org.gabmus.gfeeds.json" = sane-lib.fs.wantedText ( sane.programs.gnome-feeds.fs.".config/org.gabmus.gfeeds.json" = sane-lib.fs.wantedText (
builtins.toJSON { builtins.toJSON {
# feed format is a map from URL to a dict, # feed format is a map from URL to a dict,
# with dict["tags"] a list of string tags. # with dict["tags"] a list of string tags.

View File

@@ -6,7 +6,7 @@ let
all-feeds = config.sane.feeds; all-feeds = config.sane.feeds;
wanted-feeds = feeds.filterByFormat ["podcast"] all-feeds; wanted-feeds = feeds.filterByFormat ["podcast"] all-feeds;
in { in {
sane.user.fs.".config/gpodderFeeds.opml" = sane-lib.fs.wantedText ( sane.programs.gpodder.fs.".config/gpodderFeeds.opml" = sane-lib.fs.wantedText (
feeds.feedsToOpml wanted-feeds feeds.feedsToOpml wanted-feeds
); );
} }

View File

@@ -1,7 +1,7 @@
{ pkgs, sane-lib, ... }: { pkgs, sane-lib, ... }:
{ {
sane.user.fs.".config/kitty/kitty.conf" = sane-lib.fs.wantedText '' sane.programs.kitty.fs.".config/kitty/kitty.conf" = sane-lib.fs.wantedText ''
# docs: https://sw.kovidgoyal.net/kitty/conf/ # docs: https://sw.kovidgoyal.net/kitty/conf/
# disable terminal bell (when e.g. you backspace too many times) # disable terminal bell (when e.g. you backspace too many times)
enable_audio_bell no enable_audio_bell no

View File

@@ -2,7 +2,7 @@
{ {
# libreoffice: disable first-run stuff # libreoffice: disable first-run stuff
sane.user.fs.".config/libreoffice/4/user/registrymodifications.xcu" = sane-lib.fs.wantedText '' sane.programs.libreoffice-fresh.fs.".config/libreoffice/4/user/registrymodifications.xcu" = sane-lib.fs.wantedText ''
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<oor:items xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <oor:items xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<item oor:path="/org.openoffice.Office.Common/Misc"><prop oor:name="FirstRun" oor:op="fuse"><value>false</value></prop></item> <item oor:path="/org.openoffice.Office.Common/Misc"><prop oor:name="FirstRun" oor:op="fuse"><value>false</value></prop></item>

View File

@@ -1,10 +1,13 @@
{ sane-lib, ... }: { sane-lib, ... }:
{ {
# format is <key>=%<length>%<value> sane.programs.mpv = {
sane.user.fs.".config/mpv/mpv.conf" = sane-lib.fs.wantedText '' persist.plaintext = [ ".config/mpv/watch_later" ];
save-position-on-quit=%3%yes # format is <key>=%<length>%<value>
keep-open=%3%yes fs.".config/mpv/mpv.conf" = sane-lib.fs.wantedText ''
''; save-position-on-quit=%3%yes
keep-open=%3%yes
'';
};
} }

View File

@@ -1,8 +1,8 @@
{ lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
inherit (builtins) map; inherit (builtins) map;
inherit (lib) concatMapStrings optionalString; inherit (lib) concatMapStrings mkIf optionalString;
# this structure roughly mirrors home-manager's `programs.neovim.plugins` option # this structure roughly mirrors home-manager's `programs.neovim.plugins` option
plugins = with pkgs.vimPlugins; [ plugins = with pkgs.vimPlugins; [
# docs: surround-nvim: https://github.com/ur4ltz/surround.nvim/ # docs: surround-nvim: https://github.com/ur4ltz/surround.nvim/
@@ -72,9 +72,9 @@ let
in in
{ {
# private because there could be sensitive things in the swap # private because there could be sensitive things in the swap
sane.user.persist.private = [ ".cache/vim-swap" ]; sane.programs.neovim.persist.private = [ ".cache/vim-swap" ];
programs.neovim = { programs.neovim = mkIf config.sane.programs.neovim.enabled {
# neovim: https://github.com/neovim/neovim # neovim: https://github.com/neovim/neovim
enable = true; enable = true;
viAlias = true; viAlias = true;

View File

@@ -6,7 +6,10 @@ let
all-feeds = config.sane.feeds; all-feeds = config.sane.feeds;
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds; wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
in { in {
sane.user.fs.".config/newsflashFeeds.opml" = sane-lib.fs.wantedText ( sane.programs.newsflash = {
feeds.feedsToOpml wanted-feeds persist.plaintext = [ ".local/share/news-flash" ];
); fs.".config/newsflashFeeds.opml" = sane-lib.fs.wantedText (
feeds.feedsToOpml wanted-feeds
);
};
} }

View File

@@ -12,6 +12,6 @@
sopsFile = ../../../secrets/universal/offlineimaprc.bin; sopsFile = ../../../secrets/universal/offlineimaprc.bin;
format = "binary"; format = "binary";
}; };
sane.user.fs.".config/offlineimap/config" = sane-lib.fs.wantedSymlinkTo config.sops.secrets.offlineimaprc.path; sane.programs.offlineimap.fs.".config/offlineimap/config" = sane-lib.fs.wantedSymlinkTo config.sops.secrets.offlineimaprc.path;
} }

View File

@@ -3,7 +3,7 @@
# .ignore file is read by ripgrep (rg), silver searcher (ag), maybe others. # .ignore file is read by ripgrep (rg), silver searcher (ag), maybe others.
# ignore translation files by default when searching, as they tend to have # ignore translation files by default when searching, as they tend to have
# a LOT of duplicate text. # a LOT of duplicate text.
sane.user.fs.".ignore" = sane-lib.fs.wantedText '' sane.programs.ripgrep.fs.".ignore" = sane-lib.fs.wantedText ''
po/ po/
''; '';
} }

View File

@@ -4,17 +4,19 @@
{ pkgs, sane-lib, ... }: { pkgs, sane-lib, ... }:
{ {
sane.user.persist.plaintext = [ ".local/state/splatmoji" ]; sane.programs.splatmoji = {
sane.user.fs.".config/splatmoji/splatmoji.config" = sane-lib.fs.wantedText '' persist.plaintext = [ ".local/state/splatmoji" ];
# XXX doesn't seem to understand ~ as shorthand for `$HOME` fs.".config/splatmoji/splatmoji.config" = sane-lib.fs.wantedText ''
history_file=/home/colin/.local/state/splatmoji/history # XXX doesn't seem to understand ~ as shorthand for `$HOME`
history_length=5 history_file=/home/colin/.local/state/splatmoji/history
# TODO: wayland equiv history_length=5
paste_command=xdotool key ctrl+v # TODO: wayland equiv
# rofi_command=${pkgs.wofi}/bin/wofi --dmenu --insensitive --cache-file /dev/null paste_command=xdotool key ctrl+v
rofi_command=${pkgs.fuzzel}/bin/fuzzel -d -i -w 60 # rofi_command=${pkgs.wofi}/bin/wofi --dmenu --insensitive --cache-file /dev/null
xdotool_command=${pkgs.wtype}/bin/wtype rofi_command=${pkgs.fuzzel}/bin/fuzzel -d -i -w 60
# TODO: wayland equiv xdotool_command=${pkgs.wtype}/bin/wtype
xsel_command=xsel -b -i # TODO: wayland equiv
''; xsel_command=xsel -b -i
'';
};
} }

View File

@@ -1,11 +1,20 @@
{ config, sane-lib, ... }: { config, pkgs, sane-lib, ... }:
{ {
# TODO: this should only be shipped on gui platforms
sops.secrets."sublime_music_config" = { sops.secrets."sublime_music_config" = {
owner = config.users.users.colin.name; owner = config.users.users.colin.name;
sopsFile = ../../../secrets/universal/sublime_music_config.json.bin; sopsFile = ../../../secrets/universal/sublime_music_config.json.bin;
format = "binary"; format = "binary";
}; };
sane.user.fs.".config/sublime-music/config.json" = sane-lib.fs.wantedSymlinkTo config.sops.secrets.sublime_music_config.path; sane.programs.sublime-music = {
package = pkgs.sublime-music-mobile;
# sublime music persists any downloaded albums here.
# 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" ];
fs.".config/sublime-music/config.json" = sane-lib.fs.wantedSymlinkTo
config.sops.secrets.sublime_music_config.path;
};
} }

View File

@@ -9,12 +9,16 @@ let
); );
in in
{ {
sane.user.fs.".config/vlc/vlcrc" = sane-lib.fs.wantedText '' sane.programs.vlc = {
[podcast] # vlc remembers play position in ~/.config/vlc/vlc-qt-interface.conf
podcast-urls=${podcast-urls} persist.plaintext = [ ".config/vlc" ];
[core] fs.".config/vlc/vlcrc" = sane-lib.fs.wantedText ''
metadata-network-access=0 [podcast]
[qt] podcast-urls=${podcast-urls}
qt-privacy-ask=0 [core]
''; metadata-network-access=0
[qt]
qt-privacy-ask=0
'';
};
} }

View File

@@ -111,6 +111,7 @@ let
lshw lshw
ffmpeg ffmpeg
memtester memtester
neovim
# nettools # nettools
# networkmanager # networkmanager
nixpkgs-review nixpkgs-review
@@ -148,15 +149,15 @@ let
emote emote
evince # works on phosh evince # works on phosh
# { pkg = fluffychat-moby; dir = [ ".local/share/chat.fluffy.fluffychat" ]; } # TODO: ship normal fluffychat on non-moby? # { pkg = fluffychat-moby; persist.plaintext = [ ".local/share/chat.fluffy.fluffychat" ]; } # TODO: ship normal fluffychat on non-moby?
# foliate # e-book reader # foliate # e-book reader
# XXX by default fractal stores its state in ~/.local/share/<UUID>. # XXX by default fractal stores its state in ~/.local/share/<UUID>.
# after logging in, manually change ~/.local/share/keyrings/... to point it to some predictable subdir. # after logging in, manually change ~/.local/share/keyrings/... to point it to some predictable subdir.
# then reboot (so that libsecret daemon re-loads the keyring...?) # then reboot (so that libsecret daemon re-loads the keyring...?)
# { pkg = fractal-latest; private = [ ".local/share/fractal" ]; } # { pkg = fractal-latest; persist.private = [ ".local/share/fractal" ]; }
# { pkg = fractal-next; private = [ ".local/share/fractal" ]; } # { pkg = fractal-next; persist.private = [ ".local/share/fractal" ]; }
# "gnome.cheese" # "gnome.cheese"
"gnome.dconf-editor" "gnome.dconf-editor"
@@ -181,12 +182,7 @@ let
playerctl playerctl
# "libsForQt5.plasmatube" # Youtube player # "libsForQt5.plasmatube" # Youtube player
soundconverter soundconverter
# sublime music persists any downloaded albums here. sublime-music
# 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)
# { pkg = sublime-music; dir = [ ".local/share/sublime-music" ]; }
sublime-music-mobile
# tdesktop # broken on phosh # tdesktop # broken on phosh
# tokodon # tokodon
vlc vlc
@@ -308,75 +304,65 @@ in
ghostscriptSupport = true; ghostscriptSupport = true;
}; };
dino.private = [ ".local/share/dino" ]; dino.persist.private = [ ".local/share/dino" ];
# creds, but also 200 MB of node modules, etc # creds, but also 200 MB of node modules, etc
discord.private = [ ".config/discord" ]; discord.persist.private = [ ".config/discord" ];
# creds/session keys, etc # creds/session keys, etc
element-desktop.private = [ ".config/Element" ]; element-desktop.persist.private = [ ".config/Element" ];
# `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.dir = [ ".local/share/Emote" ]; emote.persist.plaintext = [ ".local/share/Emote" ];
# 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.private = [ ".config/gh" ]; gh.persist.private = [ ".config/gh" ];
# 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.
gpodder-configured.dir = [ "gPodder" ]; gpodder-configured.persist.plaintext = [ "gPodder" ];
# 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.
jellyfin-media-player.dir = [ ".local/share/Jellyfin Media Player" ]; jellyfin-media-player.persist.plaintext = [ ".local/share/Jellyfin Media Player" ];
# 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.dir = [ ".bitmonero" ]; monero-gui.persist.plaintext = [ ".bitmonero" ];
mpv.dir = [ ".config/mpv/watch_later" ]; mumble.persist.private = [ ".local/share/Mumble" ];
mumble.private = [ ".local/share/Mumble" ];
# not strictly necessary, but allows caching articles; offline use, etc. # not strictly necessary, but allows caching articles; offline use, etc.
newsflash.dir = [ ".local/share/news-flash" ]; nheko.persist.private = [
nheko.private = [
".config/nheko" # config file (including client token) ".config/nheko" # config file (including client token)
".cache/nheko" # media cache ".cache/nheko" # media cache
".local/share/nheko" # per-account state database ".local/share/nheko" # per-account state database
]; ];
# settings (electron app) # settings (electron app)
obsidian.dir = [ ".config/obsidian" ]; obsidian.persist.plaintext = [ ".config/obsidian" ];
# creds, media # creds, media
signal-desktop.private = [ ".config/Signal" ]; signal-desktop.persist.private = [ ".config/Signal" ];
# printer/filament settings # printer/filament settings
slic3r.dir = [ ".Slic3r" ]; slic3r.persist.plaintext = [ ".Slic3r" ];
# creds, widevine .so download. TODO: could easily manage these statically. # creds, widevine .so download. TODO: could easily manage these statically.
spotify.dir = [ ".config/spotify" ]; spotify.persist.plaintext = [ ".config/spotify" ];
steam.dir = [ steam.persist.plaintext = [
".steam" ".steam"
".local/share/Steam" ".local/share/Steam"
]; ];
# sublime music persists any downloaded albums here. tdesktop.persist.private = [ ".local/share/TelegramDesktop" ];
# 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)
# { pkg = sublime-music; dir = [ ".local/share/sublime-music" ]; }
sublime-music-mobile.dir = [ ".local/share/sublime-music" ];
tdesktop.private = [ ".local/share/TelegramDesktop" ]; tokodon.persist.private = [ ".cache/KDE/tokodon" ];
tokodon.private = [ ".cache/KDE/tokodon" ];
# hardenedMalloc solves a crash at startup # hardenedMalloc solves a crash at startup
# TODO 2023/02/02: is this safe to remove yet? # TODO 2023/02/02: is this safe to remove yet?
@@ -384,15 +370,12 @@ in
useHardenedMalloc = false; useHardenedMalloc = false;
}; };
# vlc remembers play position in ~/.config/vlc/vlc-qt-interface.conf whalebird.persist.private = [ ".config/Whalebird" ];
vlc.dir = [ ".config/vlc" ];
whalebird.private = [ ".config/Whalebird" ]; yarn.persist.plaintext = [ ".cache/yarn" ];
yarn.dir = [ ".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.private = [ ".zcash" ]; zecwallet-lite.persist.private = [ ".zcash" ];
} }
]; ];

View File

@@ -126,6 +126,7 @@ in
package = null; package = null;
suggestedPrograms = [ suggestedPrograms = [
"guiApps" "guiApps"
"splatmoji" # used by us, but 'enabling' it gets us persistence & cfg
"swaylock" "swaylock"
"swayidle" "swayidle"
"wl-clipboard" "wl-clipboard"

View File

@@ -77,15 +77,17 @@ let
type = types.bool; type = types.bool;
default = true; default = true;
}; };
dir = mkOption { persist = {
type = types.listOf types.str; plaintext = mkOption {
default = []; type = types.listOf types.str;
description = "list of home-relative paths to persist for this package"; default = [];
}; description = "list of home-relative paths to persist for this package";
private = mkOption { };
type = types.listOf types.str; private = mkOption {
default = []; type = types.listOf types.str;
description = "list of home-relative paths to persist (in encrypted format) for this package"; default = [];
description = "list of home-relative paths to persist (in encrypted format) for this package";
};
}; };
fs = mkOption { fs = mkOption {
type = types.attrs; type = types.attrs;
@@ -118,9 +120,7 @@ let
# conditionally persist relevant user dirs and create files # conditionally persist relevant user dirs and create files
sane.users = mapAttrs (user: en: optionalAttrs en { sane.users = mapAttrs (user: en: optionalAttrs en {
persist.plaintext = p.dir; inherit (p) fs persist;
persist.private = p.private;
fs = p.fs;
}) p.enableFor.user; }) p.enableFor.user;
}) cfg; }) cfg;
in in