Compare commits

..

No commits in common. "3a58722815367ca4844a5b4bbac5ad8d5b63b550" and "28a962d712ab1155101b506de8c2e021306ce7bb" have entirely different histories.

83 changed files with 311 additions and 1139 deletions

View file

@ -1,18 +0,0 @@
#!/usr/bin/env nix-shell
#! nix-shell -i bash ../shell.nix
# Get current branch name
current_branch=$(git branch --show-current)
# Only restore stash if we're on main branch and a merge just completed
if [ "$current_branch" = "main" ]; then
# Check if there are any stashes to restore
if git stash list | grep -q "stash@"; then
echo "Post-merge: restoring stashed changes on main branch"
git stash pop -q
else
echo "Post-merge: no stash to restore on main branch"
fi
else
echo "Post-merge: no action needed on branch '$current_branch'"
fi

View file

@ -1,37 +0,0 @@
#!/usr/bin/env nix-shell
#! nix-shell -i bash ../shell.nix
# Get the target branch (the branch being merged into)
target_branch=""
# Check if we're in the middle of a merge
if [ -f .git/MERGE_HEAD ]; then
# We're in a merge, check if the current branch is main
current_branch=$(git branch --show-current)
if [ "$current_branch" = "main" ]; then
target_branch="main"
fi
fi
# If we're merging into main, run nix flake check
if [ "$target_branch" = "main" ]; then
echo "Merging into main branch - running nix flake check..."
echo "stashing all uncommitted changes"
git stash -q --keep-index
echo "checking flakes all compile"
nix flake check
if [ ! $? -eq 0 ]; then
echo "Error: nix flake check failed. Merge aborted."
echo "Please fix the issues and try merging again."
exit 1
fi
echo "nix flake check passed. Merge can proceed."
else
echo "Not merging into main branch, skipping nix flake check."
fi
exit 0

View file

@ -46,56 +46,36 @@ nix multi user, multi system, configuration with `sops` secret management, `home
# Tasks: # Tasks:
## Chores:
- [ ] test out crab hole service
- [ ] learn how to use actual
## Tech Debt ## Tech Debt
- [ ] 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 - nfs export should be backed by the same values for server and client
- [ ] rework the reverse_proxy.nix file so that it is a normally named service. Then also change it so that we can hook into it with both a base domain and a subdomain to make migrating to vpn accessible services easier ## New Features
- crab-hole
## Broken things - figure out why syncthing and jellyfins permissions don't propagate downwards
- [ ] figure out steam vr things? - figure out steam vr things?
- [ ] whisper was having issues - auto turn off on power loss - nut
- zfs email after scrubbing # TODO: test this
## Data Integrity - SMART test with email results
- [ ] zfs email after scrubbing # TODO: test this - samba mounts
- [ ] SMART test with email results - offline access for nfs mounts (overlay with rsync might be a good option here? https://www.spinics.net/lists/linux-unionfs/msg07105.html note about nfs4 and overlay fs)
- [ ] zfs encryption FIDO2 2fa (look into shavee) - Create Tor guard/relay server
- [ ] rotate sops encryption keys periodically (and somehow sync between devices?) - migrate away from flakes and move to npins
- [ ] Secure Boot - https://github.com/nix-community/lanzaboote - whisper
- [ ] auto turn off on power loss - nut - zfs encryption FIDO2 2fa (look into shavee)
- Secure Boot - https://github.com/nix-community/lanzaboote
## Data Access - rotate sops encryption keys periodically (and somehow sync between devices?)
- [ ] nfs export should be backed by the same values for server and client - wake on LAN for updates
- [ ] samba mounts - remote distributed builds - https://nix.dev/tutorials/nixos/distributed-builds-setup.html
- [ ] offline access for nfs mounts (overlay with rsync might be a good option here? https://www.spinics.net/lists/linux-unionfs/msg07105.html note about nfs4 and overlay fs) - ISO target that contains authorized keys for nixos-anywhere https://github.com/diegofariasm/yggdrasil/blob/4acc43ebc7bcbf2e41376d14268e382007e94d78/hosts/bootstrap/default.nix
- [ ] figure out why syncthing and jellyfins permissions don't propagate downwards - panoramax instance
- [ ] make radarr, sonarr, and bazarr accessible over vpn - mastodon instance
- [ ] move searx, home-assistant, actual, jellyfin, paperless, and immich to only be accessible via vpn - rework the reverse_proxy.nix file so that it is a normally named service. Then also change it so that we can hook into it with both a base domain and a subdomain to make migrating to vpn accessible services easier
- move searx, home-assistant, actual, jellyfin, paperless, and immich to only be accessible via vpn
## Services - make radarr, sonarr, and bazarr accessible over vpn
- [ ] vikunja service for project management - create some sort of service that allows uploading files to jellyfin
- [ ] Create Tor guard/relay server - auto sort files into where they should go with some combination of filebot cli and picard cli
- [ ] mastodon instance - graphana accessible though tailscale
- fix panoramax package
## DevOps - actual instance
- [ ] wake on LAN for updates - intergrade radarr, sonarr, and bazarr
- [ ] remote distributed builds - https://nix.dev/tutorials/nixos/distributed-builds-setup.html - claude code MCP servers should bundle node with them so they work in all environments
- [ ] ISO target that contains authorized keys for nixos-anywhere https://github.com/diegofariasm/yggdrasil/blob/4acc43ebc7bcbf2e41376d14268e382007e94d78/hosts/bootstrap/default.nix
- [ ] fix panoramax package
- [ ] claude code MCP servers should bundle node with them so they work in all environments
## Observability
- [ ] graphana for dashboards
- [ ] prometheus and loki for metric and log collection
- [ ] zfs storage usage
- [ ] zfs drive health status
- [ ] service version lag
- [ ] network/cpu/ram utilization
- [ ] http latency
- [ ] postgres db load
- [ ] nginx queries
- [ ] ntfy.sh for push notifications
- [ ] kuma for uptime visualization

View file

@ -1,39 +1,12 @@
{ {pkgs, ...}: {
osConfig,
lib,
...
}: {
config = { config = {
gnome = lib.mkMerge [
{
colorScheme = "prefer-dark";
accentColor = "slate";
clockFormat = "24h";
nightLight = {
enable = true;
automatic = false;
fromTime = 12.0;
toTime = 11.999999999999;
temperature = 2700;
};
extraWindowControls = true;
extensions = {
dash-to-panel = {
enable = true;
};
};
}
(lib.mkIf (osConfig.networking.hostName == "horizon") {
displayScaling = 125;
experimentalFeatures = {
scaleMonitorFramebuffer = true;
};
})
];
dconf = { dconf = {
enable = true; enable = true;
settings = {
"org/gnome/shell".enabled-extensions = [
pkgs.gnomeExtensions.dash-to-panel.extensionUuid
];
};
}; };
}; };
} }

View file

@ -18,7 +18,6 @@ in {
home.packages = lib.lists.optionals userConfig.isDesktopUser ( home.packages = lib.lists.optionals userConfig.isDesktopUser (
with pkgs; [ with pkgs; [
gnomeExtensions.dash-to-panel gnomeExtensions.dash-to-panel
claude-code
] ]
); );
@ -62,22 +61,6 @@ in {
piper.enable = hardware.piperMouse.enable; piper.enable = hardware.piperMouse.enable;
krita.enable = true; krita.enable = true;
ungoogled-chromium.enable = true; ungoogled-chromium.enable = true;
inkscape.enable = true;
obsidian.enable = true;
obs-studio.enable = true;
kdenlive.enable = true;
tor-browser.enable = true;
olympus.enable = true;
libreoffice.enable = true;
claude-code.enable = osConfig.host.ai.enable;
# Windows applications that we need to figure out how to install
guild-wars-2.enable = false;
vortex.enable = false;
dungeon-draft.enable = false;
vmware-workstation.enable = true;
}) })
]; ];
}; };

View file

@ -1,43 +1,31 @@
{...}: { {pkgs, ...}: {
config = { config = {
gnome = { gnome = {
extraWindowControls = true; extraWindowControls = true;
colorScheme = "prefer-dark"; colorScheme = "prefer-dark";
clockFormat = "24h"; clockFormat = "24h";
nightLight = { extensions = [
enable = true; pkgs.gnomeExtensions.dash-to-dock
automatic = false; ];
fromTime = 12.0;
toTime = 11.999999999999;
temperature = 2700;
};
extensions = {
dash-to-dock = {
enable = true;
options = {
"dock-position" = "LEFT";
"intellihide-mode" = "ALL_WINDOWS";
"show-trash" = false;
"require-pressure-to-show" = false;
"show-mounts" = false;
};
};
};
hotkeys = { hotkeys = {
"Open Terminal" = { "Open Terminal" = {
binding = "<Super>t"; binding = "<Super>t";
command = "kgx"; command = "kgx";
}; };
"Open Firefox" = {
binding = "<Super>f";
command = "firefox";
};
}; };
}; };
dconf = { dconf = {
enable = true; enable = true;
settings = { settings = {
"org/gnome/shell/extensions/dash-to-dock" = {
"dock-position" = "LEFT";
"intellihide-mode" = "ALL_WINDOWS";
"show-trash" = false;
"require-pressure-to-show" = false;
"show-mounts" = false;
};
"org/gnome/shell" = { "org/gnome/shell" = {
favorite-apps = ["org.gnome.Nautilus.desktop" "firefox.desktop" "codium.desktop" "steam.desktop" "org.gnome.Console.desktop"]; favorite-apps = ["org.gnome.Nautilus.desktop" "firefox.desktop" "codium.desktop" "steam.desktop" "org.gnome.Console.desktop"];
# app-picker-layout = # app-picker-layout =

View file

@ -87,6 +87,7 @@
# TODO: move this into a fonts module # TODO: move this into a fonts module
home.packages = with pkgs; [ home.packages = with pkgs; [
aileron aileron
nerd-fonts.open-dyslexic
]; ];
fonts.fontconfig.enable = true; fonts.fontconfig.enable = true;
}; };

View file

@ -1,9 +1,10 @@
{ {
lib, lib,
config, config,
osConfig,
... ...
}: { }: {
config = lib.mkIf (config.impermanence.enable) { config = lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist/home/leyla" = { home.persistence."/persist/home/leyla" = {
directories = [ directories = [
"desktop" "desktop"

View file

@ -32,7 +32,6 @@ in {
"javascript.updateImportsOnFileMove.enabled" = "always"; "javascript.updateImportsOnFileMove.enabled" = "always";
"editor.tabSize" = 2; "editor.tabSize" = 2;
"editor.insertSpaces" = false; "editor.insertSpaces" = false;
# "terminal.integrated.fontFamily" = "'Droid Sans Mono', 'monospace', monospace";
} }
]; ];
@ -41,7 +40,6 @@ in {
oneDark.enable = true; oneDark.enable = true;
atomKeybindings.enable = true; atomKeybindings.enable = true;
openRemoteSsh.enable = true; openRemoteSsh.enable = true;
# openDyslexicFont.enable = false;
# html development # html development
autoRenameTag.enable = true; autoRenameTag.enable = true;

View file

@ -57,6 +57,7 @@
"ata-ST18000NT001-3NF101_ZVTEF27J" "ata-ST18000NT001-3NF101_ZVTEF27J"
"ata-ST18000NE000-3G6101_ZVTJ7359" "ata-ST18000NE000-3G6101_ZVTJ7359"
] ]
# TODO: this needs to be configured manually
[ [
"ata-ST4000NE001-2MA101_WS2275P3" "ata-ST4000NE001-2MA101_WS2275P3"
"ata-ST4000NE001-2MA101_WS227B9F" "ata-ST4000NE001-2MA101_WS227B9F"
@ -342,20 +343,6 @@
openFirewall = true; openFirewall = true;
}; };
crab-hole = {
enable = true;
port = 8085;
openFirewall = true;
show_doc = true;
downstreams = {
loopback = {
enable = true;
openFirewall = true;
};
};
upstreams.cloudFlare.enable = true;
};
qbittorrent = { qbittorrent = {
enable = true; enable = true;
mediaDir = "/srv/qbittorent"; mediaDir = "/srv/qbittorent";
@ -363,28 +350,21 @@
webuiPort = 8084; webuiPort = 8084;
}; };
sonarr = { filebot-cleanup = {
enable = true; enable = true;
licenseFile = "/srv/jellyfin/filebot_license.psm";
};
sonarr = {
enable = false;
openFirewall = true; openFirewall = true;
}; };
radarr = { radarr = {
enable = true; enable = false;
openFirewall = true; openFirewall = true;
}; };
bazarr = { bazarr = {
enable = true; enable = false;
openFirewall = true;
};
lidarr = {
enable = true;
openFirewall = true;
};
jackett = {
enable = true;
openFirewall = true;
};
flaresolverr = {
enable = true;
openFirewall = true; openFirewall = true;
}; };
}; };

View file

@ -4,5 +4,6 @@
./hardware-configuration.nix ./hardware-configuration.nix
./configuration.nix ./configuration.nix
./packages.nix ./packages.nix
./filebot.nix
]; ];
} }

View file

@ -0,0 +1,82 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.services.filebot-cleanup;
in {
options.services.filebot-cleanup = {
enable = mkEnableOption "Filebot cleanup service";
licenseFile = mkOption {
type = types.nullOr types.path;
default = null;
description = "Path to the Filebot license file";
};
cleanupDirectory = mkOption {
type = types.str;
default = "/srv/jellyfin/filebot_cleanup";
description = "Directory where cleaned up media files are stored";
};
};
config = mkIf cfg.enable {
users.groups.filebot_cleanup = {};
users.users.filebot_cleanup = {
isSystemUser = true;
group = "filebot_cleanup";
extraGroups = ["jellyfin_media"];
home = cfg.cleanupDirectory;
createHome = true;
};
nixpkgs.config.allowUnfreePredicate = pkg:
builtins.elem (lib.getName pkg) [
"filebot"
];
environment.systemPackages = with pkgs; [
filebot
];
systemd.services.filebot-cleanup = {
description = "Filebot media cleanup service";
serviceConfig = {
Type = "simple";
User = "filebot_cleanup";
Group = "filebot_cleanup";
ExecStart = pkgs.writeShellScript "filebot-cleanup" ''
${optionalString (cfg.licenseFile != null) ''
${pkgs.filebot}/bin/filebot --license "${cfg.licenseFile}"
''}
${pkgs.filebot}/bin/filebot -rename -r "/srv/jellyfin/media/Movies/" --output "${cfg.cleanupDirectory}/" --format "{jellyfin}" -non-strict --action duplicate
${pkgs.filebot}/bin/filebot -rename -r "/srv/jellyfin/media/Shows/" --output "${cfg.cleanupDirectory}/" --format "{jellyfin}" -non-strict --action duplicate
'';
StandardOutput = "journal";
StandardError = "journal";
};
wantedBy = ["multi-user.target"];
};
environment.persistence = lib.mkIf config.host.impermanence.enable {
"/persist/system/jellyfin" = {
enable = true;
hideMounts = true;
files = [
cfg.licenseFile
];
directories = [
{
directory = cfg.cleanupDirectory;
user = "filebot_cleanup";
group = "filebot_cleanup";
mode = "1770";
}
];
};
};
};
}

View file

@ -40,15 +40,13 @@
services.xserver.wacom.enable = true; services.xserver.wacom.enable = true;
# installed opentabletdriver # installed opentabletdriver
# hardware.opentabletdriver.enable = true; hardware.opentabletdriver.enable = true;
hardware.keyboard.qmk.enable = true;
# Enable the GNOME Desktop Environment. # Enable the GNOME Desktop Environment.
services.displayManager.gdm.enable = true; services.displayManager.gdm.enable = true;
services.desktopManager.gnome.enable = true; services.desktopManager.gnome.enable = true;
host = { host = {
ai.enable = true;
users = { users = {
eve = { eve = {
isDesktopUser = true; isDesktopUser = true;
@ -70,9 +68,6 @@
}; };
services.tailscale.enable = true; services.tailscale.enable = true;
# We were having weird build errors so this is disabled right now
# error: The option `devices.emergent.folders.eve_records.path' was accessed but has no value defined. Try setting the option
services.syncthing.enable = false;
# Configure keymap in X11 # Configure keymap in X11
# services.xserver.xkb.layout = "us"; # services.xserver.xkb.layout = "us";

View file

@ -12,7 +12,7 @@
(modulesPath + "/installer/scan/not-detected.nix") (modulesPath + "/installer/scan/not-detected.nix")
]; ];
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "wacom"]; boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod"];
boot.initrd.kernelModules = []; boot.initrd.kernelModules = [];
boot.kernelModules = []; boot.kernelModules = [];
boot.extraModulePackages = []; boot.extraModulePackages = [];

View file

@ -18,12 +18,12 @@
fileSystems = { fileSystems = {
"/" = { "/" = {
device = "/dev/disk/by-id/ata-TOSHIBA_DT01ACA100_77D21HVNS-part2"; device = "/dev/disk/by-uuid/8be49c65-2b57-48f1-b74d-244d26061adb";
fsType = "ext4"; fsType = "ext4";
}; };
"/boot" = { "/boot" = {
device = "/dev/disk/by-id/ata-TOSHIBA_DT01ACA100_77D21HVNS-part1"; device = "/dev/disk/by-uuid/3006-3867";
fsType = "vfat"; fsType = "vfat";
options = ["fmask=0022" "dmask=0022"]; options = ["fmask=0022" "dmask=0022"];
}; };

98
flake.lock generated
View file

@ -25,11 +25,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760701190, "lastModified": 1758287904,
"narHash": "sha256-y7UhnWlER8r776JsySqsbTUh2Txf7K30smfHlqdaIQw=", "narHash": "sha256-IGmaEf3Do8o5Cwp1kXBN1wQmZwQN3NLfq5t4nHtVtcU=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "3a9450b26e69dcb6f8de6e2b07b3fc1c288d85f5", "rev": "67ff9807dd148e704baadbd4fd783b54282ca627",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -46,11 +46,11 @@
}, },
"locked": { "locked": {
"dir": "pkgs/firefox-addons", "dir": "pkgs/firefox-addons",
"lastModified": 1760673822, "lastModified": 1759403080,
"narHash": "sha256-h+liPhhMw1yYvkDGLHzQJQShQs+yLjNgjfAyZX+sRrM=", "narHash": "sha256-EteyL8KyG9R5xzqyOBzyag4n2cSemu61VFrl3opJSqE=",
"owner": "rycee", "owner": "rycee",
"repo": "nur-expressions", "repo": "nur-expressions",
"rev": "5cca27f1bb30a26140d0cf60ab34daa45b4fa11f", "rev": "8af6dfcbcbf1115a4f5aeed77ff0db5d3c02caf0",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@ -111,6 +111,24 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils_3": {
"inputs": {
"systems": "systems_3"
},
"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 +151,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760662441, "lastModified": 1759337100,
"narHash": "sha256-mlDqR1Ntgs9uYYEAUR1IhamKBO0lxoNS4zGLzEZaY0A=", "narHash": "sha256-CcT3QvZ74NGfM+lSOILcCEeU+SnqXRvl1XCRHenZ0Us=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "722792af097dff5790f1a66d271a47759f477755", "rev": "004753ae6b04c4b18aa07192c1106800aaacf6c3",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -164,11 +182,11 @@
"lix": { "lix": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1755787066, "lastModified": 1759624822,
"narHash": "sha256-X2UwkUEban08GRSPXRr+kz8fckHqebr3P77qSvjoeOw=", "narHash": "sha256-cf40qfsfpxJU/BnQ9PEj027LdPINNSsJqm+C6Ug93BA=",
"rev": "ac9721a92e8138d29707824dbedb484c76948493", "rev": "57333a0e600c5e096a609410a2f1059b97194b1e",
"type": "tarball", "type": "tarball",
"url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/ac9721a92e8138d29707824dbedb484c76948493.tar.gz?rev=ac9721a92e8138d29707824dbedb484c76948493" "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/57333a0e600c5e096a609410a2f1059b97194b1e.tar.gz"
}, },
"original": { "original": {
"type": "tarball", "type": "tarball",
@ -185,11 +203,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759851320, "lastModified": 1756511062,
"narHash": "sha256-n5dRAIC3/78drQtFxmQRrBLd6TKfotUnX7GWu0mAcSg=", "narHash": "sha256-IgD1JR7scSEwlK/YAbmrcTWpAYT30LPldCUHdzXkaMs=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "7c31a18259b8358ac196cf803a26967c0fa1d3e4", "rev": "3f09a5eb772e02d98bb8878ab687d5b721f00d16",
"revCount": 163, "revCount": 162,
"type": "git", "type": "git",
"url": "https://git.lix.systems/lix-project/nixos-module.git" "url": "https://git.lix.systems/lix-project/nixos-module.git"
}, },
@ -227,11 +245,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760721282, "lastModified": 1758805352,
"narHash": "sha256-aAHphQbU9t/b2RRy2Eb8oMv+I08isXv2KUGFAFn7nCo=", "narHash": "sha256-BHdc43Lkayd+72W/NXRKHzX5AZ+28F3xaUs3a88/Uew=",
"owner": "LnL7", "owner": "LnL7",
"repo": "nix-darwin", "repo": "nix-darwin",
"rev": "c3211fcd0c56c11ff110d346d4487b18f7365168", "rev": "c48e963a5558eb1c3827d59d21c5193622a1477c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -263,16 +281,17 @@
}, },
"nix-vscode-extensions": { "nix-vscode-extensions": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_3",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1760720017, "lastModified": 1759369908,
"narHash": "sha256-ALb+L8zaP6IJ3BigQJ+ih7NqmaptzL/CbkNkLbhmsGE=", "narHash": "sha256-IIhaE6jAge64z+fIyi/8Vtu0JdTtapbp4CvwiuIkZ1E=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nix-vscode-extensions", "repo": "nix-vscode-extensions",
"rev": "b0897a5d1d5829eb67ca7168680873ee7a0d52b8", "rev": "a66ad2141b1440a838ead278c6edfe8a4ce75e6c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -283,11 +302,11 @@
}, },
"nixos-hardware": { "nixos-hardware": {
"locked": { "locked": {
"lastModified": 1760106635, "lastModified": 1759261527,
"narHash": "sha256-2GoxVaKWTHBxRoeUYSjv0AfSOx4qw5CWSFz2b+VolKU=", "narHash": "sha256-wPd5oGvBBpUEzMF0kWnXge0WITNsITx/aGI9qLHgJ4g=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "9ed85f8afebf2b7478f25db0a98d0e782c0ed903", "rev": "e087756cf4abbe1a34f3544c480fc1034d68742f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -315,11 +334,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1760524057, "lastModified": 1759381078,
"narHash": "sha256-EVAqOteLBFmd7pKkb0+FIUyzTF61VKi7YmvP1tw4nEw=", "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "544961dfcce86422ba200ed9a0b00dd4b1486ec5", "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -370,11 +389,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760393368, "lastModified": 1759188042,
"narHash": "sha256-8mN3kqyqa2PKY0wwZ2UmMEYMcxvNTwLaOrrDsw6Qi4E=", "narHash": "sha256-f9QC2KKiNReZDG2yyKAtDZh0rSK2Xp1wkPzKbHeQVRU=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "ab8d56e85b8be14cff9d93735951e30c3e86a437", "rev": "9fcfabe085281dd793589bdc770a2e577a3caa5d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -412,6 +431,21 @@
"repo": "default", "repo": "default",
"type": "github" "type": "github"
} }
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -9,7 +9,7 @@
src = fetchurl { src = fetchurl {
url = "http://tools.mapillary.com/uploader/download/linux/${version}"; url = "http://tools.mapillary.com/uploader/download/linux/${version}";
name = "mapillary-uploader.AppImage"; name = "mapillary-uploader.AppImage";
sha256 = "sha256-OY3SiMHUyjwPDrPWfa+mFg2BHZrz6GG/9/D5sCP2Da8="; sha256 = "sha256-Oyx7AIdA/2mwBaq7UzXOoyq/z2SU2sViMN40sY2RCQw=";
}; };
appimageContents = appimageTools.extractType2 { appimageContents = appimageTools.extractType2 {
@ -23,6 +23,9 @@ in
# Install desktop file # Install desktop file
install -Dm644 ${appimageContents}/mapillary-desktop-uploader.desktop $out/share/applications/mapillary-uploader.desktop install -Dm644 ${appimageContents}/mapillary-desktop-uploader.desktop $out/share/applications/mapillary-uploader.desktop
# Install icon
install -Dm644 ${appimageContents}/usr/share/icons/hicolor/0x0/apps/mapillary-desktop-uploader.png $out/share/pixmaps/mapillary-uploader.png
# Fix desktop file paths # Fix desktop file paths
substituteInPlace $out/share/applications/mapillary-uploader.desktop \ substituteInPlace $out/share/applications/mapillary-uploader.desktop \
--replace 'Exec=AppRun' 'Exec=${pname}' --replace 'Exec=AppRun' 'Exec=${pname}'

View file

@ -5,7 +5,6 @@
./user.nix ./user.nix
./flipperzero.nix ./flipperzero.nix
./i18n.nix ./i18n.nix
./impermanence.nix
./openssh.nix ./openssh.nix
./gnome.nix ./gnome.nix
./programs ./programs

View file

@ -1,16 +1,8 @@
{ {
lib, lib,
config, config,
pkgs,
... ...
}: let }: {
enabledExtensions =
[]
++ lib.optional config.gnome.extensions.dash-to-dock.enable pkgs.gnomeExtensions.dash-to-dock
++ lib.optional config.gnome.extensions.dash-to-panel.enable pkgs.gnomeExtensions.dash-to-panel;
extensions = config.gnome.extraExtensions ++ enabledExtensions;
in {
options.gnome = { options.gnome = {
extraWindowControls = lib.mkEnableOption "Should we add back in the minimize and maximize window controls?"; extraWindowControls = lib.mkEnableOption "Should we add back in the minimize and maximize window controls?";
clockFormat = lib.mkOption { clockFormat = lib.mkOption {
@ -42,7 +34,7 @@ in {
]; ];
default = "blue"; default = "blue";
}; };
extraExtensions = lib.mkOption { extensions = lib.mkOption {
type = lib.types.listOf lib.types.package; type = lib.types.listOf lib.types.package;
default = []; default = [];
description = "The set of extensions to install and enable in the user environment."; description = "The set of extensions to install and enable in the user environment.";
@ -68,80 +60,16 @@ in {
})); }));
default = {}; default = {};
}; };
displayScaling = lib.mkOption {
type = lib.types.nullOr (lib.types.enum [100 125 150 175 200]);
default = null;
description = "Display scaling percentage for GNOME";
};
experimentalFeatures = lib.mkOption {
type = lib.types.submodule {
options = {
scaleMonitorFramebuffer = lib.mkEnableOption "scale-monitor-framebuffer experimental feature";
};
};
default = {};
description = "GNOME experimental features to enable";
};
nightLight = lib.mkOption {
type = lib.types.submodule {
options = {
enable = lib.mkEnableOption "night light (blue light filter)";
automatic = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to automatically schedule night light based on sunset/sunrise";
};
fromTime = lib.mkOption {
type = lib.types.float;
default = 20.0;
description = "Start time for night light in 24-hour format (e.g., 20.0 for 8:00 PM)";
};
toTime = lib.mkOption {
type = lib.types.float;
default = 6.0;
description = "End time for night light in 24-hour format (e.g., 6.0 for 6:00 AM)";
};
temperature = lib.mkOption {
type = lib.types.int;
default = 4000;
description = "Color temperature for night light (1000-10000K, lower is warmer)";
};
};
};
default = {};
description = "Night light configuration";
};
extensions = {
dash-to-dock = {
enable = lib.mkEnableOption "Dash to Dock extension";
options = lib.mkOption {
type = lib.types.nullOr lib.types.attrs;
default = null;
description = "Dash to Dock configuration options. If null, no custom configuration will be applied.";
};
};
dash-to-panel = {
enable = lib.mkEnableOption "Dash to Panel extension";
options = lib.mkOption {
type = lib.types.nullOr lib.types.attrs;
default = null;
description = "Dash to Panel configuration options. If null, no custom configuration will be applied.";
};
};
};
}; };
config = { config = {
home.packages = extensions; home.packages = config.gnome.extensions;
dconf = { dconf = {
settings = lib.mkMerge [ settings = lib.mkMerge [
{ {
"org/gnome/shell" = { "org/gnome/shell" = {
disable-user-extensions = false; # enables user extensions disable-user-extensions = false; # enables user extensions
enabled-extensions = builtins.map (extension: extension.extensionUuid) extensions; enabled-extensions = builtins.map (extension: extension.extensionUuid) config.gnome.extensions;
}; };
"org/gnome/desktop/wm/preferences".button-layout = lib.mkIf config.gnome.extraWindowControls ":minimize,maximize,close"; "org/gnome/desktop/wm/preferences".button-layout = lib.mkIf config.gnome.extraWindowControls ":minimize,maximize,close";
@ -149,23 +77,7 @@ in {
"org/gnome/desktop/interface".color-scheme = config.gnome.colorScheme; "org/gnome/desktop/interface".color-scheme = config.gnome.colorScheme;
"org/gnome/desktop/interface".accent-color = config.gnome.accentColor; "org/gnome/desktop/interface".accent-color = config.gnome.accentColor;
"org/gnome/desktop/interface".clock-format = config.gnome.clockFormat; "org/gnome/desktop/interface".clock-format = config.gnome.clockFormat;
"org/gnome/desktop/interface".text-scaling-factor = lib.mkIf (config.gnome.displayScaling != null) (config.gnome.displayScaling / 100.0);
"org/gnome/mutter".experimental-features = lib.mkIf (builtins.any (x: x) (builtins.attrValues config.gnome.experimentalFeatures)) (
lib.optional config.gnome.experimentalFeatures.scaleMonitorFramebuffer "scale-monitor-framebuffer"
);
} }
# Night light configuration
(lib.mkIf config.gnome.nightLight.enable {
"org/gnome/settings-daemon/plugins/color" = {
night-light-enabled = true;
night-light-schedule-automatic = config.gnome.nightLight.automatic;
night-light-schedule-from = lib.mkIf (!config.gnome.nightLight.automatic) config.gnome.nightLight.fromTime;
night-light-schedule-to = lib.mkIf (!config.gnome.nightLight.automatic) config.gnome.nightLight.toTime;
night-light-temperature = config.gnome.nightLight.temperature;
};
})
( (
lib.mkMerge ( lib.mkMerge (
builtins.map (value: let builtins.map (value: let
@ -188,15 +100,6 @@ in {
) )
) )
) )
# Extension configurations
(lib.mkIf (config.gnome.extensions.dash-to-dock.enable && config.gnome.extensions.dash-to-dock.options != null) {
"org/gnome/shell/extensions/dash-to-dock" = config.gnome.extensions.dash-to-dock.options;
})
(lib.mkIf (config.gnome.extensions.dash-to-panel.enable && config.gnome.extensions.dash-to-panel.options != null) {
"org/gnome/shell/extensions/dash-to-panel" = config.gnome.extensions.dash-to-panel.options;
})
]; ];
}; };
}; };

View file

@ -1,31 +0,0 @@
{
config,
lib,
osConfig,
...
}: let
cfg = config.impermanence;
in {
options.impermanence = {
enable = lib.mkEnableOption "impermanence for home directory";
};
config = lib.mkMerge [
(lib.mkIf config.impermanence.enable {
assertions = [
{
assertion = osConfig.impermanence.enable;
message = "impermanence can not be enabled for a user when it is not enabled for a configuration";
}
];
})
(lib.mkIf osConfig.host.impermanence.enable {
# If impermanence is not enabled for this user but system impermanence is enabled,
# persist the entire home directory as fallback
home.persistence."/persist/home/${config.home.username}" = lib.mkIf (!cfg.enable) {
directories = ["."];
allowOther = true;
};
})
];
}

View file

@ -95,7 +95,7 @@
); );
} }
) )
(lib.mkIf config.impermanence.enable { (lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
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

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.bitwarden = { options.programs.bitwarden = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/Bitwarden" "${config.xdg.configHome}/Bitwarden"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.bruno = { options.programs.bruno = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/bruno/" "${config.xdg.configHome}/bruno/"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.calibre = { options.programs.calibre = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/calibre" "${config.xdg.configHome}/calibre"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.davinci-resolve = { options.programs.davinci-resolve = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.dataHome}/DaVinciResolve" "${config.xdg.dataHome}/DaVinciResolve"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.dbeaver-bin = { options.programs.dbeaver-bin = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.dataHome}/DBeaverData/" "${config.xdg.dataHome}/DBeaverData/"

View file

@ -12,13 +12,11 @@
./obsidian.nix ./obsidian.nix
./prostudiomasters.nix ./prostudiomasters.nix
./idea.nix ./idea.nix
./kdenlive.nix
./krita.nix ./krita.nix
./protonvpn.nix ./protonvpn.nix
./calibre.nix ./calibre.nix
./bruno.nix ./bruno.nix
./dbeaver.nix ./dbeaver.nix
./dungeon-draft.nix
./steam.nix ./steam.nix
./vscode ./vscode
./ungoogled-chromium.nix ./ungoogled-chromium.nix
@ -26,7 +24,6 @@
./mapillary-uploader.nix ./mapillary-uploader.nix
./inkscape.nix ./inkscape.nix
./gimp.nix ./gimp.nix
./guild-wars-2.nix
./proxmark3.nix ./proxmark3.nix
./freecad.nix ./freecad.nix
./onionshare.nix ./onionshare.nix
@ -36,14 +33,11 @@
./qflipper.nix ./qflipper.nix
./openvpn.nix ./openvpn.nix
./noisetorch.nix ./noisetorch.nix
./olympus.nix
./openrgb.nix ./openrgb.nix
./via.nix ./via.nix
./vortex.nix
./davinci-resolve.nix ./davinci-resolve.nix
./gdx-liftoff.nix ./gdx-liftoff.nix
./tor-browser.nix ./tor-browser.nix
./polycule.nix ./polycule.nix
./vmware-workstation.nix
]; ];
} }

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.discord = { options.programs.discord = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/discord/" "${config.xdg.configHome}/discord/"

View file

@ -1,24 +0,0 @@
{
config,
lib,
...
}: let
cfg = config.programs.dungeon-draft;
in {
options.programs.dungeon-draft = {
enable = lib.mkEnableOption "Dungeon Draft";
};
config = {
assertions = [
{
assertion = !cfg.enable;
message = ''
Dungeon Draft module is not yet fully configured.
Please download the Dungeon Draft executable (.exe) from the official website,
then configure the Wine environment and executable path as needed.
'';
}
];
};
}

View file

@ -1,6 +1,7 @@
{ {
lib, lib,
config, config,
osConfig,
... ...
}: let }: let
buildProfilePersistence = profile: { buildProfilePersistence = profile: {
@ -25,7 +26,7 @@
allowOther = true; allowOther = true;
}; };
in { in {
config = lib.mkIf (config.programs.firefox.enable && config.impermanence.enable) { config = lib.mkIf (config.programs.firefox.enable && osConfig.host.impermanence.enable) {
home.persistence."/persist${config.home.homeDirectory}" = lib.mkMerge ( home.persistence."/persist${config.home.homeDirectory}" = lib.mkMerge (
( (
lib.attrsets.mapAttrsToList lib.attrsets.mapAttrsToList

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.freecad = { options.programs.freecad = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/FreeCAD" "${config.xdg.configHome}/FreeCAD"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.gdx-liftoff = { options.programs.gdx-liftoff = {

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.gimp = { options.programs.gimp = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/GIMP" "${config.xdg.configHome}/GIMP"

View file

@ -1,24 +0,0 @@
{
config,
lib,
...
}: let
cfg = config.programs.guild-wars-2;
in {
options.programs.guild-wars-2 = {
enable = lib.mkEnableOption "Guild Wars 2";
};
config = {
assertions = [
{
assertion = !cfg.enable;
message = ''
Guild Wars 2 module is not yet fully configured.
Please install Guild Wars 2 manually via Steam or the official client,
then configure the Wine environment as needed.
'';
}
];
};
}

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.jetbrains.idea-community = { options.programs.jetbrains.idea-community = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
# configuration # configuration

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.inkscape = { options.programs.inkscape = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/inkscape" "${config.xdg.configHome}/inkscape"

View file

@ -1,36 +0,0 @@
{
config,
lib,
pkgs,
...
}: let
cfg = config.programs.kdenlive;
in {
options.programs.kdenlive = {
enable = lib.mkEnableOption "kdenlive";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.kdePackages.kdenlive;
description = "The kdenlive package to install.";
};
};
config = lib.mkIf cfg.enable (lib.mkMerge [
{
home.packages = [
cfg.package
];
}
(
lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = {
directories = [
"${config.xdg.configHome}/kdenliverc"
"${config.xdg.dataHome}/kdenlive"
];
allowOther = true;
};
}
)
]);
}

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.krita = { options.programs.krita = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/kritarc" "${config.xdg.configHome}/kritarc"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.libreoffice = { options.programs.libreoffice = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/libreoffice" "${config.xdg.configHome}/libreoffice"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.makemkv = { options.programs.makemkv = {
@ -29,7 +30,7 @@
home.file.".MakeMKV/settings.conf".source = config.lib.file.mkOutOfStoreSymlink config.sops.templates."MakeMKV.settings.conf".path; home.file.".MakeMKV/settings.conf".source = config.lib.file.mkOutOfStoreSymlink config.sops.templates."MakeMKV.settings.conf".path;
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
".MakeMKV" ".MakeMKV"

View file

@ -11,20 +11,7 @@ in {
enable = mkEnableOption "Mapillary Desktop Uploader"; enable = mkEnableOption "Mapillary Desktop Uploader";
}; };
config = mkIf cfg.enable (mkMerge [ config = mkIf cfg.enable {
{
home.packages = [pkgs.mapillary-uploader]; home.packages = [pkgs.mapillary-uploader];
}
(
mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = {
directories = [
"${config.xdg.configHome}/mapillary-uploader"
"${config.xdg.dataHome}/mapillary-uploader"
];
allowOther = true;
}; };
} }
)
]);
}

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.mfoc = { options.programs.mfoc = {

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.noisetorch = { options.programs.noisetorch = {

View file

@ -1,17 +1,13 @@
{ {
lib, lib,
config, config,
osConfig,
... ...
}: { }: {
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 osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { # TODO: map impermanence for obs
directories = [
"${config.xdg.configHome}/obs-studio"
];
allowOther = true;
};
} }
) )
]); ]);

View file

@ -1,11 +1,12 @@
{ {
lib, lib,
config, config,
osConfig,
... ...
}: { }: {
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 osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/obsidian" "${config.xdg.configHome}/obsidian"

View file

@ -1,36 +0,0 @@
{
config,
lib,
pkgs,
...
}: let
cfg = config.programs.olympus;
in {
options.programs.olympus = {
enable = lib.mkEnableOption "olympus";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.olympus;
description = "The olympus package to install.";
};
};
config = lib.mkIf cfg.enable (lib.mkMerge [
{
home.packages = [
cfg.package
];
}
(
lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = {
directories = [
"${config.xdg.configHome}/olympus"
"${config.xdg.dataHome}/olympus"
];
allowOther = true;
};
}
)
]);
}

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.onionshare = { options.programs.onionshare = {

View file

@ -2,27 +2,16 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.openrgb = { options.programs.openrgb = {
enable = lib.mkEnableOption "enable openrgb"; enable = lib.mkEnableOption "enable openrgb";
}; };
config = lib.mkIf config.programs.openrgb.enable (lib.mkMerge [ config = lib.mkIf config.programs.openrgb.enable {
{
home.packages = with pkgs; [ home.packages = with pkgs; [
openrgb openrgb
]; ];
}
(
lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = {
directories = [
"${config.xdg.configHome}/OpenRGB"
];
allowOther = true;
}; };
} }
)
]);
}

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.openvpn = { options.programs.openvpn = {

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.pdfarranger = { options.programs.pdfarranger = {

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.picard = { options.programs.picard = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/MusicBrainz" "${config.xdg.configHome}/MusicBrainz"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.piper = { options.programs.piper = {

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.polycule = { options.programs.polycule = {
@ -16,7 +17,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
# TODO: check that these are actually the correct folders # TODO: check that these are actually the correct folders
# directories = [ # directories = [

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.prostudiomasters = { options.programs.prostudiomasters = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/ProStudioMasters" "${config.xdg.configHome}/ProStudioMasters"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.protonvpn-gui = { options.programs.protonvpn-gui = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/protonvpn" "${config.xdg.configHome}/protonvpn"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.proxmark3 = { options.programs.proxmark3 = {

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.qbittorrent = { options.programs.qbittorrent = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/qBittorrent" "${config.xdg.configHome}/qBittorrent"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.qflipper = { options.programs.qflipper = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/qFlipper" "${config.xdg.configHome}/qFlipper"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.signal-desktop-bin = { options.programs.signal-desktop-bin = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/Signal" "${config.xdg.configHome}/Signal"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.steam = { options.programs.steam = {
@ -17,7 +18,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
{ {

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.tor-browser = { options.programs.tor-browser = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.dataHome}/torbrowser" "${config.xdg.dataHome}/torbrowser"

View file

@ -2,6 +2,7 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.ungoogled-chromium = { options.programs.ungoogled-chromium = {
@ -15,7 +16,7 @@
]; ];
} }
( (
lib.mkIf config.impermanence.enable { lib.mkIf osConfig.host.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = { home.persistence."/persist${config.home.homeDirectory}" = {
directories = [ directories = [
"${config.xdg.configHome}/chromium" "${config.xdg.configHome}/chromium"

View file

@ -2,28 +2,16 @@
lib, lib,
pkgs, pkgs,
config, config,
osConfig,
... ...
}: { }: {
options.programs.via = { options.programs.via = {
enable = lib.mkEnableOption "enable via"; enable = lib.mkEnableOption "enable via";
}; };
config = lib.mkIf config.programs.via.enable (lib.mkMerge [ config = lib.mkIf config.programs.via.enable {
{
home.packages = with pkgs; [ home.packages = with pkgs; [
via via
]; ];
}
(
lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = {
directories = [
"${config.xdg.configHome}/via"
"${config.xdg.dataHome}/via"
];
allowOther = true;
}; };
} }
)
]);
}

View file

@ -1,37 +0,0 @@
{
lib,
pkgs,
config,
...
}: {
options.programs.vmware-workstation = {
enable = lib.mkEnableOption "enable VMware Workstation";
};
config = lib.mkIf config.programs.vmware-workstation.enable (
lib.mkMerge [
{
home.packages = with pkgs; [
vmware-workstation
];
}
(
lib.mkIf config.impermanence.enable {
home.persistence."/persist${config.home.homeDirectory}" = {
directories = [
{
directory = ".vmware";
method = "symlink";
}
{
directory = "vmware";
method = "symlink";
}
];
allowOther = true;
};
}
)
]
);
}

View file

@ -1,24 +0,0 @@
{
config,
lib,
...
}: let
cfg = config.programs.vortex;
in {
options.programs.vortex = {
enable = lib.mkEnableOption "Vortex (Nexus Mods manager)";
};
config = {
assertions = [
{
assertion = !cfg.enable;
message = ''
Vortex module is not yet fully configured.
Please download and install Vortex manually from the Nexus Mods website,
then configure the Wine environment and dependencies as needed.
'';
}
];
};
}

View file

@ -23,6 +23,5 @@
./vitest.nix ./vitest.nix
./direnv.nix ./direnv.nix
./conventionalCommits.nix ./conventionalCommits.nix
./openDyslexicFont.nix
]; ];
} }

View file

@ -1,49 +0,0 @@
{
lib,
pkgs,
config,
...
}: {
options.programs.vscode.profiles = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({config, ...}: {
options = {
extraExtensions.openDyslexicFont = {
enable = lib.mkEnableOption "should OpenDyslexic font be set as the default font for VSCode";
package = lib.mkPackageOption pkgs "nerd-fonts.open-dyslexic" {
default = ["nerd-fonts" "open-dyslexic"];
};
};
};
config = lib.mkIf config.extraExtensions.openDyslexicFont.enable {
userSettings = {
"editor.fontFamily" = "'OpenDyslexicM Nerd Font Mono', Droid Sans Mono, monospace";
"editor.fontSize" = 14;
"editor.letterSpacing" = -0.3;
};
};
}));
};
config = let
enabledProfiles =
lib.filter (profile: profile.extraExtensions.openDyslexicFont.enable or false)
(lib.attrValues config.programs.vscode.profiles);
anyProfileUsesOpenDyslexicFont = enabledProfiles != [];
fontPackages = lib.unique (map (profile: profile.extraExtensions.openDyslexicFont.package) enabledProfiles);
in {
# Ensure OpenDyslexic font packages are installed when any VSCode profile uses them
home.packages = fontPackages;
fonts.fontconfig.enable = lib.mkIf anyProfileUsesOpenDyslexicFont true;
# Add assertion to ensure the fonts are available
assertions =
map (fontPkg: {
assertion = lib.elem fontPkg config.home.packages;
message = "OpenDyslexic font package '${fontPkg.name or "unknown"}' must be installed when using openDyslexicFont extension for VSCode.";
})
fontPackages;
};
}

View file

@ -1,144 +0,0 @@
{
config,
lib,
...
}: let
cfg = config.services.crab-hole;
in {
options.services.crab-hole = {
port = lib.mkOption {
type = lib.types.port;
default = 8080;
description = "Port for the crab-hole API to listen on.";
};
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether to open the firewall for the crab-hole API port.";
};
listen = lib.mkOption {
type = lib.types.str;
default = "0.0.0.0";
description = "Address for the crab-hole API to listen on.";
};
show_doc = lib.mkEnableOption "OpenAPI documentation (loads content from third party websites)";
downstreams = {
loopback = {
enable = lib.mkEnableOption "loopback downstream DNS server on localhost:53";
openFirewall = lib.mkEnableOption "automatic port forwarding for the loopback downstream";
};
};
extraDownstreams = lib.mkOption {
type = lib.types.listOf (lib.types.submodule {
options = {
protocol = lib.mkOption {
type = lib.types.enum ["udp" "tcp" "tls" "https" "quic"];
description = "Protocol for the downstream server.";
};
listen = lib.mkOption {
type = lib.types.str;
description = "Address to listen on for downstream connections.";
};
port = lib.mkOption {
type = lib.types.port;
description = "Port to listen on for downstream connections.";
};
};
});
default = [];
description = "List of additional downstream DNS server configurations.";
};
upstreams = {
cloudFlare = {
enable = lib.mkEnableOption "Cloudflare DNS over TLS upstream servers (1.1.1.1 and 1.0.0.1)";
};
};
extraUpstreams = lib.mkOption {
type = lib.types.listOf (lib.types.submodule {
options = {
socket_addr = lib.mkOption {
type = lib.types.str;
description = "Socket address of the upstream DNS server (e.g., \"1.1.1.1:853\" or \"[2606:4700:4700::1111]:853\").";
};
protocol = lib.mkOption {
type = lib.types.enum ["udp" "tcp" "tls" "https" "quic"];
description = "Protocol to use for upstream DNS queries.";
};
};
});
default = [];
description = "List of additional upstream DNS server configurations.";
};
};
config = lib.mkIf cfg.enable {
services.crab-hole.settings = lib.mkMerge [
{
api = {
port = cfg.port;
listen = cfg.listen;
show_doc = cfg.show_doc;
};
downstream = cfg.extraDownstreams;
upstream.name_servers = cfg.extraUpstreams;
}
(lib.mkIf cfg.downstreams.loopback.enable {
downstream = [
{
protocol = "udp";
listen = "localhost";
port = 53;
}
];
})
(lib.mkIf cfg.upstreams.cloudFlare.enable {
upstream.name_servers = [
{
socket_addr = "1.1.1.1:853";
protocol = "tls";
tls_dns_name = "1dot1dot1dot1.cloudflare-dns.com";
trust_nx_responses = false;
}
{
socket_addr = "1.0.0.1:853";
protocol = "tls";
tls_dns_name = "1dot1dot1dot1.cloudflare-dns.com";
trust_nx_responses = false;
}
{
socket_addr = "[2606:4700:4700::1111]:853";
protocol = "tls";
tls_dns_name = "1dot1dot1dot1.cloudflare-dns.com";
trust_nx_responses = false;
}
{
socket_addr = "[2606:4700:4700::1001]:853";
protocol = "tls";
tls_dns_name = "1dot1dot1dot1.cloudflare-dns.com";
trust_nx_responses = false;
}
];
})
];
# Open firewall if requested
networking.firewall = lib.mkMerge [
(lib.mkIf cfg.openFirewall {
allowedTCPPorts = [cfg.port];
})
(lib.mkIf (cfg.downstreams.loopback.enable && cfg.downstreams.loopback.openFirewall) {
allowedUDPPorts = [53];
})
];
};
}

View file

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

View file

@ -1,26 +0,0 @@
{
lib,
config,
...
}: let
workingDirectory = "/var/lib/private/crab-hole";
in {
config = lib.mkIf (config.services.immich.enable && config.host.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

@ -8,14 +8,10 @@
./actual ./actual
./bazarr ./bazarr
./crab-hole
./flaresolverr
./forgejo ./forgejo
./home-assistant ./home-assistant
./immich ./immich
./jackett
./jellyfin ./jellyfin
./lidarr
./panoramax ./panoramax
./paperless ./paperless
./qbittorent.nix ./qbittorent.nix

View file

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

View file

@ -1,19 +0,0 @@
{
lib,
config,
...
}: {
config = lib.mkIf (config.services.flaresolverr.enable && config.host.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

@ -1,28 +0,0 @@
{
lib,
config,
...
}: {
options.services.flaresolverr = {
subdomain = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Subdomain for reverse proxy. If null, service will be local only.";
};
extraSubdomains = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "Extra subdomains for reverse proxy.";
};
};
config = lib.mkIf (config.services.flaresolverr.enable && config.services.flaresolverr.subdomain != null) {
host.reverse_proxy.subdomains.flaresolverr = {
subdomain = config.services.flaresolverr.subdomain;
extraSubdomains = config.services.flaresolverr.extraSubdomains;
target = "http://127.0.0.1:${toString config.services.flaresolverr.port}";
websockets.enable = true;
forwardHeaders.enable = true;
};
};
}

View file

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

View file

@ -1,26 +0,0 @@
{
lib,
config,
...
}: let
jackett_data_directory = "/var/lib/jackett/.config/Jackett";
in {
config = lib.mkIf (config.services.jackett.enable && config.host.impermanence.enable) {
assertions = [
{
assertion = config.services.jackett.dataDir == jackett_data_directory;
message = "jackett data directory does not match persistence";
}
];
environment.persistence."/persist/system/root" = {
directories = [
{
directory = jackett_data_directory;
user = "jackett";
group = "jackett";
}
];
};
};
}

View file

@ -1,28 +0,0 @@
{
lib,
config,
...
}: {
options.services.jackett = {
subdomain = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Subdomain for reverse proxy. If null, service will be local only.";
};
extraSubdomains = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "Extra subdomains for reverse proxy.";
};
};
config = lib.mkIf (config.services.jackett.enable && config.services.jackett.subdomain != null) {
host.reverse_proxy.subdomains.jackett = {
subdomain = config.services.jackett.subdomain;
extraSubdomains = config.services.jackett.extraSubdomains;
target = "http://127.0.0.1:9117";
websockets.enable = true;
forwardHeaders.enable = true;
};
};
}

View file

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

View file

@ -1,26 +0,0 @@
{
lib,
config,
...
}: let
lidarr_data_directory = "/var/lib/lidarr/.config/Lidarr";
in {
config = lib.mkIf (config.services.lidarr.enable && config.host.impermanence.enable) {
assertions = [
{
assertion = config.services.lidarr.dataDir == lidarr_data_directory;
message = "lidarr data directory does not match persistence";
}
];
environment.persistence."/persist/system/root" = {
directories = [
{
directory = lidarr_data_directory;
user = "lidarr";
group = "lidarr";
}
];
};
};
}

View file

@ -1,28 +0,0 @@
{
lib,
config,
...
}: {
options.services.lidarr = {
subdomain = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Subdomain for reverse proxy. If null, service will be local only.";
};
extraSubdomains = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "Extra subdomains for reverse proxy.";
};
};
config = lib.mkIf (config.services.lidarr.enable && config.services.lidarr.subdomain != null) {
host.reverse_proxy.subdomains.lidarr = {
subdomain = config.services.lidarr.subdomain;
extraSubdomains = config.services.lidarr.extraSubdomains;
target = "http://127.0.0.1:8686";
websockets.enable = true;
forwardHeaders.enable = true;
};
};
}

View file

@ -1,9 +1,10 @@
{ {
lib, lib,
config, config,
osConfig,
... ...
}: { }: {
config = lib.mkIf (config.services.panoramax.enable && config.host.impermanence.enable) { config = lib.mkIf (config.services.panoramax.enable && osConfig.host.impermanence.enable) {
# TODO: configure impermanence for panoramax data # TODO: configure impermanence for panoramax data
# This would typically include directories like: # This would typically include directories like:
# - /var/lib/panoramax # - /var/lib/panoramax

View file

@ -29,8 +29,6 @@
radarr = 2014; radarr = 2014;
sonarr = 2015; sonarr = 2015;
bazarr = 2016; bazarr = 2016;
lidarr = 2017;
crab-hole = 2018;
}; };
gids = { gids = {
@ -52,8 +50,6 @@
radarr = 2014; radarr = 2014;
sonarr = 2015; sonarr = 2015;
bazarr = 2016; bazarr = 2016;
lidarr = 2017;
crab-hole = 2018;
}; };
users = config.users.users; users = config.users.users;
@ -225,18 +221,6 @@ in {
isSystemUser = true; isSystemUser = true;
group = config.users.users.bazarr.name; group = config.users.users.bazarr.name;
}; };
lidarr = {
uid = lib.mkForce uids.lidarr;
isSystemUser = true;
group = config.users.users.lidarr.name;
};
crab-hole = {
uid = lib.mkForce uids.crab-hole;
isSystemUser = true;
group = config.users.users.crab-hole.name;
};
}; };
groups = { groups = {
@ -277,7 +261,6 @@ in {
users.radarr.name users.radarr.name
users.sonarr.name users.sonarr.name
users.bazarr.name users.bazarr.name
users.lidarr.name
leyla leyla
eve eve
ivy ivy
@ -382,20 +365,6 @@ in {
users.bazarr.name users.bazarr.name
]; ];
}; };
lidarr = {
gid = lib.mkForce gids.lidarr;
members = [
users.lidarr.name
];
};
crab-hole = {
gid = lib.mkForce gids.crab-hole;
members = [
users.crab-hole.name
];
};
}; };
}; };
} }

View file

@ -1,15 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Get current branch and git status for branch-aware behavior
current_branch=$(git branch --show-current 2>/dev/null || echo "unknown")
git_status=$(git status --porcelain 2>/dev/null || echo "")
# Default values
default_target=$(hostname)
default_user="$USER"
default_host=$(hostname)
default_mode=$(if [[ "$current_branch" != "main" ]]; then echo "test"; else echo "switch"; fi)
if [ -d "result" ]; if [ -d "result" ];
then then
preserve_result=true preserve_result=true
@ -52,29 +42,14 @@ while [ $# -gt 0 ]; do
;; ;;
--help|-h) --help|-h)
echo "--help -h: print this message" echo "--help -h: print this message"
echo "--target -t: defaults to the current system" echo "--target -t: set the target system to rebuild on"
echo " currently: $default_target" echo "--flake -f: set the flake to rebuild on the target system"
echo "--flake -f: defaults to same as target" echo "--mode -m: set the mode to rebuild flake as on the target system"
echo " currently: ${target:-$default_target}" echo "--user -u: set the user to rebuild flake as on the target system"
echo "--mode -m: defaults to 'switch', but 'test' on non-main branches" echo "--host: set the host that the flake will be rebuilt on (unset for current machine)"
echo " currently would be: $default_mode"
echo "--user -u: defaults to the current user"
echo " currently: $default_user"
echo "--host: defaults to building on the current machine"
echo " currently: $default_host"
echo "--preserve-result: do not remove the generated result folder after building" echo "--preserve-result: do not remove the generated result folder after building"
echo "--no-preserve-result: remove any result folder after building" echo "--no-preserve-result: remove any result folder after building"
echo "--show-trace: show trace on builds" echo "--show-trace: show trace on builds"
echo ""
echo "Branch-aware behavior:"
echo " - On non-main branches: defaults to test mode with warning"
echo " - On main with uncommitted changes: shows warning about creating a branch"
echo " - Current branch: $current_branch"
if [[ -n "$git_status" ]]; then
echo " - Git status: uncommitted changes detected"
else
echo " - Git status: clean working tree"
fi
exit 0 exit 0
;; ;;
*) *)
@ -85,21 +60,10 @@ while [ $# -gt 0 ]; do
shift shift
done done
target=${target:-$default_target} target=${target:-$(hostname)}
flake=${flake:-$target} flake=${flake:-$target}
mode=${mode:-$default_mode} mode=${mode:-switch}
user=${user:-$default_user} user=${user:-$USER}
# Branch-aware warnings and behavior
if [[ "$current_branch" != "main" ]] && [[ "$mode" == "test" ]]; then
echo "⚠️ WARNING: You are on branch '$current_branch' (not main)"
echo " Defaulting to test mode to prevent accidental system changes"
echo " Specify --mode=switch explicitly if you want to apply changes"
elif [[ "$current_branch" == "main" ]] && [[ -n "$git_status" ]] && [[ "$mode" != "test" ]]; then
echo "⚠️ WARNING: You are on main branch with uncommitted changes"
echo " Consider creating a feature branch for development:"
echo " git checkout -b feature/your-feature-name"
fi
command="nixos-rebuild $mode --sudo --ask-sudo-password --flake .#$flake" command="nixos-rebuild $mode --sudo --ask-sudo-password --flake .#$flake"