Compare commits

..

95 commits
main ... main

Author SHA1 Message Date
69c10a87b6 feat: instealled e621-downloader 2026-03-15 22:41:48 -05:00
546cc97b57 Merge pull request 'storage-refactor' (#9) from storage-refactor into main
Reviewed-on: jan-leila/nix-config#9
2026-03-12 01:16:31 +00:00
16089e0371 fix: fixed more datasets 2026-03-07 19:00:01 -06:00
2f7bbf3e1c feat: fixed more missing datasets 2026-03-07 14:33:08 -06:00
1145703cfe feat: fixed merge incompatibilities 2026-03-07 12:03:09 -06:00
fa0adaa511 feat: reenabled auto snapshot/scrubbing 2026-03-07 11:15:45 -06:00
1289462220 Merge branch 'main' into storage-refactor 2026-03-07 10:41:38 -06:00
58bacc4635 feat: added keep alive to wg on defiant 2026-03-06 15:33:19 -06:00
12d746804d feat: updated vscode extensions config 2026-03-02 01:42:21 -06:00
c4f4276680 feat: disabled cline 2026-02-28 20:19:42 -06:00
64e29f793f feat: instealled graphql plugin for leyla vscode 2026-02-26 08:15:28 -06:00
1b5c62f2e6 feat: added open code to packages 2026-02-25 21:37:13 -06:00
50cc748330 feat: updated flake.lock 2026-02-23 22:44:23 -06:00
81680932be feat: disabled actual 2026-02-23 22:03:25 -06:00
0e1c8d0d4f feat: installed cline package 2026-02-21 17:24:11 -06:00
2efb17d30c Merge remote-tracking branch 'origin' 2026-02-20 20:08:34 -06:00
08e3ec3d74 feat: updated flake lock 2026-02-20 20:02:10 -06:00
5a1cefdf6a Merge remote-tracking branch 'origin' 2026-02-17 15:19:37 -06:00
65e0c6e0e5 fix: added missing datasets to config 2026-02-08 18:01:31 -06:00
6ce567a53b fix: added missing impermanence configs 2026-02-08 13:03:05 -06:00
3302af38b3 feat: moved legacy datasets from main into defiant configuration 2026-02-08 12:50:58 -06:00
18c738cc2f feat: disabled impermanence for all the needed services 2026-02-08 12:37:42 -06:00
67eee18d7f Merge branch 'main' into storage-refactor 2026-02-07 22:58:53 -06:00
b9a746a989 feat: added Cyberia to leyla words 2026-02-07 14:31:51 -06:00
468f1cb40f feat: added bookmark for Cyberia git 2026-02-07 14:17:08 -06:00
f86cba6d02 chore: added tasks to README.md 2026-02-07 12:14:49 -06:00
d7301886c6 chore: added tasks to README.md 2026-02-07 12:12:51 -06:00
66ed7e75ba fix: disabled IdentityFile config for ssh 2026-02-04 17:40:31 -06:00
3370cd7ab3 feat: bound impermanence filesystem datasets filesystem 2026-01-15 21:50:36 -06:00
e6e53141ce feat: switched back to main for impermanence 2026-01-15 20:09:21 -06:00
ff08812447 Merge branch 'main' into storage-refactor 2026-01-15 19:55:56 -06:00
2a3c5b76ee feat: updated flake.lock 2026-01-15 19:53:27 -06:00
769359d6e9 fix: made platformio not used built in things 2026-01-11 18:42:34 -06:00
629950bc6f feat: installed pioarduino for vscode 2026-01-11 18:19:36 -06:00
3081267b4e feat: installed kicad 2026-01-11 18:14:06 -06:00
2170040ef4 Merge branch 'main' into storage-refactor 2026-01-08 21:01:01 -06:00
2868448c2d fix: disabled build tests for jackett due to failing year rollover tests upstream 2026-01-08 20:27:06 -06:00
8df63b3094 feat: updated flake.lock 2026-01-08 20:09:40 -06:00
3891f93dba Merge branch 'main' into storage-refactor 2025-12-28 15:18:40 -06:00
cb19c771f5 fix: fixed generation when we manually set the package 2025-12-21 13:19:49 -06:00
b75aaca605 feat: added more options to pwa packages 2025-12-21 01:42:59 -06:00
aab05a8135 feat: created entries to install PWA's 2025-12-20 10:35:21 -06:00
e7aa507ea5 Merge branch 'main' into storage-refactor 2025-12-14 16:17:26 -06:00
fa0f7b0765 feat: removed ivy user 2025-12-14 13:38:46 -06:00
8cd453844a feat: updated flake.lock 2025-12-09 20:15:31 -06:00
8060e39b11 feat: updated android studio config to match new patter 2025-11-30 13:46:25 -06:00
6864312e49 Merge branch 'main' into storage-refactor 2025-11-30 13:30:00 -06:00
1c12c96efe feat: fixed disk names for twilight 2025-11-30 12:26:57 -06:00
c01ca13fcb feat: installed docker on horizon 2025-11-28 15:45:38 -06:00
dce767403a feat: updated flake.lock 2025-11-28 15:12:26 -06:00
9ed0958463 feat: installed android studio for leyla 2025-11-28 10:05:59 -06:00
4cbb3d32b2 Merge remote-tracking branch 'eve/main' 2025-11-27 22:10:34 -06:00
a0807b014c feat: moved logs to impermanence 2025-11-27 20:29:03 -06:00
adc1c1a918 Merge branch 'main' into storage-refactor 2025-11-27 20:14:09 -06:00
719a21a95e feat: switched emergent to using wayland 2025-11-27 18:44:49 -06:00
04777cfb8f feat: removed xterm 2025-11-27 18:43:03 -06:00
be8126e2c5 feat: switched to wayland 2025-11-27 18:21:55 -06:00
3d1750060d fix: fixed nix flake check 2025-11-23 15:44:59 -06:00
a4f3b3141d fix: fixed trailing mount path issue 2025-11-23 15:35:26 -06:00
2922114367 fix: fixed file system resolution 2025-11-23 11:51:53 -06:00
5dc602339c Merge branch 'main' into storage-refactor 2025-11-22 01:25:30 +00:00
ecdd407abe feat: switched jellyfin media and qbittorent media to being the same dataset 2025-11-17 17:56:31 -06:00
e196541f2a feat: filter out impermanence datasets that dont do anything 2025-11-16 00:12:29 -06:00
57fba596c2 Merge branch 'main' into storage-refactor 2025-11-16 00:11:26 -06:00
dfcacdc6fb feat: moved some datasets to common zfs storage config 2025-11-16 00:04:03 -06:00
c2701ea8f0 feat: moved services over to using the new storage datasets 2025-11-15 16:37:10 -06:00
757a3892e1 feat: updated interface for storage 2025-11-15 13:39:53 -06:00
f8edad75bf feat: updated user configs to better match original config 2025-11-14 22:06:32 -06:00
1eb66d1c31 feat: updated pool names 2025-11-12 19:27:12 -06:00
ac0f1ce2e6 feat: updated flake input to use fork 2025-11-10 15:51:28 -06:00
8aa984a389 feat: made datasets build 2025-11-10 15:49:12 -06:00
61eef3067e feat: made persist build with new impermanence system 2025-11-10 15:42:25 -06:00
d06c25f33f feat: migrated users over to new persistence structure 2025-11-10 02:38:28 -06:00
37f5e65bd6 Merge branch 'main' into storage-refactor 2025-11-09 02:33:38 -06:00
318a0a9748 feat: added sops dataset to users.nix 2025-11-08 22:37:19 -06:00
4d7d11e0c8 feat: removed now unneeded disko and impermanence modules 2025-11-08 21:19:54 -06:00
4da5d65d8f feat: added activation and resume scripts to storage and impermanence 2025-11-08 21:10:18 -06:00
1310b50794 feat: moved ssh config to use new storage config 2025-11-08 19:04:59 -06:00
5acf060e9e feat: updated imports to use new storage module only 2025-11-08 18:49:19 -06:00
703530ddfe feat: updated storage config for emergent 2025-11-08 18:48:41 -06:00
ab555f50ff fix: defiant config cache drive converted to correct format 2025-11-08 18:30:49 -06:00
d283f88160 feat: moved ollama, tailscale, and sync into folders following the new storage pattern 2025-11-08 18:28:34 -06:00
b67be1472a feat: refactored impermanence modules to follow new pattern 2025-11-08 18:17:22 -06:00
3ca0e9bf0a fix: fixed generation of disko configuration 2025-11-08 17:20:37 -06:00
730eeef242 Merge branch 'main' into storage-refactor 2025-11-08 14:26:07 -06:00
39edb65539 feat: removed broken disko config 2025-11-08 14:21:22 -06:00
9df29cc07f feat: refined options for datasets 2025-11-08 13:21:01 -06:00
0de97fa4a2 feat: added more development notes 2025-11-07 18:14:00 -06:00
adc6b90c93 feat: made impermanence create datasets for zfs and persistence 2025-11-07 16:29:56 -06:00
409fdb7276 Merge branch 'main' into storage-refactor 2025-11-06 17:07:07 -06:00
d8989bb43d feat: drafted out zfs vdev, pool, and dataset implementations 2025-11-05 10:56:04 -06:00
2fd14e4cc0 feat: added config block to zfs.nix and gave it notification functionality 2025-11-04 19:39:27 -06:00
573708fd47 moved storage option draft to its own folder 2025-11-04 15:02:49 -06:00
aeb37e658e Merge branch 'main' into storage-refactor 2025-11-04 14:28:28 -06:00
78dd22fed3 feat: started to draft out new storage interface 2025-11-03 11:55:10 -06:00
159 changed files with 6987 additions and 1886 deletions

View file

@ -71,10 +71,12 @@ nix multi user, multi system, configuration with `sops` secret management, `home
- [ ] monitor configuration in `~/.config/monitors.xml` should be sym linked to `/run/gdm/.config/monitors.xml` (https://www.reddit.com/r/NixOS/comments/u09cz9/home_manager_create_my_own_symlinks_automatically/) - [ ] monitor configuration in `~/.config/monitors.xml` should be sym linked to `/run/gdm/.config/monitors.xml` (https://www.reddit.com/r/NixOS/comments/u09cz9/home_manager_create_my_own_symlinks_automatically/)
- [ ] migrate away from flakes and move to npins - [ ] migrate away from flakes and move to npins
- [ ] `host.users` should be redone so that we just extend the base `users.users` object. Right now we cant quite do this because we have weird circular dependencies with disko/impermanence (not sure which one) and home manger enabling/disabling users per devices - [ ] `host.users` should be redone so that we just extend the base `users.users` object. Right now we cant quite do this because we have weird circular dependencies with disko/impermanence (not sure which one) and home manger enabling/disabling users per devices
- [ ] Home manager impermanence is preventing updates to the latest version of the module
## Broken things ## Broken things
- [ ] figure out steam vr things? - [ ] figure out steam vr things?
- [ ] whisper was having issues - [ ] whisper was having issues
- [ ] auto loading of ssh agent keys that we auto generate per system
## Data Integrity ## Data Integrity
- [ ] zfs email after scrubbing # TODO: test this - [ ] zfs email after scrubbing # TODO: test this
@ -102,7 +104,9 @@ nix multi user, multi system, configuration with `sops` secret management, `home
- [ ] Penpot services (need to make this custom) - [ ] Penpot services (need to make this custom)
- [ ] minecraft server with old world file - [ ] minecraft server with old world file
- [ ] storj server - [ ] storj server
- [ ] XMR miner used to heat home based on smart thermostat
- [ ] Create Tor guard/relay server - [ ] Create Tor guard/relay server
- [ ] Create i2P node
- [ ] screeps server - [ ] screeps server
- [ ] mastodon instance - [ ] mastodon instance

View file

@ -8,6 +8,5 @@
in { in {
leyla = lib.mkIf users.leyla.isNormalUser (import ./leyla); leyla = lib.mkIf users.leyla.isNormalUser (import ./leyla);
eve = lib.mkIf users.eve.isNormalUser (import ./eve); eve = lib.mkIf users.eve.isNormalUser (import ./eve);
ivy = lib.mkIf users.ivy.isNormalUser (import ./ivy);
git = lib.mkIf (osConfig.services.forgejo.enable or false) (import ./git); git = lib.mkIf (osConfig.services.forgejo.enable or false) (import ./git);
} }

View file

@ -60,7 +60,7 @@ in {
bitwarden.enable = true; bitwarden.enable = true;
discord.enable = true; discord.enable = true;
makemkv.enable = true; makemkv.enable = true;
signal-desktop-bin.enable = true; signal-desktop.enable = true;
steam.enable = true; steam.enable = true;
piper.enable = hardware.piperMouse.enable; piper.enable = hardware.piperMouse.enable;
krita.enable = true; krita.enable = true;
@ -75,7 +75,9 @@ in {
libreoffice.enable = true; libreoffice.enable = true;
noita-entangled-worlds.enable = true; noita-entangled-worlds.enable = true;
claude-code.enable = osConfig.host.ai.enable; opencode.enable = osConfig.host.ai.enable;
e621-downloader.enable = true;
# Windows applications that we need to figure out how to install # Windows applications that we need to figure out how to install
guild-wars-2.enable = false; guild-wars-2.enable = false;

View file

@ -1,55 +0,0 @@
{osConfig, ...}: let
userConfig = osConfig.host.users.ivy;
in {
imports = [
./packages.nix
];
home = {
username = userConfig.name;
homeDirectory = osConfig.users.users.ivy.home;
# This value determines the Home Manager release that your configuration is
# compatible with. This helps avoid breakage when a new Home Manager release
# introduces backwards incompatible changes.
#
# You should not change this value, even if you update Home Manager. If you do
# want to update the value, then make sure to first check the Home Manager
# release notes.
stateVersion = "23.11"; # Please read the comment before changing.
# Home Manager is pretty good at managing dotfiles. The primary way to manage
# plain files is through 'home.file'.
file = {
# # Building this configuration will create a copy of 'dotfiles/screenrc' in
# # the Nix store. Activating the configuration will then make '~/.screenrc' a
# # symlink to the Nix store copy.
# ".screenrc".source = dotfiles/screenrc;
# # You can also set the file content immediately.
# ".gradle/gradle.properties".text = ''
# org.gradle.console=verbose
# org.gradle.daemon.idletimeout=3600000
# '';
};
# Home Manager can also manage your environment variables through
# 'home.sessionVariables'. If you don't want to manage your shell through Home
# Manager then you have to manually source 'hm-session-vars.sh' located at
# either
#
# ~/.nix-profile/etc/profile.d/hm-session-vars.sh
#
# or
#
# ~/.local/state/nix/profiles/profile/etc/profile.d/hm-session-vars.sh
#
# or
#
# /etc/profiles/per-user/ivy/etc/profile.d/hm-session-vars.sh
#
sessionVariables = {
# EDITOR = "emacs";
};
};
}

View file

@ -1,73 +0,0 @@
{
lib,
pkgs,
config,
osConfig,
...
}: {
config = {
nixpkgs.config = {
allowUnfree = true;
};
# Programs that need to be installed with some extra configuration
programs = lib.mkMerge [
{
# Let Home Manager install and manage itself.
home-manager.enable = true;
}
(lib.mkIf (config.user.isDesktopUser || config.user.isTerminalUser) {
# git = {
# enable = true;
# userName = "Ivy";
# userEmail = "ivy@example.com"; # Update this with actual email
# extraConfig.init.defaultBranch = "main";
# };
openssh = {
enable = true;
hostKeys = [
{
type = "ed25519";
path = "${config.home.username}_${osConfig.networking.hostName}_ed25519";
}
];
};
})
(lib.mkIf config.user.isDesktopUser {
vscode = {
enable = true;
package = pkgs.vscodium;
mutableExtensionsDir = false;
profiles.default = {
enableUpdateCheck = false;
enableExtensionUpdateCheck = false;
extraExtensions = {
# Cline extension (Claude AI assistant)
claudeDev.enable = true;
# Auto Rename Tag
autoRenameTag.enable = true;
# Live Server
liveServer.enable = true;
};
extensions = let
extension-pkgs = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version;
in (
with extension-pkgs.open-vsx; [
streetsidesoftware.code-spell-checker
]
);
};
};
firefox.enable = true;
discord.enable = true;
signal-desktop-bin.enable = true;
claude-code.enable = true;
})
];
};
}

View file

@ -12,7 +12,7 @@
]; ];
config = { config = {
impermanence.enable = osConfig.host.impermanence.enable; impermanence.enable = osConfig.storage.impermanence.enable;
# Home Manager needs a bit of information about you and the paths it should # Home Manager needs a bit of information about you and the paths it should
# manage. # manage.

View file

@ -4,7 +4,7 @@
... ...
}: { }: {
config = lib.mkIf (config.impermanence.enable) { config = lib.mkIf (config.impermanence.enable) {
home.persistence."/persist/home/leyla" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"desktop" "desktop"
"downloads" "downloads"
@ -14,7 +14,6 @@
".bash_history" # keep shell history around ".bash_history" # keep shell history around
"${config.xdg.dataHome}/recently-used.xbel" # gnome recently viewed files "${config.xdg.dataHome}/recently-used.xbel" # gnome recently viewed files
]; ];
allowOther = true;
}; };
}; };
} }

View file

@ -41,17 +41,19 @@ in {
openrgb.enable = hardware.openRGB.enable; openrgb.enable = hardware.openRGB.enable;
via.enable = hardware.viaKeyboard.enable; via.enable = hardware.viaKeyboard.enable;
claude-code.enable = osConfig.host.ai.enable; claude-code.enable = osConfig.host.ai.enable;
opencode.enable = osConfig.host.ai.enable;
davinci-resolve.enable = hardware.graphicsAcceleration.enable; davinci-resolve.enable = hardware.graphicsAcceleration.enable;
mfoc.enable = true; mfoc.enable = true;
}) })
(lib.mkIf (hardware.directAccess.enable && config.user.isDesktopUser) { (lib.mkIf (hardware.directAccess.enable && config.user.isDesktopUser) {
anki.enable = true; anki.enable = true;
android-studio.enable = true;
makemkv.enable = true; makemkv.enable = true;
discord.enable = true; discord.enable = true;
signal-desktop-bin.enable = true; signal-desktop.enable = true;
calibre.enable = true; calibre.enable = true;
obsidian.enable = true; obsidian.enable = true;
jetbrains.idea-community.enable = true; jetbrains.idea-oss.enable = true;
vscode.enable = true; vscode.enable = true;
firefox.enable = true; firefox.enable = true;
steam.enable = true; steam.enable = true;
@ -71,6 +73,10 @@ in {
noita-entangled-worlds.enable = true; noita-entangled-worlds.enable = true;
tor-browser.enable = true; tor-browser.enable = true;
gdx-liftoff.enable = true; gdx-liftoff.enable = true;
proton-mail-pwa.enable = true;
proton-calendar-pwa.enable = true;
matrix-cyberia-pwa.enable = true;
kicad.enable = true;
}) })
]; ];
} }

View file

@ -141,6 +141,12 @@
keyword = ""; keyword = "";
tags = [""]; tags = [""];
} }
{
name = "Cyberia Git";
url = "https://git.cyberia.club";
keyword = "";
tags = [""];
}
# Template # Template
# { # {
# name = ""; # name = "";

View file

@ -58,6 +58,9 @@ in {
nearley.enable = true; nearley.enable = true;
# graphql
graphql.enable = true;
# astro development # astro development
vscodeMdx.enable = true; vscodeMdx.enable = true;
astroVscode.enable = true; astroVscode.enable = true;
@ -72,9 +75,12 @@ in {
# rust development # rust development
rustAnalyzer.enable = true; rustAnalyzer.enable = true;
# arduino development
platformIO.enable = false;
# claude development # claude development
claudeDev = lib.mkIf ai-tooling-enabled { claudeDev = lib.mkIf ai-tooling-enabled {
enable = true; enable = false;
mcp = { mcp = {
nixos = { nixos = {
enable = true; enable = true;

View file

@ -6,6 +6,7 @@
config.programs.vscode.profiles.default.userSettings = { config.programs.vscode.profiles.default.userSettings = {
"cSpell.userWords" = [ "cSpell.userWords" = [
"leyla" "leyla"
"Cyberia"
]; ];
"cSpell.languageSettings" = [ "cSpell.languageSettings" = [

View file

@ -33,44 +33,6 @@
isPrincipleUser = true; isPrincipleUser = true;
}; };
}; };
impermanence.enable = true;
storage = {
enable = true;
encryption = true;
notifications = {
enable = true;
host = "smtp.protonmail.ch";
port = 587;
to = "leyla@jan-leila.com";
user = "noreply@jan-leila.com";
tokenFile = config.sops.secrets."services/zfs_smtp_token".path;
};
pool = {
# We are having to boot off of the nvm cache drive because I cant figure out how to boot via the HBA
bootDrives = ["nvme-Samsung_SSD_990_PRO_4TB_S7KGNU0X907881F"];
vdevs = [
[
"ata-ST18000NE000-3G6101_ZVTCXVEB"
"ata-ST18000NE000-3G6101_ZVTCXWSC"
"ata-ST18000NE000-3G6101_ZVTD10EH"
"ata-ST18000NT001-3NF101_ZVTE0S3Q"
"ata-ST18000NT001-3NF101_ZVTEF27J"
"ata-ST18000NE000-3G6101_ZVTJ7359"
]
[
"ata-ST4000NE001-2MA101_WS2275P3"
"ata-ST4000NE001-2MA101_WS227B9F"
"ata-ST4000NE001-2MA101_WS227CEW"
"ata-ST4000NE001-2MA101_WS227CYN"
"ata-ST4000NE001-2MA101_WS23TBWV"
"ata-ST4000NE001-2MA101_WS23TC5F"
]
];
cache = [
"nvme-Samsung_SSD_990_PRO_4TB_S7KGNU0X907881F"
];
};
};
network_storage = { network_storage = {
enable = true; enable = true;
directories = [ directories = [
@ -104,6 +66,53 @@
}; };
}; };
storage = {
zfs = {
enable = true;
notifications = {
enable = true;
host = "smtp.protonmail.ch";
port = 587;
to = "leyla@jan-leila.com";
user = "noreply@jan-leila.com";
tokenFile = config.sops.secrets."services/zfs_smtp_token".path;
};
pool = {
encryption = {
enable = true;
};
vdevs = [
[
"ata-ST18000NE000-3G6101_ZVTCXVEB"
"ata-ST18000NE000-3G6101_ZVTCXWSC"
"ata-ST18000NE000-3G6101_ZVTD10EH"
"ata-ST18000NT001-3NF101_ZVTE0S3Q"
"ata-ST18000NT001-3NF101_ZVTEF27J"
"ata-ST18000NE000-3G6101_ZVTJ7359"
]
[
"ata-ST4000NE001-2MA101_WS2275P3"
"ata-ST4000NE001-2MA101_WS227B9F"
"ata-ST4000NE001-2MA101_WS227CEW"
"ata-ST4000NE001-2MA101_WS227CYN"
"ata-ST4000NE001-2MA101_WS23TBWV"
"ata-ST4000NE001-2MA101_WS23TC5F"
]
];
# We are having to boot off of the nvm cache drive because I cant figure out how to boot via the HBA
cache = [
{
device = "nvme-Samsung_SSD_990_PRO_4TB_S7KGNU0X907881F";
boot = true;
}
];
};
};
impermanence = {
enable = true;
};
};
systemd.network = { systemd.network = {
enable = true; enable = true;
@ -134,6 +143,7 @@
Endpoint = "185.230.126.146:51820"; Endpoint = "185.230.126.146:51820";
# Allow all traffic but use policy routing to prevent system-wide VPN # Allow all traffic but use policy routing to prevent system-wide VPN
AllowedIPs = ["0.0.0.0/0"]; AllowedIPs = ["0.0.0.0/0"];
PersistentKeepalive = 25;
} }
]; ];
}; };
@ -217,6 +227,7 @@
postgresql = { postgresql = {
enable = true; enable = true;
adminUsers = ["leyla"]; adminUsers = ["leyla"];
impermanence.enable = false;
}; };
# temp enable desktop environment for setup # temp enable desktop environment for setup
@ -235,6 +246,7 @@
reverseProxy = { reverseProxy = {
enable = true; enable = true;
openFirewall = true; openFirewall = true;
impermanence.enable = false;
acme = { acme = {
enable = true; enable = true;
email = "jan-leila@protonmail.com"; email = "jan-leila@protonmail.com";
@ -244,8 +256,7 @@
ollama = { ollama = {
enable = true; enable = true;
exposePort = true; exposePort = true;
impermanence.enable = false;
acceleration = false;
environmentVariables = { environmentVariables = {
OLLAMA_KEEP_ALIVE = "24h"; OLLAMA_KEEP_ALIVE = "24h";
@ -280,6 +291,7 @@
enable = true; enable = true;
authKeyFile = config.sops.secrets."vpn-keys/tailscale-authkey/defiant".path; authKeyFile = config.sops.secrets."vpn-keys/tailscale-authkey/defiant".path;
useRoutingFeatures = "server"; useRoutingFeatures = "server";
impermanence.enable = false;
extraUpFlags = [ extraUpFlags = [
"--advertise-exit-node" "--advertise-exit-node"
"--advertise-routes=192.168.0.0/24" "--advertise-routes=192.168.0.0/24"
@ -292,24 +304,33 @@
]; ];
}; };
syncthing.enable = true; syncthing = {
enable = true;
impermanence.enable = false;
};
fail2ban.enable = true; fail2ban = {
enable = true;
impermanence.enable = false;
};
jellyfin = { jellyfin = {
enable = true; enable = true;
domain = "media.jan-leila.com"; domain = "media.jan-leila.com";
extraDomains = ["jellyfin.jan-leila.com"]; extraDomains = ["jellyfin.jan-leila.com"];
impermanence.enable = false;
}; };
immich = { immich = {
enable = true; enable = true;
domain = "photos.jan-leila.com"; domain = "photos.jan-leila.com";
impermanence.enable = false;
}; };
forgejo = { forgejo = {
enable = true; enable = true;
reverseProxy.domain = "git.jan-leila.com"; reverseProxy.domain = "git.jan-leila.com";
impermanence.enable = false;
}; };
searx = { searx = {
@ -318,8 +339,9 @@
}; };
actual = { actual = {
enable = true; enable = false;
domain = "budget.jan-leila.com"; domain = "budget.jan-leila.com";
impermanence.enable = false;
}; };
home-assistant = { home-assistant = {
@ -327,6 +349,7 @@
domain = "home.jan-leila.com"; domain = "home.jan-leila.com";
openFirewall = true; openFirewall = true;
postgres.enable = true; postgres.enable = true;
impermanence.enable = false;
extensions = { extensions = {
sonos.enable = true; sonos.enable = true;
@ -339,11 +362,13 @@
enable = true; enable = true;
domain = "documents.jan-leila.com"; domain = "documents.jan-leila.com";
passwordFile = config.sops.secrets."services/paperless_password".path; passwordFile = config.sops.secrets."services/paperless_password".path;
impermanence.enable = false;
}; };
panoramax = { panoramax = {
enable = false; enable = false;
openFirewall = true; openFirewall = true;
impermanence.enable = false;
}; };
crab-hole = { crab-hole = {
@ -351,6 +376,7 @@
port = 8085; port = 8085;
openFirewall = true; openFirewall = true;
show_doc = true; show_doc = true;
impermanence.enable = false;
downstreams = { downstreams = {
host = { host = {
enable = true; enable = true;
@ -366,31 +392,38 @@
mediaDir = "/srv/qbittorent"; mediaDir = "/srv/qbittorent";
openFirewall = true; openFirewall = true;
webuiPort = 8084; webuiPort = 8084;
impermanence.enable = false;
}; };
sonarr = { sonarr = {
enable = true; enable = true;
openFirewall = true; openFirewall = true;
impermanence.enable = false;
}; };
radarr = { radarr = {
enable = true; enable = true;
openFirewall = true; openFirewall = true;
impermanence.enable = false;
}; };
bazarr = { bazarr = {
enable = true; enable = true;
openFirewall = true; openFirewall = true;
impermanence.enable = false;
}; };
lidarr = { lidarr = {
enable = true; enable = true;
openFirewall = true; openFirewall = true;
impermanence.enable = false;
}; };
jackett = { jackett = {
enable = true; enable = true;
openFirewall = true; openFirewall = true;
impermanence.enable = false;
}; };
flaresolverr = { flaresolverr = {
enable = true; enable = true;
openFirewall = true; openFirewall = true;
impermanence.enable = false;
}; };
}; };

View file

@ -4,5 +4,7 @@
./hardware-configuration.nix ./hardware-configuration.nix
./configuration.nix ./configuration.nix
./packages.nix ./packages.nix
./legacy-storage.nix
./legacy-impermanence.nix
]; ];
} }

View file

@ -0,0 +1,296 @@
# Legacy impermanence module for defiant
# See legacy-storage.nix for the full incremental migration plan.
#
# This file is consumed in two phases:
#
# Phase 3 (after generateBase is enabled):
# Remove the SYSTEM-LEVEL entries marked [PHASE 3] below. These will be
# handled automatically by storage.nix, ssh.nix, and the impermanence module:
# - var-lib-private-permissions activation script
# - /etc/machine-id
# - SSH host keys
# - /var/lib/nixos
# - /var/lib/systemd/coredump
# - /persist/system/var/log persistence block
#
# Phase 4 (migrate services one at a time, any order):
# For each service:
# 1. Remove the service's section marked [PHASE 4] from this file
# 2. Remove `impermanence.enable = false` for that service in configuration.nix
# For jellyfin/qbittorrent, also remove the separate media persistence blocks.
#
# Phase 5: Delete this file once empty.
{
config,
lib,
...
}: {
config = lib.mkIf config.storage.impermanence.enable {
# [PHASE 3] Remove this activation script after enabling generateBase
system.activationScripts = {
"var-lib-private-permissions" = {
deps = ["specialfs"];
text = ''
mkdir -p /persist/system/root/var/lib/private
chmod 0700 /persist/system/root/var/lib/private
'';
};
};
environment.persistence."/persist/system/root" = {
enable = true;
hideMounts = true;
# [PHASE 3] Remove this files block after enabling generateBase
files = lib.mkMerge [
["/etc/machine-id"]
# SSH host keys
(lib.mkIf config.services.openssh.enable (
lib.lists.flatten (
builtins.map (hostKey: [
hostKey.path
"${hostKey.path}.pub"
])
config.services.openssh.hostKeys
)
))
];
directories = lib.mkMerge [
# [PHASE 3] Remove these system directories after enabling generateBase
[
"/var/lib/nixos"
"/var/lib/systemd/coredump"
]
# [PHASE 4] PostgreSQL
(lib.mkIf config.services.postgresql.enable [
{
directory = "/var/lib/postgresql/16";
user = "postgres";
group = "postgres";
}
])
# [PHASE 4] Reverse Proxy (ACME)
(lib.mkIf config.services.reverseProxy.enable [
{
directory = "/var/lib/acme";
user = "acme";
group = "acme";
}
])
# [PHASE 4] Ollama
(lib.mkIf config.services.ollama.enable [
{
directory = "/var/lib/private/ollama";
user = config.services.ollama.user;
group = config.services.ollama.group;
mode = "0700";
}
])
# [PHASE 4] Tailscale
(lib.mkIf config.services.tailscale.enable [
{
directory = "/var/lib/tailscale";
user = "root";
group = "root";
}
])
# [PHASE 4] Syncthing
(lib.mkIf config.services.syncthing.enable [
{
directory = "/mnt/sync";
user = "syncthing";
group = "syncthing";
}
{
directory = "/etc/syncthing";
user = "syncthing";
group = "syncthing";
}
])
# [PHASE 4] Fail2ban
(lib.mkIf config.services.fail2ban.enable [
{
directory = "/var/lib/fail2ban";
user = "fail2ban";
group = "fail2ban";
}
])
# [PHASE 4] Jellyfin (data/cache only - media is on separate dataset)
(lib.mkIf config.services.jellyfin.enable [
{
directory = "/var/lib/jellyfin";
user = "jellyfin";
group = "jellyfin";
}
{
directory = "/var/cache/jellyfin";
user = "jellyfin";
group = "jellyfin";
}
])
# [PHASE 4] Immich
(lib.mkIf config.services.immich.enable [
{
directory = "/var/lib/immich";
user = "immich";
group = "immich";
}
])
# [PHASE 4] Forgejo
(lib.mkIf config.services.forgejo.enable [
{
directory = "/var/lib/forgejo";
user = "forgejo";
group = "forgejo";
}
])
# [PHASE 4] Actual
(lib.mkIf config.services.actual.enable [
{
directory = "/var/lib/private/actual";
user = "actual";
group = "actual";
}
])
# [PHASE 4] Home Assistant
(lib.mkIf config.services.home-assistant.enable [
{
directory = "/var/lib/hass";
user = "hass";
group = "hass";
}
])
# [PHASE 4] Paperless
(lib.mkIf config.services.paperless.enable [
{
directory = "/var/lib/paperless";
user = "paperless";
group = "paperless";
}
])
# [PHASE 4] Crab-hole
(lib.mkIf config.services.crab-hole.enable [
{
directory = "/var/lib/private/crab-hole";
user = "crab-hole";
group = "crab-hole";
}
])
# [PHASE 4] qBittorrent (config only - media is on separate dataset)
(lib.mkIf config.services.qbittorrent.enable [
{
directory = "/var/lib/qBittorrent/";
user = "qbittorrent";
group = "qbittorrent";
}
])
# [PHASE 4] Sonarr
(lib.mkIf config.services.sonarr.enable [
{
directory = "/var/lib/sonarr/.config/NzbDrone";
user = "sonarr";
group = "sonarr";
}
])
# [PHASE 4] Radarr
(lib.mkIf config.services.radarr.enable [
{
directory = "/var/lib/radarr/.config/Radarr";
user = "radarr";
group = "radarr";
}
])
# [PHASE 4] Bazarr
(lib.mkIf config.services.bazarr.enable [
{
directory = "/var/lib/bazarr";
user = "bazarr";
group = "bazarr";
}
])
# [PHASE 4] Lidarr
(lib.mkIf config.services.lidarr.enable [
{
directory = "/var/lib/lidarr/.config/Lidarr";
user = "lidarr";
group = "lidarr";
}
])
# [PHASE 4] Jackett
(lib.mkIf config.services.jackett.enable [
{
directory = "/var/lib/jackett/.config/Jackett";
user = "jackett";
group = "jackett";
}
])
# [PHASE 4] FlareSolverr
(lib.mkIf config.services.flaresolverr.enable [
{
directory = "/var/lib/flaresolverr";
user = "flaresolverr";
group = "flaresolverr";
}
])
];
};
# [PHASE 4 - LAST] Jellyfin media on separate dataset
# Requires Phase 2 media dataset merge before migrating (several days of data copy)
environment.persistence."/persist/system/jellyfin" = lib.mkIf config.services.jellyfin.enable {
enable = true;
hideMounts = true;
directories = [
{
directory = config.services.jellyfin.media_directory;
user = "jellyfin";
group = "jellyfin_media";
mode = "1770";
}
];
};
# [PHASE 4 - LAST] qBittorrent media on separate dataset
# Requires Phase 2 media dataset merge before migrating (several days of data copy)
environment.persistence."/persist/system/qbittorrent" = lib.mkIf config.services.qbittorrent.enable {
enable = true;
hideMounts = true;
directories = [
{
directory = config.services.qbittorrent.mediaDir;
user = "qbittorrent";
group = "qbittorrent";
mode = "1775";
}
];
};
# [PHASE 3] /var/log persistence - handled by storage.nix after generateBase
environment.persistence."/persist/system/var/log" = {
enable = true;
hideMounts = true;
directories = [
"/var/log"
];
};
};
}

View file

@ -0,0 +1,218 @@
# Legacy storage configuration for defiant
# This file manually defines ZFS datasets matching the existing on-disk layout
# to allow incremental migration to the new storage module (generateBase = true).
#
# ============================================================================
# INCREMENTAL MIGRATION PLAN
# ============================================================================
#
# Current disk usage (for reference):
# rpool/local/system/nix ~26G (renamed in place, no copy)
# rpool/local/system/sops ~328K (renamed in place, no copy)
# rpool/persist/system/jellyfin ~32T (renamed in place, no copy)
# rpool/persist/system/qbittorrent ~6.5T (copied into media dataset, ~6.5T temp)
# rpool free space ~30T
#
# Phase 1: Migrate base datasets on disk (boot from live USB or rescue)
# All operations in this phase are instant renames -- no data is copied.
#
# Unlock the pool:
# zfs load-key -a
#
# Step 1a: Move nix and sops out of local/ (they go to persist/local/)
# The -p flag auto-creates the parent datasets.
#
# zfs rename -p rpool/local/system/nix rpool/persist/local/nix
# zfs rename -p rpool/local/system/sops rpool/persist/local/system/sops
#
# Step 1b: Rename local/ -> ephemeral/ (takes remaining children with it)
# zfs rename rpool/local rpool/ephemeral
# # This moves: local/system/root -> ephemeral/system/root
# # local/home/leyla -> ephemeral/home/leyla
#
# Step 1c: Recreate blank snapshots on ephemeral datasets
# zfs destroy rpool/ephemeral/system/root@blank
# zfs snapshot rpool/ephemeral/system/root@blank
# zfs destroy rpool/ephemeral/home/leyla@blank
# zfs snapshot rpool/ephemeral/home/leyla@blank
#
# Step 1d: Move persist/ children under persist/replicate/
# zfs create -o canmount=off rpool/persist/replicate
# zfs create -o canmount=off rpool/persist/replicate/system
# zfs rename rpool/persist/system/root rpool/persist/replicate/system/root
# zfs rename rpool/persist/system/var rpool/persist/replicate/system/var
# zfs rename rpool/persist/home/leyla rpool/persist/replicate/home
# # Clean up the now-empty home parent
# zfs destroy rpool/persist/home
# # NOTE: Do NOT destroy rpool/persist/system -- it still contains
# # persist/system/jellyfin and persist/system/qbittorrent which are
# # migrated in Phase 2.
#
# Verify the new layout:
# zfs list -r rpool -o name,used,mountpoint
#
# Phase 2: Merge media into a single dataset (do this last)
# Strategy: Rename the jellyfin dataset to become the shared media dataset
# (zero copy, instant), then copy qbittorrent data into it (~6.5T copy).
# This avoids duplicating the 32T jellyfin dataset.
#
# Step 2a: Rename jellyfin dataset to the shared media name
# zfs rename rpool/persist/system/jellyfin rpool/persist/replicate/system/media
#
# Step 2b: Copy qbittorrent data into the media dataset
# This copies ~6.5T and may take several hours/days depending on disk speed.
# The qbittorrent data is not critical to back up so no snapshot needed.
#
# systemctl stop qbittorrent
# rsync -avPHAX /persist/system/qbittorrent/ /persist/replicate/system/media/
#
# Step 2c: Verify the data and clean up
# ls -la /persist/replicate/system/media/
# zfs destroy rpool/persist/system/qbittorrent
# # persist/system should now be empty, clean it up:
# zfs destroy rpool/persist/system
#
# Phase 3: Enable generateBase
# In the nix config:
# - Delete this file (legacy-storage.nix) and remove its import from default.nix
# - Remove [PHASE 3] entries from legacy-impermanence.nix:
# - var-lib-private-permissions activation script
# - /etc/machine-id, SSH host keys (files block)
# - /var/lib/nixos, /var/lib/systemd/coredump (directories)
# - /persist/system/var/log persistence block
# These are now handled automatically by storage.nix and ssh.nix.
# Rebuild and verify:
# sudo nixos-rebuild switch --flake .#defiant
# # Verify mounts: findmnt -t fuse.bindfs,fuse
# # Verify persist: ls /persist/replicate/system/root/var/lib/nixos
# # Verify boot: reboot and confirm system comes up cleanly
#
# Phase 4: Migrate services (one at a time, any order)
# For each service (except jellyfin/qbittorrent):
# 1. Remove the service's [PHASE 4] section from legacy-impermanence.nix
# 2. Remove `impermanence.enable = false` for that service in configuration.nix
# 3. Rebuild: sudo nixos-rebuild switch --flake .#defiant
# 4. Verify: systemctl status <service>, check the service's data is intact
# No data migration is needed -- the data already lives on the renamed
# dataset at the new path.
#
# Migrate jellyfin and qbittorrent LAST (after Phase 2 media merge):
# 1. Remove [PHASE 4 - LAST] jellyfin entries from legacy-impermanence.nix
# 2. Remove [PHASE 4 - LAST] qbittorrent entries from legacy-impermanence.nix
# 3. Remove `impermanence.enable = false` for both in configuration.nix
# 4. Rebuild: sudo nixos-rebuild switch --flake .#defiant
# 5. Verify: systemctl status jellyfin qbittorrent
#
# Phase 5: Cleanup
# Once all services are migrated and legacy-impermanence.nix is empty:
# - Delete legacy-impermanence.nix and remove its import from default.nix
# - Rebuild: sudo nixos-rebuild switch --flake .#defiant
#
# ============================================================================
#
# Current on-disk dataset layout:
# rpool/local/ - ephemeral parent
# rpool/local/home/leyla - ephemeral user home (rolled back on boot)
# rpool/local/system/nix - nix store
# rpool/local/system/root - root filesystem (rolled back on boot)
# rpool/local/system/sops - sops age key
# rpool/persist/ - persistent parent
# rpool/persist/home/leyla - persistent user home
# rpool/persist/system/jellyfin - jellyfin media
# rpool/persist/system/qbittorrent - qbittorrent media
# rpool/persist/system/root - persistent root data
# rpool/persist/system/var/log - log persistence
{lib, ...}: {
# Disable automatic base dataset generation so we can define them manually
storage.generateBase = false;
# Manually define ZFS datasets matching main's structure
storage.zfs.datasets = {
# Ephemeral datasets (local/)
"local" = {
type = "zfs_fs";
mount = null;
};
"local/home/leyla" = {
type = "zfs_fs";
mount = "/home/leyla";
snapshot = {
blankSnapshot = true;
};
};
"local/system/nix" = {
type = "zfs_fs";
mount = "/nix";
atime = "off";
relatime = "off";
snapshot = {
autoSnapshot = false;
};
};
"local/system/root" = {
type = "zfs_fs";
mount = "/";
snapshot = {
blankSnapshot = true;
};
};
"local/system/sops" = {
type = "zfs_fs";
mount = "/var/lib/sops-nix";
};
# Persistent datasets (persist/)
"persist" = {
type = "zfs_fs";
mount = null;
};
"persist/home/leyla" = {
type = "zfs_fs";
mount = "/persist/home/leyla";
snapshot = {
autoSnapshot = true;
};
};
"persist/system/jellyfin" = {
type = "zfs_fs";
mount = "/persist/system/jellyfin";
atime = "off";
relatime = "off";
};
"persist/system/qbittorrent" = {
type = "zfs_fs";
mount = "/persist/system/qbittorrent";
atime = "off";
relatime = "off";
};
"persist/system/root" = {
type = "zfs_fs";
mount = "/persist/system/root";
snapshot = {
autoSnapshot = true;
};
};
"persist/system/var/log" = {
type = "zfs_fs";
mount = "/persist/system/var/log";
};
};
# Boot commands to rollback ephemeral root and user homes on boot
boot.initrd.postResumeCommands = lib.mkAfter ''
zfs rollback -r rpool/local/system/root@blank
zfs rollback -r rpool/local/home/leyla@blank
'';
# FileSystems needed for boot
fileSystems = {
"/".neededForBoot = true;
"/persist/system/root".neededForBoot = true;
"/persist/system/var/log".neededForBoot = true;
"/persist/system/jellyfin".neededForBoot = true;
"/persist/system/qbittorrent".neededForBoot = true;
"/var/lib/sops-nix".neededForBoot = true;
"/persist/home/leyla".neededForBoot = true;
"/home/leyla".neededForBoot = true;
};
}

View file

@ -59,12 +59,22 @@
hardware = { hardware = {
piperMouse.enable = true; piperMouse.enable = true;
}; };
};
storage = { storage = {
zfs = {
enable = true; enable = true;
pool = { pool = {
mode = ""; mode = "stripe";
drives = ["wwn-0x5000039fd0cf05eb"]; vdevs = [
[
{
device = "wwn-0x5000039fd0cf05eb";
boot = true;
}
]
];
cache = [];
}; };
}; };
}; };

View file

@ -3,5 +3,6 @@
imports = [ imports = [
./configuration.nix ./configuration.nix
./hardware-configuration.nix ./hardware-configuration.nix
./legacy-storage.nix
]; ];
} }

View file

@ -0,0 +1,51 @@
# Legacy storage configuration for emergent
# This file manually defines ZFS datasets matching the existing on-disk layout
# to allow incremental migration to the new storage module (generateBase = true).
#
# Current on-disk dataset layout:
# rpool/local/ - parent (canmount=off)
# rpool/local/system/nix - nix store
# rpool/local/system/root - root filesystem
#
# Migration plan:
# Phase 1: Rename datasets on disk (boot from live USB)
# zfs rename -p rpool/local/system/nix rpool/persist/local/nix
# zfs rename rpool/local rpool/persist/local
# # This moves: local/system/root -> persist/local/root (need to rename after)
# # Actually, since local/system/root needs to become persist/local/root:
# zfs rename rpool/persist/local/system/root rpool/persist/local/root
# zfs destroy rpool/persist/local/system # now empty
# # Recreate blank snapshot:
# zfs destroy rpool/persist/local/root@blank
# zfs snapshot rpool/persist/local/root@blank
#
# Phase 2: Delete this file, remove its import from default.nix, rebuild.
{...}: {
# Disable automatic base dataset generation so we can define them manually
storage.generateBase = false;
# Manually define ZFS datasets matching the existing on-disk layout
storage.zfs.datasets = {
"local" = {
type = "zfs_fs";
mount = null;
};
"local/system/nix" = {
type = "zfs_fs";
mount = "/nix";
atime = "off";
relatime = "off";
snapshot = {
autoSnapshot = false;
};
};
"local/system/root" = {
type = "zfs_fs";
mount = "/";
snapshot = {
blankSnapshot = true;
autoSnapshot = true;
};
};
};
}

View file

@ -1,9 +1,4 @@
{ {config, ...}: {
config,
lib,
pkgs,
...
}: {
# Enable OpenGL # Enable OpenGL
hardware.graphics = { hardware.graphics = {
enable = true; enable = true;

View file

@ -32,7 +32,6 @@
isPrincipleUser = true; isPrincipleUser = true;
}; };
eve.isDesktopUser = true; eve.isDesktopUser = true;
ivy.isDesktopUser = true;
}; };
hardware = { hardware = {
@ -85,16 +84,15 @@
}; };
}; };
virtualisation.docker.enable = true;
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
cachefilesd cachefilesd
webtoon-dl webtoon-dl
android-tools
]; ];
services.cachefilesd.enable = true; services.cachefilesd.enable = true;
programs = {
adb.enable = true;
};
networking = { networking = {
networkmanager.enable = true; networkmanager.enable = true;
hostName = "horizon"; # Define your hostname. hostName = "horizon"; # Define your hostname.

View file

@ -4,10 +4,6 @@
pkgs, pkgs,
... ...
}: { }: {
imports = [
./monitors.nix
];
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
boot.initrd.availableKernelModules = ["usb_storage"]; boot.initrd.availableKernelModules = ["usb_storage"];

View file

@ -18,12 +18,12 @@
fileSystems = { fileSystems = {
"/" = { "/" = {
device = "/dev/disk/by-id/ata-TOSHIBA_DT01ACA100_77D21HVNS-part2"; device = "/dev/disk/by-id/nvme-Samsung_SSD_980_500GB_S64ENJ0RA06463Z-part2";
fsType = "ext4"; fsType = "ext4";
}; };
"/boot" = { "/boot" = {
device = "/dev/disk/by-id/ata-TOSHIBA_DT01ACA100_77D21HVNS-part1"; device = "/dev/disk/by-id/nvme-Samsung_SSD_980_500GB_S64ENJ0RA06463Z-part1";
fsType = "vfat"; fsType = "vfat";
options = ["fmask=0022" "dmask=0022"]; options = ["fmask=0022" "dmask=0022"];
}; };

View file

@ -1,199 +0,0 @@
{pkgs, ...}: {
systemd.tmpfiles.rules = [
"L+ /run/gdm/.config/monitors.xml - - - - ${pkgs.writeText "gdm-monitors.xml" ''
<monitors version="2">
<configuration>
<logicalmonitor>
<x>0</x>
<y>156</y>
<scale>1</scale>
<monitor>
<monitorspec>
<connector>DP-4</connector>
<vendor>DEL</vendor>
<product>DELL U2719D</product>
<serial>8RGXNS2</serial>
</monitorspec>
<mode>
<width>2560</width>
<height>1440</height>
<rate>59.951</rate>
</mode>
</monitor>
</logicalmonitor>
<logicalmonitor>
<x>2560</x>
<y>324</y>
<scale>1</scale>
<primary>yes</primary>
<monitor>
<monitorspec>
<connector>DP-2</connector>
<vendor>GSM</vendor>
<product>LG ULTRAGEAR</product>
<serial>0x00068c96</serial>
</monitorspec>
<mode>
<width>1920</width>
<height>1080</height>
<rate>240.001</rate>
</mode>
</monitor>
</logicalmonitor>
<logicalmonitor>
<x>4480</x>
<y>0</y>
<scale>1</scale>
<transform>
<rotation>left</rotation>
<flipped>no</flipped>
</transform>
<monitor>
<monitorspec>
<connector>HDMI-0</connector>
<vendor>HWP</vendor>
<product>HP w2207</product>
<serial>CND7332S88</serial>
</monitorspec>
<mode>
<width>1600</width>
<height>1000</height>
<rate>59.999</rate>
</mode>
</monitor>
</logicalmonitor>
</configuration>
<configuration>
<logicalmonitor>
<x>0</x>
<y>0</y>
<scale>1</scale>
<primary>yes</primary>
<monitor>
<monitorspec>
<connector>DP-1</connector>
<vendor>DEL</vendor>
<product>DELL U2719D</product>
<serial>8RGXNS2</serial>
</monitorspec>
<mode>
<width>2560</width>
<height>1440</height>
<rate>59.951</rate>
</mode>
</monitor>
</logicalmonitor>
<logicalmonitor>
<x>4480</x>
<y>226</y>
<scale>1</scale>
<transform>
<rotation>left</rotation>
<flipped>no</flipped>
</transform>
<monitor>
<monitorspec>
<connector>HDMI-1</connector>
<vendor>HWP</vendor>
<product>HP w2207</product>
<serial>CND7332S88</serial>
</monitorspec>
<mode>
<width>1680</width>
<height>1050</height>
<rate>59.954</rate>
</mode>
</monitor>
</logicalmonitor>
<logicalmonitor>
<x>2560</x>
<y>226</y>
<scale>1</scale>
<monitor>
<monitorspec>
<connector>DP-2</connector>
<vendor>GSM</vendor>
<product>LG ULTRAGEAR</product>
<serial>0x00068c96</serial>
</monitorspec>
<mode>
<width>1920</width>
<height>1080</height>
<rate>240.001</rate>
</mode>
</monitor>
</logicalmonitor>
</configuration>
<configuration>
<logicalmonitor>
<x>2560</x>
<y>228</y>
<scale>1</scale>
<primary>yes</primary>
<monitor>
<monitorspec>
<connector>DP-2</connector>
<vendor>GSM</vendor>
<product>LG ULTRAGEAR</product>
<serial>0x00068c96</serial>
</monitorspec>
<mode>
<width>1920</width>
<height>1080</height>
<rate>240.001</rate>
</mode>
</monitor>
</logicalmonitor>
<logicalmonitor>
<x>4480</x>
<y>69</y>
<scale>1</scale>
<transform>
<rotation>left</rotation>
<flipped>no</flipped>
</transform>
<monitor>
<monitorspec>
<connector>HDMI-1</connector>
<vendor>HWP</vendor>
<product>HP w2207</product>
<serial>CND7332S88</serial>
</monitorspec>
<mode>
<width>1680</width>
<height>1050</height>
<rate>59.954</rate>
</mode>
</monitor>
</logicalmonitor>
<logicalmonitor>
<x>0</x>
<y>0</y>
<scale>1</scale>
<monitor>
<monitorspec>
<connector>DP-3</connector>
<vendor>DEL</vendor>
<product>DELL U2719D</product>
<serial>8RGXNS2</serial>
</monitorspec>
<mode>
<width>2560</width>
<height>1440</height>
<rate>59.951</rate>
</mode>
</monitor>
</logicalmonitor>
<disabled>
<monitorspec>
<connector>None-1</connector>
<vendor>unknown</vendor>
<product>unknown</product>
<serial>unknown</serial>
</monitorspec>
</disabled>
</configuration>
</monitors>
''}"
];
}

View file

@ -4,8 +4,9 @@
# Load nvidia driver for Xorg and Wayland # Load nvidia driver for Xorg and Wayland
videoDrivers = ["nvidia"]; videoDrivers = ["nvidia"];
}; };
# Use X instead of wayland for gaming reasons # Temporarily enable wayland to fix boot issue
displayManager.gdm.wayland = false; # TODO: Investigate proper X11 session generation for gaming
displayManager.gdm.wayland = true;
}; };
hardware = { hardware = {

197
flake.lock generated
View file

@ -1,23 +1,5 @@
{ {
"nodes": { "nodes": {
"devshell": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1741473158,
"narHash": "sha256-kWNaq6wQUbUMlPgw8Y+9/9wP0F8SHkjy24/mN3UAppg=",
"owner": "numtide",
"repo": "devshell",
"rev": "7c9e793ebe66bcba8292989a68c0419b737a22a0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"disko": { "disko": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -25,11 +7,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1763651264, "lastModified": 1772867152,
"narHash": "sha256-8vvwZbw0s7YvBMJeyPVpWke6lg6ROgtts5N2/SMCcv4=", "narHash": "sha256-RIFgZ4O6Eg+5ysZ8Tqb3YvcqiRaNy440GEY22ltjRrs=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "e86a89079587497174ccab6d0d142a65811a4fd9", "rev": "eaafb89b56e948661d618eefd4757d9ea8d77514",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -46,11 +28,11 @@
}, },
"locked": { "locked": {
"dir": "pkgs/firefox-addons", "dir": "pkgs/firefox-addons",
"lastModified": 1763697825, "lastModified": 1772856163,
"narHash": "sha256-AgCCcVPOi1tuzuW5/StlwqBjRWSX62oL97qWuxrq5UA=", "narHash": "sha256-xD+d1+FVhKJ+oFYMTWOdVSBoXS4yeMyVZyDjMXqWEJE=",
"owner": "rycee", "owner": "rycee",
"repo": "nur-expressions", "repo": "nur-expressions",
"rev": "cefce78793603231be226fa77e7ad58e0e4899b8", "rev": "d358a550c7beac5f04fbc5a786e14af079606689",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@ -62,11 +44,11 @@
}, },
"flake-compat": { "flake-compat": {
"locked": { "locked": {
"lastModified": 1761588595, "lastModified": 1767039857,
"narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -75,6 +57,24 @@
"type": "github" "type": "github"
} }
}, },
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1767609335,
"narHash": "sha256-feveD98mQpptwrAEggBQKJTYbvwwglSbOv53uCfH9PY=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "250481aafeb741edfe23d29195671c19b36b6dca",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": { "flake-utils": {
"inputs": { "inputs": {
"systems": "systems" "systems": "systems"
@ -93,24 +93,6 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flakey-profile": { "flakey-profile": {
"locked": { "locked": {
"lastModified": 1712898590, "lastModified": 1712898590,
@ -133,11 +115,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1763748372, "lastModified": 1772845525,
"narHash": "sha256-AUc78Qv3sWir0hvbmfXoZ7Jzq9VVL97l+sP9Jgms+JU=", "narHash": "sha256-Dp5Ir2u4jJDGCgeMRviHvEQDe+U37hMxp6RSNOoMMPc=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "d10a9b16b2a3ee28433f3d1c603f4e9f1fecb8e1", "rev": "27b93804fbef1544cb07718d3f0a451f4c4cd6c0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -147,12 +129,20 @@
} }
}, },
"impermanence": { "impermanence": {
"inputs": {
"home-manager": [
"home-manager"
],
"nixpkgs": [
"nixpkgs"
]
},
"locked": { "locked": {
"lastModified": 1737831083, "lastModified": 1769548169,
"narHash": "sha256-LJggUHbpyeDvNagTUrdhe/pRVp4pnS6wVKALS782gRI=", "narHash": "sha256-03+JxvzmfwRu+5JafM0DLbxgHttOQZkUtDWBmeUkN8Y=",
"owner": "nix-community", "owner": "nix-community",
"repo": "impermanence", "repo": "impermanence",
"rev": "4b3e914cdf97a5b536a889e939fb2fd2b043a170", "rev": "7b1d382faf603b6d264f58627330f9faa5cba149",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -185,11 +175,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1763435414, "lastModified": 1767364176,
"narHash": "sha256-i2467FddWfd19q5Qoj+1/BAeg6LZmM5m4mYGRSQn/as=", "narHash": "sha256-l6YdEBYQxXjD8ujqvc0tKdwWc3K8UQOi+E4Y3DKQ318=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "192c92b603731fbc1bade6c1b18c8d8a0086f703", "rev": "1688100bba140492658d597f6b307c327f35c780",
"revCount": 169, "revCount": 179,
"type": "git", "type": "git",
"url": "https://git.lix.systems/lix-project/nixos-module.git" "url": "https://git.lix.systems/lix-project/nixos-module.git"
}, },
@ -200,18 +190,15 @@
}, },
"mcp-nixos": { "mcp-nixos": {
"inputs": { "inputs": {
"devshell": "devshell", "flake-parts": "flake-parts",
"flake-utils": "flake-utils_2", "nixpkgs": "nixpkgs"
"nixpkgs": [
"nixpkgs"
]
}, },
"locked": { "locked": {
"lastModified": 1760821194, "lastModified": 1772769318,
"narHash": "sha256-UCsJ8eDuHL14u2GFIYEY/drtZ6jht5zN/G/6QNlEy2g=", "narHash": "sha256-RAyOW5JMXRhiREqxFPOzw80fVsYVBnOPFgBSjnJ6gbY=",
"owner": "utensils", "owner": "utensils",
"repo": "mcp-nixos", "repo": "mcp-nixos",
"rev": "0ae453f38d0f088c31d4678da3a12b183165986f", "rev": "60c1efbba0de1268b42f1144c904e6c8a9627dde",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -227,11 +214,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1763505477, "lastModified": 1772379624,
"narHash": "sha256-nJRd4LY2kT3OELfHqdgWjvToNZ4w+zKCMzS2R6z4sXE=", "narHash": "sha256-NG9LLTWlz4YiaTAiRGChbrzbVxBfX+Auq4Ab/SWmk4A=",
"owner": "LnL7", "owner": "LnL7",
"repo": "nix-darwin", "repo": "nix-darwin",
"rev": "3bda9f6b14161becbd07b3c56411f1670e19b9b5", "rev": "52d061516108769656a8bd9c6e811c677ec5b462",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -268,11 +255,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1763690163, "lastModified": 1772850876,
"narHash": "sha256-MMl9P8f17unCvlk2IAinnMq/P72f51UUHVRIYnojT7w=", "narHash": "sha256-Ga19zlfMpakCY4GMwBSOljNLOF0nEYrYBXv0hP/d4rw=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nix-vscode-extensions", "repo": "nix-vscode-extensions",
"rev": "590349d9faeb398a037205c2927ffbaede980539", "rev": "22f084d4c280dfc8a9d764f7b85af38e5d69c3dc",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -283,11 +270,11 @@
}, },
"nixos-hardware": { "nixos-hardware": {
"locked": { "locked": {
"lastModified": 1762847253, "lastModified": 1771969195,
"narHash": "sha256-BWWnUUT01lPwCWUvS0p6Px5UOBFeXJ8jR+ZdLX8IbrU=", "narHash": "sha256-qwcDBtrRvJbrrnv1lf/pREQi8t2hWZxVAyeMo7/E9sw=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "899dc449bc6428b9ee6b3b8f771ca2b0ef945ab9", "rev": "41c6b421bdc301b2624486e11905c9af7b8ec68e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -299,27 +286,42 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1722073938, "lastModified": 1767640445,
"narHash": "sha256-OpX0StkL8vpXyWOGUD6G+MA26wAXK6SpT94kLJXo6B4=", "narHash": "sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i+bwD6XxMb8A=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "e36e9f57337d0ff0cf77aceb58af4c805472bfae", "rev": "9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixpkgs-unstable", "ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"nixpkgs-lib": {
"locked": {
"lastModified": 1765674936,
"narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1763421233, "lastModified": 1772773019,
"narHash": "sha256-Stk9ZYRkGrnnpyJ4eqt9eQtdFWRRIvMxpNRf4sIegnw=", "narHash": "sha256-E1bxHxNKfDoQUuvriG71+f+s/NT0qWkImXsYZNFFfCs=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "89c2b2330e733d6cdb5eae7b899326930c2c0648", "rev": "aca4d95fce4914b3892661bcb80b8087293536c6",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -349,14 +351,14 @@
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_3", "nixpkgs": "nixpkgs_3",
"rust-overlay": "rust-overlay", "rust-overlay": "rust-overlay",
"systems": "systems_3" "systems": "systems_2"
}, },
"locked": { "locked": {
"lastModified": 1764204484, "lastModified": 1771445312,
"narHash": "sha256-S45ghD/YjcKDy8Mz3DYklLMaA/z6f6mTbx0i7pAktYk=", "narHash": "sha256-8uOcu+ZurGx0LmGFCf87Zbj4ikhVPQtP+PuBscEBCv0=",
"owner": "IntQuant", "owner": "IntQuant",
"repo": "noita_entangled_worlds", "repo": "noita_entangled_worlds",
"rev": "ab2c2162157140ab519fa19f6737c044e1ed0e3b", "rev": "4a842f29d0e5fb8dc6df73d87f7bb8d2a16f0fc8",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -409,11 +411,11 @@
"secrets": { "secrets": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1759945215, "lastModified": 1768867162,
"narHash": "sha256-xmUzOuhJl6FtTjR5++OQvSoAnXe7/VA5QFCZDyFwBXo=", "narHash": "sha256-NiW2gUcdhnUbYQw476HzgBz+uVjyLnz151hzCQbWBX8=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "444229a105445339fb028d15a8d866063c5f8141", "rev": "22be81505a49cd205e9b5c91f51af69c0b885ed3",
"revCount": 21, "revCount": 23,
"type": "git", "type": "git",
"url": "ssh://git@git.jan-leila.com/jan-leila/nix-config-secrets.git" "url": "ssh://git@git.jan-leila.com/jan-leila/nix-config-secrets.git"
}, },
@ -429,11 +431,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1763607916, "lastModified": 1772495394,
"narHash": "sha256-VefBA1JWRXM929mBAFohFUtQJLUnEwZ2vmYUNkFnSjE=", "narHash": "sha256-hmIvE/slLKEFKNEJz27IZ8BKlAaZDcjIHmkZ7GCEjfw=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "877bb495a6f8faf0d89fc10bd142c4b7ed2bcc0b", "rev": "1d9b98a29a45abe9c4d3174bd36de9f28755e3ff",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -458,21 +460,6 @@
} }
}, },
"systems_2": { "systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_3": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1681028828, "lastModified": 1681028828,

View file

@ -37,6 +37,8 @@
# delete your darlings # delete your darlings
impermanence = { impermanence = {
url = "github:nix-community/impermanence"; url = "github:nix-community/impermanence";
inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager";
}; };
nix-darwin = { nix-darwin = {
@ -75,7 +77,7 @@
# MCP NixOS server for Claude Dev # MCP NixOS server for Claude Dev
mcp-nixos = { mcp-nixos = {
url = "github:utensils/mcp-nixos"; url = "github:utensils/mcp-nixos";
inputs.nixpkgs.follows = "nixpkgs"; # Not following nixpkgs because aws-sam-translator doesn't support Python 3.14 yet
}; };
# Noita Entangled Worlds package # Noita Entangled Worlds package

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,53 @@
{
lib,
buildNpmPackage,
fetchurl,
ripgrep,
makeWrapper,
jq,
...
}:
buildNpmPackage rec {
pname = "cline";
version = "2.4.2";
src = fetchurl {
url = "https://registry.npmjs.org/cline/-/cline-${version}.tgz";
hash = "sha256-2utOBC0vhoj5fR+cG+Vdo3N6+i/pNW1E4mESF/dZS/c=";
};
sourceRoot = "package";
postPatch = ''
cp ${./cline-package-lock.json} package-lock.json
# Remove @vscode/ripgrep from package.json since it tries to download
# a binary from GitHub during install, which fails in the nix sandbox.
# We provide ripgrep from nixpkgs instead via PATH wrapping.
# Also remove the man field since the man page is not included in the npm tarball.
${jq}/bin/jq 'del(.dependencies["@vscode/ripgrep"]) | del(.man)' package.json > package.json.tmp
mv package.json.tmp package.json
'';
npmDepsHash = "sha256-oHo60ghR7A4SUT0cLmIe7glPDYBK3twJ0F71RKVrxQc=";
dontNpmBuild = true;
# Skip post-install scripts to be safe
npmFlags = ["--ignore-scripts"];
nativeBuildInputs = [makeWrapper jq];
# Provide ripgrep from nixpkgs since @vscode/ripgrep was removed
postInstall = ''
wrapProgram $out/bin/cline \
--prefix PATH : ${lib.makeBinPath [ripgrep]}
'';
meta = with lib; {
description = "Autonomous coding agent CLI - capable of creating/editing files, running commands, using the browser, and more";
homepage = "https://cline.bot";
license = licenses.asl20;
mainProgram = "cline";
};
}

View file

@ -44,5 +44,11 @@
# Override h3 C library to version 4.3.0 # Override h3 C library to version 4.3.0
h3 = pkgs.callPackage ./h3-c-lib.nix {}; h3 = pkgs.callPackage ./h3-c-lib.nix {};
}) })
(final: prev: {
cline = pkgs.callPackage ./cline/default.nix {};
})
(final: prev: {
e621-downloader = pkgs.callPackage ./e621-downloader.nix {};
})
]; ];
} }

View file

@ -0,0 +1,36 @@
{
lib,
rustPlatform,
fetchFromGitHub,
pkg-config,
openssl,
...
}:
rustPlatform.buildRustPackage rec {
pname = "e621-downloader";
version = "1.7.2";
src = fetchFromGitHub {
owner = "McSib";
repo = "e621_downloader";
rev = version;
hash = "sha256-4z+PrCv8Mlp0VOJ5Akv1TXrJir1Ws/+45a6VCZGuCtk=";
};
cargoHash = "sha256-/yqNYjP7BuFQWilL2Ty+E5rd8qXj30twteptHx7cLRo=";
nativeBuildInputs = [
pkg-config
];
buildInputs = [
openssl
];
meta = with lib; {
description = "E621 and E926 downloader made in Rust";
homepage = "https://github.com/McSib/e621_downloader";
license = licenses.asl20;
mainProgram = "e621_downloader";
};
}

View file

@ -4,8 +4,12 @@
makeWrapper, makeWrapper,
jdk, jdk,
lib, lib,
xorg,
libGL, libGL,
libx11,
libxcursor,
libxext,
libxrandr,
libxxf86vm,
... ...
}: }:
stdenv.mkDerivation rec { stdenv.mkDerivation rec {
@ -24,11 +28,11 @@ stdenv.mkDerivation rec {
runtimeDependencies = lib.makeLibraryPath [ runtimeDependencies = lib.makeLibraryPath [
# glfw # glfw
libGL libGL
xorg.libX11 libx11
xorg.libXcursor libxcursor
xorg.libXext libxext
xorg.libXrandr libxrandr
xorg.libXxf86vm libxxf86vm
]; ];
installPhase = '' installPhase = ''

View file

@ -12,21 +12,29 @@ in {
type = lib.types.bool; type = lib.types.bool;
default = true; default = true;
}; };
persistencePath = lib.mkOption {
type = lib.types.str;
default =
if osConfig.storage.generateBase
then "/persist/replicate/home"
else "/persist";
description = "The base path for user home persistence. The impermanence module will automatically append the user's home directory path. Automatically adapts based on whether the system uses the new dataset layout or the legacy one.";
};
}; };
config = lib.mkMerge [ config = lib.mkMerge [
(lib.mkIf config.impermanence.enable { (lib.mkIf config.impermanence.enable {
assertions = [ assertions = [
{ {
assertion = osConfig.host.impermanence.enable; assertion = osConfig.storage.impermanence.enable;
message = "impermanence can not be enabled for a user when it is not enabled for the system"; message = "impermanence can not be enabled for a user when it is not enabled for the system";
} }
]; ];
}) })
# If impermanence is not enabled for this user but system impermanence is enabled, # If impermanence is not enabled for this user but system impermanence is enabled,
# persist the entire home directory as fallback # persist the entire home directory as fallback
(lib.mkIf (osConfig.host.impermanence.enable && !cfg.enable && cfg.fallbackPersistence.enable) { (lib.mkIf (osConfig.storage.impermanence.enable && !cfg.enable && cfg.fallbackPersistence.enable) {
home.persistence."/persist/home/${config.home.username}" = { home.persistence."${cfg.persistencePath}" = {
directories = ["."]; directories = ["."];
allowOther = true; allowOther = true;
}; };

View file

@ -52,9 +52,9 @@
addKeysToAgent = "confirm"; addKeysToAgent = "confirm";
}; };
}; };
extraConfig = lib.strings.concatLines ( # extraConfig = lib.strings.concatLines (
builtins.map (hostKey: "IdentityFile ~/.ssh/${hostKey.path}") config.programs.openssh.hostKeys # builtins.map (hostKey: "IdentityFile ~/.ssh/${hostKey.path}") config.programs.openssh.hostKeys
); # );
}; };
systemd.user.services = builtins.listToAttrs ( systemd.user.services = builtins.listToAttrs (
@ -96,7 +96,7 @@
} }
) )
(lib.mkIf config.impermanence.enable { (lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
files = lib.lists.flatten ( files = lib.lists.flatten (
builtins.map (hostKey: [".ssh/${hostKey.path}" ".ssh/${hostKey.path}.pub"]) config.programs.openssh.hostKeys builtins.map (hostKey: [".ssh/${hostKey.path}" ".ssh/${hostKey.path}.pub"]) config.programs.openssh.hostKeys
); );

View file

@ -0,0 +1,30 @@
{
lib,
pkgs,
config,
...
}: {
options.programs.android-studio = {
enable = lib.mkEnableOption "enable android-studio";
};
config = lib.mkIf config.programs.android-studio.enable (lib.mkMerge [
{
home.packages = with pkgs; [
android-studio
];
}
(
lib.mkIf config.impermanence.enable {
home.persistence."${config.impermanence.persistencePath}" = {
directories = [
"${config.xdg.configHome}/Google/AndroidStudio"
".android"
".gradle"
"${config.xdg.cacheHome}/Google/AndroidStudio"
];
};
}
)
]);
}

View file

@ -1,15 +1,13 @@
{ {
lib, lib,
config, config,
osConfig,
... ...
}: { }: {
config = lib.mkIf (config.programs.anki.enable && osConfig.host.impermanence.enable) { config = lib.mkIf (config.programs.anki.enable && config.impermanence.enable) {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.dataHome}/Anki2/" ".local/share/Anki2"
]; ];
allowOther = true;
}; };
}; };
} }

View file

@ -16,11 +16,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/Bitwarden" "${config.xdg.configHome}/Bitwarden"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -16,11 +16,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/bruno/" "${config.xdg.configHome}/bruno/"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -4,10 +4,6 @@
config, config,
... ...
}: { }: {
options.programs.calibre = {
enable = lib.mkEnableOption "enable calibre";
};
config = lib.mkIf config.programs.calibre.enable (lib.mkMerge [ config = lib.mkIf config.programs.calibre.enable (lib.mkMerge [
{ {
home.packages = with pkgs; [ home.packages = with pkgs; [
@ -16,11 +12,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/calibre" "${config.xdg.configHome}/calibre"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -16,12 +16,11 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.dataHome}/DaVinciResolve" "${config.xdg.dataHome}/DaVinciResolve"
"${config.xdg.configHome}/blackmagic" "${config.xdg.configHome}/blackmagic"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -16,11 +16,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.dataHome}/DBeaverData/" "${config.xdg.dataHome}/DBeaverData/"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -1,5 +1,6 @@
{...}: { {...}: {
imports = [ imports = [
./android-studio.nix
./firefox.nix ./firefox.nix
./signal.nix ./signal.nix
./bitwarden.nix ./bitwarden.nix
@ -13,6 +14,7 @@
./prostudiomasters.nix ./prostudiomasters.nix
./idea.nix ./idea.nix
./kdenlive.nix ./kdenlive.nix
./kicad.nix
./krita.nix ./krita.nix
./protonvpn.nix ./protonvpn.nix
./calibre.nix ./calibre.nix
@ -45,5 +47,9 @@
./gdx-liftoff.nix ./gdx-liftoff.nix
./tor-browser.nix ./tor-browser.nix
./vmware-workstation.nix ./vmware-workstation.nix
./proton-mail-pwa.nix
./proton-calendar-pwa.nix
./matrix-cyberia-pwa.nix
./e621-downloader.nix
]; ];
} }

View file

@ -6,11 +6,10 @@
config = lib.mkIf config.programs.discord.enable (lib.mkMerge [ config = lib.mkIf config.programs.discord.enable (lib.mkMerge [
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/discord/" "${config.xdg.configHome}/discord/"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -0,0 +1,16 @@
{
lib,
pkgs,
config,
...
}: {
options.programs.e621-downloader = {
enable = lib.mkEnableOption "enable e621-downloader";
};
config = lib.mkIf config.programs.e621-downloader.enable {
home.packages = with pkgs; [
e621-downloader
];
};
}

View file

@ -22,11 +22,10 @@
# Extension configuration # Extension configuration
".mozilla/firefox/${profile}/extension-settings.json" ".mozilla/firefox/${profile}/extension-settings.json"
]; ];
allowOther = true;
}; };
in { in {
config = lib.mkIf (config.programs.firefox.enable && config.impermanence.enable) { config = lib.mkIf (config.programs.firefox.enable && config.impermanence.enable) {
home.persistence."/persist${config.home.homeDirectory}" = lib.mkMerge ( home.persistence."${config.impermanence.persistencePath}" = lib.mkMerge (
( (
lib.attrsets.mapAttrsToList lib.attrsets.mapAttrsToList
(profile: _: buildProfilePersistence profile) (profile: _: buildProfilePersistence profile)

View file

@ -16,11 +16,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/FreeCAD" "${config.xdg.configHome}/FreeCAD"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -16,11 +16,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/GIMP" "${config.xdg.configHome}/GIMP"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -4,19 +4,19 @@
config, config,
... ...
}: { }: {
options.programs.jetbrains.idea-community = { options.programs.jetbrains.idea-oss = {
enable = lib.mkEnableOption "enable idea-community"; enable = lib.mkEnableOption "enable idea-oss";
}; };
config = lib.mkIf config.programs.jetbrains.idea-community.enable (lib.mkMerge [ config = lib.mkIf config.programs.jetbrains.idea-oss.enable (lib.mkMerge [
{ {
home.packages = with pkgs; [ home.packages = with pkgs; [
jetbrains.idea-community jetbrains.idea-oss
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
# configuration # configuration
"${config.xdg.configHome}/JetBrains/" "${config.xdg.configHome}/JetBrains/"

View file

@ -16,11 +16,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/inkscape" "${config.xdg.configHome}/inkscape"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -23,12 +23,11 @@ in {
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/kdenliverc" "${config.xdg.configHome}/kdenliverc"
"${config.xdg.dataHome}/kdenlive" "${config.xdg.dataHome}/kdenlive"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -0,0 +1,23 @@
{
lib,
pkgs,
config,
...
}: {
options.programs.kicad = {
enable = lib.mkEnableOption "enable kicad";
};
config = lib.mkIf config.programs.kicad.enable (lib.mkMerge [
{
home.packages = with pkgs; [
kicad
];
}
(
lib.mkIf config.impermanence.enable {
# TODO:
}
)
]);
}

View file

@ -16,12 +16,11 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/kritarc" "${config.xdg.configHome}/kritarc"
"${config.xdg.dataHome}/krita" "${config.xdg.dataHome}/krita"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -16,11 +16,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/libreoffice" "${config.xdg.configHome}/libreoffice"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -30,7 +30,7 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
".MakeMKV" ".MakeMKV"
]; ];

View file

@ -17,12 +17,11 @@ in {
} }
( (
mkIf config.impermanence.enable { mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/mapillary-uploader" "${config.xdg.configHome}/mapillary-uploader"
"${config.xdg.dataHome}/mapillary-uploader" "${config.xdg.dataHome}/mapillary-uploader"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -0,0 +1,56 @@
{
lib,
pkgs,
config,
...
}: let
cfg = config.programs.matrix-cyberia-pwa;
isChromium = cfg.package == pkgs.chromium;
isBrowserImpermanenceSupported = cfg.package == pkgs.chromium;
in {
options.programs.matrix-cyberia-pwa = {
enable = lib.mkEnableOption "enable Matrix Cyberia PWA";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.chromium;
description = "Browser package to use for the PWA";
};
impermanence = {
enable = lib.mkOption {
type = lib.types.bool;
default = isBrowserImpermanenceSupported;
description = "Enable impermanence configuration for the PWA. Only automatically enabled when using chromium.";
};
};
};
config = lib.mkIf cfg.enable (lib.mkMerge [
{
warnings =
lib.optional (config.impermanence.enable && !isBrowserImpermanenceSupported)
"matrix-cyberia-pwa: Using unsupported package. You will need to manually configure pwa for ${cfg.package.pname}. Supported package(s) ${pkgs.chromium.pname}";
}
(
lib.mkIf isChromium {
xdg.desktopEntries.matrix-cyberia-pwa = {
name = "Matrix (Cyberia)";
type = "Application";
exec = "${cfg.package}/bin/${cfg.package.pname} --app=https://chat.cyberia.club/";
icon = "matrix";
terminal = false;
categories = ["Network" "InstantMessaging"];
};
}
)
(
lib.mkIf (config.impermanence.enable && cfg.impermanence.enable && isChromium) {
home.persistence."/persist${config.home.homeDirectory}" = {
directories = [
"${config.xdg.configHome}/chromium"
];
allowOther = true;
};
}
)
]);
}

View file

@ -6,11 +6,10 @@
config = lib.mkIf config.programs.obs-studio.enable (lib.mkMerge [ config = lib.mkIf config.programs.obs-studio.enable (lib.mkMerge [
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/obs-studio" "${config.xdg.configHome}/obs-studio"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -6,7 +6,7 @@
config = lib.mkIf config.programs.obsidian.enable (lib.mkMerge [ config = lib.mkIf config.programs.obsidian.enable (lib.mkMerge [
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/obsidian" "${config.xdg.configHome}/obsidian"
]; ];

View file

@ -23,12 +23,11 @@ in {
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/olympus" "${config.xdg.configHome}/olympus"
"${config.xdg.dataHome}/olympus" "${config.xdg.dataHome}/olympus"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -16,11 +16,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/OpenRGB" "${config.xdg.configHome}/OpenRGB"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -16,11 +16,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/MusicBrainz" "${config.xdg.configHome}/MusicBrainz"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -16,7 +16,7 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/ProStudioMasters" "${config.xdg.configHome}/ProStudioMasters"
]; ];

View file

@ -0,0 +1,55 @@
{
lib,
pkgs,
config,
...
}: let
cfg = config.programs.proton-calendar-pwa;
isChromium = cfg.package == pkgs.chromium;
isBrowserImpermanenceSupported = cfg.package == pkgs.chromium;
in {
options.programs.proton-calendar-pwa = {
enable = lib.mkEnableOption "enable Proton Calendar PWA";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.chromium;
description = "Browser package to use for the PWA";
};
impermanence = {
enable = lib.mkOption {
type = lib.types.bool;
default = isBrowserImpermanenceSupported;
description = "Enable impermanence configuration for the PWA. Only automatically enabled when using chromium.";
};
};
};
config = lib.mkIf cfg.enable (lib.mkMerge [
{
warnings =
lib.optional (config.impermanence.enable && !isBrowserImpermanenceSupported)
"proton-calendar-pwa: Using unsupported package. You will need to manually configure pwa for ${cfg.package.pname}. Supported package(s) ${pkgs.chromium.pname}";
}
(
lib.mkIf isChromium {
xdg.desktopEntries.proton-calendar-pwa = {
name = "Proton Calendar";
type = "Application";
exec = "${cfg.package}/bin/${cfg.package.pname} --app=https://calendar.proton.me";
icon = "chrome-ojibjkjikcpjonjjngfkegflhmffeemk-Default";
terminal = false;
};
}
)
(
lib.mkIf (config.impermanence.enable && cfg.impermanence.enable && isChromium) {
home.persistence."/persist${config.home.homeDirectory}" = {
directories = [
"${config.xdg.configHome}/chromium"
];
allowOther = true;
};
}
)
]);
}

View file

@ -0,0 +1,55 @@
{
lib,
pkgs,
config,
...
}: let
cfg = config.programs.proton-mail-pwa;
isChromium = cfg.package == pkgs.chromium;
isBrowserImpermanenceSupported = cfg.package == pkgs.chromium;
in {
options.programs.proton-mail-pwa = {
enable = lib.mkEnableOption "enable Proton Mail PWA";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.chromium;
description = "Browser package to use for the PWA";
};
impermanence = {
enable = lib.mkOption {
type = lib.types.bool;
default = isBrowserImpermanenceSupported;
description = "Enable impermanence configuration for the PWA. Only automatically enabled when using chromium.";
};
};
};
config = lib.mkIf cfg.enable (lib.mkMerge [
{
warnings =
lib.optional (config.impermanence.enable && !isBrowserImpermanenceSupported)
"proton-mail-pwa: Using unsupported package. You will need to manually configure pwa for ${cfg.package.pname}. Supported package(s) ${pkgs.chromium.pname}";
}
(
lib.mkIf isChromium {
xdg.desktopEntries.proton-mail-pwa = {
name = "Proton Mail";
type = "Application";
exec = "${cfg.package}/bin/${cfg.package.pname} --app=https://mail.proton.me";
icon = "chrome-jnpecgipniidlgicjocehkhajgdnjekh-Default";
terminal = false;
};
}
)
(
lib.mkIf (config.impermanence.enable && cfg.impermanence.enable && isChromium) {
home.persistence."/persist${config.home.homeDirectory}" = {
directories = [
"${config.xdg.configHome}/chromium"
];
allowOther = true;
};
}
)
]);
}

View file

@ -16,7 +16,7 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/protonvpn" "${config.xdg.configHome}/protonvpn"
"${config.xdg.configHome}/Proton" "${config.xdg.configHome}/Proton"

View file

@ -16,7 +16,7 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/qBittorrent" "${config.xdg.configHome}/qBittorrent"
]; ];

View file

@ -16,11 +16,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/qFlipper" "${config.xdg.configHome}/qFlipper"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -4,19 +4,19 @@
config, config,
... ...
}: { }: {
options.programs.signal-desktop-bin = { options.programs.signal-desktop = {
enable = lib.mkEnableOption "enable signal"; enable = lib.mkEnableOption "enable signal";
}; };
config = lib.mkIf config.programs.signal-desktop-bin.enable (lib.mkMerge [ config = lib.mkIf config.programs.signal-desktop.enable (lib.mkMerge [
{ {
home.packages = with pkgs; [ home.packages = with pkgs; [
signal-desktop-bin signal-desktop
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/Signal" "${config.xdg.configHome}/Signal"
]; ];

View file

@ -18,14 +18,13 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
{ {
directory = "${config.xdg.dataHome}/Steam"; directory = "${config.xdg.dataHome}/Steam";
method = "symlink"; method = "symlink";
} }
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -16,11 +16,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.dataHome}/torbrowser" "${config.xdg.dataHome}/torbrowser"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -16,11 +16,10 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/chromium" "${config.xdg.configHome}/chromium"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -16,12 +16,11 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
"${config.xdg.configHome}/via" "${config.xdg.configHome}/via"
"${config.xdg.dataHome}/via" "${config.xdg.dataHome}/via"
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -17,7 +17,7 @@
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."${config.impermanence.persistencePath}" = {
directories = [ directories = [
{ {
directory = ".vmware"; directory = ".vmware";
@ -28,7 +28,6 @@
method = "symlink"; method = "symlink";
} }
]; ];
allowOther = true;
}; };
} }
) )

View file

@ -10,6 +10,19 @@
mcp-nixos = inputs.mcp-nixos.packages.${pkgs.stdenv.hostPlatform.system}.default; mcp-nixos = inputs.mcp-nixos.packages.${pkgs.stdenv.hostPlatform.system}.default;
anyProfileHasInstallTool = lib.any (
profile:
profile.extraExtensions.claudeDev.enable
&& profile.extraExtensions.claudeDev.installTool
) (lib.attrValues config.programs.vscode.profiles);
getInstallToolPackage = lib.findFirst (package: package != null) pkgs.cline (map (
profile:
if profile.extraExtensions.claudeDev.enable && profile.extraExtensions.claudeDev.installTool
then profile.extraExtensions.claudeDev.package
else null
) (lib.attrValues config.programs.vscode.profiles));
anyProfileHasMcpNixos = lib.any ( anyProfileHasMcpNixos = lib.any (
profile: profile:
profile.extraExtensions.claudeDev.enable profile.extraExtensions.claudeDev.enable
@ -69,6 +82,17 @@ in {
default = ["saoudrizwan" "claude-dev"]; default = ["saoudrizwan" "claude-dev"];
}; };
installTool = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to install the cline CLI tool for subagent support when the extension is enabled";
};
package = lib.mkOption {
type = lib.types.package;
default = pkgs.cline;
description = "The package to install for the cline CLI tool";
};
mcp = { mcp = {
nixos = { nixos = {
enable = lib.mkEnableOption "enable NixOS MCP server for Claude Dev"; enable = lib.mkEnableOption "enable NixOS MCP server for Claude Dev";
@ -145,6 +169,12 @@ in {
}; };
config = lib.mkMerge [ config = lib.mkMerge [
(lib.mkIf anyProfileHasInstallTool {
home.packages = [
getInstallToolPackage
];
})
(lib.mkIf anyProfileHasMcpNixos { (lib.mkIf anyProfileHasMcpNixos {
home.packages = [ home.packages = [
mcp-nixos mcp-nixos

View file

@ -16,6 +16,7 @@
./go.nix ./go.nix
./evenBetterToml.nix ./evenBetterToml.nix
./openRemoteSsh.nix ./openRemoteSsh.nix
./platformIO.nix
./rustAnalyzer.nix ./rustAnalyzer.nix
./astroVscode.nix ./astroVscode.nix
./vscodeMdx.nix ./vscodeMdx.nix
@ -25,5 +26,6 @@
./direnv.nix ./direnv.nix
./conventionalCommits.nix ./conventionalCommits.nix
./openDyslexicFont.nix ./openDyslexicFont.nix
./graphql.nix
]; ];
} }

View file

@ -21,6 +21,13 @@ in {
extensions = [ extensions = [
config.extraExtensions.go.extension config.extraExtensions.go.extension
]; ];
userSettings = {
"go.alternateTools" = {
"gopls" = "gopls";
};
"go.toolsManagement.autoUpdate" = false;
"go.useLanguageServer" = true;
};
}; };
})); }));
}; };

View file

@ -0,0 +1,27 @@
{
lib,
pkgs,
config,
...
}: let
pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version;
pkgsRepository = pkgsRepositories.open-vsx;
in {
options.programs.vscode.profiles = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({config, ...}: {
options = {
extraExtensions.graphql = {
enable = lib.mkEnableOption "should the graphql highlighting extension for vscode be enabled";
extension = lib.mkPackageOption pkgsRepository "vscode-graphql" {
default = ["graphql" "vscode-graphql-syntax"];
};
};
};
config = lib.mkIf config.extraExtensions.graphql.enable {
extensions = [
config.extraExtensions.graphql.extension
];
};
}));
};
}

View file

@ -0,0 +1,30 @@
{
lib,
pkgs,
config,
...
}: let
pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version;
pkgsRepository = pkgsRepositories.open-vsx;
in {
options.programs.vscode.profiles = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({config, ...}: {
options = {
extraExtensions.platformIO = {
enable = lib.mkEnableOption "should the platformIO extension for vscode be enabled";
extension = lib.mkPackageOption pkgsRepository "platformIO" {
default = ["pioarduino" "pioarduino-ide"];
};
};
};
config = lib.mkIf config.extraExtensions.platformIO.enable {
extensions = [
config.extraExtensions.platformIO.extension
];
userSettings = {
"platformio-ide.useBuiltinPIOCore" = false;
};
};
}));
};
}

View file

@ -8,14 +8,13 @@
./desktop.nix ./desktop.nix
./ssh.nix ./ssh.nix
./i18n.nix ./i18n.nix
./sync.nix ./sync
./impermanence.nix ./ollama
./disko.nix
./ollama.nix
./ai.nix ./ai.nix
./tailscale.nix ./tailscale
./steam.nix ./steam.nix
./server ./server
./storage
]; ];
nixpkgs.config.permittedInsecurePackages = [ nixpkgs.config.permittedInsecurePackages = [

View file

@ -47,6 +47,9 @@
# Get rid of xTerm # Get rid of xTerm
desktopManager.xterm.enable = false; desktopManager.xterm.enable = false;
excludePackages = with pkgs; [
xterm
];
}; };
# Enable the GNOME Desktop Environment. # Enable the GNOME Desktop Environment.

View file

@ -1,267 +0,0 @@
{
lib,
pkgs,
config,
inputs,
...
}: let
# there currently is a bug with disko that causes long disk names to be generated improperly this hash function should alleviate it when used for disk names instead of what we are defaulting to
# max gpt length is 36 and disk adds formats it like disk-xxxx-zfs which means we need to be 9 characters under that
hashDisk = drive: (builtins.substring 0 27 (builtins.hashString "sha256" drive));
vdevs =
builtins.map (
disks:
builtins.map (disk: lib.attrsets.nameValuePair (hashDisk disk) disk) disks
)
config.host.storage.pool.vdevs;
cache =
builtins.map (
disk: lib.attrsets.nameValuePair (hashDisk disk) disk
)
config.host.storage.pool.cache;
datasets = config.host.storage.pool.datasets // config.host.storage.pool.extraDatasets;
in {
options.host.storage = {
enable = lib.mkEnableOption "are we going create zfs disks with disko on this device";
encryption = lib.mkEnableOption "is the vdev going to be encrypted";
notifications = {
enable = lib.mkEnableOption "are notifications enabled";
host = lib.mkOption {
type = lib.types.str;
description = "what is the host that we are going to send the email to";
};
port = lib.mkOption {
type = lib.types.port;
description = "what port is the host using to receive mail on";
};
to = lib.mkOption {
type = lib.types.str;
description = "what account is the email going to be sent to";
};
user = lib.mkOption {
type = lib.types.str;
description = "what user is the email going to be set from";
};
tokenFile = lib.mkOption {
type = lib.types.str;
description = "file containing the password to be used by msmtp for notifications";
};
};
pool = {
mode = lib.mkOption {
type = lib.types.str;
default = "raidz2";
description = "what level of redundancy should this pool have";
};
# list of drives in pool that will have a boot partition put onto them
bootDrives = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "list of disks that are going to have a boot partition installed on them";
default = lib.lists.flatten config.host.storage.pool.vdevs;
};
# shorthand for vdevs if you only have 1 vdev
drives = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "list of drives that are going to be in the vdev";
default = [];
};
# list of all drives in each vdev
vdevs = lib.mkOption {
type = lib.types.listOf (lib.types.listOf lib.types.str);
description = "list of disks that are going to be in";
default = [config.host.storage.pool.drives];
};
# list of cache drives for pool
cache = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "list of drives that are going to be used as cache";
default = [];
};
# Default datasets that are needed to make a functioning system
datasets = lib.mkOption {
type = lib.types.attrsOf (inputs.disko.lib.subType {
types = {inherit (inputs.disko.lib.types) zfs_fs zfs_volume;};
});
default = {
"local" = {
type = "zfs_fs";
options.canmount = "off";
};
# nix directory needs to be available pre persist and doesn't need to be snapshotted or backed up
"local/system/nix" = {
type = "zfs_fs";
mountpoint = "/nix";
options = {
atime = "off";
relatime = "off";
canmount = "on";
};
};
# dataset for root that gets rolled back on every boot
"local/system/root" = {
type = "zfs_fs";
mountpoint = "/";
options = {
canmount = "on";
};
postCreateHook = ''
zfs snapshot rpool/local/system/root@blank
'';
};
};
};
extraDatasets = lib.mkOption {
type = lib.types.attrsOf (inputs.disko.lib.subType {
types = {inherit (inputs.disko.lib.types) zfs_fs zfs_volume;};
});
description = "List of datasets to define";
default = {};
};
};
};
config = lib.mkIf config.host.storage.enable {
programs.msmtp = lib.mkIf config.host.storage.notifications.enable {
enable = true;
setSendmail = true;
defaults = {
aliases = "/etc/aliases";
port = config.host.storage.notifications.port;
tls_trust_file = "/etc/ssl/certs/ca-certificates.crt";
tls = "on";
auth = "login";
tls_starttls = "off";
};
accounts = {
zfs_notifications = {
auth = true;
tls = true;
host = config.host.storage.notifications.host;
passwordeval = "cat ${config.host.storage.notifications.tokenFile}";
user = config.host.storage.notifications.user;
from = config.host.storage.notifications.user;
};
};
};
services.zfs = {
autoScrub.enable = true;
autoSnapshot.enable = true;
zed = lib.mkIf config.host.storage.notifications.enable {
enableMail = true;
settings = {
ZED_DEBUG_LOG = "/tmp/zed.debug.log";
ZED_EMAIL_ADDR = [config.host.storage.notifications.to];
ZED_EMAIL_PROG = "${pkgs.msmtp}/bin/msmtp";
ZED_EMAIL_OPTS = "-a zfs_notifications @ADDRESS@";
ZED_NOTIFY_INTERVAL_SECS = 3600;
ZED_NOTIFY_VERBOSE = true;
ZED_USE_ENCLOSURE_LEDS = true;
ZED_SCRUB_AFTER_RESILVER = true;
};
};
};
disko.devices = {
disk = (
builtins.listToAttrs (
builtins.map
(drive:
lib.attrsets.nameValuePair (drive.name) {
type = "disk";
device = "/dev/disk/by-id/${drive.value}";
content = {
type = "gpt";
partitions = {
ESP = lib.mkIf (builtins.elem drive.value config.host.storage.pool.bootDrives) {
# The 2GB here for the boot partition might be a bit overkill we probably only need like 1/4th of that but storage is cheap
size = "2G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = ["umask=0077"];
};
};
zfs = {
size = "100%";
content = {
type = "zfs";
pool = "rpool";
};
};
};
};
})
(
(lib.lists.flatten vdevs) ++ cache
)
)
);
zpool = {
rpool = {
type = "zpool";
mode = {
topology = {
type = "topology";
vdev = (
builtins.map (disks: {
mode = config.host.storage.pool.mode;
members =
builtins.map (disk: disk.name) disks;
})
vdevs
);
cache = builtins.map (disk: disk.name) cache;
};
};
options = {
ashift = "12";
autotrim = "on";
};
rootFsOptions =
{
canmount = "off";
mountpoint = "none";
xattr = "sa";
acltype = "posixacl";
relatime = "on";
compression = "lz4";
"com.sun:auto-snapshot" = "false";
}
// (
lib.attrsets.optionalAttrs config.host.storage.encryption {
encryption = "on";
keyformat = "hex";
keylocation = "prompt";
}
);
datasets = lib.mkMerge [
(
lib.attrsets.mapAttrs (name: value: {
type = value.type;
options = value.options;
mountpoint = value.mountpoint;
postCreateHook = value.postCreateHook;
})
datasets
)
];
};
};
};
};
}

View file

@ -1,134 +0,0 @@
{
config,
lib,
...
}: {
# options.storage = {
# zfs = {
# # TODO: enable option
# # when this option is enabled we need to configure and enable disko things
# # TODO: we need some way of managing notifications
# # TODO: we need options to configure zfs pools
# # we should have warnings when the configured pool is missing drives
# # TODO: dataset option that is a submodule that adds datasets to the system
# # warnings for when a dataset was created in the past on a system but it is now missing some of the options defined for it
# # TODO: pools and datasets need to be passed to disko
# };
# impermanence = {
# # TODO: enable option
# # TODO: datasets option that is a submodule that will be used to define what datasets to add to the storage system
# # We should by default create the `local`, `local/system/nix`, `local/system/root`, `persist` `persist/system/root`, and `persist/system/var/log` datasets
# # Then we should make a dataset for user folders local and persist
# # We should also create datasets for systemd modules that have have impermanence enabled for them
# # we need to figure out what options a dataset can have in zfs
# };
# # TODO: we should have an impermanence module for home manager that proxies its values namespaced to the user down here that matches the same interface
# # TODO: we should have a way of enabling impermanence for a systemd config
# # these should have an option to put their folder into their own dataset (this needs to support private vs non private)
# # options for features that can be added to the dataset
# };
options.host.impermanence.enable = lib.mkEnableOption "are we going to use impermanence on this device";
config = lib.mkMerge [
{
assertions = [
{
assertion = !(config.host.impermanence.enable && !config.host.storage.enable);
message = ''
Disko storage must be enabled to use impermanence.
'';
}
];
}
(
lib.mkIf config.host.impermanence.enable {
assertions = [
{
assertion = config.host.impermanence.enable && config.host.storage.enable;
message = "Impermanence can not be used without managed host storage.";
}
];
# fixes issues with /var/lib/private not having the correct permissions https://github.com/nix-community/impermanence/issues/254
system.activationScripts."createPersistentStorageDirs".deps = ["var-lib-private-permissions" "users" "groups"];
system.activationScripts = {
"var-lib-private-permissions" = {
deps = ["specialfs"];
text = ''
mkdir -p /persist/system/root/var/lib/private
chmod 0700 /persist/system/root/var/lib/private
'';
};
};
programs.fuse.userAllowOther = true;
boot.initrd.postResumeCommands = lib.mkAfter ''
zfs rollback -r rpool/local/system/root@blank
'';
fileSystems = {
"/".neededForBoot = true;
"/persist/system/root".neededForBoot = true;
"/persist/system/var/log".neededForBoot = true;
};
host.storage.pool.extraDatasets = {
# persist datasets are datasets that contain information that we would like to keep around
"persist" = {
type = "zfs_fs";
options.canmount = "off";
options = {
"com.sun:auto-snapshot" = "true";
};
};
# this is where root data actually lives
"persist/system/root" = {
type = "zfs_fs";
mountpoint = "/persist/system/root";
};
"persist/system/var/log" = {
type = "zfs_fs";
mountpoint = "/persist/system/var/log";
# logs should be append only so we shouldn't need to snapshot them
options = {
"com.sun:auto-snapshot" = "false";
};
};
};
environment.persistence."/persist/system/var/log" = {
enable = true;
hideMounts = true;
directories = [
"/var/log"
];
};
environment.persistence."/persist/system/root" = {
enable = true;
hideMounts = true;
directories = [
"/var/lib/nixos"
"/var/lib/systemd/coredump"
];
files = [
"/etc/machine-id"
];
};
# TODO: this should live in leylas home manager configuration
security.sudo.extraConfig = "Defaults lecture=never";
}
)
];
}

View file

@ -0,0 +1,6 @@
{...}: {
imports = [
./ollama.nix
./storage.nix
];
}

View file

@ -27,20 +27,6 @@
allowedUDPPorts = ports; allowedUDPPorts = ports;
}; };
})) }))
(lib.mkIf config.host.impermanence.enable {
environment.persistence."/persist/system/root" = {
enable = true;
hideMounts = true;
directories = [
{
directory = "/var/lib/private/ollama";
user = config.services.ollama.user;
group = config.services.ollama.group;
mode = "0700";
}
];
};
})
] ]
); );
} }

View file

@ -0,0 +1,37 @@
{
config,
lib,
...
}: {
options = {
services.ollama.impermanence.enable = lib.mkOption {
type = lib.types.bool;
default = config.services.ollama.enable && config.storage.impermanence.enable;
};
};
config = lib.mkIf (config.services.ollama.enable) {
storage.datasets.replicate."system/root" = {
directories."/var/lib/private/ollama" = lib.mkIf config.services.ollama.impermanence.enable {
enable = true;
owner.name = config.services.ollama.user;
group.name = config.services.ollama.group;
owner.permissions = {
read = true;
write = true;
execute = false;
};
group.permissions = {
read = false;
write = false;
execute = false;
};
other.permissions = {
read = false;
write = false;
execute = false;
};
};
};
};
}

View file

@ -3,6 +3,6 @@
./actual.nix ./actual.nix
./proxy.nix ./proxy.nix
./fail2ban.nix ./fail2ban.nix
./impermanence.nix ./storage.nix
]; ];
} }

View file

@ -1,37 +0,0 @@
{
lib,
config,
...
}: let
const = import ./const.nix;
dataDirectory = const.dataDirectory;
in {
options.services.actual = {
impermanence.enable = lib.mkOption {
type = lib.types.bool;
default = config.services.actual.enable && config.host.impermanence.enable;
};
};
config = lib.mkIf config.services.actual.impermanence.enable {
assertions = [
{
assertion = config.services.actual.settings.dataDir == dataDirectory;
message = "actual data location does not match persistence\nconfig directory: ${config.services.actual.settings.dataDir}\npersistence directory: ${dataDirectory}";
}
{
assertion = config.systemd.services.actual.serviceConfig.DynamicUser or false;
message = "actual systemd service must have DynamicUser enabled to use private directory";
}
];
environment.persistence."/persist/system/root" = {
directories = [
{
directory = dataDirectory;
user = "actual";
group = "actual";
}
];
};
};
}

View file

@ -0,0 +1,22 @@
{
lib,
config,
...
}: let
const = import ./const.nix;
dataDirectory = const.dataDirectory;
in {
options.services.actual.impermanence.enable = lib.mkOption {
type = lib.types.bool;
default = config.services.actual.enable && config.storage.impermanence.enable;
};
config = lib.mkIf config.services.actual.enable {
storage.datasets.replicate."system/root" = {
directories."${dataDirectory}" = lib.mkIf config.services.actual.impermanence.enable {
owner.name = "actual";
group.name = "actual";
};
};
};
}

View file

@ -1,5 +1,5 @@
{...}: { {...}: {
imports = [ imports = [
./impermanence.nix ./storage.nix
]; ];
} }

View file

@ -1,33 +0,0 @@
{
lib,
config,
...
}: let
bazarr_data_directory = "/var/lib/bazarr";
in {
options.services.bazarr = {
impermanence.enable = lib.mkOption {
type = lib.types.bool;
default = config.services.bazarr.enable && config.host.impermanence.enable;
};
};
config = lib.mkIf config.services.bazarr.impermanence.enable {
assertions = [
{
assertion = config.services.bazarr.dataDir == bazarr_data_directory;
message = "bazarr data directory does not match persistence";
}
];
environment.persistence."/persist/system/root" = {
directories = [
{
directory = bazarr_data_directory;
user = "bazarr";
group = "bazarr";
}
];
};
};
}

View file

@ -0,0 +1,21 @@
{
lib,
config,
...
}: let
bazarr_data_directory = "/var/lib/bazarr";
in {
options.services.bazarr.impermanence.enable = lib.mkOption {
type = lib.types.bool;
default = config.services.bazarr.enable && config.storage.impermanence.enable;
};
config = lib.mkIf config.services.bazarr.enable {
storage.datasets.replicate."system/root" = {
directories."${bazarr_data_directory}" = lib.mkIf config.services.bazarr.impermanence.enable {
owner.name = "bazarr";
group.name = "bazarr";
};
};
};
}

View file

@ -1,6 +1,6 @@
{...}: { {...}: {
imports = [ imports = [
./crab-hole.nix ./crab-hole.nix
./impermanence.nix ./storage.nix
]; ];
} }

View file

@ -1,33 +0,0 @@
{
lib,
config,
...
}: let
workingDirectory = "/var/lib/private/crab-hole";
in {
options.services.crab-hole = {
impermanence.enable = lib.mkOption {
type = lib.types.bool;
default = config.services.crab-hole.enable && config.host.impermanence.enable;
};
};
config = lib.mkIf config.services.crab-hole.impermanence.enable {
assertions = [
{
assertion =
config.systemd.services.crab-hole.serviceConfig.WorkingDirectory == (builtins.replaceStrings ["/private"] [""] workingDirectory);
message = "crab-hole working directory does not match persistence";
}
];
environment.persistence."/persist/system/root" = {
directories = [
{
directory = workingDirectory;
user = "crab-hole";
group = "crab-hole";
}
];
};
};
}

View file

@ -0,0 +1,21 @@
{
lib,
config,
...
}: let
workingDirectory = "/var/lib/private/crab-hole";
in {
options.services.crab-hole.impermanence.enable = lib.mkOption {
type = lib.types.bool;
default = config.services.crab-hole.enable && config.storage.impermanence.enable;
};
config = lib.mkIf config.services.crab-hole.enable {
storage.datasets.replicate."system/root" = {
directories."${workingDirectory}" = lib.mkIf config.services.crab-hole.impermanence.enable {
owner.name = "crab-hole";
group.name = "crab-hole";
};
};
};
}

View file

@ -1,6 +1,6 @@
{...}: { {...}: {
imports = [ imports = [
./fail2ban.nix ./fail2ban.nix
./impermanence.nix ./storage.nix
]; ];
} }

View file

@ -1,34 +0,0 @@
{
lib,
config,
...
}: let
dataFolder = "/var/lib/fail2ban";
dataFile = "fail2ban.sqlite3";
in {
options.services.fail2ban = {
impermanence.enable = lib.mkOption {
type = lib.types.bool;
default = config.services.fail2ban.enable && config.host.impermanence.enable;
};
};
config = lib.mkIf config.services.fail2ban.impermanence.enable {
assertions = [
{
assertion = config.services.fail2ban.daemonSettings.Definition.dbfile == "${dataFolder}/${dataFile}";
message = "fail2ban data file does not match persistence";
}
];
environment.persistence."/persist/system/root" = {
directories = [
{
directory = dataFolder;
user = "fail2ban";
group = "fail2ban";
}
];
};
};
}

View file

@ -0,0 +1,22 @@
{
lib,
config,
...
}: let
dataFolder = "/var/lib/fail2ban";
dataFile = "fail2ban.sqlite3";
in {
options.services.fail2ban.impermanence.enable = lib.mkOption {
type = lib.types.bool;
default = config.services.fail2ban.enable && config.storage.impermanence.enable;
};
config = lib.mkIf config.services.fail2ban.enable {
storage.datasets.replicate."system/root" = {
directories."${dataFolder}" = lib.mkIf config.services.fail2ban.impermanence.enable {
owner.name = "fail2ban";
group.name = "fail2ban";
};
};
};
}

View file

@ -1,5 +1,5 @@
{...}: { {...}: {
imports = [ imports = [
./impermanence.nix ./storage.nix
]; ];
} }

View file

@ -1,26 +0,0 @@
{
lib,
config,
...
}: {
options.services.flaresolverr = {
impermanence.enable = lib.mkOption {
type = lib.types.bool;
default = config.services.flaresolverr.enable && config.host.impermanence.enable;
};
};
config = lib.mkIf config.services.flaresolverr.impermanence.enable {
# FlareSolverr typically doesn't need persistent storage as it's a proxy service
# but we'll add basic structure in case it's needed for logs or configuration
environment.persistence."/persist/system/root" = {
directories = [
{
directory = "/var/lib/flaresolverr";
user = "flaresolverr";
group = "flaresolverr";
}
];
};
};
}

View file

@ -0,0 +1,19 @@
{
lib,
config,
...
}: {
options.services.flaresolverr.impermanence.enable = lib.mkOption {
type = lib.types.bool;
default = config.services.flaresolverr.enable && config.storage.impermanence.enable;
};
config = lib.mkIf config.services.flaresolverr.enable {
storage.datasets.replicate."system/root" = {
directories."/var/lib/flaresolverr" = lib.mkIf config.services.flaresolverr.impermanence.enable {
owner.name = "flaresolverr";
group.name = "flaresolverr";
};
};
};
}

View file

@ -4,6 +4,6 @@
./proxy.nix ./proxy.nix
./database.nix ./database.nix
./fail2ban.nix ./fail2ban.nix
./impermanence.nix ./storage.nix
]; ];
} }

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