Compare commits

..

1 Commits

Author SHA1 Message Date
8f9cef6ff3 WIP: sxmo: ship deps via package instead of at the DE level 2023-06-23 02:12:23 +00:00
245 changed files with 4101 additions and 17967 deletions

View File

@@ -16,8 +16,6 @@ directly here; even the sources for those packages is often kept here too.
[uninsane-org]: https://uninsane.org [uninsane-org]: https://uninsane.org
## Layout ## Layout
- `doc/`
- instructions for tasks i find myself doing semi-occasionally in this repo.
- `hosts/` - `hosts/`
- the bulk of config which isn't factored with external use in mind. - the bulk of config which isn't factored with external use in mind.
- that is, if you were to add this repo to a flake.nix for your own use, - that is, if you were to add this repo to a flake.nix for your own use,
@@ -39,7 +37,9 @@ directly here; even the sources for those packages is often kept here too.
- inline code for wholly custom packages (e.g. `pkgs/additional/sane-scripts/` for CLI tools - inline code for wholly custom packages (e.g. `pkgs/additional/sane-scripts/` for CLI tools
that are highly specific to my setup). that are highly specific to my setup).
- `scripts/` - `scripts/`
- scripts which aren't reachable on a deployed system, but may aid manual deployments - scripts which are referenced by other things in this repo.
- these aren't generally user-facing, but they're factored out so that they can
be invoked directly when i need to debug.
- `secrets/` - `secrets/`
- encrypted keys, API tokens, anything which one or more of my machines needs - encrypted keys, API tokens, anything which one or more of my machines needs
read access to but shouldn't be world-readable. read access to but shouldn't be world-readable.
@@ -106,6 +106,3 @@ this repo exists in a few known locations:
if you want to contact me for questions, or collaborate to split something useful into a shared repo, etc, if you want to contact me for questions, or collaborate to split something useful into a shared repo, etc,
you can reach me via any method listed [here](https://uninsane.org/about). you can reach me via any method listed [here](https://uninsane.org/about).
patches, for this repo or any other i host, will be warmly welcomed in any manner you see fit:
`git send-email`, DM'ing the patch over Matrix/Lemmy/ActivityPub/etc, even a literal PR where you
link me to your own clone.

50
TODO.md
View File

@@ -1,10 +1,8 @@
## BUGS ## BUGS
- why i need to manually restart `wireguard-wg-ovpns` on servo periodically - why i need to manually restart `wireguard-wg-ovpns` on servo periodically
- else DNS fails - else DNS fails
- fix epiphany URL bar input on moby
## REFACTORING: ## REFACTORING:
### sops/secrets ### sops/secrets
- attach secrets to the thing they're used by (sane.programs) - attach secrets to the thing they're used by (sane.programs)
- rework secrets to leverage `sane.fs` - rework secrets to leverage `sane.fs`
@@ -15,11 +13,14 @@
- will make it easier to test new services? - will make it easier to test new services?
### upstreaming ### upstreaming
- split out a sxmo module usable by NUR consumers - split out a trust-dns module
- see: <https://github.com/NixOS/nixpkgs/pull/205866#issuecomment-1575753054>
- bump nodejs version in lemmy-ui - bump nodejs version in lemmy-ui
- add updateScripts to all my packages in nixpkgs - add updateScripts to all my packages in nixpkgs
- fix lightdm-mobile-greeter for newer libhandy - fix lightdm-mobile-greeter for newer libhandy
- port zecwallet-lite to a from-source build - port zecwallet-lite to a from-source build
- fix or abandon Whalebird
- FIX failed CI on bonsai PR: <https://github.com/NixOS/nixpkgs/pull/233892>
- REVIEW/integrate jellyfin dataDir config: <https://github.com/NixOS/nixpkgs/pull/233617> - REVIEW/integrate jellyfin dataDir config: <https://github.com/NixOS/nixpkgs/pull/233617>
- remove `libsForQt5.callPackage` broadly: <https://github.com/NixOS/nixpkgs/issues/180841> - remove `libsForQt5.callPackage` broadly: <https://github.com/NixOS/nixpkgs/issues/180841>
@@ -32,50 +33,45 @@
- have `sane.programs` be wrapped such that they run in a cgroup? - have `sane.programs` be wrapped such that they run in a cgroup?
- at least, only give them access to the portion of the fs they *need*. - at least, only give them access to the portion of the fs they *need*.
- Android takes approach of giving each app its own user: could hack that in here. - Android takes approach of giving each app its own user: could hack that in here.
- **systemd-run** takes a command and runs it in a temporary scope (cgroup)
- presumably uses the same options as systemd services
- see e.g. <https://github.com/NixOS/nixpkgs/issues/113903#issuecomment-857296349>
- flatpak does this, somehow
- apparmor? SElinux? (desktop) "portals"?
- see Spectrum OS; Alyssa Ross; etc
- bubblewrap-based sandboxing: <https://github.com/nixpak/nixpak>
- canaries for important services - canaries for important services
- e.g. daily email checks; daily backup checks - e.g. daily email checks; daily backup checks
- integrate `nix check` into Gitea actions?
### user experience ### user experience
- neovim: set up language server (lsp; rnix-lsp; nvim-lspconfig) - firefox/librewolf: don't show browserpass/sponsorblock/metamask "first run" on every boot
- Helix: make copy-to-system clipboard be the default
- firefox/librewolf: persist history
- just not cookies or tabs
- moby: improve gPodder launch time - moby: improve gPodder launch time
- moby: theme GTK apps (i.e. non-adwaita styles) - moby: replace jellyfin-desktop with jellyfin-vue?
- especially, make the menubar collapsible - allows (maybe) to cache media for offline use
- try Gradience tool specifically for theming adwaita? <https://linuxphoneapps.org/apps/com.github.gradienceteam.gradience/> - "newer" jellyfin client
- not packaged for nix
- moby/sxmo: display numerical vol percentage in topbar
- moby/sxmo: include librewolf, jellyfin in `apps` menu
- find a nice desktop ActivityPub client
- package Nix/NixOS docs for Zeal - package Nix/NixOS docs for Zeal
- install [doc-browser](https://github.com/qwfy/doc-browser) - install [doc-browser](https://github.com/qwfy/doc-browser)
- this supports both dash (zeal) *and* the datasets from <https://devdocs.io> (which includes nix!) - this supports both dash (zeal) *and* the datasets from <https://devdocs.io> (which includes nix!)
- install [devhelp](https://wiki.gnome.org/Apps/Devhelp) (gnome) - install [devhelp](https://wiki.gnome.org/Apps/Devhelp) (gnome)
- auto-mount servo
- have xdg-open parse `<repo:...> URIs (or adjust them so that it _can_ parse) - have xdg-open parse `<repo:...> URIs (or adjust them so that it _can_ parse)
- `sane.programs`: auto-populate defaults with everything from `pkgs`
- zsh: disable "command not found" corrections
- sane-bt-search: show details like 5.1 vs stereo, h264 vs h265 - sane-bt-search: show details like 5.1 vs stereo, h264 vs h265
- uninsane.org: make URLs relative to allow local use (and as offline homepage)
- email: fix so that local mail doesn't go to junk
- git sendmail flow adds the DKIM signatures, but gets delivered locally w/o having the sig checked, so goes into Junk
- could change junk filter from "no DKIM success" to explicit "DKIM failed"
### perf ### perf
- add `pkgs.impure-cached.<foo>` package set to build things with ccache enabled
- every package here can be auto-generated, and marked with some env var so that it doesn't pollute the pure package set
- would be super handy for package prototyping!
- why does nixos-rebuild switch take 5 minutes when net is flakey? - why does nixos-rebuild switch take 5 minutes when net is flakey?
- trying to auto-mount servo? - trying to auto-mount servo?
- something to do with systemd services restarting/stalling - something to do with systemd services restarting/stalling
- maybe wireguard & its refresh operation, specifically? - maybe wireguard & its refresh operation, specifically?
- get moby to build without binfmt emulation (i.e. make all emulation explicit) - fix OOM for large builds like webkitgtk
- then i can distribute builds across servo + desko, and also allow servo to pull packages from desko w/o worrying about purity - these use significant /tmp space.
- either place /tmp on encrypted-cleared-at-boot storage
- which probably causes each CPU load for the encryption
- **or set up encrypted swap**
- encrypted swap could remove the need for my encrypted-cleared-at-boot stuff
## NEW FEATURES: ## NEW FEATURES:
- add a FTP-accessible file share to servo
- just /var/www?
- migrate MAME cabinet to nix - migrate MAME cabinet to nix
- boot it from PXE from servo? - boot it from PXE from servo?
- enable IPv6 - enable IPv6

View File

@@ -1,13 +0,0 @@
to ship `pkgs.foo` on some host, either:
- add it as an entry in `suggestedPrograms` to the appropriate category in `hosts/common/programs/assorted.nix`, or
- `sane.programs.foo.enableFor.user.colin = true` in `hosts/by-name/myhost/default.nix`
if the program needs customization (persistence, configs, secrets):
- add a file for it at `hosts/common/programs/<foo>.nix`
- set the options, `sane.programs.foo.{fs,persist}`
if it's unclear what fs paths a program uses:
- run one of these commands, launch the program, run it again, and `diff`:
- `du -x --apparent-size ~`
- `find ~ -xdev`
- or, inspect the whole tmpfs root with `ncdu -x /`

62
flake.lock generated
View File

@@ -1,15 +1,12 @@
{ {
"nodes": { "nodes": {
"flake-utils": { "flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": { "locked": {
"lastModified": 1687709756, "lastModified": 1678901627,
"narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=", "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7", "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -21,11 +18,11 @@
"mobile-nixos": { "mobile-nixos": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1690059310, "lastModified": 1683422260,
"narHash": "sha256-4zcoDp8wwZVfGSzXltC5x+eH4kDWC/eJpyQNgr7shAA=", "narHash": "sha256-79zaClbubRkBNlJ04OSADILuLQHH48N5fu296hEWYlw=",
"owner": "nixos", "owner": "nixos",
"repo": "mobile-nixos", "repo": "mobile-nixos",
"rev": "56fc9f9619f305f0865354975a98d22410eed127", "rev": "ba4638836e94a8f16d1d1f9e8c0530b86078029c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -39,11 +36,11 @@
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
}, },
"locked": { "locked": {
"lastModified": 1687251388, "lastModified": 1684319086,
"narHash": "sha256-E9cVlgeCvzPbA/G3mCDCzz8TdRwXyGYzIjmwcvIfghg=", "narHash": "sha256-5wwlkWqP1cQUPXp/PJsi09FkgAule5yBghngRZZbUQg=",
"owner": "edolstra", "owner": "edolstra",
"repo": "nix-serve", "repo": "nix-serve",
"rev": "d6df5bd8584f37e22cff627db2fc4058a4aab5ee", "rev": "e6e3d09438e803daa5374ad8edf1271289348456",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -69,11 +66,11 @@
}, },
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1690066826, "lastModified": 1687031877,
"narHash": "sha256-6L2qb+Zc0BFkh72OS9uuX637gniOjzU6qCDBpjB2LGY=", "narHash": "sha256-yMFcVeI+kZ6KD2QBrFPNsvBrLq2Gt//D0baHByMrjFY=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "ce45b591975d070044ca24e3003c830d26fea1c8", "rev": "e2e2059d19668dab1744301b8b0e821e3aae9c99",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -85,11 +82,11 @@
}, },
"nixpkgs-unpatched": { "nixpkgs-unpatched": {
"locked": { "locked": {
"lastModified": 1691006197, "lastModified": 1686960236,
"narHash": "sha256-DbtxVWPt+ZP5W0Usg7jAyTomIM//c3Jtfa59Ht7AV8s=", "narHash": "sha256-AYCC9rXNLpUWzD9hm+askOfpliLEC9kwAo7ITJc4HIw=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "66aedfd010204949cb225cf749be08cb13ce1813", "rev": "04af42f3b31dba0ef742d254456dc4c14eedac86",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -116,11 +113,11 @@
"nixpkgs-stable": "nixpkgs-stable" "nixpkgs-stable": "nixpkgs-stable"
}, },
"locked": { "locked": {
"lastModified": 1690199016, "lastModified": 1687058111,
"narHash": "sha256-yTLL72q6aqGmzHq+C3rDp3rIjno7EJZkFLof6Ika7cE=", "narHash": "sha256-xDSn/APfAdJinHV4reTfplX5XnLsJSGdVwHpmdgP9Mo=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "c36df4fe4bf4bb87759b1891cab21e7a05219500", "rev": "1634d2da53f079e7f5924efa7a96511cd9596f81",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -129,21 +126,6 @@
"type": "github" "type": "github"
} }
}, },
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"uninsane-dot-org": { "uninsane-dot-org": {
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
@@ -152,11 +134,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1691106178, "lastModified": 1686876043,
"narHash": "sha256-3mZ9gTvMpbZA9ea9ovoQpn2wKuQY0QZ7MDdEjArYdAQ=", "narHash": "sha256-71SNPU2aeeJx29JSeW4JCJb8HXAuZRvL7sbh+c3wgkk=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "f4d91aa201b6e49af690f250d4786bd1d8b4dcfd", "rev": "0e0aa12aca143639f158b3a5c0c00349fcc2166c",
"revCount": 205, "revCount": 199,
"type": "git", "type": "git",
"url": "https://git.uninsane.org/colin/uninsane" "url": "https://git.uninsane.org/colin/uninsane"
}, },

View File

@@ -23,6 +23,9 @@
# preferably, i would rewrite the human-readable https URLs to nix-specific github: URLs with a helper, # preferably, i would rewrite the human-readable https URLs to nix-specific github: URLs with a helper,
# but `inputs` is required to be a strict attrset: not an expression. # but `inputs` is required to be a strict attrset: not an expression.
inputs = { inputs = {
# <https://github.com/nixos/nixpkgs/tree/nixos-22.11>
# nixpkgs-stable.url = "github:nixos/nixpkgs?ref=nixos-22.11";
# branch workflow: # branch workflow:
# - daily: # - daily:
# - nixos-unstable cut from master after enough packages have been built in caches. # - nixos-unstable cut from master after enough packages have been built in caches.
@@ -94,17 +97,7 @@
evalHost = { name, local, target }: nixpkgs.lib.nixosSystem { evalHost = { name, local, target }: nixpkgs.lib.nixosSystem {
system = target; system = target;
modules = [ modules = [
{ (import ./hosts/instantiate.nix { localSystem = local; hostName = name; })
nixpkgs = (if (local != null) then {
buildPlatform = local;
} else {}) // {
# TODO: does the earlier `system` arg to nixosSystem make its way here?
hostPlatform.system = target;
};
# nixpkgs.buildPlatform = local; # set by instantiate.nix instead
# nixpkgs.config.replaceStdenv = { pkgs }: pkgs.ccacheStdenv;
}
(import ./hosts/instantiate.nix { hostName = name; })
self.nixosModules.default self.nixosModules.default
self.nixosModules.passthru self.nixosModules.passthru
{ {
@@ -113,6 +106,12 @@
self.overlays.sane-all self.overlays.sane-all
]; ];
} }
({ lib, ... }: {
# TODO: does the earlier `system` arg to nixosSystem make its way here?
nixpkgs.hostPlatform.system = target;
# nixpkgs.buildPlatform = local; # set by instantiate.nix instead
# nixpkgs.config.replaceStdenv = { pkgs }: pkgs.ccacheStdenv;
})
]; ];
}; };
in { in {
@@ -178,10 +177,15 @@
disable-flakey-tests = final: prev: import ./overlays/disable-flakey-tests.nix final prev; disable-flakey-tests = final: prev: import ./overlays/disable-flakey-tests.nix final prev;
pkgs = final: prev: import ./overlays/pkgs.nix final prev; pkgs = final: prev: import ./overlays/pkgs.nix final prev;
pins = final: prev: import ./overlays/pins.nix final prev; pins = final: prev: import ./overlays/pins.nix final prev;
preferences = final: prev: import ./overlays/preferences.nix final prev;
optimizations = final: prev: import ./overlays/optimizations.nix final prev; optimizations = final: prev: import ./overlays/optimizations.nix final prev;
passthru = final: prev: passthru = final: prev:
let let
stable =
if inputs ? "nixpkgs-stable" then (
final': prev': {
stable = inputs.nixpkgs-stable.legacyPackages."${prev'.stdenv.hostPlatform.system}";
}
) else (final': prev': {});
mobile = (import "${mobile-nixos}/overlay/overlay.nix"); mobile = (import "${mobile-nixos}/overlay/overlay.nix");
uninsane = uninsane-dot-org.overlay; uninsane = uninsane-dot-org.overlay;
# nix-serve' = nix-serve.overlay; # nix-serve' = nix-serve.overlay;
@@ -192,7 +196,8 @@
inherit (nix-serve.packages."${next.system}") nix-serve; inherit (nix-serve.packages."${next.system}") nix-serve;
}; };
in in
(mobile final prev) (stable final prev)
// (mobile final prev)
// (uninsane final prev) // (uninsane final prev)
// (nix-serve' final prev) // (nix-serve' final prev)
; ;
@@ -244,74 +249,32 @@
apps."x86_64-linux" = apps."x86_64-linux" =
let let
pkgs = self.legacyPackages."x86_64-linux"; pkgs = self.legacyPackages."x86_64-linux";
deployScript = host: addr: action: pkgs.writeShellScript "deploy-${host}" '' deployScript = action: pkgs.writeShellScript "deploy-moby" ''
nix build '.#nixosConfigurations.${host}.config.system.build.toplevel' --out-link ./result-${host} $@ nixos-rebuild --flake '.#moby' build $@
sudo nix sign-paths -r -k /run/secrets/nix_serve_privkey $(readlink ./result-${host}) sudo nix sign-paths -r -k /run/secrets/nix_serve_privkey $(readlink ./result)
nixos-rebuild --flake '.#moby' ${action} --target-host colin@moby-hn --use-remote-sudo $@
# XXX: this triggers another config eval & (potentially) build.
# if the config changed between these invocations, the above signatures might not apply to the deployed config.
# let the user handle that edge case by re-running this whole command
nixos-rebuild --flake '.#${host}' ${action} --target-host colin@${addr} --use-remote-sudo $@
''; '';
in { in {
help = {
type = "app";
program = let
helpMsg = builtins.toFile "nixos-config-help-message" ''
commands:
- `nix run '.#help'`
- show this message
- `nix run '.#update-feeds'`
- updates metadata for all feeds
- `nix run '.#init-feed' <url>`
- `nix run '.#deploy-{lappy,moby,moby-test,servo}' [nixos-rebuild args ...]`
- `nix run '.#check-nur'`
'';
in builtins.toString (pkgs.writeShellScript "nixos-config-help" ''
cat ${helpMsg}
'');
};
update-feeds = { update-feeds = {
type = "app"; type = "app";
program = "${pkgs.feeds.updateScript}"; program = "${pkgs.feeds.updateScript}";
}; };
init-feed = { init-feed = {
# use like `nix run '.#init-feed' uninsane.org`
type = "app"; type = "app";
program = "${pkgs.feeds.initFeedScript}"; program = "${pkgs.feeds.initFeedScript}";
}; };
deploy-lappy = {
type = "app";
program = ''${deployScript "lappy" "lappy" "switch"}'';
};
deploy-moby-test = { deploy-moby-test = {
# `nix run '.#deploy-moby-test'`
type = "app"; type = "app";
program = ''${deployScript "moby" "moby-hn" "test"}''; program = ''${deployScript "test"}'';
}; };
deploy-moby = { deploy-moby = {
# `nix run '.#deploy-moby-switch'`
type = "app"; type = "app";
program = ''${deployScript "moby" "moby-hn" "switch"}''; program = ''${deployScript "switch"}'';
};
deploy-servo = {
type = "app";
program = ''${deployScript "servo" "servo" "switch"}'';
};
check-nur = {
# `nix run '.#check-nur'`
# validates that my repo can be included in the Nix User Repository
type = "app";
program = builtins.toString (pkgs.writeShellScript "check-nur" ''
cd ${./.}/integrations/nur
NIX_PATH= NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 nix-env -f . -qa \* --meta --xml \
--allowed-uris https://static.rust-lang.org \
--option restrict-eval true \
--option allow-import-from-derivation true \
--drv-path --show-trace \
-I nixpkgs=$(nix-instantiate --find-file nixpkgs) \
-I ../../
'');
}; };
}; };

View File

@@ -4,11 +4,6 @@
./fs.nix ./fs.nix
]; ];
# sane.guest.enable = true;
# services.distccd.enable = true;
# sane.programs.distcc.enableFor.user.guest = true;
sops.secrets.colin-passwd.neededForUsers = true; sops.secrets.colin-passwd.neededForUsers = true;
sane.roles.build-machine.enable = true; sane.roles.build-machine.enable = true;
@@ -22,11 +17,9 @@
sane.gui.sway.enable = true; sane.gui.sway.enable = true;
sane.programs.iphoneUtils.enableFor.user.colin = true; sane.programs.iphoneUtils.enableFor.user.colin = true;
sane.programs.steam.enableFor.user.colin = true;
sane.programs.guiApps.suggestedPrograms = [ "desktopGuiApps" ]; sane.programs.guiApps.suggestedPrograms = [ "desktopGuiApps" ];
sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" "desktopConsoleUtils" ]; sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" ];
# sane.programs.devPkgs.enableFor.user.colin = true;
boot.loader.efi.canTouchEfiVariables = false; boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ]; sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
@@ -36,7 +29,6 @@
# don't enable wifi by default: it messes with connectivity. # don't enable wifi by default: it messes with connectivity.
systemd.services.iwd.enable = false; systemd.services.iwd.enable = false;
systemd.services.wpa_supplicant.enable = false;
# default config: https://man.archlinux.org/man/snapper-configs.5 # default config: https://man.archlinux.org/man/snapper-configs.5
# defaults to something like: # defaults to something like:
@@ -50,6 +42,17 @@
ALLOW_USERS = [ "colin" ]; ALLOW_USERS = [ "colin" ];
}; };
programs.steam = {
enable = true;
# not sure if needed: stole this whole snippet from the wiki
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
};
sane.user.persist.plaintext = [
".steam"
".local/share/Steam"
];
# docs: https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersion # docs: https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersion
system.stateVersion = "21.05"; system.stateVersion = "21.05";
} }

View File

@@ -2,10 +2,17 @@
{ {
sane.persist.root-on-tmpfs = true; sane.persist.root-on-tmpfs = true;
# increase /tmp space (defaults to 50% of RAM) for building large nix things. # we need a /tmp for building large nix things.
# a cross-compiled kernel, particularly, will easily use 30+GB of tmp # a cross-compiled kernel, particularly, will easily use 30+GB of tmp
fileSystems."/tmp".options = [ "size=64G" ]; fileSystems."/tmp" = {
device = "none";
fsType = "tmpfs";
options = [
"mode=777"
"size=64G"
"defaults"
];
};
fileSystems."/nix" = { fileSystems."/nix" = {
# device = "/dev/disk/by-uuid/985a0a32-da52-4043-9df7-615adec2e4ff"; # device = "/dev/disk/by-uuid/985a0a32-da52-4043-9df7-615adec2e4ff";
device = "/dev/disk/by-uuid/0ab0770b-7734-4167-88d9-6e4e20bb2a56"; device = "/dev/disk/by-uuid/0ab0770b-7734-4167-88d9-6e4e20bb2a56";

View File

@@ -19,7 +19,7 @@
"desktopGuiApps" "desktopGuiApps"
"stepmania" "stepmania"
]; ];
sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" "desktopConsoleUtils" ]; sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" ];
sops.secrets.colin-passwd.neededForUsers = true; sops.secrets.colin-passwd.neededForUsers = true;
@@ -34,6 +34,9 @@
ALLOW_USERS = [ "colin" ]; ALLOW_USERS = [ "colin" ];
}; };
# TODO: only here for debugging
# services.ipfs.enable = true;
# docs: https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersion # docs: https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersion
system.stateVersion = "21.05"; system.stateVersion = "21.05";
} }

View File

@@ -2,6 +2,15 @@
{ {
sane.persist.root-on-tmpfs = true; sane.persist.root-on-tmpfs = true;
# we need a /tmp of default size (half RAM) for building large nix things
fileSystems."/tmp" = {
device = "none";
fsType = "tmpfs";
options = [
"mode=777"
"defaults"
];
};
fileSystems."/nix" = { fileSystems."/nix" = {
device = "/dev/disk/by-uuid/75230e56-2c69-4e41-b03e-68475f119980"; device = "/dev/disk/by-uuid/75230e56-2c69-4e41-b03e-68475f119980";

View File

@@ -1,6 +1,6 @@
# doesn't actually *enable* anything, # doesn't actually *enable* anything,
# but sets up any modules such that if they *were* enabled, they'll act as expected. # but sets up any modules such that if they *were* enabled, they'll act as expected.
{ pkgs, ... }: { ... }:
{ {
sane.gui.sxmo = { sane.gui.sxmo = {
greeter = "sway"; greeter = "sway";
@@ -28,11 +28,5 @@
# see <repo:mil/sxmo-utils:scripts/deviceprofiles> # see <repo:mil/sxmo-utils:scripts/deviceprofiles>
# SXMO_DEVICE_NAME = "pine64,pinephone-1.2"; # SXMO_DEVICE_NAME = "pine64,pinephone-1.2";
}; };
package = pkgs.sxmo-utils.overrideAttrs (base: {
postPatch = (base.postPatch or "") + ''
# after volume-button navigation mode, restore full keyboard functionality
cp ${./xkb_mobile_normal_buttons} ./configs/xkb/xkb_mobile_normal_buttons
'';
});
}; };
} }

View File

@@ -1,26 +1,13 @@
# Pinephone
# other setups to reference:
# - <https://hamblingreen.gitlab.io/2022/03/02/my-pinephone-setup.html>
# - sxmo Arch user. lots of app recommendations
#
# wikis, resources, ...:
# - Linux Phone Apps: <https://linuxphoneapps.org/>
# - massive mobile-friendly app database
# - Mobian wiki: <https://wiki.mobian-project.org/doku.php?id=start>
# - recommended apps, chatrooms
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
{ {
imports = [ imports = [
./bootloader.nix ./firmware.nix
./fs.nix ./fs.nix
./gps.nix
./kernel.nix ./kernel.nix
./polyfill.nix ./polyfill.nix
]; ];
sane.roles.client = true; sane.roles.client = true;
sane.zsh.showDeadlines = false; # unlikely to act on them when in shell
sane.services.wg-home.enable = true; sane.services.wg-home.enable = true;
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip; sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
@@ -31,31 +18,36 @@
sops.secrets.colin-passwd.neededForUsers = true; sops.secrets.colin-passwd.neededForUsers = true;
sane.programs.web-browser.config = {
# compromise impermanence for the sake of usability
persistCache = "private";
persistData = "private";
# i don't do crypto stuff on moby
addons.ether-metamask.enable = false;
# addons.sideberry.enable = false;
};
sane.user.persist.plaintext = [ sane.user.persist.plaintext = [
# TODO: make this just generally conditional upon pulse being enabled? # TODO: make this just generally conditional upon pulse being enabled?
".config/pulse" # persist pulseaudio volume ".config/pulse" # persist pulseaudio volume
]; ];
sane.gui.sxmo.enable = true; sane.gui.sxmo.enable = true;
sane.programs.guiApps.suggestedPrograms = [ "handheldGuiApps" ];
# sane.programs.consoleUtils.enableFor.user.colin = false; # sane.programs.consoleUtils.enableFor.user.colin = false;
# sane.programs.guiApps.enableFor.user.colin = false; # sane.programs.guiApps.enableFor.user.colin = false;
sane.programs.sequoia.enableFor.user.colin = false; sane.programs.sequoia.enableFor.user.colin = false;
sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well
# disabled for faster deploys # disabled for faster deploys (gthumb depends on webkitgtk, particularly)
sane.programs.soundconverter.enableFor.user.colin = false; sane.programs.soundconverter.enableFor.user.colin = false;
sane.programs.gthumb.enableFor.user.colin = false;
# sane.programs.firefox.mime.priority = 300; # prefer other browsers when possible sane.programs.jellyfin-media-player.enableFor.user.colin = false;
# HACK/TODO: make `programs.P.env.VAR` behave according to `mime.priority`
# sane.programs.firefox.env = lib.mkForce {};
# sane.programs.epiphany.env.BROWSER = "epiphany";
# sane.programs.firefox.enableFor.user.colin = false; # use epiphany instead
# sane.programs.mpv.enableFor.user.colin = true; # sane.programs.mpv.enableFor.user.colin = true;
boot.loader.efi.canTouchEfiVariables = false; boot.loader.efi.canTouchEfiVariables = false;
# /boot space is at a premium. default was 20. # /boot space is at a premium. default was 20.
# even 10 can be too much # even 10 can be too much
# TODO: compress moby kernels!
boot.loader.generic-extlinux-compatible.configurationLimit = 8; boot.loader.generic-extlinux-compatible.configurationLimit = 8;
# mobile.bootloader.enable = false; # mobile.bootloader.enable = false;
# mobile.boot.stage-1.enable = false; # mobile.boot.stage-1.enable = false;
@@ -114,50 +106,6 @@
services.wireplumber.environment.ALSA_CONFIG_UCM2 = ucm-env; services.wireplumber.environment.ALSA_CONFIG_UCM2 = ucm-env;
}; };
services.udev.extraRules = let
chmod = "${pkgs.coreutils}/bin/chmod";
chown = "${pkgs.coreutils}/bin/chown";
in ''
# make Pinephone flashlight writable by user.
# taken from postmarketOS: <repo:postmarketOS/pmaports:device/main/device-pine64-pinephone/60-flashlight.rules>
SUBSYSTEM=="leds", DEVPATH=="*/*:flash", RUN+="${chmod} g+w /sys%p/brightness /sys%p/flash_strobe", RUN+="${chown} :video /sys%p/brightness /sys%p/flash_strobe"
# make Pinephone front LEDs writable by user.
SUBSYSTEM=="leds", DEVPATH=="*/*:indicator", RUN+="${chmod} g+w /sys%p/brightness", RUN+="${chown} :video /sys%p/brightness"
'';
hardware.opengl.driSupport = true; hardware.opengl.driSupport = true;
services.xserver.displayManager.job.preStart = let
dmesg = "${pkgs.util-linux}/bin/dmesg";
grep = "${pkgs.gnugrep}/bin/grep";
modprobe = "${pkgs.kmod}/bin/modprobe";
in ''
# common boot failure:
# blank screen (no backlight even), with the following log:
# ```syslog
# sun8i-dw-hdmi 1ee0000.hdmi: Couldn't get the HDMI PHY
# ...
# sun4i-drm display-engine: Couldn't bind all pipelines components
# ...
# sun8i-dw-hdmi: probe of 1ee0000.hdmi failed with error -17
# ```
#
# in particular, that `probe ... failed` occurs *only* on failed boots
# (the other messages might sometimes occur even on successful runs?)
#
# reloading the sun8i hdmi driver usually gets the screen on, showing boot text.
# then restarting display-manager.service gets us to the login.
#
# NB: the above log is default level. though less specific, there's a `err` level message that also signals this:
# sun4i-drm display-engine: failed to bind 1ee0000.hdmi (ops sun8i_dw_hdmi_ops [sun8i_drm_hdmi]): -17
if (${dmesg} --kernel --level err --color=never --notime | ${grep} -q 'sun4i-drm display-engine: failed to bind 1ee0000.hdmi')
then
echo "reprobing sun8i_drm_hdmi"
# if a command here fails it errors the whole service, so prefer to log instead
${modprobe} -r sun8i_drm_hdmi || echo "failed to unload sun8i_drm_hdmi"
${modprobe} sun8i_drm_hdmi || echo "failed to load sub8i_drm_hdmi"
fi
'';
} }

View File

@@ -1,24 +0,0 @@
# pinephone GPS happens in EG25 modem
# serial control interface to modem is /dev/ttyUSB2
# after enabling GPS, readout is /dev/ttyUSB1
#
# minimal process to enable modem and GPS:
# - `echo 1 > /sys/class/modem-power/modem-power/device/powered`
# - `screen /dev/ttyUSB2 115200`
# - `AT+QGPSCFG="nmeasrc",1`
# - `AT+QGPS=1`
#
# now, something like `gpsd` can directly read from /dev/ttyUSB1.
#
# initial GPS fix can take 15+ minutes.
# meanwhile, services like eg25-manager can speed this up by uploading assisted GPS data to the modem.
#
# geoclue somehow fits in here as a geospatial provider that leverages GPS and also other sources like radio towers
{ ... }:
{
services.gpsd.enable = true;
services.gpsd.devices = [ "/dev/ttyUSB1" ];
# TODO: enable eg25-manager, and bring online both the modem and GPS on boot
}

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 118 KiB

View File

@@ -1,179 +1,17 @@
# this file configures preferences per program, without actually enabling any programs. { sane-lib, ... }:
# the goal is to separate the place where we decide *what* to use (i.e. `sane.programs.firefox.enable = true` -- at the toplevel)
# from where we specific how that thing should behave *if* it's in use.
#
# NixOS backgrounds:
# - <https://github.com/NixOS/nixos-artwork>
# - <https://github.com/NixOS/nixos-artwork/issues/50> (colorful; unmerged)
# - <https://github.com/NixOS/nixos-artwork/pull/60/files> (desktop-oriented; clean; unmerged)
# - <https://itsfoss.com/content/images/2023/04/nixos-tutorials.png>
{ lib, pkgs, sane-lib, ... }:
let
# TODO: generate this from the .svg
# bg = ./nixos-bg-02.png;
bg = pkgs.runCommand "nixos-bg.png" { nativeBuildInputs = [ pkgs.inkscape ]; } ''
inkscape ${./nixos-bg-02.svg} -o $out
'';
in
{ {
sane.programs.firefox.config = {
# compromise impermanence for the sake of usability
persistCache = "private";
persistData = "private";
# i don't do crypto stuff on moby
addons.ether-metamask.enable = false;
# sidebery UX doesn't make sense on small screen
addons.sidebery.enable = false;
};
sane.gui.sxmo = { sane.gui.sxmo = {
nogesture = true;
settings = { settings = {
### hardware: touch screen # touch screen
SXMO_LISGD_INPUT_DEVICE = "/dev/input/by-path/platform-1c2ac00.i2c-event"; SXMO_LISGD_INPUT_DEVICE = "/dev/input/by-path/platform-1c2ac00.i2c-event";
# vol and power are detected correctly by upstream # vol and power are detected correctly by upstream
# preferences
### preferences # N.B. some deviceprofiles explicitly set SXMO_SWAY_SCALE, overwriting what we put here.
# notable bemenu options: SXMO_SWAY_SCALE = "1.5";
# - see `bemenu --help` for all SXMO_ROTATION_GRAVITY = "12800";
# -P, --prefix text to show before highlighted item.
# --scrollbar display scrollbar. (none (default), always, autohide)
# -H, --line-height defines the height to make each menu line (0 = default height). (wx)
# -M, --margin defines the empty space on either side of the menu. (wx)
# -W, --width-factor defines the relative width factor of the menu (from 0 to 1). (wx)
# -B, --border defines the width of the border in pixels around the menu. (wx)
# -R --border-radius defines the radius of the border around the menu (0 = no curved borders).
# --ch defines the height of the cursor (0 = scales with line height). (wx)
# --cw defines the width of the cursor. (wx)
# --hp defines the horizontal padding for the entries in single line mode. (wx)
# --fn defines the font to be used ('name [size]'). (wx)
# --tb defines the title background color. (wx)
# --tf defines the title foreground color. (wx)
# --fb defines the filter background color. (wx)
# --ff defines the filter foreground color. (wx)
# --nb defines the normal background color. (wx)
# --nf defines the normal foreground color. (wx)
# --hb defines the highlighted background color. (wx)
# --hf defines the highlighted foreground color. (wx)
# --fbb defines the feedback background color. (wx)
# --fbf defines the feedback foreground color. (wx)
# --sb defines the selected background color. (wx)
# --sf defines the selected foreground color. (wx)
# --ab defines the alternating background color. (wx)
# --af defines the alternating foreground color. (wx)
# --scb defines the scrollbar background color. (wx)
# --scf defines the scrollbar foreground color. (wx)
# --bdr defines the border color. (wx)
#
# colors are specified as `#RRGGBB`
# defaults:
# --ab "#222222"
# --af "#bbbbbb"
# --bdr "#005577"
# --border 3
# --cb "#222222"
# --center
# --cf "#bbbbbb"
# --fb "#222222"
# --fbb "#eeeeee"
# --fbf "#222222"
# --ff "#bbbbbb"
# --fixed-height
# --fn 'Sxmo 14'
# --hb "#005577"
# --hf "#eeeeee"
# --line-height 20
# --list 16
# --margin 40
# --nb "#222222"
# --nf "#bbbbbb"
# --no-overlap
# --no-spacing
# --sb "#323232"
# --scb "#005577"
# --scf "#eeeeee"
# --scrollbar autohide
# --tb "#005577"
# --tf "#eeeeee"
# --wrap
BEMENU_OPTS = let
bg = "#1d1721"; # slight purple
fg0 = "#d8d8d8"; # inactive text (light grey)
fg1 = "#ffffff"; # active text (white)
accent0 = "#1f5e54"; # darker but saturated teal
accent1 = "#418379"; # teal (matches nixos-bg)
accent2 = "#5b938a"; # brighter but muted teal
in lib.concatStringsSep " " [
"--wrap --scrollbar autohide --fixed-height"
"--center --margin 45"
"--no-spacing"
# XXX: font size doesn't seem to take effect (would prefer larger)
"--fn 'Sxmo 14' --line-height 22 --border 3"
"--bdr '${accent0}'" # border
"--scf '${accent2}' --scb '${accent0}'" # scrollbar
"--tb '${accent0}' --tf '${fg0}'" # title
"--fb '${accent0}' --ff '${fg1}'" # filter (i.e. text that's been entered)
"--hb '${accent1}' --hf '${fg1}'" # selected item
"--nb '${bg}' --nf '${fg0}'" # normal lines (even)
"--ab '${bg}' --af '${fg0}'" # alternated lines (odd)
"--cf '${accent0}' --cb '${accent0}'" # cursor (not very useful)
];
DEFAULT_COUNTRY = "US"; DEFAULT_COUNTRY = "US";
BROWSWER = "librewolf";
# BEMENU lines (wayland DMENU):
# - camera is 9th entry
# - flashlight is 10th entry
# - config is 14th entry. inside that:
# - autorotate is 11th entry
# - system menu is 19th entry
# - close is 20th entry
# - power is 15th entry
# - close is 16th entry
SXMO_BEMENU_LANDSCAPE_LINES = "11"; # default 8
SXMO_BEMENU_PORTRAIT_LINES = "16"; # default 16
SXMO_BG_IMG = "${bg}";
SXMO_LOCK_IDLE_TIME = "15"; # how long between screenoff -> lock -> back to screenoff (default: 8)
# gravity: how far to tilt the device before the screen rotates
# for a given setting, normal <-> invert requires more movement then left <-> right
# i.e. the settingd doesn't feel completely symmetric
# SXMO_ROTATION_GRAVITY default is 16374
# SXMO_ROTATION_GRAVITY = "12800"; # uncomfortably high
# SXMO_ROTATION_GRAVITY = "12500"; # kinda uncomfortable when walking
SXMO_ROTATION_GRAVITY = "12000";
SXMO_SCREENSHOT_DIR = "/home/colin/Pictures"; # default: "$HOME"
# test new scales by running `swaymsg -- output DSI-1 scale x.y`
# SXMO_SWAY_SCALE = "1.5"; # hard to press gPodder icons
SXMO_SWAY_SCALE = "1.8";
# SXMO_SWAY_SCALE = "2";
SXMO_WORKSPACE_WRAPPING = "5"; # how many workspaces. default: 4
# wvkbd layers:
# - full
# - landscape
# - special (e.g. coding symbols like ~)
# - emoji
# - nav
# - simple (like landscape, but no parens/tab/etc; even fewer chars)
# - simplegrid (simple, but grid layout)
# - dialer (digits)
# - cyrillic
# - arabic
# - persian
# - greek
# - georgian
WVKBD_LANDSCAPE_LAYERS = "landscape,special,emoji";
WVKBD_LAYERS = "full,special,emoji";
}; };
package = pkgs.sxmo-utils.overrideAttrs (base: {
postPatch = (base.postPatch or "") + ''
cat <<EOF >> ./configs/default_hooks/sxmo_hook_start.sh
# rotate UI based on physical display angle by default
sxmo_daemons.sh start autorotate sxmo_autorotate.sh
EOF
'';
});
}; };
} }

View File

@@ -18,16 +18,10 @@
sane.roles.build-machine.enable = true; sane.roles.build-machine.enable = true;
sane.roles.build-machine.emulation = false; sane.roles.build-machine.emulation = false;
sane.zsh.showDeadlines = false; # ~/knowledge doesn't always exist sane.zsh.showDeadlines = false; # ~/knowledge doesn't always exist
sane.programs.consoleUtils.suggestedPrograms = [
"desktopConsoleUtils"
"sane-scripts.stop-all-servo"
];
sane.services.dyn-dns.enable = true; sane.services.dyn-dns.enable = true;
sane.services.wg-home.enable = true; sane.services.wg-home.enable = true;
sane.services.wg-home.enableWan = true; sane.services.wg-home.enableWan = true;
sane.services.wg-home.ip = config.sane.hosts.by-name."servo".wg-home.ip; sane.services.wg-home.ip = config.sane.hosts.by-name."servo".wg-home.ip;
sane.nixcache.substituters.servo = false;
sane.nixcache.substituters.desko = false;
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade # sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade
# automatically log in at the virtual consoles. # automatically log in at the virtual consoles.

View File

@@ -2,6 +2,15 @@
{ {
sane.persist.root-on-tmpfs = true; sane.persist.root-on-tmpfs = true;
# we need a /tmp for building large nix things
fileSystems."/tmp" = {
device = "none";
fsType = "tmpfs";
options = [
"mode=777"
"defaults"
];
};
fileSystems."/nix" = { fileSystems."/nix" = {
device = "/dev/disk/by-uuid/cc81cca0-3cc7-4d82-a00c-6243af3e7776"; device = "/dev/disk/by-uuid/cc81cca0-3cc7-4d82-a00c-6243af3e7776";
@@ -35,7 +44,7 @@
sane.persist.sys.plaintext = [ sane.persist.sys.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"; directory = "/var/lib/uninsane"; }
]; ];
# make sure large media is stored to the HDD # make sure large media is stored to the HDD
sane.persist.sys.ext = [ sane.persist.sys.ext = [
@@ -43,22 +52,21 @@
user = "colin"; user = "colin";
group = "users"; group = "users";
mode = "0777"; mode = "0777";
path = "/var/lib/uninsane/media/Videos"; directory = "/var/lib/uninsane/media/Videos";
} }
{ {
user = "colin"; user = "colin";
group = "users"; group = "users";
mode = "0777"; mode = "0777";
path = "/var/lib/uninsane/media/freeleech"; directory = "/var/lib/uninsane/media/freeleech";
}
{
user = "colin";
group = "users";
mode = "0777";
path = "/var/lib/uninsane/media/datasets";
} }
]; ];
# in-memory compressed RAM (seems to be dynamically sized)
# zramSwap = {
# enable = true;
# };
# btrfs doesn't easily support swapfiles # btrfs doesn't easily support swapfiles
# swapDevices = [ # swapDevices = [
# { device = "/nix/persist/swapfile"; size = 4096; } # { device = "/nix/persist/swapfile"; size = 4096; }

View File

@@ -13,7 +13,7 @@ in
lib.mkIf false lib.mkIf false
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
{ inherit user group; mode = "0700"; path = svc-dir; } { inherit user group; mode = "0700"; directory = svc-dir; }
]; ];
services.calibre-web.enable = true; services.calibre-web.enable = true;

View File

@@ -20,7 +20,7 @@
# lib.mkIf false # lib.mkIf false
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
{ user = "ejabberd"; group = "ejabberd"; path = "/var/lib/ejabberd"; } { user = "ejabberd"; group = "ejabberd"; directory = "/var/lib/ejabberd"; }
]; ];
sane.ports.ports."3478" = { sane.ports.ports."3478" = {
protocol = [ "tcp" "udp" ]; protocol = [ "tcp" "udp" ];

View File

@@ -20,9 +20,9 @@ in
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.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"; directory = "/var/lib/opendkim"; }
{ user = "root"; group = "root"; path = "/var/lib/postfix"; } { user = "root"; group = "root"; directory = "/var/lib/postfix"; }
{ user = "root"; group = "root"; path = "/var/spool/mail"; } { user = "root"; group = "root"; directory = "/var/spool/mail"; }
# *probably* don't need these dirs: # *probably* don't need these dirs:
# "/var/lib/dhparams" # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/dhparams.nix # "/var/lib/dhparams" # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/dhparams.nix
# "/var/lib/dovecot" # "/var/lib/dovecot"

View File

@@ -16,7 +16,7 @@
mode = "0400"; mode = "0400";
}; };
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
{ user = "freshrss"; group = "freshrss"; path = "/var/lib/freshrss"; } { user = "freshrss"; group = "freshrss"; directory = "/var/lib/freshrss"; }
]; ];
services.freshrss.enable = true; services.freshrss.enable = true;

View File

@@ -4,7 +4,7 @@
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.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"; directory = "/var/lib/gitea"; }
]; ];
services.gitea.enable = true; services.gitea.enable = true;
services.gitea.user = "git"; # default is 'gitea' services.gitea.user = "git"; # default is 'gitea'

View File

@@ -12,7 +12,7 @@ lib.mkIf false # i don't actively use ipfs anymore
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.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"; directory = "/var/lib/ipfs"; }
]; ];
networking.firewall.allowedTCPPorts = [ 4001 ]; networking.firewall.allowedTCPPorts = [ 4001 ];

View File

@@ -3,7 +3,7 @@
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.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"; directory = "/var/lib/jackett"; }
]; ];
services.jackett.enable = true; services.jackett.enable = true;

View File

@@ -41,7 +41,7 @@
}; };
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin"; } { user = "jellyfin"; group = "jellyfin"; mode = "0700"; directory = "/var/lib/jellyfin"; }
]; ];
sane.fs."/var/lib/jellyfin/config/logging.json" = { sane.fs."/var/lib/jellyfin/config/logging.json" = {
# "Emby.Dlna" logging: <https://jellyfin.org/docs/general/networking/dlna> # "Emby.Dlna" logging: <https://jellyfin.org/docs/general/networking/dlna>

View File

@@ -5,7 +5,7 @@ let
in in
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
{ inherit user group; mode = "0700"; path = stateDir; } { inherit user group; mode = "0700"; directory = stateDir; }
]; ];
services.komga.enable = true; services.komga.enable = true;

View File

@@ -11,7 +11,7 @@
]; ];
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
{ user = "matrix-synapse"; group = "matrix-synapse"; path = "/var/lib/matrix-synapse"; } { user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/matrix-synapse"; }
]; ];
services.matrix-synapse.enable = true; services.matrix-synapse.enable = true;
# this changes the default log level from INFO to WARN. # this changes the default log level from INFO to WARN.

View File

@@ -6,7 +6,7 @@
lib.mkIf false lib.mkIf false
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
{ user = "matrix-synapse"; group = "matrix-synapse"; path = "/var/lib/mx-puppet-discord"; } { user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/mx-puppet-discord"; }
]; ];
services.matrix-synapse.settings.app_service_config_files = [ services.matrix-synapse.settings.app_service_config_files = [

View File

@@ -1,14 +1,16 @@
# config docs: # config docs:
# - <https://github.com/matrix-org/matrix-appservice-irc/blob/develop/config.sample.yaml> # - <https://github.com/matrix-org/matrix-appservice-irc/blob/develop/config.sample.yaml>
# TODO: /quit message for bridged users reveals to IRC users that i'm using a bridge;
# probably want to remove that. # probably want to remove that.
{ config, lib, ... }: { config, lib, ... }:
let let
ircServer = { name, additionalAddresses ? [], sasl ? true, port ? 6697 }: let ircServer = { name, additionalAddresses ? [], sasl ? true }: let
lowerName = lib.toLower name; lowerName = lib.toLower name;
in { in {
# XXX sasl: appservice doesn't support NickServ identification (only SASL, or PASS if sasl = false) # XXX sasl: appservice doesn't support NickServ identification (only SASL, or PASS if sasl = false)
inherit name additionalAddresses sasl port; inherit name additionalAddresses sasl;
port = 6697;
ssl = true; ssl = true;
botConfig = { botConfig = {
# bot has no presence in IRC channel; only real Matrix users # bot has no presence in IRC channel; only real Matrix users
@@ -103,7 +105,7 @@ in
sane.persist.sys.plaintext = [ sane.persist.sys.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"; directory = "/var/lib/matrix-appservice-irc"; }
]; ];
# XXX: matrix-appservice-irc PreStart tries to chgrp the registration.yml to matrix-synapse, # XXX: matrix-appservice-irc PreStart tries to chgrp the registration.yml to matrix-synapse,
@@ -149,7 +151,6 @@ in
}; };
"irc.oftc.net" = ircServer { "irc.oftc.net" = ircServer {
name = "oftc"; name = "oftc";
sasl = false;
# notable channels: # notable channels:
# - #sxmo # - #sxmo
# - #sxmo-offtopic # - #sxmo-offtopic

View File

@@ -3,8 +3,8 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
{ user = "mautrix-signal"; group = "mautrix-signal"; path = "/var/lib/mautrix-signal"; } { user = "mautrix-signal"; group = "mautrix-signal"; directory = "/var/lib/mautrix-signal"; }
{ user = "signald"; group = "signald"; path = "/var/lib/signald"; } { user = "signald"; group = "signald"; directory = "/var/lib/signald"; }
]; ];
# allow synapse to read the registration file # allow synapse to read the registration file

View File

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

View File

@@ -101,8 +101,7 @@ in
}; };
# allow ActivityPub clients to discover how to reach @user@uninsane.org # allow ActivityPub clients to discover how to reach @user@uninsane.org
# see: https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3361/ # TODO: waiting on https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3361/
# not sure this makes sense while i run multiple AP services (pleroma, lemmy)
# locations."/.well-known/nodeinfo" = { # locations."/.well-known/nodeinfo" = {
# proxyPass = "http://127.0.0.1:4000"; # proxyPass = "http://127.0.0.1:4000";
# extraConfig = pleromaExtraConfig; # extraConfig = pleromaExtraConfig;
@@ -135,8 +134,8 @@ in
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
# TODO: mode? # TODO: mode?
{ user = "acme"; group = "acme"; path = "/var/lib/acme"; } { user = "acme"; group = "acme"; directory = "/var/lib/acme"; }
{ user = "colin"; group = "users"; path = "/var/www/sites"; } { user = "colin"; group = "users"; directory = "/var/www/sites"; }
]; ];
# let's encrypt default chain looks like: # let's encrypt default chain looks like:

View File

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

View File

@@ -1,21 +1,14 @@
# docs: # docs:
# - <https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/pleroma.nix> # - https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/pleroma.nix
# - <https://docs.pleroma.social/backend/configuration/cheatsheet/> # - https://docs.pleroma.social/backend/configuration/cheatsheet/
# example config:
# - <https://git.pleroma.social/pleroma/pleroma/-/blob/develop/config/config.exs>
# #
# to run it in a oci-container: <https://github.com/barrucadu/nixfiles/blob/master/services/pleroma.nix> # to run it in a oci-container: https://github.com/barrucadu/nixfiles/blob/master/services/pleroma.nix
#
# admin frontend: <https://fed.uninsane.org/pleroma/admin>
{ config, pkgs, ... }: { config, pkgs, ... }:
let
logLevel = "warn";
# logLevel = "debug";
in
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
{ user = "pleroma"; group = "pleroma"; path = "/var/lib/pleroma"; } # TODO: mode? could be more granular
{ user = "pleroma"; group = "pleroma"; directory = "/var/lib/pleroma"; }
]; ];
services.pleroma.enable = true; services.pleroma.enable = true;
services.pleroma.secretConfigFile = config.sops.secrets.pleroma_secrets.path; services.pleroma.secretConfigFile = config.sops.secrets.pleroma_secrets.path;
@@ -103,22 +96,10 @@ in
backends: [{ExSyslogger, :ex_syslogger}] backends: [{ExSyslogger, :ex_syslogger}]
config :logger, :ex_syslogger, config :logger, :ex_syslogger,
level: :${logLevel} level: :warn
# level: :debug
# policies => list of message rewriting facilities to be enabled
# transparence => whether to publish these rules in node_info (and /about)
config :pleroma, :mrf,
policies: [Pleroma.Web.ActivityPub.MRF.SimplePolicy],
transparency: true
# reject => { host, reason }
config :pleroma, :mrf_simple,
reject: [ {"threads.net", "megacorp"}, {"*.threads.net", "megacorp"} ]
# reject: [ [host: "threads.net", reason: "megacorp"], [host: "*.threads.net", reason: "megacorp"] ]
# XXX colin: not sure if this actually _does_ anything # XXX colin: not sure if this actually _does_ anything
# better to steal emoji from other instances?
# - <https://docs.pleroma.social/backend/configuration/cheatsheet/#mrf_steal_emoji>
config :pleroma, :emoji, config :pleroma, :emoji,
shortcode_globs: ["/emoji/**/*.png"], shortcode_globs: ["/emoji/**/*.png"],
groups: [ groups: [
@@ -167,7 +148,6 @@ in
# inherit kTLS; # inherit kTLS;
locations."/" = { locations."/" = {
proxyPass = "http://127.0.0.1:4000"; proxyPass = "http://127.0.0.1:4000";
recommendedProxySettings = true;
# documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx # documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx
extraConfig = '' extraConfig = ''
# XXX colin: this block is in the nixos examples: i don't understand all of it # XXX colin: this block is in the nixos examples: i don't understand all of it
@@ -186,18 +166,17 @@ in
add_header Referrer-Policy same-origin; add_header Referrer-Policy same-origin;
add_header X-Download-Options noopen; add_header X-Download-Options noopen;
# proxy_http_version 1.1; proxy_http_version 1.1;
# proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade"; proxy_set_header Connection "upgrade";
# # proxy_set_header Host $http_host; # proxy_set_header Host $http_host;
# proxy_set_header Host $host; proxy_set_header Host $host;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# colin: added this due to Pleroma complaining in its logs # colin: added this due to Pleroma complaining in its logs
# proxy_set_header X-Real-IP $remote_addr; # proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-Proto $scheme; # proxy_set_header X-Forwarded-Proto $scheme;
# NB: this defines the maximum upload size
client_max_body_size 16m; client_max_body_size 16m;
''; '';
}; };

View File

@@ -3,7 +3,7 @@
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
# TODO: mode? # TODO: mode?
{ user = "postgres"; group = "postgres"; path = "/var/lib/postgresql"; } { user = "postgres"; group = "postgres"; directory = "/var/lib/postgresql"; }
]; ];
services.postgresql.enable = true; services.postgresql.enable = true;
# services.postgresql.dataDir = "/opt/postgresql/13"; # services.postgresql.dataDir = "/opt/postgresql/13";

View File

@@ -10,7 +10,7 @@
lib.mkIf false lib.mkIf false
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
{ user = "prosody"; group = "prosody"; path = "/var/lib/prosody"; } { user = "prosody"; group = "prosody"; directory = "/var/lib/prosody"; }
]; ];
sane.ports.ports."5222" = { sane.ports.ports."5222" = {
protocol = [ "tcp" ]; protocol = [ "tcp" ];

View File

@@ -3,7 +3,7 @@
{ {
sane.persist.sys.plaintext = [ sane.persist.sys.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 = "transmission"; path = "/var/lib/transmission"; } { user = "transmission"; group = "transmission"; directory = "/var/lib/transmission"; }
]; ];
services.transmission.enable = true; services.transmission.enable = true;
services.transmission.settings = { services.transmission.settings = {

View File

@@ -1,25 +1,15 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
{ {
services.trust-dns.enable = true; sane.services.trust-dns.enable = true;
services.trust-dns.settings.listen_addrs_ipv4 = [ sane.services.trust-dns.listenAddrsIPv4 = [
# specify each address explicitly, instead of using "*". # specify each address explicitly, instead of using "*".
# this ensures responses are sent from the address at which the request was received. # this ensures responses are sent from the address at which the request was received.
config.sane.hosts.by-name."servo".lan-ip config.sane.hosts.by-name."servo".lan-ip
"10.0.1.5" "10.0.1.5"
]; ];
# don't bind to IPv6 until i explicitly test that stack sane.services.trust-dns.quiet = true;
services.trust-dns.settings.listen_addrs_ipv6 = [];
services.trust-dns.quiet = true;
# services.trust-dns.debug = true;
sane.ports.ports."53" = {
protocol = [ "udp" "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-dns-hosting";
};
sane.dns.zones."uninsane.org".TTL = 900; sane.dns.zones."uninsane.org".TTL = 900;
@@ -61,15 +51,18 @@
]; ];
}; };
services.trust-dns.settings.zones = [ "uninsane.org" ]; # we need trust-dns to load our zone by relative path instead of /nix/store path
# because we generate it at runtime.
sane.services.trust-dns.zones."uninsane.org".file = lib.mkForce "uninsane.org.zone";
sane.services.trust-dns.zonedir = null;
services.trust-dns.package = sane.services.trust-dns.package =
let let
sed = "${pkgs.gnused}/bin/sed"; sed = "${pkgs.gnused}/bin/sed";
zone-dir = "/var/lib/trust-dns"; zone-dir = "/var/lib/trust-dns";
zone-wan = "${zone-dir}/wan/uninsane.org.zone"; zone-wan = "${zone-dir}/wan/uninsane.org.zone";
zone-lan = "${zone-dir}/lan/uninsane.org.zone"; zone-lan = "${zone-dir}/lan/uninsane.org.zone";
zone-template = pkgs.writeText "uninsane.org.zone.in" config.sane.dns.zones."uninsane.org".rendered; zone-template = pkgs.writeText "uninsane.org.zone.in" config.sane.services.trust-dns.zones."uninsane.org".text;
in pkgs.writeShellScriptBin "named" '' in pkgs.writeShellScriptBin "named" ''
# compute wan/lan values # compute wan/lan values
mkdir -p ${zone-dir}/{ovpn,wan,lan} mkdir -p ${zone-dir}/{ovpn,wan,lan}
@@ -100,17 +93,6 @@
exit 1 exit 1
''; '';
systemd.services.trust-dns.serviceConfig = {
DynamicUser = lib.mkForce false;
User = "trust-dns";
Group = "trust-dns";
};
users.groups.trust-dns = {};
users.users.trust-dns = {
group = "trust-dns";
isSystemUser = true;
};
sane.services.dyn-dns.restartOnChange = [ "trust-dns.service" ]; sane.services.dyn-dns.restartOnChange = [ "trust-dns.service" ];
networking.nat.enable = true; networking.nat.enable = true;

View File

@@ -13,7 +13,7 @@
./programs ./programs
./secrets.nix ./secrets.nix
./ssh.nix ./ssh.nix
./users ./users.nix
./vpn.nix ./vpn.nix
]; ];
@@ -23,6 +23,9 @@
sane.programs.sysadminUtils.enableFor.system = lib.mkDefault true; sane.programs.sysadminUtils.enableFor.system = lib.mkDefault true;
sane.programs.consoleUtils.enableFor.user.colin = lib.mkDefault true; sane.programs.consoleUtils.enableFor.user.colin = lib.mkDefault true;
# some services which use private directories error if the parent (/var/lib/private) isn't 700.
sane.fs."/var/lib/private".dir.acl.mode = "0700";
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
nixpkgs.config.allowBroken = true; # NIXPKGS_ALLOW_BROKEN nixpkgs.config.allowBroken = true; # NIXPKGS_ALLOW_BROKEN
@@ -40,39 +43,48 @@
# does the builder use some content-addressed db to efficiently dedupe? # does the builder use some content-addressed db to efficiently dedupe?
nix.settings.auto-optimise-store = true; nix.settings.auto-optimise-store = true;
systemd.services.nix-daemon.serviceConfig = { fonts = {
# the nix-daemon manages nix builders enableDefaultFonts = true;
# kill nix-daemon subprocesses when systemd-oomd detects an out-of-memory condition fonts = with pkgs; [ font-awesome noto-fonts-emoji hack-font ];
# see: fontconfig.enable = true;
# - nixos PR that enabled systemd-oomd: <https://github.com/NixOS/nixpkgs/pull/169613> fontconfig.defaultFonts = {
# - systemd's docs on these properties: <https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#ManagedOOMSwap=auto%7Ckill> emoji = [ "Font Awesome 6 Free" "Noto Color Emoji" ];
# monospace = [ "Hack" ];
# systemd's docs warn that without swap, systemd-oomd might not be able to react quick enough to save the system. serif = [ "DejaVu Serif" ];
# see `man oomd.conf` for further tunables that may help. sansSerif = [ "DejaVu Sans" ];
# };
# alternatively, apply this more broadly with `systemd.oomd.enableSystemSlice = true` or `enableRootSlice`
# TODO: also apply this to the guest user's slice (user-1100.slice)
# TODO: also apply this to distccd
ManagedOOMMemoryPressure = "kill";
ManagedOOMSwap = "kill";
}; };
# XXX: twitter-color-emoji doesn't cross-compile; but not-fonts-emoji does
system.activationScripts.nixClosureDiff = { # fonts = {
supportsDryActivation = true; # enableDefaultFonts = true;
text = '' # fonts = with pkgs; [ font-awesome twitter-color-emoji hack-font ];
# show which packages changed versions or are new/removed in this upgrade # fontconfig.enable = true;
# source: <https://github.com/luishfonseca/dotfiles/blob/32c10e775d9ec7cc55e44592a060c1c9aadf113e/modules/upgrade-diff.nix> # fontconfig.defaultFonts = {
${pkgs.nvd}/bin/nvd --nix-bin-dir=${pkgs.nix}/bin diff /run/current-system "$systemConfig" # emoji = [ "Font Awesome 6 Free" "Twitter Color Emoji" ];
''; # monospace = [ "Hack" ];
}; # serif = [ "DejaVu Serif" ];
# sansSerif = [ "DejaVu Sans" ];
# };
# };
# disable non-required packages like nano, perl, rsync, strace # disable non-required packages like nano, perl, rsync, strace
environment.defaultPackages = []; environment.defaultPackages = [];
# programs.vim.defaultEditor = true;
environment.variables = {
EDITOR = "vim";
# git claims it should use EDITOR, but it doesn't!
GIT_EDITOR = "vim";
# TODO: these should be moved to `home.sessionVariables` (home-manager)
# Electron apps should use native wayland backend:
# https://nixos.wiki/wiki/Slack#Wayland
# Discord under sway crashes with this.
# NIXOS_OZONE_WL = "1";
# LIBGL_ALWAYS_SOFTWARE = "1";
};
# dconf docs: <https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/desktop_migration_and_administration_guide/profiles> # dconf docs: <https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/desktop_migration_and_administration_guide/profiles>
# this lets programs temporarily write user-level dconf settings (aka gsettings).
# they're written to ~/.config/dconf/user, unless `DCONF_PROFILE` is set to something other than the default of /etc/dconf/profile/user
# find keys/values with `dconf dump /` # find keys/values with `dconf dump /`
programs.dconf.enable = true; programs.dconf.enable = true;
programs.dconf.packages = [ programs.dconf.packages = [
@@ -85,7 +97,6 @@
''; '';
}) })
]; ];
# sane.programs.glib.enableFor.user.colin = true; # for `gsettings`
# link debug symbols into /run/current-system/sw/lib/debug # link debug symbols into /run/current-system/sw/lib/debug
# hopefully picked up by gdb automatically? # hopefully picked up by gdb automatically?

View File

@@ -1,6 +1,3 @@
# where to find good stuff?
# - podcast rec thread: <https://lemmy.ml/post/1565858>
#
# candidates: # candidates:
# - The Nonlinear Library (podcast): <https://forum.effectivealtruism.org/posts/JTZTBienqWEAjGDRv/listen-to-more-ea-content-with-the-nonlinear-library> # - The Nonlinear Library (podcast): <https://forum.effectivealtruism.org/posts/JTZTBienqWEAjGDRv/listen-to-more-ea-content-with-the-nonlinear-library>
# - has ~10 posts per day, text-to-speech; i would need better tagging before adding this # - has ~10 posts per day, text-to-speech; i would need better tagging before adding this
@@ -107,8 +104,6 @@ let
(fromDb "feeds.megaphone.fm/recodedecode" // tech) (fromDb "feeds.megaphone.fm/recodedecode" // tech)
## Matrix (chat) Live ## Matrix (chat) Live
(fromDb "feed.podbean.com/matrixlive/feed.xml" // tech) (fromDb "feed.podbean.com/matrixlive/feed.xml" // tech)
(fromDb "cast.postmarketos.org" // tech)
(fromDb "podcast.thelinuxexp.com" // tech)
## Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232> ## Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232>
(fromDb "rss.art19.com/your-welcome" // pol) (fromDb "rss.art19.com/your-welcome" // pol)
(fromDb "seattlenice.buzzsprout.com" // pol) (fromDb "seattlenice.buzzsprout.com" // pol)
@@ -119,18 +114,12 @@ let
## The Witch Trials of J.K. Rowling ## The Witch Trials of J.K. Rowling
## - <https://www.thefp.com/witchtrials> ## - <https://www.thefp.com/witchtrials>
(mkPod "https://feeds.megaphone.fm/RUNMED9919162779" // pol // infrequent) (mkPod "https://feeds.megaphone.fm/RUNMED9919162779" // pol // infrequent)
## Atlas Obscura
(fromDb "feeds.simplecast.com/xKJ93w_w" // uncat)
## Ezra Klein Show
(fromDb "feeds.simplecast.com/82FI35Px" // pol)
## Wireshark Podcast o_0
(fromDb "sharkbytes.transistor.fm" // tech)
]; ];
texts = [ texts = [
# AGGREGATORS (> 1 post/day) # AGGREGATORS (> 1 post/day)
(fromDb "lwn.net" // tech) (fromDb "lwn.net" // tech)
# (fromDb "lesswrong.com" // rat) (fromDb "lesswrong.com" // rat)
# (fromDb "econlib.org" // pol) # (fromDb "econlib.org" // pol)
# AGGREGATORS (< 1 post/day) # AGGREGATORS (< 1 post/day)
@@ -172,11 +161,10 @@ let
(fromDb "ianthehenry.com" // tech) (fromDb "ianthehenry.com" // tech)
(fromDb "bitbashing.io" // tech) (fromDb "bitbashing.io" // tech)
(fromDb "idiomdrottning.org" // uncat) (fromDb "idiomdrottning.org" // uncat)
(mkText "http://boginjr.com/feed" // tech // infrequent)
(mkText "https://anish.lakhwara.com/home.html" // tech // weekly) (mkText "https://anish.lakhwara.com/home.html" // tech // weekly)
(fromDb "jefftk.com" // tech) (fromDb "jefftk.com" // tech)
(fromDb "pomeroyb.com" // tech) (fromDb "pomeroyb.com" // tech)
# (mkText "https://til.simonwillison.net/tils/feed.atom" // tech // weekly) (mkText "https://til.simonwillison.net/tils/feed.atom" // tech // weekly)
# TECH PROJECTS # TECH PROJECTS
(fromDb "blog.rust-lang.org" // tech) (fromDb "blog.rust-lang.org" // tech)
@@ -226,7 +214,6 @@ let
(fromDb "preposterousuniverse.com" // rat) (fromDb "preposterousuniverse.com" // rat)
(mkSubstack "eliqian" // rat // weekly) (mkSubstack "eliqian" // rat // weekly)
(mkText "https://acoup.blog/feed" // rat // weekly) (mkText "https://acoup.blog/feed" // rat // weekly)
(fromDb "mindingourway.com" // rat)
## mostly dating topics. not advice, or humor, but looking through a social lens ## mostly dating topics. not advice, or humor, but looking through a social lens
(fromDb "putanumonit.com" // rat) (fromDb "putanumonit.com" // rat)

View File

@@ -7,7 +7,6 @@ let fsOpts = rec {
common = [ common = [
"_netdev" "_netdev"
"noatime" "noatime"
"user" # allow any user with access to the device to mount the fs
"x-systemd.requires=network-online.target" "x-systemd.requires=network-online.target"
"x-systemd.after=network-online.target" "x-systemd.after=network-online.target"
"x-systemd.mount-timeout=10s" # how long to wait for mount **and** how long to wait for unmount "x-systemd.mount-timeout=10s" # how long to wait for mount **and** how long to wait for unmount
@@ -20,6 +19,7 @@ let fsOpts = rec {
]; ];
ssh = common ++ [ ssh = common ++ [
"user"
"identityfile=/home/colin/.ssh/id_ed25519" "identityfile=/home/colin/.ssh/id_ed25519"
"allow_other" "allow_other"
"default_permissions" "default_permissions"
@@ -57,37 +57,6 @@ let fsOpts = rec {
}; };
in in
{ {
# some services which use private directories error if the parent (/var/lib/private) isn't 700.
sane.fs."/var/lib/private".dir.acl.mode = "0700";
# in-memory compressed RAM
# defaults to compressing at most 50% size of RAM
# claimed compression ratio is about 2:1
# - but on moby w/ zstd default i see 4-7:1 (ratio lowers as it fills)
# note that idle overhead is about 0.05% of capacity (e.g. 2B per 4kB page)
# docs: <https://www.kernel.org/doc/Documentation/blockdev/zram.txt>
#
# to query effectiveness:
# `cat /sys/block/zram0/mm_stat`. whitespace separated fields:
# - *orig_data_size* (bytes)
# - *compr_data_size* (bytes)
# - mem_used_total (bytes)
# - mem_limit (bytes)
# - mem_used_max (bytes)
# - *same_pages* (pages which are e.g. all zeros (consumes no additional mem))
# - *pages_compacted* (pages which have been freed thanks to compression)
# - huge_pages (incompressible)
#
# see also:
# - `man zramctl`
zramSwap.enable = true;
# how much ram can be swapped into the zram device.
# this shouldn't be higher than the observed compression ratio.
# the default is 50% (why?)
# 100% should be "guaranteed" safe so long as the data is even *slightly* compressible.
# but it decreases working memory under the heaviest of loads by however much space the compressed memory occupies (e.g. 50% if 2:1; 25% if 4:1)
zramSwap.memoryPercent = 100;
# fileSystems."/mnt/servo-nfs" = { # fileSystems."/mnt/servo-nfs" = {
# device = "servo-hn:/"; # device = "servo-hn:/";
# noCheck = true; # noCheck = true;
@@ -108,6 +77,34 @@ in
# }; # };
sane.fs."/mnt/servo-media" = sane-lib.fs.wantedSymlinkTo "/mnt/servo-nfs/media"; sane.fs."/mnt/servo-media" = sane-lib.fs.wantedSymlinkTo "/mnt/servo-nfs/media";
fileSystems."/mnt/servo-media-wan" = {
device = "colin@uninsane.org:/var/lib/uninsane/media";
fsType = "fuse.sshfs";
options = fsOpts.sshColin ++ fsOpts.noauto;
noCheck = true;
};
sane.fs."/mnt/servo-media-wan" = sane-lib.fs.wantedDir;
fileSystems."/mnt/servo-media-lan" = {
device = "colin@servo:/var/lib/uninsane/media";
fsType = "fuse.sshfs";
options = fsOpts.sshColin ++ fsOpts.noauto;
noCheck = true;
};
sane.fs."/mnt/servo-media-lan" = sane-lib.fs.wantedDir;
fileSystems."/mnt/servo-root-wan" = {
device = "colin@uninsane.org:/";
fsType = "fuse.sshfs";
options = fsOpts.sshRoot ++ fsOpts.noauto;
noCheck = true;
};
sane.fs."/mnt/servo-root-wan" = sane-lib.fs.wantedDir;
fileSystems."/mnt/servo-root-lan" = {
device = "colin@servo:/";
fsType = "fuse.sshfs";
options = fsOpts.sshRoot ++ fsOpts.noauto;
noCheck = true;
};
sane.fs."/mnt/servo-root-lan" = sane-lib.fs.wantedDir;
fileSystems."/mnt/desko-home" = { fileSystems."/mnt/desko-home" = {
device = "colin@desko:/home/colin"; device = "colin@desko:/home/colin";
fsType = "fuse.sshfs"; fsType = "fuse.sshfs";

View File

@@ -23,6 +23,7 @@
# non-free firmware # non-free firmware
hardware.enableRedistributableFirmware = true; hardware.enableRedistributableFirmware = true;
services.fwupd.enable = true;
# powertop will default to putting USB devices -- including HID -- to sleep after TWO SECONDS # powertop will default to putting USB devices -- including HID -- to sleep after TWO SECONDS
powerManagement.powertop.enable = false; powerManagement.powertop.enable = false;

View File

@@ -1,7 +1,7 @@
{ ... }: { ... }:
{ {
imports = [ imports = [
./keyring ./keyring.nix
./mime.nix ./mime.nix
./ssh.nix ./ssh.nix
./xdg-dirs.nix ./xdg-dirs.nix

View File

@@ -0,0 +1,11 @@
{ config, sane-lib, ... }:
{
sane.user.persist.private = [ ".local/share/keyrings" ];
sane.user.fs."private/.local/share/keyrings/default" = {
generated.script.script = builtins.readFile ../../../scripts/init-keyring;
# TODO: is this `wantedBy` needed? can we inherit it?
wantedBy = [ config.sane.fs."/home/colin/private".unit ];
};
}

View File

@@ -1,17 +0,0 @@
{ config, pkgs, sane-lib, ... }:
let
init-keyring = pkgs.static-nix-shell.mkBash {
pname = "init-keyring";
src = ./.;
};
in
{
sane.user.persist.private = [ ".local/share/keyrings" ];
sane.user.fs."private/.local/share/keyrings/default" = {
generated.command = [ "${init-keyring}/bin/init-keyring" ];
wantedBy = [ config.sane.fs."/home/colin/private".unit ];
wantedBeforeBy = [ ]; # don't created this as part of `multi-user.target`
};
}

View File

@@ -1,28 +1,43 @@
{ config, lib, ...}: { config, sane-lib, ...}:
let let
# ProgramConfig -> { "<mime-type>" = { priority, desktop }; } www = config.sane.programs.web-browser.config.browser.desktop;
weightedMimes = prog: builtins.mapAttrs (_key: desktop: { priority = prog.mime.priority; desktop = desktop; }) prog.mime.associations; pdf = "org.gnome.Evince.desktop";
# [ { "<mime-type>" = { priority, desktop } ]; } ] -> { "<mime-type>" = [ { priority, desktop } ... ]; } md = "obsidian.desktop";
mergeMimes = mimes: lib.foldAttrs (item: acc: [item] ++ acc) [] mimes; thumb = "org.gnome.gThumb.desktop";
# [ { priority, desktop } ... ] -> Self video = "vlc.desktop";
sortOneMimeType = associations: builtins.sort (l: r: assert l.priority != r.priority; l.priority < r.priority) associations; # audio = "mpv.desktop";
sortMimes = mimes: builtins.mapAttrs (_k: sortOneMimeType) mimes; audio = "vlc.desktop";
removePriorities = mimes: builtins.mapAttrs (_k: associations: builtins.map (a: a.desktop) associations) mimes;
# [ ProgramConfig ]
enabledPrograms = builtins.filter (p: p.enabled) (builtins.attrValues config.sane.programs);
# [ { "<mime-type>" = { prority, desktop } ]
enabledWeightedMimes = builtins.map weightedMimes enabledPrograms;
in in
{ {
# the xdg mime type for a file can be found with: # the xdg mime type for a file can be found with:
# - `xdg-mime query filetype path/to/thing.ext` # - `xdg-mime query filetype path/to/thing.ext`
# the default handler for a mime type can be found with:
# - `xdg-mime query default <mimetype>` (e.g. x-scheme-handler/http)
#
# we can have single associations or a list of associations. # we can have single associations or a list of associations.
# there's also options to *remove* [non-default] associations from specific apps # there's also options to *remove* [non-default] associations from specific apps
xdg.mime.enable = true; xdg.mime.enable = true;
xdg.mime.defaultApplications = removePriorities (sortMimes (mergeMimes enabledWeightedMimes)); xdg.mime.defaultApplications = {
# AUDIO
"audio/flac" = audio;
"audio/mpeg" = audio;
"audio/x-vorbis+ogg" = audio;
# IMAGES
"image/heif" = thumb; # apple codec
"image/png" = thumb;
"image/jpeg" = thumb;
# VIDEO
"video/mp4" = video;
"video/quicktime" = video;
"video/webm" = video;
"video/x-matroska" = video;
# HTML
"text/html" = www;
"x-scheme-handler/http" = www;
"x-scheme-handler/https" = www;
"x-scheme-handler/about" = www;
"x-scheme-handler/unknown" = www;
# RICH-TEXT DOCUMENTS
"application/pdf" = pdf;
"text/markdown" = md;
};
} }

View File

@@ -1,29 +1,26 @@
# TODO: this should be moved to users/colin.nix { config, lib, sane-lib, ... }:
{ config, lib, ... }:
with lib;
let let
host = config.networking.hostName; host = config.networking.hostName;
user-pubkey-full = config.sane.ssh.pubkeys."colin@${host}" or {}; user-pubkey-full = config.sane.ssh.pubkeys."colin@${host}" or {};
user-pubkey = user-pubkey-full.asUserKey or null; user-pubkey = user-pubkey-full.asUserKey or null;
host-keys = lib.filter (k: k.user == "root") (lib.attrValues config.sane.ssh.pubkeys); host-keys = filter (k: k.user == "root") (attrValues config.sane.ssh.pubkeys);
known-hosts-text = lib.concatStringsSep known-hosts-text = concatStringsSep
"\n" "\n"
(builtins.map (k: k.asHostKey) host-keys) (map (k: k.asHostKey) host-keys)
; ;
in in
{ {
# ssh key is stored in private storage # ssh key is stored in private storage
sane.user.persist.private = [ sane.user.persist.private = [ ".ssh/id_ed25519" ];
{ type = "file"; path = ".ssh/id_ed25519"; } sane.user.fs.".ssh/id_ed25519.pub" =
]; mkIf (user-pubkey != null) (sane-lib.fs.wantedText user-pubkey);
sane.user.fs.".ssh/id_ed25519.pub" = lib.mkIf (user-pubkey != null) { sane.user.fs.".ssh/known_hosts" = sane-lib.fs.wantedText known-hosts-text;
symlink.text = user-pubkey;
};
sane.user.fs.".ssh/known_hosts".symlink.text = known-hosts-text;
users.users.colin.openssh.authorizedKeys.keys = users.users.colin.openssh.authorizedKeys.keys =
let let
user-keys = lib.filter (k: k.user == "colin") (lib.attrValues config.sane.ssh.pubkeys); user-keys = filter (k: k.user == "colin") (attrValues config.sane.ssh.pubkeys);
in in
builtins.map (k: k.asUserKey) user-keys; map (k: k.asUserKey) user-keys;
} }

View File

@@ -1,9 +1,9 @@
{ ... }: { lib, sane-lib, ...}:
{ {
# XDG defines things like ~/Desktop, ~/Downloads, etc. # XDG defines things like ~/Desktop, ~/Downloads, etc.
# these clutter the home, so i mostly don't use them. # these clutter the home, so i mostly don't use them.
sane.user.fs.".config/user-dirs.dirs".symlink.text = '' sane.user.fs.".config/user-dirs.dirs" = sane-lib.fs.wantedText ''
XDG_DESKTOP_DIR="$HOME/.xdg/Desktop" XDG_DESKTOP_DIR="$HOME/.xdg/Desktop"
XDG_DOCUMENTS_DIR="$HOME/dev" XDG_DOCUMENTS_DIR="$HOME/dev"
XDG_DOWNLOAD_DIR="$HOME/tmp" XDG_DOWNLOAD_DIR="$HOME/tmp"
@@ -16,5 +16,5 @@
# prevent `xdg-user-dirs-update` from overriding/updating our config # prevent `xdg-user-dirs-update` from overriding/updating our config
# see <https://manpages.ubuntu.com/manpages/bionic/man5/user-dirs.conf.5.html> # see <https://manpages.ubuntu.com/manpages/bionic/man5/user-dirs.conf.5.html>
sane.user.fs.".config/user-dirs.conf".symlink.text = "enabled=False"; sane.user.fs.".config/user-dirs.conf" = sane-lib.fs.wantedText "enabled=False";
} }

View File

@@ -42,8 +42,6 @@
sane.ids.pict-rs.gid = 2409; sane.ids.pict-rs.gid = 2409;
sane.ids.sftpgo.uid = 2410; sane.ids.sftpgo.uid = 2410;
sane.ids.sftpgo.gid = 2410; sane.ids.sftpgo.gid = 2410;
sane.ids.trust-dns.uid = 2411;
sane.ids.trust-dns.gid = 2411;
sane.ids.colin.uid = 1000; sane.ids.colin.uid = 1000;
sane.ids.guest.uid = 1100; sane.ids.guest.uid = 1100;

View File

@@ -11,37 +11,17 @@
# - `man iwd.config` for global config # - `man iwd.config` for global config
# - `man iwd.network` for per-SSID config # - `man iwd.network` for per-SSID config
# use `iwctl` to control # use `iwctl` to control
# networking.networkmanager.wifi.backend = "iwd"; networking.networkmanager.wifi.backend = "iwd";
# networking.wireless.iwd.enable = true; networking.wireless.iwd.enable = true;
# networking.wireless.iwd.settings = { networking.wireless.iwd.settings = {
# # auto-connect to a stronger network if signal drops below this value # auto-connect to a stronger network if signal drops below this value
# # bedroom -> bedroom connection is -35 to -40 dBm # bedroom -> bedroom connection is -35 to -40 dBm
# # bedroom -> living room connection is -60 dBm # bedroom -> living room connection is -60 dBm
# General.RoamThreshold = "-52"; # default -70 General.RoamThreshold = "-52"; # default -70
# General.RoamThreshold5G = "-52"; # default -76 General.RoamThreshold5G = "-52"; # default -76
# }; };
# plugins mostly add support for establishing different VPN connections.
# the default plugin set includes mostly proprietary VPNs:
# - fortisslvpn (Fortinet)
# - iodine (DNS tunnels)
# - l2tp
# - openconnect (Cisco Anyconnect / Juniper / ocserv)
# - openvpn
# - vpnc (Cisco VPN)
# - sstp
#
# i don't use these, and notably they drag in huge dependency sets and don't cross compile well.
# e.g. openconnect drags in webkitgtk (for SSO)!
networking.networkmanager.plugins = lib.mkForce [];
networking.firewall.allowedUDPPorts = [ networking.firewall.allowedUDPPorts = [
1900 # to received UPnP advertisements. required by sane-ip-check-upnp 1900 # to received UPnP advertisements. required by sane-ip-check-upnp
]; ];
# keyfile.path = where networkmanager should look for connection credentials
networking.networkmanager.extraConfig = ''
[keyfile]
path=/var/lib/NetworkManager/system-connections
'';
} }

View File

@@ -6,11 +6,13 @@
sane.persist.stores.private.prefix = "/home/colin"; sane.persist.stores.private.prefix = "/home/colin";
sane.persist.sys.plaintext = [ sane.persist.sys.plaintext = [
# TODO: these should be private.. somehow
"/var/log" "/var/log"
"/var/backup" # for e.g. postgres dumps "/var/backup" # for e.g. postgres dumps
]; # TODO: move elsewhere
sane.persist.sys.cryptClearOnBoot = [ "/var/lib/alsa" # preserve output levels, default devices
"/var/lib/colord" # preserve color calibrations (?)
"/var/lib/machines" # maybe not needed, but would be painful to add a VM and forget.
"/var/lib/systemd/backlight" # backlight brightness
"/var/lib/systemd/coredump" "/var/lib/systemd/coredump"
]; ];
} }

View File

@@ -2,8 +2,5 @@
{ ... }: { ... }:
{ {
sane.programs.aerc = { sane.programs.aerc.secrets.".config/aerc/accounts.conf" = ../../../secrets/common/aerc_accounts.conf.bin;
secrets.".config/aerc/accounts.conf" = ../../../secrets/common/aerc_accounts.conf.bin;
mime.associations."x-scheme-handler/mailto" = "aerc.desktop";
};
} }

View File

@@ -1,217 +1,340 @@
{ pkgs, ... }: { lib, pkgs, ... }:
let let
declPackageSet = pkgs: { inherit (builtins) attrNames;
package = null;
suggestedPrograms = pkgs;
};
in
{
sane.programs = {
# PACKAGE SETS
"sane-scripts.backup" = declPackageSet [
"sane-scripts.backup-ls"
"sane-scripts.backup-restore"
];
"sane-scripts.bittorrent" = declPackageSet [
"sane-scripts.bt-add"
"sane-scripts.bt-rm"
"sane-scripts.bt-search"
"sane-scripts.bt-show"
];
"sane-scripts.dev" = declPackageSet [
"sane-scripts.dev-cargo-loop"
"sane-scripts.git-init"
];
"sane-scripts.cli" = declPackageSet [
"sane-scripts.deadlines"
"sane-scripts.find-dotfiles"
"sane-scripts.ip-check"
"sane-scripts.ip-reconnect"
"sane-scripts.private-change-passwd"
"sane-scripts.private-do"
"sane-scripts.private-init"
"sane-scripts.private-lock"
"sane-scripts.private-unlock"
"sane-scripts.rcp"
"sane-scripts.reboot"
"sane-scripts.reclaim-boot-space"
"sane-scripts.reclaim-disk-space"
"sane-scripts.secrets-dump"
"sane-scripts.secrets-unlock"
"sane-scripts.secrets-update-keys"
"sane-scripts.shutdown"
"sane-scripts.ssl-dump"
"sane-scripts.sudo-redirect"
"sane-scripts.sync-from-servo"
"sane-scripts.vpn-down"
"sane-scripts.vpn-up"
"sane-scripts.which"
"sane-scripts.wipe-browser"
];
"sane-scripts.sys-utils" = declPackageSet [
"sane-scripts.ip-port-forward"
];
flattenedPkgs = pkgs // (with pkgs; {
# XXX can't `inherit` a nested attr, so we move them to the toplevel
"cacert.unbundled" = pkgs.cacert.unbundled;
"gnome.cheese" = gnome.cheese;
"gnome.dconf-editor" = gnome.dconf-editor;
"gnome.file-roller" = gnome.file-roller;
"gnome.gnome-disk-utility" = gnome.gnome-disk-utility;
"gnome.gnome-maps" = gnome.gnome-maps;
"gnome.nautilus" = gnome.nautilus;
"gnome.gnome-system-monitor" = gnome.gnome-system-monitor;
"gnome.gnome-terminal" = gnome.gnome-terminal;
"gnome.gnome-weather" = gnome.gnome-weather;
"gnome.totem" = gnome.totem;
"libsForQt5.plasmatube" = libsForQt5.plasmatube;
});
sysadminUtils = declPackageSet [ sysadminPkgs = {
"btrfs-progs" inherit (flattenedPkgs)
btrfs-progs
"cacert.unbundled" # some services require unbundled /etc/ssl/certs "cacert.unbundled" # some services require unbundled /etc/ssl/certs
"cryptsetup" cryptsetup
"dig" dig
"efibootmgr" efibootmgr
"fatresize" fatresize
"fd" fd
"file" file
# "fwupd" gawk
"gawk" git
"git" gptfdisk
"gptfdisk" hdparm
"hdparm" htop
"htop" iftop
"iftop" inetutils # for telnet
"inetutils" # for telnet iotop
"iotop" iptables
"iptables" jq
"jq" killall
"killall" lsof
"lsof" miniupnpc
"miniupnpc" nano
"nano" netcat
# "ncdu" # ncurses disk usage. doesn't cross compile (zig) nethogs
"neovim" nmap
"netcat" openssl
"nethogs" parted
"nmap" pciutils
"openssl" powertop
"parted" pstree
"pciutils" ripgrep
"powertop" screen
"pstree" smartmontools
"ripgrep" socat
"screen" strace
"smartmontools" subversion
"socat" tcpdump
"strace" tree
"subversion" usbutils
"tcpdump" wget
"tree" wirelesstools # iwlist
"usbutils" ;
"wget" };
"wirelesstools" # iwlist sysadminExtraPkgs = {
]; # application-specific packages
sysadminExtraUtils = declPackageSet [ inherit (pkgs)
"backblaze-b2" backblaze-b2
"duplicity" duplicity
"sane-scripts.backup" sqlite # to debug sqlite3 databases
"sqlite" # to debug sqlite3 databases ;
]; };
iphonePkgs = {
inherit (pkgs)
ifuse
ipfs
libimobiledevice
;
};
tuiPkgs = {
inherit (pkgs)
aerc # email client
offlineimap # email mailox sync
sfeed # RSS fetcher
visidata # TUI spreadsheet viewer/editor
w3m
;
};
consoleMediaPkgs = {
inherit (pkgs)
ffmpeg
imagemagick
sox
yt-dlp
;
};
# TODO: split these into smaller groups. # TODO: split these into smaller groups.
# - moby doesn't want a lot of these. # - moby doesn't want a lot of these.
# - categories like # - categories like
# - dev? # - dev?
# - debugging? # - debugging?
consoleUtils = declPackageSet [ consolePkgs = {
"alsaUtils" # for aplay, speaker-test inherit (pkgs)
# "cdrtools" alsaUtils # for aplay, speaker-test
"clinfo" cdrtools
"dmidecode" clinfo
"dtrx" # `unar` alternative, "Do The Right eXtraction" dmidecode
"efivar" efivar
# "flashrom" flashrom
"git" # needed as a user package, for config. fwupd
# "gnupg" gh # MS GitHub cli
# "gocryptfs" git # needed as a user package, for config.
# "gopass" gnupg
# "gopass-jsonapi" gocryptfs
"helix" # text editor gopass # TODO: shouldn't be needed here
"kitty" # TODO: move to GUI, but `ssh servo` from kitty sets `TERM=xterm-kitty` in the remove and breaks things gopass-jsonapi
"libsecret" # for managing user keyrings. TODO: what needs this? lift into the consumer kitty # TODO: move to GUI, but `ssh servo` from kitty sets `TERM=xterm-kitty` in the remove and breaks things
"lm_sensors" # for sensors-detect. TODO: what needs this? lift into the consumer libsecret # for managing user keyrings
"lshw" lm_sensors # for sensors-detect
# "memtester" lshw
"neovim" # needed as a user package, for swap persistence # memtester
# "nettools" neovim
# "networkmanager" # nettools
# "nixos-generators" # networkmanager
"nmon" nixpkgs-review
# "node2nix" # nixos-generators
# "oathToolkit" # for oathtool nmon
# "ponymix" # node2nix
"pulsemixer" # oathToolkit # for oathtool
"python3" # ponymix
# "python3Packages.eyeD3" # music tagging pulsemixer
"ripgrep" # needed as a user package so that its user-level config file can be installed python3
"rsync" ripgrep # needed as a user package so that its user-level config file can be installed
"sane-scripts.bittorrent" rsync
"sane-scripts.cli" # python3Packages.eyeD3 # music tagging
"snapper" sane-scripts
"sops" sequoia
"speedtest-cli" snapper
# "ssh-to-age" sops
"sudo" speedtest-cli
# "tageditor" # music tagging # ssh-to-age
# "unar" sudo
"wireguard-tools" # tageditor # music tagging
"xdg-terminal-exec" unar
"xdg-utils" # for xdg-open wireguard-tools
# "yarn" xdg-utils # for xdg-open
"zsh" # yarn
]; zsh
;
};
desktopConsoleUtils = declPackageSet [ guiPkgs = {
"gh" # MS GitHub cli inherit (flattenedPkgs)
"nix-index" # celluloid # mpv frontend
"nixpkgs-review" cozy # audiobook player
"sane-scripts.dev" # emote
"sequoia" evince # works on phosh
];
consoleMediaUtils = declPackageSet [ # { pkg = fluffychat-moby; persist.plaintext = [ ".local/share/chat.fluffy.fluffychat" ]; } # TODO: ship normal fluffychat on non-moby?
"ffmpeg"
"imagemagick"
"sox"
"yt-dlp"
];
tuiApps = declPackageSet [ # foliate # e-book reader
"aerc" # email client
"msmtp" # sendmail
"offlineimap" # email mailbox sync
"sfeed" # RSS fetcher
"visidata" # TUI spreadsheet viewer/editor
"w3m" # web browser
];
iphoneUtils = declPackageSet [ # XXX by default fractal stores its state in ~/.local/share/<UUID>.
"ifuse" # after logging in, manually change ~/.local/share/keyrings/... to point it to some predictable subdir.
"ipfs" # then reboot (so that libsecret daemon re-loads the keyring...?)
"libimobiledevice" # { pkg = fractal-latest; persist.private = [ ".local/share/fractal" ]; }
"sane-scripts.sync-from-iphone" # { pkg = fractal-next; persist.private = [ ".local/share/fractal" ]; }
];
devPkgs = declPackageSet [ # "gnome.cheese"
"clang" # gnome-feeds # RSS reader (with claimed mobile support)
"nodejs" "gnome.file-roller"
"tree-sitter" # "gnome.gnome-maps" # works on phosh
]; "gnome.nautilus"
# gnome-podcasts
# "gnome.gnome-system-monitor"
# "gnome.gnome-terminal" # works on phosh
# "gnome.gnome-weather"
gpodder
gthumb
jellyfin-media-player
komikku
koreader
# lollypop
# mpv
# networkmanagerapplet
# newsflash
nheko
pavucontrol
# picard # music tagging
# "libsForQt5.plasmatube" # Youtube player
soundconverter
# sublime-music
# tdesktop # broken on phosh
# tokodon
vlc
# pleroma client (Electron). input is broken on phosh. TODO(2023/02/02): fix electron19 input (insecure)
# whalebird
xterm # broken on phosh
;
};
desktopGuiPkgs = {
inherit (flattenedPkgs)
audacity
brave # for the integrated wallet -- as a backup
chromium
dino
electrum
element-desktop
font-manager
gajim # XMPP client
gimp # broken on phosh
"gnome.dconf-editor"
"gnome.gnome-disk-utility"
# "gnome.totem" # video player, supposedly supports UPnP
handbrake
hase
inkscape
kdenlive
kid3 # audio tagging
krita
libreoffice-fresh
mumble
obsidian
slic3r
steam
wireshark # could maybe ship the cli as sysadmin pkg
;
};
x86GuiPkgs = {
inherit (pkgs)
discord
# kaiteki # Pleroma client
# gnome.zenity # for kaiteki (it will use qarma, kdialog, or zenity)
# gpt2tc # XXX: unreliable mirror
# INDIVIDUAL PACKAGE DEFINITIONS # logseq # Personal Knowledge Management
losslesscut-bin
makemkv
monero-gui
signal-desktop
spotify
tor-browser-bundle-bin
zecwallet-lite
;
};
# packages not part of any package set; not enabled by default
otherPkgs = {
inherit (pkgs)
lemmy-server
mx-sanebot
stepmania
;
};
# define -- but don't enable -- the packages in some attrset.
declarePkgs = pkgsAsAttrs: lib.mapAttrs (_n: p: {
# no need to actually define the package here: it's defaulted
# package = mkDefault p;
}) pkgsAsAttrs;
in
{
sane.programs = lib.mkMerge [
(declarePkgs consoleMediaPkgs)
(declarePkgs consolePkgs)
(declarePkgs desktopGuiPkgs)
(declarePkgs guiPkgs)
(declarePkgs iphonePkgs)
(declarePkgs sysadminPkgs)
(declarePkgs sysadminExtraPkgs)
(declarePkgs tuiPkgs)
(declarePkgs x86GuiPkgs)
(declarePkgs otherPkgs)
{
# link the various package sets into their own meta packages
consoleMediaUtils = {
package = null;
suggestedPrograms = attrNames consoleMediaPkgs;
};
consoleUtils = {
package = null;
suggestedPrograms = attrNames consolePkgs;
};
desktopGuiApps = {
package = null;
suggestedPrograms = attrNames desktopGuiPkgs;
};
guiApps = {
package = null;
suggestedPrograms = (attrNames guiPkgs)
++ [ "web-browser" ]
++ [ "tuiApps" ]
++ lib.optional (pkgs.system == "x86_64-linux") "x86GuiApps";
};
iphoneUtils = {
package = null;
suggestedPrograms = attrNames iphonePkgs;
};
sysadminUtils = {
package = null;
suggestedPrograms = attrNames sysadminPkgs;
};
sysadminExtraUtils = {
package = null;
suggestedPrograms = attrNames sysadminExtraPkgs;
};
tuiApps = {
package = null;
suggestedPrograms = attrNames tuiPkgs;
};
x86GuiApps = {
package = null;
suggestedPrograms = attrNames x86GuiPkgs;
};
}
{
# nontrivial package definitions
dino.persist.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.persist.private = [ ".config/discord" ]; discord.persist.private = [ ".config/discord" ];
# creds/session keys, etc
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.persist.plaintext = [ ".local/share/Emote" ]; emote.persist.plaintext = [ ".local/share/Emote" ];
fluffychat-moby.persist.plaintext = [ ".local/share/chat.fluffy.fluffychat" ];
# 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.private = [ ".config/gh" ];
@@ -222,6 +345,13 @@ in
mumble.persist.private = [ ".local/share/Mumble" ]; mumble.persist.private = [ ".local/share/Mumble" ];
# not strictly necessary, but allows caching articles; offline use, etc.
nheko.persist.private = [
".config/nheko" # config file (including client token)
".cache/nheko" # media cache
".local/share/nheko" # per-account state database
];
# settings (electron app) # settings (electron app)
obsidian.persist.plaintext = [ ".config/obsidian" ]; obsidian.persist.plaintext = [ ".config/obsidian" ];
@@ -238,8 +368,8 @@ in
tokodon.persist.private = [ ".cache/KDE/tokodon" ]; tokodon.persist.private = [ ".cache/KDE/tokodon" ];
# hardenedMalloc solves an "unable to connect to Tor" error when pressing the "connect" button # hardenedMalloc solves a crash at startup
# - still required as of 2023/07/14 # TODO 2023/02/02: is this safe to remove yet?
tor-browser-bundle-bin.package = pkgs.tor-browser-bundle-bin.override { tor-browser-bundle-bin.package = pkgs.tor-browser-bundle-bin.override {
useHardenedMalloc = false; useHardenedMalloc = false;
}; };
@@ -250,5 +380,6 @@ in
# 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.private = [ ".zcash" ];
}; }
];
} }

View File

@@ -1,44 +0,0 @@
{ pkgs, ... }:
let
chattyNoOauth = pkgs.chatty.override {
# the OAuth feature (presumably used for web-based logins) pulls a full webkitgtk.
# especially when using the gtk3 version of evolution-data-server, it's an ancient webkitgtk_4_1.
# disable OAuth for a faster build & smaller closure
evolution-data-server = pkgs.evolution-data-server.override {
enableOAuth2 = false;
gnome-online-accounts = pkgs.gnome-online-accounts.override {
# disables the upstream "goabackend" feature -- presumably "Gnome Online Accounts Backend"
# frees us from webkit_4_1, in turn.
enableBackend = false;
gvfs = pkgs.gvfs.override {
# saves 20 minutes of build time, for unused feature
samba = null;
};
};
};
};
chatty-latest = pkgs.chatty-latest.override {
evolution-data-server-gtk4 = pkgs.evolution-data-server-gtk4.override {
gnome-online-accounts = pkgs.gnome-online-accounts.override {
# disables the upstream "goabackend" feature -- presumably "Gnome Online Accounts Backend"
# frees us from webkit_4_1, in turn.
enableBackend = false;
gvfs = pkgs.gvfs.override {
# saves 20 minutes of build time, for unused feature
samba = null;
};
};
};
};
in
{
sane.programs.chatty = {
# package = chattyNoOauth;
package = chatty-latest;
suggestedPrograms = [ "gnome-keyring" ];
persist.private = [
".local/share/chatty" # matrix avatars and files
# ".purple" # XMPP stuff
];
};
}

View File

@@ -4,48 +4,28 @@
imports = [ imports = [
./aerc.nix ./aerc.nix
./assorted.nix ./assorted.nix
./chatty.nix
./cozy.nix ./cozy.nix
./element-desktop.nix
./epiphany.nix
./evince.nix
./firefox.nix
./fontconfig.nix
./fractal.nix
./fwupd.nix
./git.nix ./git.nix
./gnome-feeds.nix ./gnome-feeds.nix
./gnome-keyring.nix
./gpodder.nix ./gpodder.nix
./gthumb.nix
./helix.nix
./imagemagick.nix ./imagemagick.nix
./jellyfin-media-player.nix ./jellyfin-media-player.nix
./kitty ./kitty
./komikku.nix ./komikku.nix
./koreader ./koreader
./libreoffice.nix ./libreoffice.nix
./lemoa.nix
./megapixels.nix
./mepo.nix
./mpv.nix ./mpv.nix
./msmtp.nix
./neovim.nix ./neovim.nix
./newsflash.nix ./newsflash.nix
./nheko.nix
./nix-index.nix
./obsidian.nix
./offlineimap.nix ./offlineimap.nix
./ripgrep.nix ./ripgrep.nix
./sfeed.nix ./sfeed.nix
./splatmoji.nix ./splatmoji.nix
./steam.nix ./steam.nix
./sublime-music.nix ./sublime-music.nix
./tangram.nix
./tuba.nix
./vlc.nix ./vlc.nix
./web-browser.nix
./wireshark.nix ./wireshark.nix
./xarchiver.nix
./zeal.nix ./zeal.nix
./zsh ./zsh
]; ];

View File

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

View File

@@ -1,45 +0,0 @@
# epiphany web browser
# - GTK4/webkitgtk
#
# usability notes:
# - touch-based scroll works well (for moby)
# - URL bar constantly resets cursor to the start of the line as i type
# - maybe due to the URLbar suggestions getting in the way
{ pkgs, ... }:
{
sane.programs.epiphany = {
# XXX(2023/07/08): running on moby without this hack fails, with:
# - `bwrap: Can't make symlink at /var/run: File exists`
# this could be due to:
# - epiphany is somewhere following a symlink into /var/run instead of /run
# - (nothing in `env` or in this repo touches /var/run)
# - no xdg-desktop-portal is installed (unlikely)
#
# a few other users have hit this, in different contexts:
# - <https://gitlab.gnome.org/GNOME/gnome-builder/-/issues/1164>
# - <https://github.com/flatpak/flatpak/issues/3477>
# - <https://github.com/NixOS/nixpkgs/issues/197085>
package = pkgs.epiphany.overrideAttrs (upstream: {
preFixup = ''
gappsWrapperArgs+=(
--set WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS "1"
);
'' + (upstream.preFixup or "");
});
persist.private = [
".cache/epiphany"
".local/share/epiphany"
# also .config/epiphany, but appears empty
];
mime.priority = 200; # default priority is 100: install epiphany only as a fallback
mime.associations = let
desktop = "org.gnome.Epiphany.desktop";
in {
"text/html" = desktop;
"x-scheme-handler/http" = desktop;
"x-scheme-handler/https" = desktop;
"x-scheme-handler/about" = desktop;
"x-scheme-handler/unknown" = desktop;
};
};
}

View File

@@ -1,4 +0,0 @@
{ ... }:
{
sane.programs.evince.mime.associations."application/pdf" = "org.gnome.Evince.desktop";
}

View File

@@ -1,15 +0,0 @@
{ config, lib, pkgs, ... }:
{
fonts = lib.mkIf config.sane.programs.fontconfig.enabled {
fontconfig.enable = true;
fontconfig.defaultFonts = {
emoji = [ "Font Awesome 6 Free" "Noto Color Emoji" ];
monospace = [ "Hack" ];
serif = [ "DejaVu Serif" ];
sansSerif = [ "DejaVu Sans" ];
};
#vvv enables dejavu_fonts, freefont_ttf, gyre-fonts, liberation_ttf, unifont, noto-fonts-emoji
enableDefaultPackages = true;
packages = with pkgs; [ font-awesome noto-fonts-emoji hack-font ];
};
}

View File

@@ -1,12 +0,0 @@
{ pkgs, ... }:
{
sane.programs.fractal = {
# package = pkgs.fractal-latest;
package = pkgs.fractal-next;
# XXX by default fractal stores its state in ~/.local/share/stable/<UUID>.
persist.private = [ ".local/share/stable" ];
suggestedPrograms = [ "gnome-keyring" ];
};
}

View File

@@ -1,7 +0,0 @@
{ config, lib, ... }:
{
services.fwupd = lib.mkIf config.sane.programs.fwupd.enabled {
# enables the dbus service, which i think the frontend speaks to.
enable = true;
};
}

View File

@@ -1,8 +1,6 @@
{ lib, pkgs, ... }: { lib, pkgs, ... }:
let let
# TODO: use formats.gitIni or lib.generators.toGitINI
# - see: <repo:nixos/nixpkgs:pkgs/pkgs-lib/formats.nix>
mkCfg = lib.generators.toINI { }; mkCfg = lib.generators.toINI { };
in in
{ {
@@ -13,15 +11,7 @@ in
user.name = "Colin"; user.name = "Colin";
user.email = "colin@uninsane.org"; user.email = "colin@uninsane.org";
alias.br = "branch";
alias.co = "checkout"; alias.co = "checkout";
alias.cp = "cherry-pick";
alias.d = "difftool";
alias.dif = "diff"; # common typo
alias.difsum = "diff --compact-summary"; #< show only the list of files which changed, not contents
alias.rb = "rebase";
alias.st = "status";
alias.stat = "status";
# difftastic docs: # difftastic docs:
# - <https://difftastic.wilfred.me.uk/git.html> # - <https://difftastic.wilfred.me.uk/git.html>
@@ -32,10 +22,5 @@ in
# render dates as YYYY-MM-DD HH:MM:SS +TZ # render dates as YYYY-MM-DD HH:MM:SS +TZ
log.date = "iso"; log.date = "iso";
sendemail.annotate = "yes";
sendemail.confirm = "always";
stash.showPatch = true;
}; };
} }

View File

@@ -1,10 +0,0 @@
{ config, lib, pkgs, ... }:
{
sane.programs.gnome-keyring = {
package = pkgs.gnome.gnome-keyring;
};
# adds gnome-keyring as a xdg-data-portal (xdg.portal)
services.gnome.gnome-keyring = lib.mkIf config.sane.programs.gnome-keyring.enabled {
enable = true;
};
}

View File

@@ -1,13 +0,0 @@
{ pkgs, ... }:
{
sane.programs.gthumb = {
# compile without webservices to avoid the expensive webkitgtk dependency
package = pkgs.gthumb.override { withWebservices = false; };
mime.associations = {
"image/heif" = "org.gnome.gThumb.desktop"; # apple codec
"image/png" = "org.gnome.gThumb.desktop";
"image/jpeg" = "org.gnome.gThumb.desktop";
"image/svg+xml" = "org.gnome.gThumb.desktop";
};
};
}

View File

@@ -1,22 +0,0 @@
# Helix text editor
# debug log: `~/.cache/helix/helix.log`
# binary name is `hx`
{ ... }:
{
sane.programs.helix = {
# 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" ];
fs.".config/helix/config.toml".symlink.text = ''
# docs: <https://docs.helix-editor.com/configuration.html>
[editor.soft-wrap]
enable = true
[editor.whitespace.render]
space = "all"
tab = "all"
newline = "none"
'';
};
}

View File

@@ -6,4 +6,5 @@
}; };
suggestedPrograms = [ "ghostscript" ]; suggestedPrograms = [ "ghostscript" ];
}; };
sane.programs.ghostscript = {};
} }

View File

@@ -3,9 +3,7 @@
{ {
sane.programs.jellyfin-media-player = { sane.programs.jellyfin-media-player = {
# package = pkgs.jellyfin-media-player; # package = pkgs.jellyfin-media-player;
# qt6 version is slightly buggy, but also most qtwebengine apps (e.g. zeal) are on qt5 package = pkgs.jellyfin-media-player-qt6;
# so using qt6 would force yet *another* qtwebengine compile.
# package = pkgs.jellyfin-media-player-qt6;
# 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

View File

@@ -1,8 +1,7 @@
{ lib, ... }: { ... }:
{ {
sane.programs.kitty = { sane.programs.kitty.fs.".config/kitty/kitty.conf".symlink.text = ''
fs.".config/kitty/kitty.conf".symlink.text = ''
# 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
@@ -10,8 +9,6 @@
map ctrl+n new_os_window_with_cwd map ctrl+n new_os_window_with_cwd
include ${./PaperColor_dark.conf} include ${./PaperColor_dark.conf}
''; '';
env.TERMINAL = lib.mkDefault "kitty";
};
# include ${pkgs.kitty-themes}/themes/PaperColor_dark.conf # include ${pkgs.kitty-themes}/themes/PaperColor_dark.conf

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, sane-lib, ... }: { config, lib, sane-lib, ... }:
let let
feeds = sane-lib.feeds; feeds = sane-lib.feeds;
@@ -10,12 +10,11 @@ let
# limit = 0 => download and keep *all* articles # limit = 0 => download and keep *all* articles
# download_full_article = true => populate feed by downloading the webpage -- not just what's encoded in the RSS <article> tags # download_full_article = true => populate feed by downloading the webpage -- not just what's encoded in the RSS <article> tags
# - use this for articles where the RSS only encodes content previews # - use this for articles where the RSS only encodes content previews
# - in practice, most articles don't work with download_full_article = false
# enable_filter = true => only render content that matches the filter_element css selector. # enable_filter = true => only render content that matches the filter_element css selector.
let fields = [ let fields = [
(lib.escapeShellArg feed.url) (lib.escapeShellArg feed.url)
"limit = 5" "limit = 5"
"download_full_article = true" "download_full_article = false"
"include_images = true" "include_images = true"
"enable_filter = false" "enable_filter = false"
"filter_element = \"\"" "filter_element = \"\""
@@ -23,7 +22,6 @@ let
) wantedFeeds; ) wantedFeeds;
in { in {
sane.programs.koreader = { sane.programs.koreader = {
package = pkgs.koreader-from-src;
# koreader applies these lua "patches" at boot: # koreader applies these lua "patches" at boot:
# - <https://github.com/koreader/koreader/wiki/User-patches> # - <https://github.com/koreader/koreader/wiki/User-patches>
# - TODO: upstream this patch to koreader # - TODO: upstream this patch to koreader

View File

@@ -1,7 +0,0 @@
{ ... }:
{
sane.programs.lemoa = {
# creds
persist.private = [ ".local/share/io.github.lemmygtk.lemoa" ];
};
}

View File

@@ -1,13 +1,8 @@
{ pkgs, ... }: { ... }:
{ {
sane.programs.libreoffice = { # libreoffice: disable first-run stuff
# package = pkgs.libreoffice-bin; sane.programs.libreoffice-fresh.fs.".config/libreoffice/4/user/registrymodifications.xcu".symlink.text = ''
# package = pkgs.libreoffice-still;
package = pkgs.libreoffice-fresh;
# disable first-run stuff
fs.".config/libreoffice/4/user/registrymodifications.xcu".symlink.text = ''
<?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>
@@ -16,5 +11,4 @@
''; '';
# <item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeDonateShown" oor:op="fuse"><value>1667693880</value></prop></item> # <item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeDonateShown" oor:op="fuse"><value>1667693880</value></prop></item>
# <item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeGetInvolvedShown" oor:op="fuse"><value>1667693880</value></prop></item> # <item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeGetInvolvedShown" oor:op="fuse"><value>1667693880</value></prop></item>
};
} }

View File

@@ -1,11 +0,0 @@
{ pkgs, ... }:
{
sane.programs.megapixels.package = pkgs.megapixels.override {
# megapixels uses zbar to read barcodes.
# zbar by default ships zbarcam-gtk and zbarcam-qt, neither of which megapixels needs.
# but the latter takes a dep on qt, which bloats the closure and the build, so disable this feature.
zbar = pkgs.zbar.override {
enableVideo = false;
};
};
}

View File

@@ -1,26 +0,0 @@
# docs: <https://git.sr.ht/~mil/mepo>
# irc #mepo:irc.oftc.net
{ config, lib, ... }:
{
sane.programs.mepo = {
persist.plaintext = [ ".cache/mepo/tiles" ];
# ~/.cache/mepo/savestate has precise coordinates and pins: keep those private
persist.private = [
{ type = "file"; path = ".cache/mepo/savestate"; }
];
# give mepo access to gpsd for location data, if that's enabled.
# same with geoclue2.
suggestedPrograms = lib.optional config.services.gpsd.enable "gpsd"
++ lib.optional config.services.geoclue2.enable "geoclue2-with-demo-agent"
;
};
# programs.mepo = lib.mkIf config.sane.programs.mepo.enabled {
# # enable location services (via geoclue)
# enable = true;
# # more precise, via gpsd ("may require additional config")
# # programs.mepo.gpsd.enable = true
# };
}

View File

@@ -1,82 +1,13 @@
# mpv docs: { ... }:
# - <https://mpv.io/manual/master>
# - <https://github.com/mpv-player/mpv/wiki>
# curated mpv mods/scripts/users:
# - <https://github.com/stax76/awesome-mpv>
{ pkgs, ... }:
{ {
sane.programs.mpv = { sane.programs.mpv = {
package = pkgs.wrapMpv pkgs.mpv-unwrapped {
youtubeSupport = false; #< XXX(2023/08/03): doesn't cross compile until next staging -> master merge
scripts = with pkgs.mpvScripts; [
mpris
# uosc
pkgs.mpv-uosc-latest
];
};
persist.plaintext = [ ".config/mpv/watch_later" ]; persist.plaintext = [ ".config/mpv/watch_later" ];
fs.".config/mpv/input.conf".symlink.text = '' # format is <key>=%<length>%<value>
# let volume keys be interpreted by the system.
# this is important for sxmo.
VOLUME_UP ignore
VOLUME_DOWN ignore
'';
fs.".config/mpv/mpv.conf".symlink.text = '' fs.".config/mpv/mpv.conf".symlink.text = ''
save-position-on-quit=yes save-position-on-quit=%3%yes
keep-open=yes keep-open=%3%yes
# use uosc instead (for On Screen Controls)
osc=no
# uosc provides its own seeking/volume indicators, so you also don't need this
osd-bar=no
# uosc will draw its own window controls if you disable window border
border=no
''; '';
fs.".config/mpv/script-opts/osc.conf".symlink.text = ''
# make the on-screen controls *always* visible
# unfortunately, this applies to full-screen as well
# - docs: <https://mpv.io/manual/master/#on-screen-controller-visibility>
# if uosc is installed, this file is unused
visibility=always
'';
fs.".config/mpv/script-opts/uosc.conf".symlink.text = let
play_pause_btn = "cycle:play_arrow:pause:no=pause/yes=play_arrow";
rev_btn = "command:replay_10:seek -10";
fwd_btn = "command:forward_30:seek 30";
in ''
# docs:
# - <https://github.com/tomasklaen/uosc>
# - <https://superuser.com/questions/1775550/add-new-buttons-to-mpv-uosc-ui>
timeline_style=bar
timeline_persistency=paused,audio
controls_persistency=paused,audio
volume_persistency=audio
volume_opacity=0.75
# speed_persistency=paused,audio
# vvv want a close button?
top_bar=always
top_bar_persistency=paused
controls=menu,<video>subtitles,<has_many_audio>audio,<has_many_video>video,<has_many_edition>editions,<stream>stream-quality,space,${rev_btn},${play_pause_btn},${fwd_btn},space,speed:1.0,gap,<video>fullscreen
text_border=6.0
font_bold=yes
background_text=ff8080
foreground=ff8080
ui_scale=1.0
'';
mime.priority = 200; # default = 100; 200 means to yield to other apps
mime.associations."audio/flac" = "mpv.desktop";
mime.associations."audio/mpeg" = "mpv.desktop";
mime.associations."audio/x-vorbis+ogg" = "mpv.desktop";
mime.associations."video/mp4" = "mpv.desktop";
mime.associations."video/quicktime" = "mpv.desktop";
mime.associations."video/webm" = "mpv.desktop";
mime.associations."video/x-matroska" = "mpv.desktop";
}; };
} }

View File

@@ -1,25 +0,0 @@
# docs: <https://nixos.wiki/wiki/Msmtp>
# validate with e.g.
# - `echo -e "Content-Type: text/plain\r\nSubject: Test\r\n\r\nHello World" | sendmail test@uninsane.org`
{ config, lib, ... }:
{
sane.programs.msmtp = {
secrets.".config/msmtp/password.txt" = ../../../secrets/common/msmtp_password.txt.bin;
};
programs.msmtp = lib.mkIf config.sane.programs.msmtp.enabled {
enable = true;
accounts = {
default = {
auth = true;
tls = true;
tls_starttls = false; # needed else sendmail hangs
from = "Colin <colin@uninsane.org>";
host = "mx.uninsane.org";
user = "colin";
passwordeval = "cat ~/.config/msmtp/password.txt";
};
};
};
}

View File

@@ -5,21 +5,35 @@ let
inherit (lib) concatMapStrings mkIf 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: vim-surround: https://github.com/tpope/vim-surround
{ plugin = vim-surround; }
# docs: fzf-vim (fuzzy finder): https://github.com/junegunn/fzf.vim # docs: fzf-vim (fuzzy finder): https://github.com/junegunn/fzf.vim
plugin = fzf-vim; { plugin = fzf-vim; }
} ({
{ # docs: tex-conceal-vim: https://github.com/KeitaNakamura/tex-conceal.vim/
plugin = tex-conceal-vim;
type = "viml";
config = ''
" present prettier fractions
let g:tex_conceal_frac=1
'';
})
({
plugin = vim-SyntaxRange;
type = "viml";
config = ''
" enable markdown-style codeblock highlighting for tex code
autocmd BufEnter * call SyntaxRange#Include('```tex', '```', 'tex', 'NonText')
" autocmd Syntax tex set conceallevel=2
'';
})
({
# treesitter syntax highlighting: https://nixos.wiki/wiki/Tree_sitters # treesitter syntax highlighting: https://nixos.wiki/wiki/Tree_sitters
# docs: https://github.com/nvim-treesitter/nvim-treesitter # docs: https://github.com/nvim-treesitter/nvim-treesitter
# config taken from: https://github.com/i077/system/blob/master/modules/home/neovim/default.nix # config taken from: https://github.com/i077/system/blob/master/modules/home/neovim/default.nix
# this is required for tree-sitter to even highlight # this is required for tree-sitter to even highlight
plugin = nvim-treesitter.withPlugins (_: nvim-treesitter.allGrammars ++ [ plugin = nvim-treesitter.withAllGrammars;
# XXX: this is apparently not enough to enable syntax highlighting!
# nvim-treesitter ships its own queries which may be distinct from e.g. helix.
# the queries aren't included when i ship the grammar in this manner
pkgs.tree-sitter-nix-shell
]);
type = "lua"; type = "lua";
config = '' config = ''
require'nvim-treesitter.configs'.setup { require'nvim-treesitter.configs'.setup {
@@ -50,48 +64,15 @@ let
vim.o.foldmethod = 'expr' vim.o.foldmethod = 'expr'
vim.o.foldexpr = 'nvim_treesitter#foldexpr()' vim.o.foldexpr = 'nvim_treesitter#foldexpr()'
''; '';
} })
{
# docs: tex-conceal-vim: https://github.com/KeitaNakamura/tex-conceal.vim/
plugin = tex-conceal-vim;
type = "viml";
config = ''
" present prettier fractions
let g:tex_conceal_frac=1
'';
}
{
# source: <https://github.com/LnL7/vim-nix>
# fixes auto-indent (incl tab size) when editing .nix files
plugin = vim-nix;
}
{
# docs: surround-nvim: https://github.com/ur4ltz/surround.nvim/
# docs: vim-surround: https://github.com/tpope/vim-surround
plugin = vim-surround;
}
{
plugin = vim-SyntaxRange;
type = "viml";
config = ''
" enable markdown-style codeblock highlighting for tex code
autocmd BufEnter * call SyntaxRange#Include('```tex', '```', 'tex', 'NonText')
" autocmd Syntax tex set conceallevel=2
'';
}
]; ];
plugin-packages = map (p: p.plugin) plugins; plugin-packages = map (p: p.plugin) plugins;
plugin-config-viml = concatMapStrings (p: optionalString (p.type or "" == "viml") p.config) plugins; plugin-config-tex = concatMapStrings (p: optionalString (p.type or "" == "viml") p.config) plugins;
plugin-config-lua = concatMapStrings (p: optionalString (p.type or "" == "lua") p.config) plugins; plugin-config-lua = concatMapStrings (p: optionalString (p.type or "" == "lua") p.config) plugins;
in 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.private = [ ".cache/vim-swap" ];
env.EDITOR = "vim";
# git claims it should use EDITOR, but it doesn't!
env.GIT_EDITOR = "vim";
};
programs.neovim = mkIf config.sane.programs.neovim.enabled { programs.neovim = mkIf config.sane.programs.neovim.enabled {
# neovim: https://github.com/neovim/neovim # neovim: https://github.com/neovim/neovim
@@ -99,7 +80,7 @@ in
viAlias = true; viAlias = true;
vimAlias = true; vimAlias = true;
configure = { configure = {
packages.plugins = { packages.myVimPackage = {
start = plugin-packages; start = plugin-packages;
}; };
customRC = '' customRC = ''
@@ -135,8 +116,8 @@ in
set list set list
set listchars=tab:\·,trail:·,extends:,precedes:,nbsp: set listchars=tab:\·,trail:·,extends:,precedes:,nbsp:
""""" PLUGIN CONFIG (vim) """"" PLUGIN CONFIG (tex)
${plugin-config-viml} ${plugin-config-tex}
""""" PLUGIN CONFIG (lua) """"" PLUGIN CONFIG (lua)
lua <<EOF lua <<EOF

View File

@@ -1,9 +0,0 @@
{ ... }:
{
# 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
];
}

View File

@@ -1,7 +0,0 @@
{ config, lib, ... }:
{
# provides `nix-locate`, backed by the manually run `nix-index`
sane.programs.nix-index = {
persist.plaintext = [ ".cache/nix-index" ];
};
}

View File

@@ -1,4 +0,0 @@
{ ... }:
{
sane.programs.obsidian.mime.associations."text/markdown" = "obsidian.desktop";
}

View File

@@ -10,11 +10,13 @@
# 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
history_length=5 history_length=5
paste_command=${pkgs.wtype}/bin/wtype -M Ctrl -k v # TODO: wayland equiv
paste_command=xdotool key ctrl+v
# rofi_command=${pkgs.wofi}/bin/wofi --dmenu --insensitive --cache-file /dev/null # rofi_command=${pkgs.wofi}/bin/wofi --dmenu --insensitive --cache-file /dev/null
rofi_command=${pkgs.fuzzel}/bin/fuzzel -d -i -w 60 rofi_command=${pkgs.fuzzel}/bin/fuzzel -d -i -w 60
xdotool_command=${pkgs.wtype}/bin/wtype xdotool_command=${pkgs.wtype}/bin/wtype
xsel_command=${pkgs.findutils}/bin/xargs ${pkgs.wl-clipboard}/bin/wl-copy # TODO: wayland equiv
xsel_command=xsel -b -i
''; '';
}; };
} }

View File

@@ -1,42 +0,0 @@
# Tangram is a GTK/webkit browser
# it views each tab as a distinct application, persisted, and where the 'home' button action is specific to each tab.
# it supports ephemeral tabs, but UX is heavily geared to GCing those as early as possible.
{ pkgs, ... }:
let
dconfProfile = pkgs.writeTextFile {
name = "dconf-tangram-profile";
destination = "/etc/dconf/profile/tangram";
text = ''
user-db:tangram
system-db:site
'';
};
in
{
sane.programs.tangram = {
# XXX(2023/07/08): running on moby without disabling the webkit sandbox fails, with:
# - `bwrap: Can't make symlink at /var/run: File exists`
# see epiphany.nix for more info
package = pkgs.tangram.overrideAttrs (upstream: {
preFixup = ''
gappsWrapperArgs+=(
--set WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS "1"
--set DCONF_PROFILE "${dconfProfile}/etc/dconf/profile/tangram"
);
'' + (upstream.preFixup or "");
});
persist.private = [
".cache/Tangram"
".local/share/Tangram"
# dconf achieves atomic writes via `mv`, so a symlink doesn't work
# moreover, i have to persist the *whole* directory:
# - `user-db:tangram/user` causes a schema failure
# - bind-mounting `~/private/.config/dconf/tangram` causes dconf to try a cross-fs `mv`, which fails
# - dconf provides no way to specify an alternate ~/.config/dconf dir, except by overriding XDG_CONFIG_HOME
# { type = "file"; path = ".config/dconf/tangram"; method = "bind"; }
".config/dconf"
];
};
}

View File

@@ -1,4 +0,0 @@
{ ... }:
{
sane.programs.tuba.suggestedPrograms = [ "gnome-keyring" ];
}

View File

@@ -10,13 +10,8 @@ let
in in
{ {
sane.programs.vlc = { sane.programs.vlc = {
persist.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) persist.plaintext = [ ".config/vlc" ];
".config/vlc"
# vlc caches artwork. i'm not sure where it gets the artwork (internet? embedded metadata?)
".cache/vlc"
];
fs.".config/vlc/vlcrc".symlink.text = '' fs.".config/vlc/vlcrc".symlink.text = ''
[podcast] [podcast]
podcast-urls=${podcast-urls} podcast-urls=${podcast-urls}
@@ -25,13 +20,5 @@ in
[qt] [qt]
qt-privacy-ask=0 qt-privacy-ask=0
''; '';
mime.associations."audio/flac" = "vlc.desktop";
mime.associations."audio/mpeg" = "vlc.desktop";
mime.associations."audio/x-vorbis+ogg" = "vlc.desktop";
mime.associations."video/mp4" = "vlc.desktop";
mime.associations."video/quicktime" = "vlc.desktop";
mime.associations."video/webm" = "vlc.desktop";
mime.associations."video/x-matroska" = "vlc.desktop";
}; };
} }

View File

@@ -9,20 +9,21 @@
{ config, lib, pkgs, ...}: { config, lib, pkgs, ...}:
with lib; with lib;
let let
cfg = config.sane.programs.firefox.config; cfg = config.sane.programs.web-browser.config;
mobile-prefs = lib.optionals false pkgs.librewolf-pmos-mobile.extraPrefsFiles;
# allow easy switching between firefox and librewolf with `defaultSettings`, below # allow easy switching between firefox and librewolf with `defaultSettings`, below
librewolfSettings = { librewolfSettings = {
browser = pkgs.librewolf-unwrapped; browser = pkgs.librewolf-unwrapped;
extraPrefsFiles = pkgs.librewolf-unwrapped.extraPrefsFiles ++ mobile-prefs; # browser = pkgs.librewolf-unwrapped.overrideAttrs (drv: {
# # this allows side-loading unsigned addons
# MOZ_REQUIRE_SIGNING = false;
# });
libName = "librewolf"; libName = "librewolf";
dotDir = ".librewolf"; dotDir = ".librewolf";
cacheDir = ".cache/librewolf"; cacheDir = ".cache/librewolf"; # TODO: is it?
desktop = "librewolf.desktop"; desktop = "librewolf.desktop";
}; };
firefoxSettings = { firefoxSettings = {
browser = pkgs.firefox-esr-unwrapped; browser = pkgs.firefox-esr-unwrapped;
extraPrefsFiles = mobile-prefs;
libName = "firefox"; libName = "firefox";
dotDir = ".mozilla/firefox"; dotDir = ".mozilla/firefox";
cacheDir = ".cache/mozilla"; cacheDir = ".cache/mozilla";
@@ -46,7 +47,8 @@ let
package = pkgs.wrapFirefox cfg.browser.browser { package = pkgs.wrapFirefox cfg.browser.browser {
# inherit the default librewolf.cfg # inherit the default librewolf.cfg
# it can be further customized via ~/.librewolf/librewolf.overrides.cfg # it can be further customized via ~/.librewolf/librewolf.overrides.cfg
inherit (cfg.browser) extraPrefsFiles libName; inherit (pkgs.librewolf-unwrapped) extraPrefsFiles;
inherit (cfg.browser) libName;
extraNativeMessagingHosts = optional cfg.addons.browserpass-extension.enable pkgs.browserpass; extraNativeMessagingHosts = optional cfg.addons.browserpass-extension.enable pkgs.browserpass;
# extraNativeMessagingHosts = [ pkgs.gopass-native-messaging-host ]; # extraNativeMessagingHosts = [ pkgs.gopass-native-messaging-host ];
@@ -70,10 +72,7 @@ let
}; };
UserMessaging = { UserMessaging = {
ExtensionRecommendations = false; ExtensionRecommendations = false;
FeatureRecommendations = false;
SkipOnboarding = true; SkipOnboarding = true;
UrlbarInterventions = false;
WhatsNew = false;
}; };
# these were taken from Librewolf # these were taken from Librewolf
@@ -145,62 +144,54 @@ in
{ {
config = mkMerge [ config = mkMerge [
({ ({
sane.programs.firefox.configOption = mkOption { sane.programs.web-browser.configOption = mkOption {
type = types.submodule configOpts; type = types.submodule configOpts;
default = {}; default = {};
}; };
sane.programs.firefox.config.addons = { sane.programs.web-browser.config.addons = {
# get names from:
# - ~/ref/nix-community/nur-combined/repos/rycee/pkgs/firefox-addons/generated-firefox-addons.nix
# `wget ...xpi`; `unar ...xpi`; `cat */manifest.json | jq '.browser_specific_settings.gecko.id'`
browserpass-extension = { browserpass-extension = {
package = pkgs.firefox-extensions.browserpass-extension; # package = addon "browserpass-ce" "browserpass@maximbaz.com" "sha256-sXgUBbRvMnRpeIW1MTkmTcoqtW/8RDXAkxAq1evFkpc=";
enable = lib.mkDefault true; package = localAddon pkgs.browserpass-extension;
};
bypass-paywalls-clean = {
package = pkgs.firefox-extensions.bypass-paywalls-clean;
enable = lib.mkDefault true; enable = lib.mkDefault true;
}; };
# TODO: build bypass-paywalls from source? it's mysteriously disappeared from the Mozilla store.
# bypass-paywalls-clean.package = addon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-oUwdqdAwV3DezaTtOMx7A/s4lzIws+t2f08mwk+324k=";
# bypass-paywalls-clean.enable = lib.mkDefault true;
ether-metamask = { ether-metamask = {
package = pkgs.firefox-extensions.ether-metamask; package = addon "ether-metamask" "webextension@metamask.io" "sha256-G+MwJDOcsaxYSUXjahHJmkWnjLeQ0Wven8DU/lGeMzA=";
enable = lib.mkDefault false; # until i can disable the first-run notification enable = lib.mkDefault true;
}; };
i2p-in-private-browsing = { i2p-in-private-browsing = {
package = pkgs.firefox-extensions.i2p-in-private-browsing; package = addon "i2p-in-private-browsing" "i2ppb@eyedeekay.github.io" "sha256-dJcJ3jxeAeAkRvhODeIVrCflvX+S4E0wT/PyYzQBQWs=";
enable = lib.mkDefault config.services.i2p.enable; enable = lib.mkDefault config.services.i2p.enable;
}; };
sidebery = { sidebery = {
package = pkgs.firefox-extensions.sidebery; package = addon "sidebery" "{3c078156-979c-498b-8990-85f7987dd929}" "sha256-YONfK/rIjlsrTgRHIt3km07Q7KnpIW89Z9r92ZSCc6w=";
enable = lib.mkDefault true; enable = lib.mkDefault true;
}; };
sponsorblock = { sponsorblock = {
package = pkgs.firefox-extensions.sponsorblock; package = addon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-hRsvLaAsVm3dALsTrJqHTNgRFAQcU7XSaGhr5G6+mFs=";
enable = lib.mkDefault true; enable = lib.mkDefault true;
}; };
ublacklist = { ublacklist = {
package = pkgs.firefox-extensions.ublacklist; package = addon "ublacklist" "@ublacklist" "sha256-RqY5iHzbL2qizth7aguyOKWPyINXmrwOlf/OsfqAS48=";
enable = lib.mkDefault true; enable = lib.mkDefault true;
}; };
ublock-origin = { ublock-origin = {
package = pkgs.firefox-extensions.ublock-origin; package = addon "ublock-origin" "uBlock0@raymondhill.net" "sha256-eHlQrU/b9X/6sTbHBpGAd+0VsLT7IrVCnd0AQ948lyA=";
enable = lib.mkDefault true; enable = lib.mkDefault true;
}; };
}; };
}) })
({ ({
sane.programs.firefox = { sane.programs.web-browser = {
inherit package; inherit package;
mime.associations = let
inherit (cfg.browser) desktop;
in {
"text/html" = desktop;
"x-scheme-handler/http" = desktop;
"x-scheme-handler/https" = desktop;
"x-scheme-handler/about" = desktop;
"x-scheme-handler/unknown" = desktop;
};
# env.BROWSER = "${package}/bin/${cfg.browser.libName}";
env.BROWSER = cfg.browser.libName; # used by misc tools like xdg-email, as fallback
# uBlock filter list configuration. # uBlock filter list configuration.
# specifically, enable the GDPR cookie prompt blocker. # specifically, enable the GDPR cookie prompt blocker.
# data.toOverwrite.filterLists is additive (i.e. it supplements the default filters) # data.toOverwrite.filterLists is additive (i.e. it supplements the default filters)
@@ -219,7 +210,6 @@ in
} }
} }
''; '';
# TODO: this is better suited in `extraPrefs` during `wrapFirefox` call
fs."${cfg.browser.dotDir}/${cfg.browser.libName}.overrides.cfg".symlink.text = '' fs."${cfg.browser.dotDir}/${cfg.browser.libName}.overrides.cfg".symlink.text = ''
// if we can't query the revocation status of a SSL cert because the issuer is offline, // if we can't query the revocation status of a SSL cert because the issuer is offline,
// treat it as unrevoked. // treat it as unrevoked.
@@ -241,22 +231,16 @@ in
''; '';
}; };
}) })
(mkIf config.sane.programs.firefox.enabled { (mkIf config.sane.programs.web-browser.enabled {
# TODO: move the persistence into the sane.programs API (above) # TODO: move the persistence into the sane.programs API (above)
# flush the cache to disk to avoid it taking up too much tmp. # flush the cache to disk to avoid it taking up too much tmp
sane.user.persist.byPath."${cfg.browser.cacheDir}".store = sane.user.persist.byPath."${cfg.browser.cacheDir}" = lib.mkIf (cfg.persistCache != null) {
if (cfg.persistData != null) then store = cfg.persistCache;
cfg.persistData };
else
"cryptClearOnBoot"
;
sane.user.persist.byPath."${cfg.browser.dotDir}/default".store = sane.user.persist.byPath."${cfg.browser.dotDir}/default" = lib.mkIf (cfg.persistData != null) {
if (cfg.persistData != null) then store = cfg.persistData;
cfg.persistData };
else
"cryptClearOnBoot"
;
}) })
]; ];
} }

View File

@@ -1,4 +1,5 @@
{ config, ... }: { config, ... }:
{ {
sane.programs.wireshark = {};
programs.wireshark.enable = config.sane.programs.wireshark.enabled; programs.wireshark.enable = config.sane.programs.wireshark.enabled;
} }

View File

@@ -1,7 +0,0 @@
{ pkgs, ... }:
{
sane.programs.xarchiver.package = pkgs.xarchiver.override {
# unar doesn't cross compile well, so disable support for it
unar = null;
};
}

View File

@@ -13,7 +13,6 @@ let
}; };
in { 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-qt5; package = pkgs.zeal-qt5;
persist.plaintext = [ persist.plaintext = [
".cache/Zeal" ".cache/Zeal"

View File

@@ -1,31 +1,33 @@
# zsh files/init order
# - see `man zsh` => "STARTUP/SHUTDOWN FILES"
# - /etc/zshenv
# - $ZDOTDIR/.zshenv
# - if login shell:
# - /etc/zprofile
# - $ZDOTDIR/.zprofile
# - if interactive:
# - /etc/zshrc
# - $ZDOTDIR/.zshrc
# - if login (again):
# - /etc/zlogin
# - ZDOTDIR/.zlogin
# - at exit:
# - $ZDOTDIR/.zlogout
# - /etc/zlogout
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
inherit (lib) mkIf mkMerge mkOption types; inherit (lib) mkIf mkMerge mkOption types;
cfg = config.sane.zsh; cfg = config.sane.zsh;
# powerlevel10k prompt config
# p10k.zsh is the auto-generated config, and i overwrite those defaults here, below.
p10k-overrides = ''
# powerlevel10k launches a gitstatusd daemon to accelerate git prompt queries.
# this keeps open file handles for any git repo i touch for 60 minutes (by default).
# that prevents unmounting whatever device the git repo is on -- particularly problematic for ~/private.
# i can disable gitstatusd and get slower fallback git queries:
# - either universally
# - or selectively by path
# see: <https://github.com/romkatv/powerlevel10k/issues/246>
typeset -g POWERLEVEL9K_VCS_DISABLED_DIR_PATTERN='(/home/colin/private/*|/home/colin/knowledge/*)'
# typeset -g POWERLEVEL9K_DISABLE_GITSTATUS=true
# show user@host also when logged into the current machine.
# default behavior is to show it only over ssh.
typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_CONTENT_EXPANSION='$P9K_CONTENT'
'';
prezto-init = ''
source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
source ${pkgs.zsh-prezto}/share/zsh-prezto/init.zsh
'';
in in
{ {
imports = [
./p10k.nix
./starship.nix
];
options = { options = {
sane.zsh = { sane.zsh = {
showDeadlines = mkOption { showDeadlines = mkOption {
@@ -33,41 +35,112 @@ in
default = true; default = true;
description = "show upcoming deadlines (frommy PKM) upon shell init"; description = "show upcoming deadlines (frommy PKM) upon shell init";
}; };
p10k = mkOption {
type = types.bool;
default = false;
description = "enable powerlevel10k prompt and prezto";
};
starship = mkOption {
type = types.bool;
default = true;
description = "enable starship prompt";
};
}; };
}; };
config = mkMerge [ config = mkMerge [
({ ({
sane.programs.zsh = { sane.programs.zsh = {
persist.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"
];
persist.plaintext = [ persist.plaintext = [
# cache gitstatus otherwise p10k fetches it from the net EVERY BOOT # we don't need to full zsh dir -- just the history file --
# but zsh will sometimes backup the history file and we get fewer errors if we do proper mounts instead of symlinks.
# TODO: should be private?
".local/share/zsh"
# cache gitstatus otherwise p10k fetched it from the net EVERY BOOT
".cache/gitstatus" ".cache/gitstatus"
]; ];
fs.".config/zsh/.zshrc".symlink.text = '' # zsh/prezto complains if zshrc doesn't exist; but it does allow an "empty" file.
# zsh/prezto complains if zshrc doesn't exist or is empty; fs.".config/zsh/.zshrc".symlink.text = "# ";
# preserve this comment to prevent that from ever happening.
'' + lib.optionalString cfg.showDeadlines '' # prezto = oh-my-zsh fork; controls prompt, auto-completion, etc.
# see: https://github.com/sorin-ionescu/prezto
# i believe this file is auto-sourced by the prezto init.zsh script.
fs.".config/zsh/.zpreztorc".symlink.text = ''
zstyle ':prezto:*:*' color 'yes'
# modules (they ship with prezto):
# ENVIRONMENT: configures jobs to persist after shell exit; other basic niceties
# TERMINAL: auto-titles terminal (e.g. based on cwd)
# EDITOR: configures shortcuts like Ctrl+U=undo, Ctrl+L=clear
# HISTORY: `history-stat` alias, setopts for good history defaults
# DIRECTORY: sets AUTO_CD, adds `d` alias to list directory stack, and `1`-`9` to cd that far back the stack
# SPECTRUM: helpers for term colors and styling. used by prompts? might be unnecessary
# UTILITY: configures aliases like `ll`, `la`, disables globbing for things like rsync
# adds aliases like `get` to fetch a file. also adds `http-serve` alias??
# COMPLETION: tab completion. requires `utility` module prior to loading
# TODO: enable AUTO_PARAM_SLASH
zstyle ':prezto:load' pmodule \
'environment' \
'terminal' \
'editor' \
'history' \
'directory' \
'spectrum' \
'utility' \
'completion' \
'prompt'
# default keymap. try also `vicmd` (vim normal mode, AKA "cmd mode") or `vi`.
zstyle ':prezto:module:editor' key-bindings 'emacs'
zstyle ':prezto:module:prompt' theme 'powerlevel10k'
# disable `mv` confirmation (and `rm`, too, unfortunately)
zstyle ':prezto:module:utility' safe-ops 'no'
'';
};
})
(mkIf config.sane.programs.zsh.enabled {
# enable zsh completions
environment.pathsToLink = [ "/share/zsh" ];
programs.zsh = {
enable = true;
histFile = "$HOME/.local/share/zsh/history";
shellAliases = {
":q" = "exit";
# common typos
"cd.." = "cd ..";
"cd../" = "cd ../";
};
setOptions = [
# defaults:
"HIST_IGNORE_DUPS"
"SHARE_HISTORY"
"HIST_FCNTL_LOCK"
# disable `rm *` confirmations
"rmstarsilent"
];
# .zshenv config:
shellInit = ''
ZDOTDIR=$HOME/.config/zsh
'';
# .zshrc config:
interactiveShellInit =
(builtins.readFile ./p10k.zsh)
+ p10k-overrides
+ prezto-init
+ ''
# zmv is a way to do rich moves/renames, with pattern matching/substitution.
# see for an example: <https://filipe.kiss.ink/zmv-zsh-rename/>
autoload -Uz zmv
HISTORY_IGNORE='(sane-shutdown *|sane-reboot *|rm *|nixos-rebuild.* switch)'
# extra aliases
# TODO: move to `shellAliases` config?
function nd() {
mkdir -p "$1";
pushd "$1";
}
''
+ lib.optionalString cfg.showDeadlines ''
${pkgs.sane-scripts.deadlines}/bin/sane-deadlines ${pkgs.sane-scripts.deadlines}/bin/sane-deadlines
'' + '' ''
+ ''
HISTFILE="$HOME/.local/share/zsh/history"
# auto-cd into any of these dirs by typing them and pressing 'enter': # auto-cd into any of these dirs by typing them and pressing 'enter':
hash -d 3rd="/home/colin/dev/3rd" hash -d 3rd="/home/colin/dev/3rd"
hash -d dev="/home/colin/dev" hash -d dev="/home/colin/dev"
@@ -80,68 +153,14 @@ in
hash -d uninsane="/home/colin/dev/uninsane" hash -d uninsane="/home/colin/dev/uninsane"
hash -d Videos="/home/colin/Videos" hash -d Videos="/home/colin/Videos"
''; '';
};
})
(mkIf config.sane.programs.zsh.enabled {
# enable zsh completions
environment.pathsToLink = [ "/share/zsh" ];
programs.zsh = {
enable = true;
shellAliases = {
":q" = "exit";
# common typos
"cd.." = "cd ..";
"cd../" = "cd ../";
};
setOptions = [
# docs: `man zshoptions`
# nixos defaults:
"HIST_FCNTL_LOCK"
"HIST_IGNORE_DUPS"
"SHARE_HISTORY"
# customizations:
"AUTO_CD" # type directory name to go there
"AUTO_MENU" # show auto-complete menu on double-tab
"CDABLE_VARS" # allow auto-cd to use my `hash` aliases -- not just immediate subdirs
"CLOBBER" # allow `foo > bar.txt` to overwrite bar.txt
"NO_CORRECT" # don't try to correct commands
"PIPE_FAIL" # when `cmd_a | cmd_b`, make $? be non-zero if *any* of cmd_a or cmd_b fail
"RM_STAR_SILENT" # disable `rm *` confirmations
];
# .zshenv config:
shellInit = ''
ZDOTDIR=$HOME/.config/zsh
'';
# system-wide .zshrc config:
interactiveShellInit = ''
# zmv is a way to do rich moves/renames, with pattern matching/substitution.
# see for an example: <https://filipe.kiss.ink/zmv-zsh-rename/>
autoload -Uz zmv
HISTORY_IGNORE='(sane-shutdown *|sane-reboot *|rm *|nixos-rebuild.* switch|switch)'
# extra aliases
# TODO: move to `shellAliases` config?
function nd() {
mkdir -p "$1";
pushd "$1";
}
function switch() {
sudo nixos-rebuild --flake . switch --keep-going;
}
'';
syntaxHighlighting.enable = true; syntaxHighlighting.enable = true;
vteIntegration = true; vteIntegration = true;
}; };
# enable a command-not-found hook to show nix packages that might provide the binary typed. # enable a command-not-found hook to show nix packages that might provide the binary typed.
# programs.nix-index.enableZshIntegration = true; programs.nix-index.enable = true;
programs.command-not-found.enable = false; programs.command-not-found.enable = false; #< mutually exclusive with nix-index
}) })
]; ];
} }

View File

@@ -1,75 +0,0 @@
{ config, lib, pkgs, ...}:
let
# powerlevel10k prompt config
# p10k.zsh is the auto-generated config, and i overwrite those defaults here, below.
p10k-overrides = ''
# powerlevel10k launches a gitstatusd daemon to accelerate git prompt queries.
# this keeps open file handles for any git repo i touch for 60 minutes (by default).
# that prevents unmounting whatever device the git repo is on -- particularly problematic for ~/private.
# i can disable gitstatusd and get slower fallback git queries:
# - either universally
# - or selectively by path
# see: <https://github.com/romkatv/powerlevel10k/issues/246>
typeset -g POWERLEVEL9K_VCS_DISABLED_DIR_PATTERN='(/home/colin/private/*|/home/colin/knowledge/*)'
# typeset -g POWERLEVEL9K_DISABLE_GITSTATUS=true
# show user@host also when logged into the current machine.
# default behavior is to show it only over ssh.
typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_CONTENT_EXPANSION='$P9K_CONTENT'
'';
prezto-init = ''
source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
source ${pkgs.zsh-prezto}/share/zsh-prezto/init.zsh
'';
in {
config = lib.mkIf config.sane.zsh.p10k {
sane.programs.zsh = {
# prezto = oh-my-zsh fork; controls prompt, auto-completion, etc.
# see: https://github.com/sorin-ionescu/prezto
# this file is auto-sourced by the prezto init.zsh script.
# TODO: i should work to move away from prezto:
# - it's FUCKING SLOW to initialize (that might also be powerlevel10k tho)
# - it messes with my other `setopt`s
fs.".config/zsh/.zpreztorc".symlink.text = ''
zstyle ':prezto:*:*' color 'yes'
zstyle ':prezto:module:utility' correct 'no' # prezto: don't setopt CORRECT
# modules (they ship with prezto):
# ENVIRONMENT: configures jobs to persist after shell exit; other basic niceties
# TERMINAL: auto-titles terminal (e.g. based on cwd)
# EDITOR: configures shortcuts like Ctrl+U=undo, Ctrl+L=clear
# HISTORY: `history-stat` alias, setopts for good history defaults
# DIRECTORY: sets AUTO_CD, adds `d` alias to list directory stack, and `1`-`9` to cd that far back the stack. also overrides CLOBBER and some other options
# SPECTRUM: helpers for term colors and styling. used by prompts? might be unnecessary
# UTILITY: configures aliases like `ll`, `la`, disables globbing for things like rsync
# adds aliases like `get` to fetch a file. also adds `http-serve` alias??
# COMPLETION: tab completion. requires `utility` module prior to loading
zstyle ':prezto:load' pmodule \
'environment' \
'terminal' \
'editor' \
'history' \
'spectrum' \
'utility' \
'completion' \
'prompt'
# default keymap. try also `vicmd` (vim normal mode, AKA "cmd mode") or `vi`.
zstyle ':prezto:module:editor' key-bindings 'emacs'
zstyle ':prezto:module:prompt' theme 'powerlevel10k'
# disable `mv` confirmation (and `rm`, too, unfortunately)
zstyle ':prezto:module:utility' safe-ops 'no'
'';
};
programs.zsh.interactiveShellInit = (builtins.readFile ./p10k.zsh)
+ p10k-overrides
+ prezto-init
;
};
}

View File

@@ -1,101 +0,0 @@
# starship prompt: <https://starship.rs/config/#prompt>
# my own config heavily based off:
# - <https://starship.rs/presets/pastel-powerline.html>
{ config, lib, pkgs, ...}:
let
enabled = config.sane.zsh.starship;
toml = pkgs.formats.toml {};
colors = {
# colors sorted by the order they appear in the status bar
_01_purple = "#9A348E";
_02_pink = "#DA627D";
_03_orange = "#FCA17D";
_04_teal = "#86BBD8";
_05_blue = "#06969A";
_06_blue = "#33658A";
};
in {
config = lib.mkIf config.sane.zsh.starship {
sane.programs.zsh = lib.mkIf enabled {
fs.".config/zsh/.zshrc".symlink.text = ''
eval "$(${pkgs.starship}/bin/starship init zsh)"
'';
fs.".config/starship.toml".symlink.target = toml.generate "starship.toml" {
format = builtins.concatStringsSep "" [
"[](${colors._01_purple})"
"$os"
"$username"
"$hostname"
"[](bg:${colors._02_pink} fg:${colors._01_purple})"
"$directory"
"[](fg:${colors._02_pink} bg:${colors._03_orange})"
"$git_branch"
"$git_status"
"[](fg:${colors._03_orange} bg:${colors._04_teal})"
"[](fg:${colors._04_teal} bg:${colors._05_blue})"
"[](fg:${colors._05_blue} bg:${colors._06_blue})"
"$time"
"$status"
"[ ](fg:${colors._06_blue})"
];
add_newline = false; # no blank line before prompt
os.style = "bg:${colors._01_purple}";
os.format = "[$symbol]($style)";
os.disabled = false;
# os.symbols.NixOS = "❄️"; # removes the space after logo
# TODO: tune foreground color of username
username.style_user = "bg:${colors._01_purple}";
username.style_root = "bold bg:${colors._01_purple}";
username.format = "[$user ]($style)";
hostname.style = "bold bg:${colors._01_purple}";
hostname.format = "[$ssh_symbol$hostname ]($style)";
directory.style = "bg:${colors._02_pink} fg:#ffffff";
directory.format = "[ $path ]($style)";
directory.truncation_length = 3;
directory.truncation_symbol = "/";
# git_branch.symbol = ""; # looks good in nerd fonts
git_branch.symbol = "";
git_branch.style = "bg:${colors._03_orange} fg:#ffffff";
# git_branch.style = "bg:#FF8262";
git_branch.format = "[ $symbol $branch ]($style)";
git_status.style = "bold bg:${colors._03_orange} fg:#ffffff";
# git_status.style = "bg:#FF8262";
git_status.format = "[$all_status$ahead_behind ]($style)";
git_status.ahead = "$count";
git_status.behind = "$count";
# git_status.diverged = "⇣$behind_count⇡$ahead_count";
git_status.diverged = "$ahead_count$behind_count";
git_status.modified = "*";
git_status.stashed = "";
git_status.untracked = "";
time.disabled = true;
time.time_format = "%R"; # Hour:Minute Format
time.style = "bg:${colors._06_blue}";
time.format = "[ $time ]($style)";
status.disabled = false;
status.style = "bg:${colors._06_blue}";
# status.success_symbol = "♥ ";
# status.success_symbol = "💖";
# status.success_symbol = "💙";
# status.success_symbol = "💚";
# status.success_symbol = "💜";
# status.success_symbol = "✔️'";
status.success_symbol = "";
status.symbol = "";
# status.symbol = "❗️";
# status.symbol = "‼️";
status.format = "[$symbol]($style)";
};
};
};
}

View File

@@ -29,18 +29,14 @@
let let
inherit (lib.strings) hasSuffix removeSuffix; inherit (lib.strings) hasSuffix removeSuffix;
secretsForHost = host: let secretsForHost = host: sane-lib.joinAttrsets (
extraAttrsForPath = path: lib.optionalAttrs (sane-lib.path.isChild "guest" path && builtins.hasAttr "guest" config.users.users) {
owner = "guest";
};
in sane-lib.joinAttrsets (
map map
(path: lib.optionalAttrs (hasSuffix ".bin" path) (sane-lib.nameValueToAttrs { (path: lib.optionalAttrs (hasSuffix ".bin" path) (sane-lib.nameValueToAttrs {
name = removeSuffix ".bin" path; name = removeSuffix ".bin" path;
value = { value = {
sopsFile = ../../secrets/${host}/${path}; sopsFile = ../../secrets/${host}/${path};
format = "binary"; format = "binary";
} // (extraAttrsForPath path); };
})) }))
(sane-lib.enumerateFilePaths ../../secrets/${host}) (sane-lib.enumerateFilePaths ../../secrets/${host})
); );
@@ -66,6 +62,7 @@ in
{ {
"jackett_apikey".owner = config.users.users.colin.name; "jackett_apikey".owner = config.users.users.colin.name;
"mx-sanebot-env".owner = config.users.users.colin.name; "mx-sanebot-env".owner = config.users.users.colin.name;
"snippets".owner = config.users.users.colin.name;
"transmission_passwd".owner = config.users.users.colin.name; "transmission_passwd".owner = config.users.users.colin.name;
} }
]; ];

View File

@@ -2,6 +2,7 @@
let let
inherit (builtins) attrValues head map mapAttrs tail; inherit (builtins) attrValues head map mapAttrs tail;
inherit (lib) concatStringsSep mkMerge reverseList;
in in
{ {
sane.ssh.pubkeys = sane.ssh.pubkeys =
@@ -9,9 +10,9 @@ in
# path is a DNS-style path like [ "org" "uninsane" "root" ] # path is a DNS-style path like [ "org" "uninsane" "root" ]
keyNameForPath = path: keyNameForPath = path:
let let
rev = lib.reverseList path; rev = reverseList path;
name = head rev; name = head rev;
host = lib.concatStringsSep "." (tail rev); host = concatStringsSep "." (tail rev);
in in
"${name}@${host}"; "${name}@${host}";
@@ -22,10 +23,9 @@ in
(name: { (name: {
inherit name; inherit name;
value = { value = {
root = hostCfg.ssh.host_pubkey;
} // (lib.optionalAttrs hostCfg.ssh.authorized {
colin = hostCfg.ssh.user_pubkey; colin = hostCfg.ssh.user_pubkey;
}); root = hostCfg.ssh.host_pubkey;
};
}) })
hostCfg.names hostCfg.names
; ;
@@ -34,7 +34,7 @@ in
map keysForHost (builtins.attrValues config.sane.hosts.by-name) map keysForHost (builtins.attrValues config.sane.hosts.by-name)
) )
); );
in lib.mkMerge (map in mkMerge (map
({ path, value }: { ({ path, value }: {
"${keyNameForPath path}" = lib.mkIf (value != null) value; "${keyNameForPath path}" = lib.mkIf (value != null) value;
}) })

134
hosts/common/users.nix Normal file
View File

@@ -0,0 +1,134 @@
{ config, pkgs, lib, sane-lib, ... }:
# installer docs: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/installation-device.nix
with lib;
let
cfg = config.sane.guest;
fs = sane-lib.fs;
in
{
options = {
sane.guest.enable = mkOption {
default = false;
type = types.bool;
};
};
config = {
# Users are exactly these specified here;
# old ones will be deleted (from /etc/passwd, etc) upon upgrade.
users.mutableUsers = false;
# docs: https://nixpkgs-manual-sphinx-markedown-example.netlify.app/generated/options-db.xml.html#users-users
users.users.colin = {
# sets group to "users" (?)
isNormalUser = true;
home = "/home/colin";
createHome = true;
homeMode = "0700";
# i don't get exactly what this is, but nixos defaults to this non-deterministically
# in /var/lib/nixos/auto-subuid-map and i don't want that.
subUidRanges = [
{ startUid=100000; count=1; }
];
group = "users";
extraGroups = [
"dialout" # required for modem access (moby)
"feedbackd"
"input" # for /dev/input/<xyz>: sxmo
"networkmanager"
"nixbuild"
"transmission" # servo, to admin /var/lib/uninsane/media
"video" # phosh/mobile. XXX colin: unsure if necessary
"wheel"
"wireshark"
];
# initial password is empty, in case anything goes wrong.
# if `colin-passwd` (a password hash) is successfully found/decrypted, that becomes the password at boot.
initialPassword = lib.mkDefault "";
passwordFile = lib.mkIf (config.sops.secrets ? "colin-passwd") config.sops.secrets.colin-passwd.path;
shell = pkgs.zsh;
# mount encrypted stuff at login
# some other nix pam users:
# - <https://github.com/g00pix/nixconf/blob/32c04f6fa843fed97639dd3f09e157668d3eea1f/profiles/sshfs.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>
pamMount = let
priv = config.fileSystems."/home/colin/private";
in {
fstype = priv.fsType;
path = priv.device;
mountpoint = priv.mountPoint;
options = builtins.concatStringsSep "," priv.options;
};
};
security.pam.mount.enable = true;
sane.users.colin.default = true;
# ensure ~ perms are known to sane.fs module.
# TODO: this is generic enough to be lifted up into sane.fs itself.
sane.fs."/home/colin".dir.acl = {
user = "colin";
group = config.users.users.colin.group;
mode = config.users.users.colin.homeMode;
};
sane.user.persist.plaintext = [
"archive"
"dev"
# TODO: records should be private
"records"
"ref"
"tmp"
"use"
"Music"
"Pictures"
"Videos"
".cache/nix"
".cache/nix-index"
# ".cargo"
# ".rustup"
];
# convenience
sane.user.fs."knowledge" = fs.wantedSymlinkTo "private/knowledge";
sane.user.fs."nixos" = fs.wantedSymlinkTo "dev/nixos";
sane.user.fs."Books/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Books";
sane.user.fs."Videos/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Videos";
sane.user.fs."Videos/servo-incomplete" = fs.wantedSymlinkTo "/mnt/servo-media/incomplete";
sane.user.fs."Music/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Music";
sane.user.fs."Pictures/servo-macros" = fs.wantedSymlinkTo "/mnt/servo-media/Pictures/macros";
# used by password managers, e.g. unix `pass`
sane.user.fs.".password-store" = fs.wantedSymlinkTo "knowledge/secrets/accounts";
sane.persist.sys.plaintext = mkIf cfg.enable [
# intentionally allow other users to write to the guest folder
{ directory = "/home/guest"; user = "guest"; group = "users"; mode = "0775"; }
];
users.users.guest = mkIf cfg.enable {
isNormalUser = true;
home = "/home/guest";
subUidRanges = [
{ startUid=200000; count=1; }
];
group = "users";
initialPassword = lib.mkDefault "";
shell = pkgs.zsh;
openssh.authorizedKeys.keys = [
# TODO: insert pubkeys that should be allowed in
];
};
security.sudo = {
enable = true;
wheelNeedsPassword = false;
};
};
}

View File

@@ -1,92 +0,0 @@
{ config, pkgs, lib, ... }:
{
# docs: https://nixpkgs-manual-sphinx-markedown-example.netlify.app/generated/options-db.xml.html#users-users
users.users.colin = {
# sets group to "users" (?)
isNormalUser = true;
home = "/home/colin";
createHome = true;
homeMode = "0700";
# i don't get exactly what this is, but nixos defaults to this non-deterministically
# in /var/lib/nixos/auto-subuid-map and i don't want that.
subUidRanges = [
{ startUid=100000; count=1; }
];
group = "users";
extraGroups = [
"dialout" # required for modem access (moby)
"feedbackd"
"input" # for /dev/input/<xyz>: sxmo
"networkmanager"
"nixbuild"
"transmission" # servo, to admin /var/lib/uninsane/media
"video" # mobile; for LEDs & maybe for camera?
"wheel"
"wireshark"
];
# initial password is empty, in case anything goes wrong.
# if `colin-passwd` (a password hash) is successfully found/decrypted, that becomes the password at boot.
initialPassword = lib.mkDefault "";
passwordFile = lib.mkIf (config.sops.secrets ? "colin-passwd") config.sops.secrets.colin-passwd.path;
shell = pkgs.zsh;
# mount encrypted stuff at login
# some other nix pam users:
# - <https://github.com/g00pix/nixconf/blob/32c04f6fa843fed97639dd3f09e157668d3eea1f/profiles/sshfs.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>
pamMount = let
priv = config.fileSystems."/home/colin/private";
in {
fstype = priv.fsType;
path = priv.device;
mountpoint = priv.mountPoint;
options = builtins.concatStringsSep "," priv.options;
};
};
security.pam.mount.enable = true;
sane.users.colin = {
default = true;
persist.plaintext = [
"archive"
"dev"
# TODO: records should be private
"records"
"ref"
"tmp"
"use"
"Books"
"Music"
"Pictures"
"Videos"
# these are persisted simply to save on RAM.
# ~/.cache/nix can become several GB.
# fontconfig and mesa_shader_cache are < 10 MB.
".cache/fontconfig"
".cache/mesa_shader_cache"
".cache/nix"
# ".cargo"
# ".rustup"
];
# convenience
fs."knowledge".symlink.target = "private/knowledge";
fs."nixos".symlink.target = "dev/nixos";
fs."Books/servo".symlink.target = "/mnt/servo-media/Books";
fs."Videos/servo".symlink.target = "/mnt/servo-media/Videos";
fs."Videos/servo-incomplete".symlink.target = "/mnt/servo-media/incomplete";
fs."Music/servo".symlink.target = "/mnt/servo-media/Music";
fs."Pictures/servo-macros".symlink.target = "/mnt/servo-media/Pictures/macros";
# used by password managers, e.g. unix `pass`
fs.".password-store".symlink.target = "knowledge/secrets/accounts";
};
}

View File

@@ -1,18 +0,0 @@
{ config, pkgs, lib, sane-lib, ... }:
{
imports = [
./colin.nix
./guest.nix
./root.nix
];
# Users are exactly these specified here;
# old ones will be deleted (from /etc/passwd, etc) upon upgrade.
users.mutableUsers = false;
security.sudo = {
enable = true;
wheelNeedsPassword = false;
};
}

View File

@@ -1,33 +0,0 @@
{ config, pkgs, lib, ... }:
let
cfg = config.sane.guest;
in
{
options = with lib; {
sane.guest.enable = mkOption {
default = false;
type = types.bool;
};
};
config = lib.mkIf cfg.enable {
users.users.guest = {
isNormalUser = true;
home = "/home/guest";
subUidRanges = [
{ startUid=200000; count=1; }
];
group = "users";
initialPassword = lib.mkDefault "";
shell = pkgs.zsh;
};
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 [
# intentionally allow other users to write to the guest folder
{ path = "/home/guest"; user = "guest"; group = "users"; mode = "0775"; }
];
};
}

View File

@@ -1,10 +0,0 @@
{ ... }:
{
sane.persist.sys.cryptClearOnBoot = [
# when running commands as root, some things may create ~/.cache entries.
# notably:
# - `/root/.cache/nix/` takes up ~10 MB on lappy/desko/servo
# - `/root/.cache/mesa_shader_cache` takes up 1-2 MB on moby
{ path = "/root"; user = "root"; group = "root"; mode = "0700"; }
];
}

View File

@@ -1,10 +1,10 @@
# trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup # trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup
# args from flake-level `import` # args from flake-level `import`
{ hostName }: { hostName, localSystem }:
# module args # module args
{ ... }: { lib, ... }:
{ {
imports = [ imports = [
@@ -14,4 +14,5 @@
]; ];
networking.hostName = hostName; networking.hostName = hostName;
nixpkgs.buildPlatform = lib.mkIf (localSystem != null) localSystem;
} }

View File

@@ -2,7 +2,7 @@
{ {
imports = [ imports = [
./derived-secrets ./derived-secrets.nix
./gui ./gui
./hardware ./hardware
./hostnames.nix ./hostnames.nix

View File

@@ -1,14 +1,10 @@
{ config, lib, pkgs, ... }: { config, lib, ... }:
let let
inherit (builtins) toString;
hash-path-with-salt = pkgs.static-nix-shell.mkBash { inherit (lib) mapAttrs mkOption types;
pname = "hash-path-with-salt";
src = ./.;
};
cfg = config.sane.derived-secrets; cfg = config.sane.derived-secrets;
secret = with lib; types.submodule { secret = types.submodule {
options = { options = {
len = mkOption { len = mkOption {
type = types.int; type = types.int;
@@ -21,7 +17,7 @@ let
in in
{ {
options = { options = {
sane.derived-secrets = with lib; mkOption { sane.derived-secrets = mkOption {
type = types.attrsOf secret; type = types.attrsOf secret;
default = {}; default = {};
description = '' description = ''
@@ -34,13 +30,17 @@ in
}; };
config = { config = {
sane.fs = lib.mapAttrs (path: c: { sane.fs = mapAttrs (path: c: {
generated.command = [ generated.script.script = ''
"${hash-path-with-salt}/bin/hash-path-with-salt" echo "$1" | cat /dev/stdin /etc/ssh/host_keys/ssh_host_ed25519_key \
path | sha512sum \
c.encoding | cut -c 1-${toString (c.len * 2)} \
(builtins.toString (c.len * 2)) | tr a-z A-Z \
]; | basenc -d --base16 \
| basenc --${c.encoding} \
> "$1"
'';
generated.script.scriptArgs = [ path ];
generated.acl.mode = "0600"; generated.acl.mode = "0600";
}) cfg; }) cfg;
}; };

Some files were not shown because too many files have changed in this diff Show More