initial commit

This commit is contained in:
gwg313 2026-04-15 18:26:05 -04:00
commit ebc1be5217
Signed by: gwg313
GPG key ID: 60FF63B4826B7400
143 changed files with 7721 additions and 0 deletions

106
modules/aspects/roles.nix Normal file
View file

@ -0,0 +1,106 @@
{
lib,
...
}:
{
options.dendritic.roles = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ ... }:
{
options = {
roles = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
features = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
};
}
)
);
default = { };
};
config.dendritic.roles = {
core-user.features = [
"shell"
"nh"
"system-nix"
];
security-baseline.features = [
"security-kernel-hardened"
"system-services"
"security-systemd"
"security-sysctl"
"security-firewall"
"security-auditd"
"security-malware-clamav"
"ntp-chrony"
"security-usbguard"
];
desktop-wayland.features = [
"browser-brave"
"wm-niri"
"terminal-ghostty"
"audio"
"bluetooth"
"gnupg-agent"
"wayland"
"proton"
"earlyoom"
"dolphin"
];
laptop.features = [
"hardware-laptop"
"security-systemd-bluetooth"
];
server.roles = [
"security-baseline"
"security-sysctl-strict"
];
server.features = [
"security-ssh-hardening"
"security-firewall-nftables"
"ops-server-base"
];
developer.features = [
"developer-cli"
"editor-neovim"
"containers-podman"
"ops-k8s"
"virtualization-libvirt"
"security-sudo-rs"
"security-ssh-client"
"dev-devenv"
];
secrets-managed.features = [
"secrets-system-sops"
"secrets-home-sops"
];
theme-stylix.features = [
"theme-system-stylix"
"theme-home-stylix"
];
workstation.roles = [
"core-user"
"security-baseline"
"desktop-wayland"
"developer"
"secrets-managed"
"theme-stylix"
];
};
}

View file

@ -0,0 +1,34 @@
{ ... }:
{
config.dendritic.features.containers-podman = {
nixosModules = [
(
{ pkgs, ... }:
{
virtualisation = {
podman = {
enable = true;
# Create a `docker` alias for podman, to use it as a drop-in replacement
dockerCompat = true;
# Required for containers under podman-compose to be able to talk to each other.
defaultNetwork.settings.dns_enabled = true;
};
};
environment.systemPackages = with pkgs; [
buildah # Tool for building OCI (Open Container Initiative) and Docker container images.
distrobox # Lightweight utility for running Linux distributions in containers.
dive # A tool for exploring a Docker image, allowing inspection of layer contents.
grype # A vulnerability scanner for container images and filesystems.
hadolint # Dockerfile linter to analyze and enforce best practices in containerization.
podman-compose # Podman plugin for managing multi-container applications.
podman-tui # Text-based user interface (TUI) for Podman, facilitating container management.
syft # Open-source tool for scanning and analyzing container images for software composition and vulnerabilities.
];
}
)
];
};
}

View file

@ -0,0 +1,45 @@
{ ... }:
{
config.dendritic.features.audio = {
nixosModules = [
(
{ pkgs, ... }:
{
# Enable sound with pipewire.
services.pulseaudio.enable = false;
# hardware.alsa.enablePersistence = true;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
# If you want to use JACK applications, uncomment this
#jack.enable = true;
# use the example session manager (no others are packaged yet so this is enabled by default,
# no need to redefine it in your config for now)
#media-session.enable = true;
extraConfig.pipewire.adjust-sample-rate = {
"context.properties" = {
"default.clock.rate" = 192000;
#"defautlt.allowed-rates" = [ 192000 48000 44100 ];
"defautlt.allowed-rates" = [ 192000 ];
#"default.clock.quantum" = 32;
#"default.clock.min-quantum" = 32;
#"default.clock.max-quantum" = 32;
};
};
};
environment.systemPackages = with pkgs; [
pipewire
wireplumber
easyeffects
pavucontrol
];
}
)
];
};
}

View file

@ -0,0 +1,22 @@
{ ... }:
{
config.dendritic.features.bluetooth = {
nixosModules = [
(
{ lib, ... }:
{
services.blueman.enable = true;
hardware.bluetooth = {
enable = lib.mkForce true;
powerOnBoot = true;
};
services.upower = {
enable = true;
};
}
)
];
};
}

View file

@ -0,0 +1,148 @@
{ ... }:
{
config.dendritic.features.dolphin.homeModules = [
(
{ pkgs, config, ... }:
let
user = config.dendritic.current.primaryUser;
placesXbel = ''
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xbel>
<xbel version="1.0"
xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks">
<bookmark href="file:///home/${user}/Documents">
<title>Documents</title>
<info>
<metadata owner="http://freedesktop.org">
<bookmark:icon name="folder-documents"/>
<bookmark:isSystemItem>false</bookmark:isSystemItem>
</metadata>
</info>
</bookmark>
<bookmark href="file:///home/${user}/Downloads">
<title>Downloads</title>
<info>
<metadata owner="http://freedesktop.org">
<bookmark:icon name="folder-download"/>
<bookmark:isSystemItem>false</bookmark:isSystemItem>
</metadata>
</info>
</bookmark>
<bookmark href="file:///home/${user}/repos">
<title>Repositories</title>
<info>
<metadata owner="http://freedesktop.org">
<bookmark:icon name="folder-git"/>
<bookmark:isSystemItem>false</bookmark:isSystemItem>
</metadata>
</info>
</bookmark>
</xbel>
'';
in
{
home.packages = with pkgs; [
kdePackages.dolphin
kdePackages.kio
kdePackages.kio-extras
kdePackages.kio-fuse
kdePackages.ark
kdePackages.ffmpegthumbs
kdePackages.kdegraphics-thumbnailers
# whitesur-icon-theme
];
# Helps some non-KDE apps pick Dolphin for directory browsing.
xdg.mimeApps = {
enable = true;
defaultApplications = {
"inode/directory" = [ "org.kde.dolphin.desktop" ];
};
};
# Dolphin / KDE bookmarks ("Places" in the sidebar).
home.file.".local/share/user-places.xbel".text = placesXbel;
# Optional: keep GTK bookmarks too, for apps that still use them.
gtk.gtk3.bookmarks = [
"file:///home/${user}/Documents Documents"
"file:///home/${user}/Downloads Downloads"
"file:///home/${user}/repos Repositories"
];
# Basic KDE config so Dolphin behaves sanely outside Plasma.
xdg.configFile."kdeglobals".text = ''
[Icons]
Theme=WhiteSur
[KDE]
SingleClick=false
'';
# Dolphin settings.
xdg.configFile."dolphinrc".text = ''
[General]
BrowseThroughArchives=true
ShowFullPath=false
ShowSpaceInfo=true
ShowZoomSlider=true
[KFileDialog Settings]
Places Icons Auto-resize=false
Places Icons Static Size=22
[MainWindow]
MenuBar=Disabled
ToolBarsMovable=Disabled
[PreviewSettings]
Plugins=appimagethumbnail,audiothumbnail,blenderthumbnail,comicbookthumbnail,directorythumbnail,ebookthumbnail,exrthumbnail,fontthumbnail,gvsthumbnail,htmlthumbnail,imagethumbnail,jpegthumbnail,opendocumentthumbnail,postscriptthumbnail,rawthumbnail,svgthumbnail,windowsexethumbnail
[UiSettings]
ShowStatusBar=false
ShowZoomSlider=true
'';
# File dialog / view settings.
xdg.configFile."kiorc".text = ''
[Confirmations]
ConfirmDelete=true
ConfirmEmptyTrash=true
[Executable scripts]
behaviourOnLaunch=alwaysAsk
'';
# Optional: make Ark the preferred archive app in many cases.
xdg.desktopEntries.ark = {
name = "Ark";
exec = "ark %U";
terminal = false;
categories = [
"Qt"
"KDE"
"Utility"
"Archiving"
];
mimeType = [
"application/zip"
"application/x-tar"
"application/x-compressed-tar"
"application/x-bzip-compressed-tar"
"application/x-xz-compressed-tar"
"application/x-7z-compressed"
"application/x-rar"
];
};
home.sessionVariables = {
XDG_ICON_DIR = "${pkgs.whitesur-icon-theme}/share/icons/WhiteSur";
};
}
)
];
}

View file

@ -0,0 +1,29 @@
{ ... }:
{
config.dendritic.features.earlyoom = {
nixosModules = [
(
{ ... }:
{
services.earlyoom = {
enable = true;
freeMemThreshold = 15;
freeSwapThreshold = 10;
extraArgs = [
"-g"
"--sort-by-rss"
"--avoid"
"^(niri|ghostty|systemd|qemu-system.*)"
"--prefer"
"^(brave|electron|chromium|firefox|libreoffice|gimp|podman|conmon)"
];
};
}
)
];
};
}

View file

@ -0,0 +1,21 @@
{ ... }:
{
config.dendritic.features.gnupg-agent = {
nixosModules = [
(
{ pkgs, ... }:
{
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
pinentryPackage = pkgs.pinentry-qt;
};
environment.sessionVariables = {
SSH_AUTH_SOCK = "/run/user/1000/gnupg/S.gpg-agent.ssh";
};
}
)
];
};
}

View file

@ -0,0 +1,90 @@
{ ... }:
{
config.dendritic.features.wm-niri = {
homeModules = [
(
{ pkgs, inputs, ... }:
{
imports = [
inputs.niri.homeModules.niri
../../home/programs/niri/settings.nix
../../home/programs/niri/keybinds.nix
../../home/programs/niri/rules.nix
../../home/programs/niri/autostart.nix
../../home/programs/niri/noctaliashell.nix
];
services.gnome-keyring.enable = true;
}
)
];
nixosModules = [
(
{ pkgs, lib, ... }:
{
imports = [
../../nixos/gui/xdg.nix
];
services.greetd =
let
niri-config = pkgs.writeText "niri-config" ''
hotkey-overlay {
skip-at-startup
}
environment {
GTK_USE_PORTAL "0"
GDK_DEBUG "no-portals"
}
// other settings
spawn-at-startup "sh" "-c" "${pkgs.greetd.regreet}/bin/regreet; pkill -f niri"
'';
in
{
enable = true;
settings = {
default_session = {
command = "niri -c ${niri-config}";
user = "greeter";
};
};
};
programs.regreet.enable = true;
# services.displayManager.enable = false;
# services.displayManager = {
# sddm = {
# package = pkgs.kdePackages.sddm;
# enable = true;
# wayland.enable = true;
# };
# };
# services.displayManager.gdm = {
# enable = false;
# wayland = true;
# };
services.displayManager.enable = lib.mkForce false;
services.xserver = {
enable = true;
xkb = {
variant = "";
layout = "us";
};
};
environment = {
variables = {
TERMINAL = "ghostty";
EDITOR = "nvim";
VISUAL = "nvim";
PAGER = "moar";
PASSWORD_STORE_DIR = "$HOME/.local/share/password-store";
};
};
}
)
];
};
}

View file

@ -0,0 +1,36 @@
{ ... }:
{
config.dendritic.features = {
theme-home-stylix = {
includeInEmbeddedHomeManager = false;
homeModules = [
({ inputs, pkgs, ... }: {
imports = [
inputs.stylix.homeModules.stylix
];
stylix.enable = true;
stylix.base16Scheme = "${pkgs.base16-schemes}/share/themes/atelier-sulphurpool-light.yaml";
})
];
};
theme-system-stylix.nixosModules = [
({ inputs, pkgs, ... }: {
imports = [
inputs.stylix.nixosModules.stylix
];
stylix = {
enable = true;
base16Scheme = "${pkgs.base16-schemes}/share/themes/atelier-sulphurpool-light.yaml";
fonts = {
monospace = {
name = "JetBrainsMono Nerd Font";
};
};
};
})
];
};
}

View file

@ -0,0 +1,36 @@
{ ... }:
{
config.dendritic.features.wayland = {
nixosModules = [
(
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
wlr-randr
wl-clipboard
];
environment.sessionVariables = {
POLKIT_AUTH_AGENT = "${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1";
GSETTINGS_SCHEMA_DIR = "${pkgs.gsettings-desktop-schemas}/share/gsettings-schemas/${pkgs.gsettings-desktop-schemas.name}/glib-2.0/schemas";
WLR_NO_HARDWARE_CURSORS = "1";
NIXOS_OZONE_WL = "1";
MOZ_ENABLE_WAYLAND = "1";
SDL_VIDEODRIVER = "wayland";
_JAVA_AWT_WM_NONREPARENTING = "1";
CLUTTER_BACKEND = "wayland";
# WLR_RENDERER = "vulkan";
GTK_USE_PORTAL = "1";
#NIXOS_XDG_OPEN_USE_PORTAL = "1"; # Sets the desktop portal to use flatpak
WLR_NO_HARDWARE_CURSOR = "1";
GDK_BACKEND = "wayland";
QT_QPA_PLATFORM = "wayland;xcb";
QT_AUTO_SCREEN_SCALE_FACTOR = "1";
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
QT_QPA_PLATFORMTHEME = "qt5ct";
};
}
)
];
};
}

View file

@ -0,0 +1,15 @@
{ ... }:
{
config.dendritic.features.developer-cli.nixosModules = [
(
{ pkgs, inputs, ... }:
{
imports = [ inputs.nix-index-database.nixosModules.default ];
environment.systemPackages = with pkgs; [ git ];
programs.command-not-found.enable = false;
programs.nix-index-database.comma.enable = true;
}
)
];
}

View file

@ -0,0 +1,8 @@
{ ... }:
{
config.dendritic.features.editor-neovim.homeModules = [
({ pkgs, ... }: {
home.packages = with pkgs; [ neovim ];
})
];
}

View file

@ -0,0 +1,18 @@
{ ... }:
{
config.dendritic.features.hardware-laptop = {
nixosModules = [
(
{ config, ... }:
{
networking.networkmanager.enable = true;
powerManagement.enable = true;
services.tlp.enable = true;
}
)
];
};
}

95
modules/features/nvim.nix Normal file
View file

@ -0,0 +1,95 @@
{ inputs, ... }:
{
config.dendritic.features.editor-neovim.homeModules = [
({ pkgs, lib, ... }: {
imports = [
inputs.nvf.homeManagerModules.default
../home/programs/neovim/options.nix
../home/programs/neovim/languages.nix
../home/programs/neovim/picker.nix
../home/programs/neovim/snacks.nix
../home/programs/neovim/keymaps.nix
../home/programs/neovim/utils.nix
../home/programs/neovim/mini.nix
];
programs.nvf = {
enable = true;
settings.vim = {
startPlugins = with pkgs; [
vimPlugins.grug-far-nvim
vimPlugins.image-nvim
vimPlugins.vim-hoogle
vimPlugins.telescope_hoogle
vimPlugins.zk-nvim
vimPlugins.cyberdream-nvim
vimPlugins.octo-nvim
];
luaConfigRC.colorscheme = ''
vim.cmd.colorscheme("cyberdream-light")
'';
luaConfigRC.zk_nvim = ''
local ok, zk = pcall(require, "zk")
if not ok then return end
zk.setup({
picker = "select",
lsp = {
config = {
name = "zk",
cmd = { "zk", "lsp" },
filetypes = { "markdown" },
},
auto_attach = { enabled = true },
},
})
'';
};
settings.vim.augroups = [
{ name = "SwiftSetup"; }
];
settings.vim.autocmds = [
{
event = [ "FileType" ];
pattern = [ "swift" ];
group = "SwiftSetup";
desc = "Start sourcekit-lsp for Swift files";
callback = lib.generators.mkLuaInline ''
function()
local lspconfig = require("lspconfig")
for _, client in pairs(vim.lsp.get_active_clients()) do
if client.name == "sourcekit" then return end
end
lspconfig.sourcekit.setup({
cmd = { "sourcekit-lsp" },
filetypes = { "swift", "swiftpm" },
root_dir = lspconfig.util.root_pattern("Package.swift", ".git"),
})
end
'';
}
{
event = [ "BufWritePost" ];
pattern = [ "*.swift" ];
group = "SwiftSetup";
desc = "Format Swift files on save";
callback = lib.generators.mkLuaInline ''
function()
if vim.fn.executable("swift-format") == 1 then
vim.cmd("silent! noautocmd !swift-format -i %")
vim.cmd("checktime")
end
end
'';
}
];
};
})
];
}

View file

@ -0,0 +1,23 @@
{ ... }:
{
config.dendritic.features.ops-k8s.homeModules = [ ];
config.dendritic.features.ops-k8s.nixosModules = [
(
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
argocd # Declarative, GitOps continuous delivery tool for Kubernetes.
k3d # Lightweight utility to run Kubernetes clusters using Docker.
k9s # Kubernetes CLI to visually navigate and manage resources in clusters.
kind # Kubernetes IN Docker: Tool for running local Kubernetes clusters using Docker container nodes.
kubectl # Kubernetes command-line tool for interacting with clusters.
kubectx # Switch between Kubernetes contexts and namespaces with ease.
kubernetes-helm # Package manager for Kubernetes applications, simplifying deployment and management.
minikube # Local Kubernetes cluster for easy testing and development.
stern # Multi-container log tailing and streaming for Kubernetes.
];
}
)
];
}

View file

@ -0,0 +1,59 @@
{ ... }:
{
config.dendritic.features.nh = {
homeModules = [
(
{ config, ... }:
let
NH_NO_CHECKS = "1";
configFor = flakePath: {
enable = true;
clean = {
enable = true;
extraArgs = "--keep 3 --keep-since 8d";
};
flake = flakePath;
};
in
{
home.sessionVariables = {
inherit NH_NO_CHECKS;
};
programs.nh = configFor "${config.home.homeDirectory}/nix-config";
}
)
];
nixosModules = [
(
{ config, ... }:
let
NH_NO_CHECKS = "1";
user = config.dendritic.current.primaryUser;
configFor = flakePath: {
enable = true;
clean = {
enable = true;
extraArgs = "--keep 3 --keep-since 8d";
};
flake = flakePath;
};
in
{
environment.variables = {
inherit NH_NO_CHECKS;
};
programs.nh = configFor "/home/${user}/nix-config";
}
)
];
};
}

View file

@ -0,0 +1,130 @@
{ ... }:
{
config.dendritic.features.browser-brave.homeModules = [
(
{ pkgs, ... }:
{
programs.brave = {
enable = true;
commandLineArgs = [
# Wayland Native
"--enable-features=UseOzonePlatform"
"--ozone-platform=wayland"
# Hardware Acceleration (NVIDIA optimized)
"--enable-accelerated-video-decode"
"--enable-gpu-rasterization"
"--enable-zero-copy"
"--ignore-gpu-blocklist"
# Performance
"--enable-features=VaapiVideoDecoder"
"--enable-features=VaapiVideoEncoder"
"--enable-features=CanvasOopRasterization"
"--disable-features=UseChromeOSDirectVideoDecoder"
# Privacy & Security
"--disable-features=MediaRouter" # Disable Chromecast
"--disable-features=OptimizationHints" # No Google suggestions
"--disable-features=AutofillSavePaymentMethods"
"--disable-background-networking" # No telemetry
"--disable-sync" # Manual sync control
# Wayland-specific fixes
"--disable-features=WaylandWpColorManagerV1" # Color management fix
# UI/UX
"--force-dark-mode" # Match Stylix theme
"--enable-features=WebUIDarkMode"
"--no-default-browser-check"
];
extensions = [
# let
# ids = [
"cjpalhdlnbpafiamejdnhcphjbkeiagm" # ublock origin
"dbepggeogbaibhgnhhndojpepiihcmeb" # vimium
"eimadpbcbfnmbkopoojfekhnkhdbieeh" # dark reader
"pkehgijcmpdhfbdbbnkijodmdjhbjlgp" # privacy badger
"ghmbeldphafepmbegfdlkpapadhbakde" # proton pass
"mmjbdbjnoablegbkcklggeknkfcjkjia" # custom new tab page
];
# in
# map (id: { inherit id; }) ids;
};
xdg.configFile."BraveSoftware/Brave-Browser/Policies/managed/policy.json".text = builtins.toJSON {
BraveShieldsAdControl = 2;
BraveShieldsTrackersBlocked = 1;
BraveShieldsHttpsEverywhere = 1;
BraveRewardsDisabled = 1;
BraveWalletDisabled = 1;
BraveVPNDisabled = 1;
BraveAIChatEnabled = 0;
PasswordManagerEnabled = 0;
BravePlaylistEnabled = 0;
BraveWebDiscoveryEnabled = 0;
BraveStatsPingEnabled = 0;
DnsOverHttpsMode = "automatic";
BraveDarkMode = 1;
};
home.sessionVariables = {
DEFAULT_BROWSER = "${pkgs.brave}/bin/brave";
BROWSER = "${pkgs.brave}/bin/brave";
};
xdg.desktopEntries = {
brave-incognito = {
name = "Brave (Private window)";
genericName = "Navigateur Web";
exec = "brave --incognito";
icon = "brave-browser";
terminal = false;
categories = [
"Network"
"WebBrowser"
];
mimeType = [
"text/html"
"text/xml"
];
};
brave-tor = {
name = "Brave (Private window w/Tor)";
genericName = "Navigateur Web";
exec = "brave --tor";
icon = "brave-browser";
terminal = false;
categories = [
"Network"
"WebBrowser"
];
};
};
# =================================================================
# BRAVE SETTINGS (via brave://flags)
# =================================================================
# These need to be set manually in brave://flags on first launch:
# - Enable Tab Groups (UI)
# - Enable Parallel Downloading
# - Enable Reader Mode
# - GPU Rasterization: Enabled
# - Override software rendering list: Enabled
#
# Privacy settings (brave://settings/privacy):
# - Block trackers & ads: Aggressive
# - Block all fingerprinting
# - Upgrade connections to HTTPS
# - Block scripts: Off (breaks sites, use uBlock instead)
# - Block cookies: Only 3rd party
#
# Appearance (brave://settings/appearance):
# - Show home button: Off
# - Show bookmarks bar: Only on new tab
# - Use wide address bar: On
}
)
];
}

View file

@ -0,0 +1,23 @@
{ ... }:
{
config.dendritic.features.cli-zoxide = {
homeModules = [
(
{ ... }:
{
programs.zoxide = {
enable = true;
enableZshIntegration = true;
};
programs.zsh = {
shellAliases = {
cd = "z";
};
};
}
)
];
};
}

View file

@ -0,0 +1,150 @@
{ ... }:
{
config.dendritic.features.cli-zsh = {
homeModules = [
(
{ config, pkgs, ... }:
{
programs.zsh = {
enable = true;
enableCompletion = true;
autosuggestion.enable = true;
syntaxHighlighting.enable = true;
syntaxHighlighting.highlighters = [
"main"
"brackets"
"pattern"
"regexp"
"root"
"line"
];
historySubstringSearch.enable = true;
shellAliases = {
update = "sudo nixos-rebuild switch";
clean = "nix-collect-garbage -d";
repair = "nix-store --repair --verify --check-contents";
reload = "source ~/.zshrc";
"." = "cd ../";
".." = "cd ../../";
"..." = "cd ../../../";
"...." = "cd ../../../../";
ps = "procs";
grep = "rg";
cat = "bat --theme=base16 --color=always --paging=never --tabs=2 --wrap=never --plain";
vim = "nvim";
# Default flags
rm = "rm -i";
chmod = "chmod -R";
cp = "cp -R -i -v";
mv = "mv -i -v";
mkdir = "mkdir -p -v";
df = "df -h";
du = "du -h -s";
dd = "dd status=progress bs=4M conv=fdatasync ";
wgetpaste = "wgetpaste -Xx";
sudo = "sudo "; # Makes sudo work with es
ssh = "TERM=xterm ssh"; # Fixes some issues with ssh on some terminals
wget = "wget -c";
ping = "ping -c 5";
ftp = "ftp -p";
# Misc alieses I use often
ports = "ss -tulanp";
rmd = "rm -rf";
mine = "sudo chown -R $(whoami):users";
benchmark = "hyperfine --warmup 3 ";
c = "clear";
listen = "lsof -P -i -n";
octal = "stat -c '%a %n'";
f = "$(pay-respects zsh)";
};
history = {
size = 10000;
path = "${config.xdg.dataHome}/zsh/history";
};
initContent = ''
eval "$(pay-respects zsh --alias)"
# search history based on what's typed in the prompt
autoload -U history-search-end
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey "^[OA" history-beginning-search-backward-end
bindkey "^[OB" history-beginning-search-forward-end
# General completion behavior
zstyle ':completion:*' completer _extensions _complete _approximate
# Use cache
zstyle ':completion:*' use-cache on
zstyle ':completion:*' cache-path "$XDG_CACHE_HOME/zsh/.zcompcache"
# Complete the alias
zstyle ':completion:*' complete true
# Autocomplete options
zstyle ':completion:*' complete-options true
# Completion matching control
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
zstyle ':completion:*' keep-prefix true
# Group matches and describe
zstyle ':completion:*' menu select
zstyle ':completion:*' list-grouped false
zstyle ':completion:*' list-separator '''
zstyle ':completion:*' group-name '''
zstyle ':completion:*' verbose yes
zstyle ':completion:*:matches' group 'yes'
zstyle ':completion:*:warnings' format '%F{red}%B-- No match for: %d --%b%f'
zstyle ':completion:*:messages' format '%d'
zstyle ':completion:*:corrections' format '%B%d (errors: %e)%b'
zstyle ':completion:*:descriptions' format '[%d]'
# Colors
zstyle ':completion:*' list-colors ''${(s.:.)LS_COLORS}
# case insensitive tab completion
zstyle ':completion:*:*:cd:*' tag-order local-directories directory-stack path-directories
zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'users' 'expand'
zstyle ':completion:*:*:-command-:*:*' group-order aliases builtins functions commands
zstyle ':completion:*' special-dirs true
zstyle ':completion:*' squeeze-slashes true
# Sort
zstyle ':completion:*' sort false
zstyle ":completion:*:git-checkout:*" sort false
zstyle ':completion:*' file-sort modification
zstyle ':completion:*:eza' sort false
zstyle ':completion:complete:*:options' sort false
zstyle ':completion:files' sort false
autoload -U compinit && compinit
export CARAPACE_BRIDGES='zsh,fish,bash,inshellisense' # optional
zstyle ':completion:*' format $'\e[2;37mCompleting %d\e[m'
source <(carapace _carapace)
zstyle ':completion:*:git:*' group-order 'main commands' 'alias commands' 'external commands'
'';
};
home.packages = with pkgs; [
fastfetch
pay-respects
];
}
)
];
};
}

View file

@ -0,0 +1,20 @@
{ ... }:
{
config.dendritic.features.dev-devenv = {
homeModules = [
(
{ pkgs, ... }:
{
home.packages = with pkgs; [
cachix
devenv
];
programs.direnv.enable = true;
programs.direnv.nix-direnv.enable = true;
}
)
];
};
}

View file

@ -0,0 +1,136 @@
{ ... }:
{
config.dendritic.features.filemanager-yazi = {
homeModules = [
(
{ pkgs, lib, ... }:
{
programs.yazi = {
enable = true;
enableZshIntegration = true;
shellWrapperName = "y";
plugins = {
starship = pkgs.yaziPlugins.starship;
full-border = pkgs.yaziPlugins.full-border;
chmod = pkgs.yaziPlugins.chmod;
compress = pkgs.yaziPlugins.compress;
smart-paste = pkgs.yaziPlugins.smart-paste;
smart-enter = pkgs.yaziPlugins.smart-enter;
smart-filter = pkgs.yaziPlugins.smart-filter;
};
settings = {
yazi = {
ratio = [
1
4
3
];
sort_by = "natural";
sort_sensitive = true;
sort_reverse = false;
sort_dir_first = true;
linemode = "none";
show_hidden = true;
show_symlink = true;
};
preview = {
image_filter = "lanczos3";
image_quality = 90;
tab_size = 1;
max_width = 600;
max_height = 900;
cache_dir = "";
ueberzug_scale = 1;
ueberzug_offset = [
0
0
0
0
];
};
tasks = {
micro_workers = 5;
macro_workers = 10;
bizarre_retry = 5;
};
};
initLua = ''
require("starship"):setup()
require("full-border"):setup()
require("smart-enter"):setup {
open_multi = true,
}
'';
keymap = {
mgr.prepend_keymap = [
{
on = [
"c"
"a"
"a"
];
run = "plugin compress";
desc = "Archive selected files";
}
{
on = [
"c"
"a"
"p"
];
run = "plugin compress -p";
desc = "Archive selected files (password)";
}
{
on = [
"c"
"a"
"h"
];
run = "plugin compress -ph";
desc = "Archive selected files (password+header)";
}
{
on = [
"c"
"a"
"l"
];
run = "plugin compress -l";
desc = "Archive selected files (compression level)";
}
{
on = [
"c"
"a"
"u"
];
run = "plugin compress -phl";
desc = "Archive selected files (password+header+level)";
}
{
on = "p";
run = "plugin smart-paste";
desc = "Paste into the hovered directory or CWD";
}
{
on = "l";
run = "plugin smart-enter";
desc = "Enter the child directory, or open the file";
}
{
on = "F";
run = "plugin smart-filter";
desc = "Smart filter";
}
];
};
};
}
)
];
};
}

View file

@ -0,0 +1,46 @@
{ ... }:
{
config.dendritic.features.git-lazygit = {
homeModules = [
(
{ config, lib, ... }:
let
accent = "#${config.lib.stylix.colors.base0D}";
muted = "#${config.lib.stylix.colors.base03}";
in
{
programs.lazygit = {
enable = true;
settings = lib.mkForce {
disableStartupPopups = true;
notARepository = "skip";
promptToReturnFromSubprocess = false;
update.method = "never";
git = {
commit.signOff = true;
overrideGpg = true;
};
gui = {
theme = {
activeBorderColor = [
accent
"bold"
];
inactiveBorderColor = [ muted ];
};
showListFooter = false;
showRandomTip = false;
showCommandLog = false;
showBottomLine = false;
nerdFontsVersion = "3";
};
};
};
}
)
];
};
}

View file

@ -0,0 +1,38 @@
{ ... }:
{
config.dendritic.features.terminal-ghostty = {
homeModules = [
(
{ pkgs, lib, ... }:
{
programs.ghostty = {
enable = true;
enableZshIntegration = true;
installVimSyntax = true;
settings = {
window-padding-x = 10;
window-padding-y = 10;
auto-update = "off";
working-directory = "home";
window-inherit-working-directory = false; # avoid inheritance
keybinds = [ ];
# background-opacity = 0.8;
background-opacity = 1;
confirm-close-surface = false;
font-family = lib.mkForce "Comic Code Ligatures";
# font-family = lib.mkForce "Terminus";
font-size = 14;
gtk-titlebar = false;
# theme = "Teerb";
};
};
home.packages = with pkgs; [
ueberzugpp
terminus_font_ttf
];
}
)
];
};
}

View file

@ -0,0 +1,27 @@
{ ... }:
{
config.dendritic.features.proton.homeModules = [
(
{ pkgs, ... }:
{
home.packages = with pkgs; [
proton-vpn
proton-pass
proton-authenticator
];
# Fix Proton Authenticator desktop entry
xdg.desktopEntries = {
"Proton Authenticator" = {
name = "Proton Authenticator";
exec = "env WEBKIT_DISABLE_COMPOSITING_MODE=1 ${pkgs.proton-authenticator}/bin/proton-authenticator";
icon = "proton-authenticator";
type = "Application";
categories = [ "Utility" ];
terminal = false;
};
};
}
)
];
}

View file

@ -0,0 +1,34 @@
{ ... }:
{
config.dendritic.features = {
secrets-home-sops.homeModules = [
({ inputs, config, ... }: {
imports = [
inputs.sops-nix.homeModules.sops
];
sops.defaultSopsFile = ../../secrets/users/${config.dendritic.current.primaryUser}.yaml;
sops.defaultSopsFormat = "yaml";
sops.age.keyFile = "${config.home.homeDirectory}/.config/sops/age/keys.txt";
sops.secrets."user/test" = {
path = ".config/secrets/test";
};
})
];
secrets-system-sops.nixosModules = [
({ inputs, config, ... }: {
imports = [
inputs.sops-nix.nixosModules.sops
];
sops.defaultSopsFile = ../../secrets/hosts/${config.dendritic.current.hostName}.yaml;
sops.defaultSopsFormat = "yaml";
sops.age.keyFile = "/home/${config.dendritic.current.primaryUser}/.config/sops/age/keys.txt";
sops.secrets."system/example" = { };
})
];
};
}

View file

@ -0,0 +1,22 @@
{ ... }:
{
config.dendritic.features.security-auditd = {
nixosModules = [
(
{ ... }:
{
# start as early in the boot process as possible
boot.kernelParams = [ "audit=1" ];
security.auditd.enable = true;
security.audit.enable = true;
security.audit.rules = [
# Log all program executions on 64-bit architecture
"-a exit,always -F arch=b64 -S execve"
];
}
)
];
};
}

View file

@ -0,0 +1,17 @@
{ ... }:
{
config.dendritic.features.security-firewall = {
nixosModules = [
(
{ ... }:
{
networking.nftables.enable = true;
networking.firewall = {
enable = true;
};
}
)
];
};
}

View file

@ -0,0 +1,102 @@
{ ... }:
{
config.dendritic.features.security-kernel-hardened = {
nixosModules = [
(
{ pkgs, ... }:
{
boot.kernelPackages = pkgs.linuxPackages_hardened;
security = {
protectKernelImage = true;
lockKernelModules = false; # this breaks iptables, wireguard, and virtd
# force-enable the Page Table Isolation (PTI) Linux kernel feature
forcePageTableIsolation = true;
# User namespaces are required for sandboxing.
# this means you cannot set `"user.max_user_namespaces" = 0;` in sysctl
allowUserNamespaces = true;
# Disable unprivileged user namespaces, unless containers are enabled
# unprivilegedUsernsClone = true;
allowSimultaneousMultithreading = true;
};
boot.kernelParams = [
# make it harder to influence slab cache layout
"slab_nomerge"
# enables zeroing of memory during allocation and free time
# helps mitigate use-after-free vulnerabilaties
"init_on_alloc=1"
"init_on_free=1"
# randomizes page allocator freelist, improving security by
# making page allocations less predictable
"page_alloc.shuffel=1"
# enables Kernel Page Table Isolation, which mitigates Meltdown and
# prevents some KASLR bypasses
"pti=on"
# randomizes the kernel stack offset on each syscall
# making attacks that rely on a deterministic stack layout difficult
"randomize_kstack_offset=on"
# disables vsyscalls, they've been replaced with vDSO
"vsyscall=none"
# disables debugfs, which exposes sensitive info about the kernel
"debugfs=off"
# certain exploits cause an "oops", this makes the kernel panic if an "oops" occurs
"oops=panic"
# only alows kernel modules that have been signed with a valid key to be loaded
# making it harder to load malicious kernel modules
# can make VirtualBox or Nvidia drivers unusable
"module.sig_enforce=1"
# prevents user space code excalation
"lockdown=confidentiality"
# "rd.udev.log_level=3"
# "udev.log_priority=3"
];
boot.blacklistedKernelModules = [
# Obscure networking protocols
"dccp"
"sctp"
"rds"
"tipc"
"n-hdlc"
"ax25"
"netrom"
"x25"
"rose"
"decnet"
"econet"
"af_802154"
"ipx"
"appletalk"
"psnap"
"p8023"
"p8022"
"can"
"atm"
# Various rare filesystems
"cramfs"
"freevxfs"
"jffs2"
"hfs"
"hfsplus"
"udf"
# Not so rare filesystems
"squashfs"
"cifs"
"nfs"
"nfsv3"
"nfsv4"
"ksmbd"
"gfs2"
# vivid driver is only useful for testing purposes and has been the
# cause of privilege escalation vulnerabilities
"vivid"
];
}
)
];
};
}

View file

@ -0,0 +1,33 @@
{ ... }:
{
config.dendritic.features.security-malware-clamav = {
nixosModules = [
(
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
clamav
];
services.clamav = {
daemon.enable = true;
updater.enable = true;
updater.frequency = 12; # Number of database checks per day
scanner = {
enable = true;
# 4:00 AM
interval = "*-*-* 04:00:00";
scanDirectories = [
"/home"
"/var/lib"
"/tmp"
"/etc"
"/var/tmp"
];
};
};
}
)
];
};
}

View file

@ -0,0 +1,87 @@
{ ... }:
{
config.dendritic.features.security-ssh-client = {
nixosModules = [
(
{ ... }:
{
programs.ssh = {
# disable unnecessary forwardings
forwardX11 = false;
# explicitly define cryptography algorithms to avoid the use of weak algorithms
# AES CTR modes have been removed to mitigate the Terrapin attack
# https://terrapin-attack.com/
ciphers = [
"aes256-gcm@openssh.com"
"aes128-gcm@openssh.com"
];
hostKeyAlgorithms = [
"ssh-ed25519"
"ssh-ed25519-cert-v01@openssh.com"
"sk-ssh-ed25519@openssh.com"
"sk-ssh-ed25519-cert-v01@openssh.com"
"rsa-sha2-256"
"rsa-sha2-256-cert-v01@openssh.com"
"rsa-sha2-512"
"rsa-sha2-512-cert-v01@openssh.com"
];
macs = [
"hmac-sha2-256-etm@openssh.com"
"hmac-sha2-512-etm@openssh.com"
"umac-128-etm@openssh.com"
];
kexAlgorithms = [
"sntrup761x25519-sha512@openssh.com"
"curve25519-sha256"
"curve25519-sha256@libssh.org"
"diffie-hellman-group16-sha512"
"diffie-hellman-group18-sha512"
];
extraConfig = "
# disable unnecessary forwardings
ForwardAgent no
ForwardX11Trusted no
GatewayPorts no
Tunnel no
# disable unnecessary authentication methods
ChallengeResponseAuthentication no
HostbasedAuthentication no
# define authentication methods to be used
PasswordAuthentication yes
PubkeyAuthentication yes
PreferredAuthentications publickey,password
# disable pre-connection compression as it could cause security issues
Compression no
# in addition to checking a host's hostname, also check the host's IP address
# this provides extra safety against DNS spoofing attacks
CheckHostIP yes
# ask the user if the user wants to accept the new host's host key
StrictHostKeyChecking ask
# hash the entries in the known_hosts file to prevent disclosure
# of the file's content
HashKnownHosts yes
# send a keepalive message to the server when the session has been idle for 60 seconds
# this prevents/detects connection timeouts
ServerAliveInterval 60
# increase the number of password retries
NumberOfPasswordPrompts 5
# display an ASCII art of the server's host key
VisualHostKey yes
";
};
}
)
];
};
}

View file

@ -0,0 +1,177 @@
{ ... }:
{
config.dendritic.features = {
security-ssh-server-hardening.nixosModules = [
(
{ config, ... }:
{
services.fail2ban = {
enable = true;
maxretry = 5;
bantime = "1h";
# ignoreIP = [
# "172.16.0.0/12"
# "192.168.0.0/16"
# "2601:881:8100:8de0:31e6:ac52:b5be:462a"
# "matrix.org"
# "app.element.io" # don't ratelimit matrix users
# ];
bantime-increment = {
enable = true; # Enable increment of bantime after each violation
multipliers = "1 2 4 8 16 32 64 128 256";
maxtime = "168h"; # Do not ban for more than 1 week
overalljails = true; # Calculate the bantime based on all the violations
};
};
# https://www.ssh-audit.com/hardening_guides.html
# https://github.com/jtesta/ssh-audit
services.openssh = {
enable = true;
settings = {
########## Features ##########
# disallow ssh-agent forwarding to prevent lateral movement
AllowAgentForwarding = false;
# prevent TCP ports from being forwarded over SSH tunnels
# **please be aware that disabling TCP forwarding does not prevent port forwarding**
# any user with an interactive login shell can spin up his/her own instance of sshd
AllowTcpForwarding = true;
# prevent StreamLocal (Unix-domain socket) forwarding
AllowStreamLocalForwarding = false;
# disables all forwarding features
# overrides all other forwarding switches
DisableForwarding = false;
# disallow remote hosts from connecting to forwarded ports
# i.e. forwarded ports are forced to bind to 127.0.0.1 instad of 0.0.0.0
GatewayPorts = "no";
# prevent tun device forwarding
PermitTunnel = false;
# suppress MOTD
PrintMotd = false;
# disable X11 forwarding since it is not necessary
X11Forwarding = false;
########## Authentication ##########
# AllowUsers = ["${user}"];
# Use keys only. Remove if you want to SSH using password (not recommended)
PasswordAuthentication = false;
HostbasedAuthentication = false;
# enable pubkey authentication
PubkeyAuthentication = true;
# Forbid root login through SSH.
PermitRootLogin = "no";
# nix enables pam by default
# UsePAM = false;
# challenge-response authentication backend it not configured by default
# therefore, it is set to "no" by default to avoid the use of an unconfigured backend
ChallengeResponseAuthentication = false;
# set maximum authentication retries to prevent brute force attacks
MaxAuthTries = 3;
# disallow connecting using empty passwords
PermitEmptyPasswords = false;
########## Cryptography ##########
# explicitly define cryptography algorithms to avoid the use of weak algorithms
# AES CTR modes have been removed to mitigate the Terrapin attack
# https://terrapin-attack.com/
Ciphers = [
"aes256-gcm@openssh.com"
"aes128-gcm@openssh.com"
];
Macs = [
"hmac-sha2-256-etm@openssh.com"
"hmac-sha2-512-etm@openssh.com"
"umac-128-etm@openssh.com"
];
KexAlgorithms = [
"sntrup761x25519-sha512@openssh.com"
"curve25519-sha256"
"curve25519-sha256@libssh.org"
"diffie-hellman-group16-sha512"
"diffie-hellman-group18-sha512"
];
# hostKeyAlgorithms = [
# "rsa-sha2-512"
# "rsa-sha2-256"
# "ssh-ed25519"
# ];
########## Connection Preferences ##########
# enforce SSH server to only use SSH protocol version 2
# SSHv1 contains security issues and should be avoided at all costs
# SSHv1 is disabled by default after OpenSSH 7.0, but this option is
# specified anyways to ensure this configuration file's compatibility
# with older versions of OpenSSH server
Protocol = 2;
# number of client alive messages sent without client responding
ClientAliveCountMax = 2;
# send a keepalive message to the client when the session has been idle for 300 seconds
# this prevents/detects connection timeouts
ClientAliveInterval = 300;
# compression before encryption might cause security issues
Compression = false;
# prevent SSH trust relationships from allowing lateral movements
IgnoreRhosts = true;
# log verbosely for addtional information
LogLevel = "VERBOSE";
# allow a maximum of two multiplexed sessions over a single TCP connection
MaxSessions = 2;
# let ClientAliveInterval handle keepalive
TCPKeepAlive = false;
# disable reverse DNS lookups
# UseDNS = false;
};
extraConfig = ''
########## Features ##########
# accept locale-related environment variables
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
########## Connection Preferences ##########
# disable reverse DNS lookups
UseDNS no
########## Disable GSS ##########
GSSAPIAuthentication no
'';
};
}
)
];
};
}

View file

@ -0,0 +1,24 @@
{ ... }:
{
config.dendritic.features.security-sudo-rs = {
nixosModules = [
(
{ config, ... }:
let
user = config.dendritic.current.primaryUser;
in
{
security = {
sudo.enable = false;
sudo-rs = {
enable = true;
execWheelOnly = true;
wheelNeedsPassword = true;
};
};
}
)
];
};
}

View file

@ -0,0 +1,50 @@
{ ... }:
{
config.dendritic.features.security-usbguard = {
nixosModules = [
(
{
config,
pkgs,
lib,
...
}:
let
user = config.dendritic.current.primaryUser;
in
{
services.usbguard = {
enable = true;
IPCAllowedUsers = [
"root"
user
];
# presentDevicePolicy refers to how to treat USB devices
# that are already connected when the daemon starts
presentDevicePolicy = "allow";
rules = lib.mkBefore ''
# allow `only` devices with mass storage interfaces (USB Mass Storage)
allow with-interface equals { 08:*:* }
# allow mice and keyboards
# allow with-interface equals { 03:*:* }
# Reject devices with suspicious combination of interfaces
reject with-interface all-of { 08:*:* 03:00:* }
reject with-interface all-of { 08:*:* 03:01:* }
reject with-interface all-of { 08:*:* e0:*:* }
reject with-interface all-of { 08:*:* 02:*:* }
'';
};
environment.systemPackages = with pkgs; [
usbguard
usbguard-notifier
];
}
)
];
};
}

View file

@ -0,0 +1,18 @@
# Breaks tracing and perf tools
{ ... }:
{
config.dendritic.features.security-sysctl-bpf = {
nixosModules = [
(
{ ... }:
{
boot.kernel.sysctl = {
"kernel.unprivileged_bpf_disabled" = 1;
# should be enabled along with bpf above
"net.core.bpf_jit_harden" = 2;
};
}
)
];
};
}

View file

@ -0,0 +1,17 @@
# Restricts dmesg
{ ... }:
{
config.dendritic.features.security-sysctl-debug = {
nixosModules = [
(
{ ... }:
{
boot.kernel.sysctl = {
"kernel.kptr_restrict" = 2;
"kernel.dmesg_restrict" = 1;
};
}
)
];
};
}

View file

@ -0,0 +1,29 @@
{ ... }:
{
config.dendritic.features.security-sysctl-kernel = {
nixosModules = [
(
{ ... }:
{
boot.kernel.sysctl = {
"fs.suid_dumpable" = 0;
# prevent pointer leaks
# Note: certian container runtimes or browser sandboxes might rely on the following
# restrict loading TTY line disciplines to the CAP_SYS_MODULE
"dev.tty.ldisk_autoload" = 0;
# prevent exploit of use-after-free flaws
"vm.unprivileged_userfaultfd" = 0;
# kexec is used to boot another kernel during runtime and can be abused
"kernel.kexec_load_disabled" = 1;
# Kernel self-protection
# SysRq exposes a lot of potentially dangerous debugging functionality to unprivileged users
# 4 makes it so a user can only use the secure attention key. A value of 0 would disable completely
"kernel.sysrq" = 4;
# restrict all usage of performance events to the CAP_PERFMON capability
"kernel.perf_event_paranoid" = 3;
};
}
)
];
};
}

View file

@ -0,0 +1,54 @@
{ ... }:
{
config.dendritic.features.security-sysctl-network = {
nixosModules = [
(
{ ... }:
{
boot.kernel.sysctl = {
# protect against SYN flood attacks (denial of service attack)
"net.ipv4.tcp_syncookies" = 1;
# protection against TIME-WAIT assassination
"net.ipv4.tcp_rfc1337" = 1;
# enable source validation of packets received (prevents IP spoofing)
"net.ipv4.conf.default.rp_filter" = 1;
"net.ipv4.conf.all.rp_filter" = 1;
"net.ipv4.conf.all.accept_redirects" = 0;
"net.ipv4.conf.default.accept_redirects" = 0;
"net.ipv4.conf.all.secure_redirects" = 0;
"net.ipv4.conf.default.secure_redirects" = 0;
# Protect against IP spoofing
"net.ipv6.conf.all.accept_redirects" = 0;
"net.ipv6.conf.default.accept_redirects" = 0;
"net.ipv4.conf.all.send_redirects" = 0;
"net.ipv4.conf.default.send_redirects" = 0;
# prevent man-in-the-middle attacks
"net.ipv4.icmp_echo_ignore_all" = 1;
# ignore ICMP request, helps avoid Smurf attacks
"net.ipv4.conf.all.forwarding" = 0;
"net.ipv4.conf.default.accept_source_route" = 0;
"net.ipv4.conf.all.accept_source_route" = 0;
"net.ipv6.conf.all.accept_source_route" = 0;
"net.ipv6.conf.default.accept_source_route" = 0;
# Reverse path filtering causes the kernel to do source validation of
"net.ipv6.conf.all.forwarding" = 0;
"net.ipv6.conf.all.accept_ra" = 0;
"net.ipv6.conf.default.accept_ra" = 0;
## TCP hardening
# Prevent bogus ICMP errors from filling up logs.
"net.ipv4.icmp_ignore_bogus_error_responses" = 1;
# Disable TCP SACK
"net.ipv4.tcp_sack" = 0;
"net.ipv4.tcp_dsack" = 0;
"net.ipv4.tcp_fack" = 0;
};
}
)
];
};
}

View file

@ -0,0 +1,16 @@
# Breaks Debuggers
{ ... }:
{
config.dendritic.features.security-sysctl-ptrace = {
nixosModules = [
(
{ ... }:
{
boot.kernel.sysctl = {
"kernel.yama.ptrace_scope" = 2;
};
}
)
];
};
}

View file

@ -0,0 +1,12 @@
# Enable on server not dev machines
{ ... }:
{
config.dendritic.features.security-sysctl-strict = {
features = [
"security-sysctl-ptrace"
"security-sysctl-bpf"
"security-sysctl-debug"
"security-sysctl-userns"
];
};
}

View file

@ -0,0 +1,16 @@
# Can break containers and flatpaks
{ ... }:
{
config.dendritic.features.security-sysctl-userns = {
nixosModules = [
(
{ lib, ... }:
{
boot.kernel.sysctl = lib.mkForce {
"kernel.unprivileged_userns_clone" = 0;
};
}
)
];
};
}

View file

@ -0,0 +1,35 @@
{ ... }:
{
config.dendritic.features.security-sysctl-userspace = {
nixosModules = [
(
{ ... }:
{
boot.kernel.sysctl = {
# 0 breaks browsers
"kernel.unprivileged_userns_clone" = 1;
"vm.mmap_min_addr" = 65536;
"vm.swappiness" = 10;
# ASLR memory protection (64-bit systems)
"vm.mmap_rnd_bits" = 32;
"vm.mmap_rnd_compat_bits" = 16;
# only permit symlinks to be followed when outside of a world-writable sticky directory
"fs.protected_symlinks" = 1;
"fs.protected_hardlinks" = 1;
# Prevent creating files in potentially attacker-controlled environments
"fs.protected_fifos" = 2;
"fs.protected_regular" = 2;
# Randomize memory
"kernel.randomize_va_space" = 2;
# Exec Shield (Stack protection)
"kernel.exec-shield" = 1;
};
}
)
];
};
}

View file

@ -0,0 +1,21 @@
{ ... }:
{
config.dendritic.features.security-sysctl = {
features = [
"security-sysctl-kernel"
"security-sysctl-network"
"security-sysctl-userspace"
];
nixosModules = [
(
{ pkgs, ... }:
{
environment.systemPackages = [ pkgs.kernel-hardening-checker ];
}
)
];
};
}

View file

@ -0,0 +1,46 @@
{ ... }:
{
config.dendritic.features.security-systemd-ask-password-console = {
nixosModules = [
(
{ ... }:
{
systemd.services.systemd-ask-password-console.serviceConfig = {
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
ProtectClock = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectProc = "invisible";
PrivateTmp = true;
PrivateMounts = true;
PrivateNetwork = true;
PrivateDevices = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
RestrictAddressFamilies = [
"~AF_INET6"
"~AF_INET"
"~AF_PACKET"
];
MemoryDenyWriteExecute = true;
DevicePolicy = "closed";
LockPersonality = true;
SystemCallFilter = [
"~@keyring"
"~@swap"
"~@clock"
"~@module"
"~@obsolete"
"~@cpu-emulation"
];
};
}
)
];
};
}

View file

@ -0,0 +1,46 @@
{ ... }:
{
config.dendritic.features.security-systemd-ask-password-wall = {
nixosModules = [
(
{ ... }:
{
systemd.services.systemd-ask-password-wall.serviceConfig = {
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
ProtectClock = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectProc = "invisible";
PrivateTmp = true;
PrivateMounts = true;
PrivateNetwork = true;
PrivateDevices = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
RestrictAddressFamilies = [
"~AF_INET6"
"~AF_INET"
"~AF_PACKET"
];
MemoryDenyWriteExecute = true;
DevicePolicy = "closed";
LockPersonality = true;
SystemCallFilter = [
"~@keyring"
"~@swap"
"~@clock"
"~@module"
"~@obsolete"
"~@cpu-emulation"
];
};
}
)
];
};
}

View file

@ -0,0 +1,51 @@
{ ... }:
{
config.dendritic.features.security-systemd-auditd = {
nixosModules = [
(
{ ... }:
{
systemd.services.auditd.serviceConfig = {
NoNewPrivileges = true;
ProtectSystem = "full";
ProtectHome = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
ProtectProc = "invisible";
ProtectClock = true;
PrivateTmp = true;
PrivateNetwork = true;
PrivateMounts = true;
PrivateDevices = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
RestrictAddressFamilies = [
"~AF_INET6"
"~AF_INET"
"~AF_PACKET"
];
MemoryDenyWriteExecute = true;
LockPersonality = true;
SystemCallFilter = [
"~@clock"
"~@module"
"~@mount"
"~@swap"
"~@obsolete"
"~@cpu-emulation"
];
SystemCallArchitectures = "native";
CapabilityBoundingSet = [
"~CAP_CHOWN"
"~CAP_FSETID"
"~CAP_SETFCAP"
];
};
}
)
];
};
}

View file

@ -0,0 +1,28 @@
{ ... }:
{
config.dendritic.features.security-systemd-bluetooth = {
nixosModules = [
(
{ lib, ... }:
{
systemd.services.bluetooth.serviceConfig = lib.mkForce {
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectHostname = true;
ProtectControlGroups = true;
ProtectProc = "invisible";
SystemCallFilter = [
"~@obsolete"
"~@cpu-emulation"
"~@swap"
"~@reboot"
"~@mount"
];
SystemCallArchitectures = "native";
};
}
)
];
};
}

View file

@ -0,0 +1,50 @@
{ ... }:
{
config.dendritic.features.security-systemd-dbus = {
nixosModules = [
(
{ ... }:
{
systemd.services.dbus.serviceConfig = {
NoNewPrivileges = true;
ProtectSystem = "stric";
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
PrivateMounts = true;
PrivateDevices = true;
PrivateTmp = true;
RestrictSUIDSGID = true;
RestrictRealtime = true;
RestrictAddressFamilies = [
"AF_UNIX"
];
RestrictNamespaces = true;
SystemCallErrorNumber = "EPERM";
SystemCallArchitectures = "native";
SystemCallFilter = [
"~@obsolete"
"~@resources"
"~@debug"
"~@mount"
"~@reboot"
"~@swap"
"~@cpu-emulation"
];
LockPersonality = true;
IPAddressDeny = [
"0.0.0.0/0"
"::/0"
];
MemoryDenyWriteExecute = true;
DevicePolicy = "closed";
UMask = 0077;
};
}
)
];
};
}

View file

@ -0,0 +1,49 @@
{ ... }:
{
config.dendritic.features.security-systemd-getty = {
nixosModules = [
(
{ ... }:
{
systemd.services."getty@".serviceConfig = {
NoNewPrivileges = true;
ProtectSystem = "stric";
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectClock = true;
PrivateMounts = true;
PrivateTmp = true;
RestrictSUIDSGID = true;
RestrictRealtime = true;
RestrictAddressFamilies = [
"AF_UNIX"
"AF_NETLINK"
];
RestrictNamespaces = true;
SystemCallErrorNumber = "EPERM";
SystemCallArchitectures = "native";
SystemCallFilter = [
"~@obsolete"
"~@debug"
"~@reboot"
"~@swap"
"~@clock"
"~@cpu-emulation"
];
LockPersonality = true;
IPAddressDeny = [
"0.0.0.0/0"
"::/0"
];
MemoryDenyWriteExecute = true;
UMask = 0077;
};
}
)
];
};
}

View file

@ -0,0 +1,18 @@
{ ... }:
{
config.dendritic.features.security-systemd-journald = {
nixosModules = [
(
{ ... }:
{
systemd.services.systemd-journald.serviceConfig = {
NoNewPrivileges = true;
ProtectProc = "invisible";
ProtectHostname = true;
PrivateMounts = true;
};
}
)
];
};
}

View file

@ -0,0 +1,33 @@
{ ... }:
{
config.dendritic.features.security-systemd-machined = {
nixosModules = [
(
{ ... }:
{
systemd.services.systemd-machined.serviceConfig = {
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
ProtectClock = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectProc = "invisible";
PrivateTmp = true;
PrivateMounts = true;
PrivateUsers = true;
PrivateNetwork = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
RestrictAddressFamilies = [ "AF_UNIX" ];
MemoryDenyWriteExecute = true;
SystemCallArchitectures = "native";
};
}
)
];
};
}

View file

@ -0,0 +1,38 @@
{ ... }:
{
config.dendritic.features.security-systemd-ncsd = {
nixosModules = [
(
{ ... }:
{
systemd.services.nscd.serviceConfig = {
ProtectClock = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
ProtectProc = "invisible";
RestrictNamespaces = true;
RestrictRealtime = true;
MemoryDenyWriteExecute = true;
LockPersonality = true;
SystemCallFilter = [
"~@mount"
"~@swap"
"~@clock"
"~@obsolete"
"~@cpu-emulation"
];
SystemCallArchitectures = "native";
CapabilityBoundingSet = [
"~CAP_CHOWN"
"~CAP_FSETID"
"~CAP_SETFCAP"
];
};
}
)
];
};
}

View file

@ -0,0 +1,47 @@
{ ... }:
{
config.dendritic.features.security-systemd-networkmanager-dispatcher = {
nixosModules = [
(
{ ... }:
{
systemd.services.NetworkManager-dispatcher.serviceConfig = {
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
ProtectClock = true;
ProtectHostname = true;
ProtectProc = "invisible";
PrivateTmp = true;
PrivateMounts = true;
RestrictRealtime = true;
RestrictAddressFamilies = [
"AF_UNIX"
"AF_NETLINK"
"AF_INET"
"AF_INET6"
"AF_PACKET"
];
RestrictNamespaces = true;
RestrictSUIDSGID = true;
MemoryDenyWriteExecute = true;
SystemCallFilter = [
"~@mount"
"~@module"
"~@swap"
"~@obsolete"
"~@cpu-emulation"
"ptrace"
];
SystemCallArchitectures = "native";
LockPersonality = true;
CapabilityBoundingSet = "CAP_NET_ADMIN CAP_NET_RAW";
};
}
)
];
};
}

View file

@ -0,0 +1,44 @@
{ ... }:
{
config.dendritic.features.security-systemd-networkmanager = {
nixosModules = [
(
{ ... }:
{
systemd.services.NetworkManager.serviceConfig = {
NoNewPrivileges = true;
ProtectHome = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
ProtectClock = true;
ProtectHostname = true;
ProtectProc = "invisible";
PrivateTmp = true;
RestrictRealtime = true;
RestrictAddressFamilies = [
"AF_UNIX"
"AF_NETLINK"
"AF_INET"
"AF_INET6"
"AF_PACKET"
];
RestrictNamespaces = true;
RestrictSUIDSGID = true;
MemoryDenyWriteExecute = true;
SystemCallFilter = [
"~@mount"
"~@module"
"~@swap"
"~@obsolete"
"~@cpu-emulation"
"ptrace"
];
SystemCallArchitectures = "native";
LockPersonality = true;
};
}
)
];
};
}

View file

@ -0,0 +1,68 @@
{ ... }:
{
config.dendritic.features.security-systemd-nix-daemon = {
nixosModules = [
(
{ ... }:
{
systemd.services.nix-daemon.serviceConfig = {
NoNewPrivileges = true;
ProtectControlGroups = true;
ProtectKernelModules = true;
PrivateMounts = true;
PrivateTmp = true;
PrivateDevices = true;
RestrictSUIDSGID = true;
RestrictRealtime = true;
RestrictNamespaces = [ "~cgroup" ];
RestrictAddressFamilies = [
"AF_UNIX"
"AF_NETLINK"
"AF_INET6"
"AF_INET"
];
CapabilityBoundingSet = [
"~CAP_SYS_CHROOT"
"~CAP_BPF"
"~CAP_AUDIT_WRITE"
"~CAP_AUDIT_CONTROL"
"~CAP_AUDIT_READ"
"~CAP_SYS_PTRACE"
"~CAP_SYS_NICE"
"~CAP_SYS_RESOURCE"
"~CAP_SYS_RAWIO"
"~CAP_SYS_TIME"
"~CAP_SYS_PACCT"
"~CAP_LINUX_IMMUTABLE"
"~CAP_IPC_LOCK"
"~CAP_WAKE_ALARM"
"~CAP_SYS_TTY_CONFIG"
"~CAP_SYS_BOOT"
"~CAP_LEASE"
"~CAP_BLOCK_SUSPEND"
"~CAP_MAC_ADMIN"
"~CAP_MAC_OVERRIDE"
];
SystemCallErrorNumber = "EPERM";
SystemCallArchitectures = "native";
SystemCallFilter = [
"~@resources"
"~@module"
"~@obsolete"
"~@debug"
"~@reboot"
"~@swap"
"~@cpu-emulation"
"~@clock"
"~@raw-io"
];
LockPersonality = true;
MemoryDenyWriteExecute = true;
DevicePolicy = "closed";
UMask = 0077;
};
}
)
];
};
}

View file

@ -0,0 +1,44 @@
{ ... }:
{
config.dendritic.features.security-systemd-reload-vconsole = {
nixosModules = [
(
{ ... }:
{
systemd.services.reload-systemd-vconsole-setup.serviceConfig = {
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
ProtectClock = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectProc = "invisible";
PrivateTmp = true;
PrivateMounts = true;
PrivateNetwork = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
RestrictAddressFamilies = [
"~AF_INET6"
"~AF_INET"
"~AF_PACKET"
];
MemoryDenyWriteExecute = true;
DevicePolicy = "closed";
LockPersonality = true;
SystemCallFilter = [
"~@keyring"
"~@swap"
"~@obsolete"
"~@cpu-emulation"
];
SystemCallArchitectures = "native";
};
}
)
];
};
}

View file

@ -0,0 +1,48 @@
{ ... }:
{
config.dendritic.features.security-systemd-rescue = {
nixosModules = [
(
{ ... }:
{
systemd.services.rescue.serviceConfig = {
NoNewPrivileges = true;
ProtectSystem = "full";
ProtectClock = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
ProtectProc = "invisible";
PrivateTmp = true;
PrivateNetwork = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
RestrictAddressFamilies = [
"~AF_INET6"
"~AF_INET"
"~AF_PACKET"
];
MemoryDenyWriteExecute = true;
LockPersonality = true;
SystemCallFilter = [
"~@swap"
"~@clock"
"~@obsolete"
"~@cpu-emulation"
"~@resources"
];
SystemCallArchitectures = "native";
CapabilityBoundingSet = [
"~CAP_CHOWN"
"~CAP_FSETID"
"~CAP_SETFCAP"
];
};
}
)
];
};
}

View file

@ -0,0 +1,44 @@
{ ... }:
{
config.dendritic.features.security-systemd-rtkit = {
nixosModules = [
(
{ lib, ... }:
{
systemd.services.rtkit-daemon.serviceConfig = {
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
ProtectClock = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectControlGroups = lib.mkDefault true;
PrivateTmp = lib.mkDefault true;
PrivateMounts = true;
PrivateDevices = true;
RestrictNamespaces = true;
RestrictSUIDSGID = true;
RestrictAddressFamilies = [
"~AF_INET6"
"~AF_INET"
"~AF_PACKET"
];
MemoryDenyWriteExecute = true;
DevicePolicy = "closed";
LockPersonality = true;
SystemCallFilter = [
"~@keyring"
"~@swap"
"~@clock"
"~@module"
"~@obsolete"
"~@cpu-emulation"
];
};
}
)
];
};
}

View file

@ -0,0 +1,42 @@
{ ... }:
{
config.dendritic.features.security-systemd-sshd = {
nixosModules = [
(
{ ... }:
{
systemd.services.sshd.serviceConfig = {
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = "read-only";
ProtectClock = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
ProtectProc = "invisible";
PrivateTmp = true;
PrivateMounts = true;
PrivateDevices = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
MemoryDenyWriteExecute = true;
LockPersonality = true;
DevicePolicy = "closed";
SystemCallFilter = [
"~@keyring"
"~@swap"
"~@clock"
"~@module"
"~@obsolete"
"~@cpu-emulation"
];
SystemCallArchitectures = "native";
};
}
)
];
};
}

View file

@ -0,0 +1,23 @@
{ ... }:
{
config.dendritic.features.security-systemd-udevd = {
nixosModules = [
(
{ ... }:
{
systemd.services.systemd-udevd.serviceConfig = {
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
ProtectClock = true;
ProtectProc = "invisible";
RestrictNamespaces = true;
CapabilityBoundingSet = "~CAP_SYS_PTRACE ~CAP_SYS_PACCT";
};
}
)
];
};
}

View file

@ -0,0 +1,41 @@
{ ... }:
{
config.dendritic.features.security-systemd-user = {
nixosModules = [
(
{ ... }:
{
systemd.services."user@".serviceConfig = {
ProtectSystem = "strict";
ProtectClock = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectProc = "invisible";
PrivateTmp = true;
PrivateNetwork = true;
MemoryDenyWriteExecute = true;
RestrictAddressFamilies = [
"AF_UNIX"
"AF_NETLINK"
"AF_BLUETOOTH"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallFilter = [
"~@keyring"
"~@swap"
"~@debug"
"~@module"
"~@obsolete"
"~@cpu-emulation"
];
SystemCallArchitectures = "native";
};
}
)
];
};
}

View file

@ -0,0 +1,58 @@
{ ... }:
{
config.dendritic.features.security-systemd = {
features = [
"security-systemd-ask-password-console"
"security-systemd-ask-password-wall"
"security-systemd-auditd"
# "security-systemd-dbus" using dbus-broker
"security-systemd-display-manager"
# "security-systemd-getty"
"security-systemd-journald"
"security-systemd-machined"
"security-systemd-ncsd"
"security-systemd-networkmanager"
"security-systemd-networkmanager-dispatcher"
"security-systemd-nix-daemon"
"security-systemd-reload-vconsole"
"security-systemd-rescue"
"security-systemd-rtkit"
"security-systemd-sshd"
"security-systemd-udevd"
#"security-systemd-user"
];
nixosModules = [
(
{ lib, ... }:
{
services = {
# mDNS/DNS-SD
avahi.enable = false;
# Geoclue (location services)
geoclue2.enable = false;
# udisks2.enable = false;
# accounts-daemon.enable = lib.mkDefault false;
};
# Only needed for WWAN/3G/4G modems, otherwise it runs `mmcli` unnecessarily
networking.modemmanager.enable = false;
# Bluetooth has a long history of vulnerabilities
hardware.bluetooth.enable = false;
# Prefer manual upgrades on a hardened system
system.autoUpgrade.enable = false;
systemd.coredump.enable = false;
# ➡️ Sets the kernel's resource limit (ulimit -c 0)
security.pam.loginLimits = [
{
domain = "*"; # Applies to all users/sessions
type = "-"; # Set both soft and hard limits
item = "core"; # The soft/hard limit item
value = "0"; # Core dumps size is limited to 0 (effectively disabled)
}
];
}
)
];
};
}

View file

@ -0,0 +1,68 @@
{ ... }:
{
config.dendritic.features.security-systemd-display-manager = {
nixosModules = [
(
{ lib, ... }:
{
systemd.services.display-manager.serviceConfig = {
ProtectSystem = "full";
ProtectControlGroups = true;
ProtectClock = true;
ProtectKernelModules = true;
PrivateMounts = true;
PrivateIPC = true;
RestrictSUIDSGID = true;
RestrictRealtime = true;
RestrictNamespaces = [
"~cgroup"
];
RestrictAddressFamilies = [
"AF_UNIX"
"AF_NETLINK"
"AF_INET"
"AF_INET6"
];
SystemCallErrorNumber = "EPERM";
SystemCallFilter = [
"~@obsolete"
"~@cpu-emulation"
"~@clock"
"~@swap"
"~@module"
"~@reboot"
"~@raw-io"
"~@debug"
];
SystemCallArchitectures = "native";
LockPersonality = true;
IPAddressDeny = [
"0.0.0.0/0"
"::/0"
];
CapabilityBoundingSet = [
"CAP_SYS_ADMIN"
"CAP_SETUID"
"CAP_SETGID"
"CAP_SETPCAP"
"CAP_KILL"
"CAP_SYS_TTY_CONFIG"
"CAP_DAC_OVERRIDE"
"CAP_DAC_READ_SEARCH"
"CAP_FOWNER"
"CAP_IPC_OWNER"
"CAP_FSETID"
"CAP_SETFCAP"
"CAP_CHOWN"
];
DeviceAllow = "/dev/tty7 rw";
DevicePolicy = "closed";
UMask = 0077;
LogLevelMax = "debug";
KeyringMode = lib.mkForce "private";
};
}
)
];
};
}

View file

@ -0,0 +1,41 @@
{ ... }:
{
config.dendritic.features.shell = {
features = [
"filemanager-yazi"
"cli-zoxide"
"git-lazygit"
"cli-zsh"
];
homeModules = [
(
{ pkgs, ... }:
{
programs.home-manager.enable = true;
programs.zsh.enable = true;
home.packages = with pkgs; [ ripgrep ];
}
)
../home/programs/starship.nix
../home/programs/eza.nix
../home/programs/bat.nix
../home/programs/carapace.nix
../home/programs/fzf.nix
../home/programs/btop.nix
../home/programs/atuin.nix
../home/programs/broot.nix
];
nixosModules = [
(
{ config, pkgs, ... }:
{
programs.zsh.enable = true;
users.users.${config.dendritic.current.primaryUser}.shell = pkgs.zsh;
}
)
];
};
}

View file

@ -0,0 +1,16 @@
{ ... }:
{
config.dendritic.features.networkmanager = {
nixosModules = [
(
{ ... }:
{
networking.networkmanager = {
enable = true;
wifi.scanRandMacAddress = true;
};
}
)
];
};
}

View file

@ -0,0 +1,45 @@
{ ... }:
{
config.dendritic.features.ntp-chrony = {
nixosModules = [
(
{ ... }:
{
services.chrony = {
enable = true;
enableNTS = true;
servers = [
"time.cloudflare.com iburst nts"
"ntppool1.time.nl iburst nts"
"nts.netnod.se iburst nts"
"ptbtime1.ptb.de iburst nts"
"time.dfm.dk iburst nts"
"time.cifelli.xyz iburst nts"
];
# havent worked out the kinks yet
# extraConfig = ''
# minsources 3
# authselectmode require
# # EF
# dscp 46
# driftfile /var/lib/chrony/drift
# dumpdir /var/lib/chrony
# ntsdumpdir /var/lib/chrony
# leapseclist /usr/share/zoneinfo/leap-seconds.list
# makestep 1.0 3
# rtconutc
# cmdport 0
# noclientlog
# '';
};
}
)
];
};
}

View file

@ -0,0 +1,36 @@
{ ... }:
{
config.dendritic.features.system-nix = {
nixosModules = [
(
{ config, ... }:
let
user = config.dendritic.current.primaryUser;
in
{
nixpkgs.config.allowUnfree = true;
nix.settings = {
experimental-features = [
"nix-command"
"flakes"
];
auto-optimise-store = true;
download-buffer-size = 262144000;
trusted-users = [ user ];
warn-dirty = false;
accept-flake-config = true;
};
services.fstrim.enable = true;
time.timeZone = "America/Toronto";
}
)
];
};
}

View file

@ -0,0 +1,41 @@
{ ... }:
{
config.dendritic.features.system-services = {
nixosModules = [
(
{ ... }:
{
users.groups.netdev = { };
services = {
dbus.implementation = "broker";
logrotate = {
enable = true;
settings = {
header = {
dateext = true;
};
"var/log/audit/audit.log" = {
frequency = "daily";
rotate = 3;
size = "100k";
};
};
};
journald = {
storage = "volatile"; # Store logs in memory
upload.enable = false; # Disable remote log upload (the default)
extraConfig = ''
SystemMaxUse=500M
SystemMaxFileSize=50M
'';
};
};
}
)
];
};
}

View file

@ -0,0 +1,63 @@
{ ... }:
{
config.dendritic.features.virtualization-libvirt = {
nixosModules = [
(
{ config, pkgs, ... }:
let
user = config.dendritic.current.primaryUser;
in
{
networking.firewall.trustedInterfaces = [ "virbr0" ];
boot.kernelModules = [ "kvm-amd" ];
environment.systemPackages = with pkgs; [
virt-manager
virtiofsd
vagrant
];
users.users.${user} = {
extraGroups = [
"libvirtd"
"qemu-libvirtd"
"kvm"
];
};
# Allow VM to run as non-root without ulimit
security.pam.loginLimits = [
{
domain = "${user}";
type = "soft";
item = "memlock";
value = "20000000";
}
{
domain = "${user}";
type = "hard";
item = "memlock";
value = "20000000";
}
];
virtualisation.libvirtd = {
enable = true;
# qemu.ovmf.enable = true;
# qemu.runAsRoot = false;
onBoot = "ignore";
onShutdown = "shutdown";
qemu = {
package = pkgs.qemu_kvm;
runAsRoot = true;
swtpm.enable = true;
};
};
users.extraGroups.libvirtd.members = [ "${user}" ];
}
)
];
};
}

9
modules/home/devenv.nix Normal file
View file

@ -0,0 +1,9 @@
{pkgs, ...}: {
home.packages = with pkgs; [
cachix
devenv
];
programs.direnv.enable = true;
programs.direnv.nix-direnv.enable = true;
}

View file

@ -0,0 +1,9 @@
# ✨ Magical shell history
{...}: {
programs.atuin = {
enable = true;
flags = [
"--disable-up-arrow"
];
};
}

View file

@ -0,0 +1,6 @@
# A cat clone with syntax highlighting and Git integration.
{...}: {
programs.bat = {
enable = true;
};
}

View file

@ -0,0 +1,123 @@
{ pkgs, ... }:
{
programs.brave = {
enable = true;
commandLineArgs = [
# Wayland Native
"--enable-features=UseOzonePlatform"
"--ozone-platform=wayland"
# Hardware Acceleration (NVIDIA optimized)
"--enable-accelerated-video-decode"
"--enable-gpu-rasterization"
"--enable-zero-copy"
"--ignore-gpu-blocklist"
# Performance
"--enable-features=VaapiVideoDecoder"
"--enable-features=VaapiVideoEncoder"
"--enable-features=CanvasOopRasterization"
"--disable-features=UseChromeOSDirectVideoDecoder"
# Privacy & Security
"--disable-features=MediaRouter" # Disable Chromecast
"--disable-features=OptimizationHints" # No Google suggestions
"--disable-features=AutofillSavePaymentMethods"
"--disable-background-networking" # No telemetry
"--disable-sync" # Manual sync control
# Wayland-specific fixes
"--disable-features=WaylandWpColorManagerV1" # Color management fix
# UI/UX
"--force-dark-mode" # Match Stylix theme
"--enable-features=WebUIDarkMode"
"--no-default-browser-check"
];
extensions = [
# let
# ids = [
"cjpalhdlnbpafiamejdnhcphjbkeiagm" # ublock origin
"dbepggeogbaibhgnhhndojpepiihcmeb" # vimium
"eimadpbcbfnmbkopoojfekhnkhdbieeh" # dark reader
"pkehgijcmpdhfbdbbnkijodmdjhbjlgp" # privacy badger
"ghmbeldphafepmbegfdlkpapadhbakde" # proton pass
"mmjbdbjnoablegbkcklggeknkfcjkjia" # custom new tab page
];
# in
# map (id: { inherit id; }) ids;
};
xdg.configFile."BraveSoftware/Brave-Browser/Policies/managed/policy.json".text = builtins.toJSON {
BraveShieldsAdControl = 2;
BraveShieldsTrackersBlocked = 1;
BraveShieldsHttpsEverywhere = 1;
BraveRewardsDisabled = 1;
BraveWalletDisabled = 1;
BraveVPNDisabled = 1;
BraveAIChatEnabled = 0;
PasswordManagerEnabled = 0;
BravePlaylistEnabled = 0;
BraveWebDiscoveryEnabled = 0;
BraveStatsPingEnabled = 0;
DnsOverHttpsMode = "automatic";
BraveDarkMode = 1;
};
home.sessionVariables = {
DEFAULT_BROWSER = "${pkgs.brave}/bin/brave";
BROWSER = "${pkgs.brave}/bin/brave";
};
xdg.desktopEntries = {
brave-incognito = {
name = "Brave (Private window)";
genericName = "Navigateur Web";
exec = "brave --incognito";
icon = "brave-browser";
terminal = false;
categories = [
"Network"
"WebBrowser"
];
mimeType = [
"text/html"
"text/xml"
];
};
brave-tor = {
name = "Brave (Private window w/Tor)";
genericName = "Navigateur Web";
exec = "brave --tor";
icon = "brave-browser";
terminal = false;
categories = [
"Network"
"WebBrowser"
];
};
};
# =================================================================
# BRAVE SETTINGS (via brave://flags)
# =================================================================
# These need to be set manually in brave://flags on first launch:
# - Enable Tab Groups (UI)
# - Enable Parallel Downloading
# - Enable Reader Mode
# - GPU Rasterization: Enabled
# - Override software rendering list: Enabled
#
# Privacy settings (brave://settings/privacy):
# - Block trackers & ads: Aggressive
# - Block all fingerprinting
# - Upgrade connections to HTTPS
# - Block scripts: Off (breaks sites, use uBlock instead)
# - Block cookies: Only 3rd party
#
# Appearance (brave://settings/appearance):
# - Show home button: Off
# - Show bookmarks bar: Only on new tab
# - Use wide address bar: On
}

View file

@ -0,0 +1,7 @@
# An interactive treeview directory navigator
{...}: {
programs.broot = {
enable = true;
enableZshIntegration = true;
};
}

View file

@ -0,0 +1,5 @@
{...}: {
programs.btop = {
enable = true;
};
}

View file

@ -0,0 +1,6 @@
{ ... }:
{
programs.carapace = {
enable = true;
};
}

View file

@ -0,0 +1,15 @@
# A modern replacement for 'ls'.
{...}: {
programs.eza = {
enable = true;
enableZshIntegration = true;
git = true;
icons = "auto";
extraOptions = [
"--group-directories-first"
"--no-quotes"
"--git-ignore"
"--icons=always"
];
};
}

View file

@ -0,0 +1,33 @@
# Fzf is a general-purpose command-line fuzzy finder.
{
config,
lib,
...
}: let
accent = "#" + config.lib.stylix.colors.base0D;
foreground = "#" + config.lib.stylix.colors.base05;
muted = "#" + config.lib.stylix.colors.base03;
in {
programs.fzf = {
enable = true;
enableZshIntegration = true;
colors = lib.mkForce {
"fg+" = accent;
"bg+" = "-1";
"fg" = foreground;
"bg" = "-1";
"prompt" = muted;
"pointer" = accent;
};
defaultOptions = [
"--margin=1"
"--layout=reverse"
"--border=none"
"--info='hidden'"
"--header=''"
"--prompt='/ '"
"-i"
"--no-bold"
];
};
}

View file

@ -0,0 +1,31 @@
{
pkgs,
lib,
...
}: {
programs.ghostty = {
enable = true;
enableZshIntegration = true;
installVimSyntax = true;
settings = {
window-padding-x = 10;
window-padding-y = 10;
auto-update = "off";
working-directory = "home";
window-inherit-working-directory = false; # avoid inheritance
keybinds = [];
# background-opacity = 0.8;
background-opacity = 1;
confirm-close-surface = false;
font-family = lib.mkForce "Comic Code Ligatures";
# font-family = lib.mkForce "Terminus";
font-size = 14;
gtk-titlebar = false;
# theme = "Teerb";
};
};
home.packages = with pkgs; [
ueberzugpp
terminus_font_ttf
];
}

View file

@ -0,0 +1,6 @@
# A terminal-based Kubernetes CLI.
{...}: {
programs.k9s = {
enable = true;
};
}

View file

@ -0,0 +1,256 @@
{
programs.nvf.settings.vim = {
globals.mapleader = " ";
binds = {
whichKey = {
enable = true;
# TODO: registers
register = { };
};
};
keymaps = [
# General Mappings
{
key = "s";
mode = "n";
silent = true;
action = "<cmd>lua require('flash').jump()<cr>";
desc = "Flash";
}
{
key = "K";
mode = "n";
silent = true;
action = "<cmd>lua vim.lsp.buf.hover()<cr>";
desc = "LSP Hover";
}
{
key = "<C-tab>";
mode = "n";
silent = true;
action = "<cmd>bnext<cr>";
desc = "Next Buffer";
}
{
key = "<leader>bd";
mode = "n";
silent = true;
action = "<cmd>bd<cr>";
desc = "Close current buffer";
}
# Disable Arrow Keys in Normal Mode
# {
# key = "<Up>";
# mode = "n";
# silent = true;
# action = "k";
# desc = "Disable Up Arrow";
# }
# {
# key = "<Down>";
# mode = "n";
# silent = true;
# action = "j";
# desc = "Disable Down Arrow";
# }
# {
# key = "<Left>";
# mode = "n";
# silent = true;
# action = "h";
# desc = "Disable Left Arrow";
# }
# {
# key = "<Right>";
# mode = "n";
# silent = true;
# action = "l";
# desc = "Disable Right Arrow";
# }
# UI
{
key = "<leader>uw";
mode = "n";
silent = true;
action = "<cmd>set wrap!<cr>";
desc = "Toggle word wrapping";
}
{
key = "<leader>ul";
mode = "n";
silent = true;
action = "<cmd>set linebreak!<cr>";
desc = "Toggle linebreak";
}
{
key = "<leader>us";
mode = "n";
silent = true;
action = "<cmd>set spell!<cr>";
desc = "Toggle spellLazyGitcheck";
}
{
key = "<leader>uc";
mode = "n";
silent = true;
action = "<cmd>set cursorline!<cr>";
desc = "Toggle cursorline";
}
{
key = "<leader>un";
mode = "n";
silent = true;
action = "<cmd>set number!<cr>";
desc = "Toggle line numbers";
}
{
key = "<leader>ur";
mode = "n";
silent = true;
action = "<cmd>set relativenumber!<cr>";
desc = "Toggle relative line numbers";
}
{
key = "<leader>ut";
mode = "n";
silent = true;
action = "<cmd>set showtabline=2<cr>";
desc = "Show tabline";
}
{
key = "<leader>uT";
mode = "n";
silent = true;
action = "<cmd>set showtabline=0<cr>";
desc = "Hide tabline";
}
# Windows
{
key = "<leader>ws";
mode = "n";
silent = true;
action = "<cmd>split<cr>";
desc = "Split";
}
{
key = "<leader>wv";
mode = "n";
silent = true;
action = "<cmd>vsplit<cr>";
desc = "VSplit";
}
{
key = "<leader>wd";
mode = "n";
silent = true;
action = "<cmd>close<cr>";
desc = "Close";
}
{
key = "<leader>ma";
mode = "n";
silent = true;
action = "<cmd>close<cr>";
desc = "Close";
}
{
key = "<C-Left>";
mode = "n";
silent = true;
action = "<cmd>lua require('smart-splits').move_cursor_left()<cr>";
desc = "Move to left split";
}
{
key = "<C-Down>";
mode = "n";
silent = true;
action = "<cmd>lua require('smart-splits').move_cursor_down()<cr>";
desc = "Move to lower split";
}
{
key = "<C-Up>";
mode = "n";
silent = true;
action = "<cmd>lua require('smart-splits').move_cursor_up()<cr>";
desc = "Move to upper split";
}
{
key = "<C-Right>";
mode = "n";
silent = true;
action = "<cmd>lua require('smart-splits').move_cursor_right()<cr>";
desc = "Move to right split";
}
{
key = "<M-Left>";
mode = "n";
silent = true;
action = "<cmd>lua require('smart-splits').resize_left()<cr>";
desc = "Resize left";
}
{
key = "<M-Down>";
mode = "n";
silent = true;
action = "<cmd>lua require('smart-splits').resize_down()<cr>";
desc = "Resize down";
}
{
key = "<M-Up>";
mode = "n";
silent = true;
action = "<cmd>lua require('smart-splits').resize_up()<cr>";
desc = "Resize up";
}
{
key = "<M-Right>";
mode = "n";
silent = true;
action = "<cmd>lua require('smart-splits').resize_right()<cr>";
desc = "Resize right";
}
{
key = "<leader>w=";
mode = "n";
silent = true;
action = "<C-w>=";
desc = "Equalize Splits";
}
{
key = "<leader>we";
mode = "n";
silent = true;
action = "<cmd>lua require('smart-splits').swap_buf_right()<cr>";
desc = "Swap Buffer Right";
}
{
key = "<leader>wh";
mode = "n";
silent = true;
action = "<cmd>lua require('smart-splits').swap_buf_left()<cr>";
desc = "Swap Buffer Left";
}
{
key = "<C-o>";
mode = "n";
silent = true;
action = "<C-o>zz";
desc = "Jump back and center";
}
{
key = "<C-i>";
mode = "n";
silent = true;
action = "<C-i>zz";
desc = "Jump forward and center";
}
];
};
}

View file

@ -0,0 +1,132 @@
{
lib,
pkgs,
...
}:
{
programs.nvf.settings.vim = {
diagnostics = {
enable = true;
config = {
signs = {
text = {
"vim.diagnostic.severity.Error" = " ";
"vim.diagnostic.severity.Warn" = " ";
"vim.diagnostic.severity.Hint" = " ";
"vim.diagnostic.severity.Info" = " ";
};
};
underline = true;
update_in_insert = true;
virtual_text = {
format =
lib.generators.mkLuaInline
# lua
''
function(diagnostic)
return string.format("%s", diagnostic.message)
--return string.format("%s (%s)", diagnostic.message, diagnostic.source)
end
'';
};
};
nvim-lint = {
enable = true;
};
};
syntaxHighlighting = true;
treesitter = {
enable = true;
autotagHtml = true;
context.enable = true;
highlight = {
enable = true;
};
};
lsp = {
enable = true;
trouble.enable = true;
lspSignature.enable = true;
lspconfig.enable = true;
formatOnSave = true;
inlayHints.enable = true;
null-ls.enable = true;
servers.nixd.settings.nil.nix.autoArchive = true;
otter-nvim = {
enable = true;
setupOpts = {
buffers.set_filetype = true;
lsp = {
diagnostic_update_event = [
"BufWritePost"
"InsertLeave"
];
};
};
};
lspkind.enable = true;
lspsaga = {
enable = true;
setupOpts = {
ui = {
code_action = "";
};
lightbulb = {
sign = false;
virtual_text = true;
};
breadcrumbs.enable = false;
};
};
};
languages = {
enableDAP = true;
enableExtraDiagnostics = true;
enableFormat = true;
enableTreesitter = true;
astro.enable = true;
python.enable = true;
java.enable = true;
clang.enable = true;
go.enable = true;
markdown = {
enable = true;
format.type = [ "prettierd" ];
extensions = {
markview-nvim = {
enable = true;
};
};
extraDiagnostics.enable = true;
};
ts.enable = true;
ts.extensions.ts-error-translator.enable = true;
css.enable = true;
svelte.enable = true;
ocaml.enable = true;
haskell.enable = true;
haskell.lsp.enable = true;
haskell.treesitter.enable = true;
haskell.dap.enable = false;
html.enable = true;
bash.enable = true;
nix.enable = true;
nix.format.type = [ "nixfmt" ];
tailwind.enable = true;
typst = {
enable = true;
lsp.enable = true;
lsp.servers = [ "tinymist" ];
format.enable = true;
treesitter.enable = true;
};
rust.enable = true;
};
formatter = {
conform-nvim = {
enable = true;
};
};
};
}

View file

@ -0,0 +1,14 @@
{
programs.nvf.settings.vim.mini = {
starter.enable = true;
comment.enable = true;
# cursorword.enable = true;
icons.enable = true;
indentscope.enable = true;
notify.enable = true;
pairs.enable = true;
diff.enable = true;
git.enable = true;
# snippets.enable = true;
};
}

View file

@ -0,0 +1,23 @@
{
programs.nvf.settings.vim = {
viAlias = false;
vimAlias = true;
withNodeJs = true;
# syntaxHighlighting = true;
options = {
autoindent = true;
shiftwidth = 2;
signcolumn = "yes";
tabstop = 2;
softtabstop = 2;
wrap = false;
undofile = true;
shada = "!,'100,<50,s10,h";
};
clipboard = {
enable = true;
registers = "unnamedplus";
providers.wl-copy.enable = true;
};
};
}

View file

@ -0,0 +1,256 @@
{
programs.nvf.settings.vim = {
utility = {
oil-nvim.enable = true;
snacks-nvim = {
setupOpts = {
picker.enabled = true;
explorer.enabled = true;
};
};
};
keymaps = [
# Top Pickers & Explorer
{
key = "<leader> ";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.smart()<cr>";
desc = "Smart Find Files";
}
{
key = "<leader>,";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.buffers()<cr>";
desc = "Buffers";
}
{
key = "<leader>/";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.grep()<cr>";
desc = "Grep";
}
{
key = "<leader>:";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.command_history()<cr>";
desc = "Command History";
}
{
key = "<leader>e";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.explorer()<cr>";
desc = "File Explorer";
}
{
key = "-";
mode = "n";
silent = true;
action = "<cmd>Oil<cr>";
desc = "Oil";
}
# Find
{
key = "<leader>fb";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.buffers()<cr>";
desc = "Buffers";
}
{
key = "<leader>fc";
mode = "n";
silent = true;
action = ''<cmd>lua Snacks.picker.files({ cwd = vim.fn.stdpath("config") })<cr>'';
desc = "Find Config File";
}
{
key = "<leader>ff";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.files()<cr>";
desc = "Find Files";
}
{
key = "<leader>fg";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.git_files()<cr>";
desc = "Find Git Files";
}
{
key = "<leader>fp";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.projects()<cr>";
desc = "Projects";
}
{
key = "<leader>fr";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.recent()<cr>";
desc = "Recent";
}
{
key = "<leader>fn";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.notifications()<cr>";
desc = "Notification History";
}
{
key = "<leader>fe";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.icons()<cr>";
desc = "Emoji";
}
# Git
{
key = "<leader>gb";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.git_branches()<cr>";
desc = "Git Branches";
}
{
key = "<leader>gL";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.git_log()<cr>";
desc = "Git Log Line";
}
{
key = "<leader>gs";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.git_status()<cr>";
desc = "Git Status";
}
{
key = "<leader>gS";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.git_stash()<cr>";
desc = "Git Stash";
}
{
key = "<leader>gd";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.git_diff()<cr>";
desc = "Git Diff (Hunks)";
}
{
key = "<leader>gf";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.git_log_file()<cr>";
desc = "Git Log File";
}
# Grep
{
key = "<leader>sb";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.lines()<cr>";
desc = "Buffer Lines";
}
{
key = "<leader>st";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.todo_comments()<cr>";
desc = "Todos";
}
{
key = "<leader>sB";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.grep_buffers()<cr>";
desc = "Grep Open Buffers";
}
{
key = "<leader>sg";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.grep()<cr>";
desc = "Grep";
}
{
key = "<leader>sw";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.grep_word()<cr>";
desc = "Visual selection or word";
}
{
key = "<leader>sr";
mode = "n";
silent = true;
action = "<cmd>nohlsearch<cr>";
desc = "Reset search";
}
# LSP
{
key = "gd";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.lsp_definitions()<cr>";
desc = "Goto Definition";
}
{
key = "gD";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.lsp_declarations()<cr>";
desc = "Goto Declaration";
}
{
key = "gr";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.lsp_references()<cr>";
desc = "References";
nowait = true;
}
{
key = "gI";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.lsp_implementations()<cr>";
desc = "Goto Implementation";
}
{
key = "gy";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.lsp_type_definitions()<cr>";
desc = "Goto Type Definition";
}
{
key = "<leader>ss";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.lsp_symbols()<cr>";
desc = "LSP Symbols";
}
{
key = "<leader>sS";
mode = "n";
silent = true;
action = "<cmd>lua Snacks.picker.lsp_workspace_symbols()<cr>";
desc = "LSP Workspace Symbols";
}
];
};
}

View file

@ -0,0 +1,19 @@
{
programs.nvf.settings.vim.utility.snacks-nvim = {
enable = true;
setupOpts = {
image = {
enabled = true;
doc = {
inline = false;
float = true;
};
};
quickfile.enabled = true;
statuscolumn.enabled = true;
zen.enabled = true;
bufdelete.enabled = true;
gitsigns.enabled = true;
};
};
}

View file

@ -0,0 +1,149 @@
{
lib,
pkgs,
...
}:
{
programs.nvf.settings.vim = {
undoFile.enable = true;
# theme = lib.mkForce {
# enable = true;
# name = "catppuccin";
# style = "latte";
# transparent = false;
# };
navigation = {
harpoon.enable = true;
};
utility = {
motion.flash-nvim.enable = true;
outline.aerial-nvim.enable = true;
diffview-nvim.enable = true;
surround.enable = true;
smart-splits.enable = true;
yanky-nvim.enable = true;
};
tabline.nvimBufferline.enable = true;
notes.todo-comments.enable = true;
# assistant.copilot = {
# enable = true;
# cmp.enable = true;
# };
statusline.lualine.enable = true;
autocomplete = {
nvim-cmp = {
enable = true;
sources = {
buffer = "[Buffer]";
nvim-cmp = null;
path = "[Path]";
};
sourcePlugins = [
pkgs.vimPlugins.cmp-cmdline
];
};
};
snippets.luasnip.enable = true;
snippets.luasnip.customSnippets.snipmate = {
all = [
{
trigger = "if";
body = "if $1 else $2";
}
];
nix = [
{
trigger = "mkOption";
body = ''
mkOption {
type = $1;
default = $2;
description = $3;
example = $4;
}
'';
}
];
haskell = [
{
trigger = "zzis";
body = ''
insert :: (Ord a) => a -> [a] -> [a]
insert x [] = [x]
insert x (y:ys)
| x <= y = x : y : ys
| otherwise = y : insert x ys
insertionSort :: (Ord a) => [a] -> [a]
insertionSort [] = []
insertionSort (x:xs) = insert x (insertionSort xs)
'';
}
{
trigger = "zzso";
body = ''
sortOn :: Ord b => (a -> b) -> [a] -> [a]
sortOn f = foldr insert []
where
insert x [] = [x]
insert x (y:ys)
| f x <= f y = x : y : ys
| otherwise = y : insert x ys
'';
}
];
};
ui = {
noice.enable = true;
colorizer.enable = true;
};
visuals = {
rainbow-delimiters.enable = true;
nvim-scrollbar = {
enable = false;
};
};
git = {
enable = true;
gitsigns.enable = true;
};
terminal.toggleterm = {
enable = true;
lazygit = {
enable = true;
mappings.open = "<leader>gl";
};
};
formatter.conform-nvim.enable = true;
binds.hardtime-nvim.enable = true;
utility.motion.precognition.enable = true;
binds.hardtime-nvim.setupOpts = {
max_count = 3; # Optional: limit of consecutive presses
disabled_keys = {
"<Up>" = false;
"<Down>" = false;
"<Left>" = false;
"<Right>" = false;
};
restricted_keys = {
"<Up>" = [
"n"
"x"
];
"<Down>" = [
"n"
"x"
];
"<Left>" = [
"n"
"x"
];
"<Right>" = [
"n"
"x"
];
};
};
};
}

View file

@ -0,0 +1,10 @@
{pkgs}: {
browser = "${pkgs.firefox}/bin/firefox";
terminal = "${pkgs.ghostty}/bin/ghostty";
fileManager = "${pkgs.thunar}/bin/thunar";
appLauncher = "${pkgs.walker}/bin/walker";
screenshotArea = "${pkgs.bash}/bin/bash -c '${pkgs.grim}/bin/grim -g \"\\\$(${pkgs.slurp}/bin/slurp)\" - | ${pkgs.wl-clipboard}/bin/wl-copy'";
screenshotWindow = "${pkgs.bash}/bin/bash -c '${pkgs.grim}/bin/grim -g \"\\\$(${pkgs.slurp}/bin/slurp -w)\" - | ${pkgs.wl-clipboard}/bin/wl-copy'";
screenshotOutput = "${pkgs.bash}/bin/bash -c '${pkgs.grim}/bin/grim - | ${pkgs.wl-clipboard}/bin/wl-copy'";
}

View file

@ -0,0 +1,26 @@
{
lib,
pkgs,
...
}:
{
home.packages = with pkgs; [
xwayland-satellite
xdg-desktop-portal-gtk
];
programs.niri.settings.spawn-at-startup = [
{
command = [
"systemctl"
"--user"
"start"
"hyprpolkitagent"
];
}
{ command = [ "xwayland-satellite" ]; }
{ command = [ "qs" ]; }
{ command = [ "swww-daemon" ]; }
#{ command = ["${pkgs.swaybg}/bin/swaybg" "-o" "DP-1" "-i" "/home/lysec/nixos/assets/wallpapers/clouds.png" "-m" "fill"]; }
#{ command = ["sh" "-c" "swww-daemon & swww img /home/lysec/nixos/wallpapers/cloud.png"]; }
];
}

View file

@ -0,0 +1,106 @@
{
lib,
config,
pkgs,
...
}:
let
apps = import ./applications.nix { inherit pkgs; };
in
{
programs.niri.settings.binds =
with config.lib.niri.actions;
let
pactl = "${pkgs.pulseaudio}/bin/pactl";
volume-up = spawn pactl [
"set-sink-volume"
"@DEFAULT_SINK@"
"+5%"
];
volume-down = spawn pactl [
"set-sink-volume"
"@DEFAULT_SINK@"
"-5%"
];
in
{
# Quickshell Keybinds Start
"super+space".action = spawn [
"noctalia-shell"
"ipc"
"call"
"launcher"
"toggle"
];
"super+shift+Slash".action = show-hotkey-overlay;
"super+l".action = spawn [
"noctalia-shell"
"ipc"
"call"
"lockScreen"
"lock"
];
"xf86audioraisevolume".action = volume-up;
"xf86audiolowervolume".action = volume-down;
"XF86MonBrightnessDown".action = spawn [
"noctalia-shell"
"ipc"
"call"
"brightness"
"decrease"
];
"XF86MonBrightnessUp".action = spawn [
"noctalia-shell"
"ipc"
"call"
"brightness"
"increase"
];
"super+q".action = close-window;
# "super+b".action = spawn apps.browser;
"super+Return".action = spawn apps.terminal;
#"super+Control+Return".action = spawn apps.appLauncher;
"super+E".action = spawn apps.fileManager;
"super+o".action = toggle-overview;
"super+f".action = maximize-column;
"super+Shift+f".action = fullscreen-window;
"super+t".action = toggle-window-floating;
"super+r".action = switch-preset-column-width;
"super+Shift+r".action = switch-preset-window-height;
"super+b".action =
spawn-sh "${pkgs.grim}/bin/grim \"$HOME/Pictures/screenshots/desktop-$(${pkgs.busybox}/bin/date +%Y%m%d%H%M).png\"";
"super+Shift+b".action =
spawn-sh "${pkgs.grim}/bin/grim -g \"$(${pkgs.slurp}/bin/slurp -d)\" - | ${pkgs.wl-clipboard}/bin/wl-copy"; # Screenshot selection directly to clipboard
"super+Left".action = focus-column-left;
"super+Right".action = focus-column-right;
"super+Down".action = focus-workspace-down;
"super+Up".action = focus-workspace-up;
"super+Shift+Left".action = move-column-left;
"super+Shift+Right".action = move-column-right;
"super+Shift+Down".action = move-column-to-workspace-down;
"super+Shift+Up".action = move-column-to-workspace-up;
"super+Control+Left".action = focus-monitor-left;
"super+Control+Right".action = focus-monitor-right;
"super+Control+Down".action = focus-monitor-down;
"super+Control+Up".action = focus-monitor-up;
"super+BracketLeft".action = consume-or-expel-window-left;
"super+BracketRight".action = consume-or-expel-window-right;
"super+Comma".action = consume-window-into-column;
"super+Period".action = expel-window-from-column;
"super+Home".action = focus-column-first;
"super+End".action = focus-column-last;
};
}

View file

@ -0,0 +1,78 @@
{
pkgs,
inputs,
...
}:
{
imports = [
inputs.noctalia.homeModules.default
];
# configure options
programs.noctalia-shell = {
enable = true;
settings = {
# configure noctalia here
nightLight = {
enabled = true;
};
dock = {
enabled = false;
};
bar = {
density = "default";
position = "top";
floating = true;
showCapsule = false;
widgets = {
left = [
{
id = "ControlCenter";
useDistroLogo = true;
}
{
id = "Network";
}
{
id = "Bluetooth";
}
];
center = [
{
hideUnoccupied = false;
id = "Workspace";
labelMode = "none";
}
];
right = [
{
id = "Tray";
}
{
alwaysShowPercentage = false;
id = "Battery";
warningThreshold = 30;
}
{
formatHorizontal = "HH:mm";
formatVertical = "HH mm";
id = "Clock";
useMonospacedFont = true;
usePrimaryColor = true;
}
];
};
};
colorSchemes.predefinedScheme = "Monochrome";
general = {
avatarImage = "/home/gwg313/.face";
radiusRatio = 0.2;
};
location = {
monthBeforeDay = true;
name = "Ottawa, Canada";
};
};
# this may also be a string or a path to a JSON file.
};
}

View file

@ -0,0 +1,48 @@
{
config,
pkgs,
...
}:
{
programs.niri.settings = {
layer-rules = [
{
matches = [
{
namespace = "^quickshell-wallpaper$";
}
];
#place-within-backdrop = true;
}
{
matches = [
{
namespace = "^quickshell-overview$";
}
];
place-within-backdrop = true;
}
{
matches = [
{
namespace = "^swww-daemon$";
}
];
place-within-backdrop = true;
}
];
window-rules = [
{
matches = [ { } ];
geometry-corner-radius = {
top-left = 20.0;
top-right = 20.0;
bottom-left = 20.0;
bottom-right = 20.0;
};
clip-to-geometry = true;
}
];
};
}

View file

@ -0,0 +1,31 @@
{ pkgs, ... }:
let
brightnessScript = pkgs.writeShellScriptBin "brightness" ''
BUS=10
STEP=5
MIN=0
MAX=100
OSD_FILE="/tmp/brightness_osd_level"
current=$(ddcutil --bus=$BUS getvcp 10 | grep -oP "current value\\s*=\\s*\\K[0-9]+")
new=$current
if [[ "$1" == "up" ]]; then
new=$((current + STEP))
(( new > MAX )) && new=$MAX
elif [[ "$1" == "down" ]]; then
new=$((current - STEP))
(( new < MIN )) && new=$MIN
else
exit 1
fi
ddcutil --bus=$BUS setvcp 10 "$new"
echo "$new" > "$OSD_FILE"
'';
in
{
home.packages = [
brightnessScript
];
}

View file

@ -0,0 +1,155 @@
{
config,
pkgs,
...
}: {
home.sessionVariables = {
XDG_ICON_DIR = "${pkgs.whitesur-icon-theme}/share/icons/WhiteSur";
GSETTINGS_SCHEMA_DIR = "${pkgs.gsettings-desktop-schemas}/share/gsettings-schemas/${pkgs.gsettings-desktop-schemas.name}/glib-2.0/schemas";
XCURSOR_THEME = "Bibata-Original-Ice";
XCURSOR_SIZE = "20";
};
programs.niri = {
enable = true;
package = pkgs.niri;
settings = {
environment = {
# CLUTTER_BACKEND = "wayland";
# DISPLAY = null;
# MOZ_ENABLE_WAYLAND = "1";
# NIXOS_OZONE_WL = "1";
# QT_QPA_PLATFORM = "wayland;xcb";
# QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
SDL_VIDEODRIVER = "wayland";
WLR_RENDERER = "vulkan";
WLR_NO_HARDWARE_CURSORS = "1";
QT_QPA_PLATFORMTHEME = "qt6ct";
GTK_IM_MODULE = "simple";
# GDK_BACKEND = "wayland,x11";
};
spawn-at-startup = [
{
command = [
"noctalia-shell"
];
}
];
prefer-no-csd = true;
hotkey-overlay = {
skip-at-startup = true;
};
switch-events = {
lid-close.action.spawn = [
"noctalia-shell"
"ipc"
"call"
"lockScreen"
"lock"
];
};
layout = {
preset-column-widths = [
{proportion = 1. / 3.;}
{proportion = 1. / 2.;}
{proportion = 2. / 3.;}
];
default-column-width = {
proportion = 0.5;
};
preset-window-heights = [
{proportion = 1. / 3.;}
{proportion = 1. / 2.;}
{proportion = 2. / 3.;}
];
background-color = "#00000000";
focus-ring = {
enable = true;
width = 3;
active = {
color = "#A8AEFF";
};
inactive = {
color = "#505050";
};
};
gaps = 6;
struts = {
left = 20;
right = 20;
top = 20;
bottom = 20;
};
};
input = {
touchpad = {
click-method = "button-areas";
dwt = true;
dwtp = true;
natural-scroll = true;
scroll-method = "two-finger";
tap = true;
tap-button-map = "left-right-middle";
middle-emulation = true;
accel-profile = "adaptive";
};
focus-follows-mouse.enable = true;
focus-follows-mouse.max-scroll-amount = "0%";
warp-mouse-to-focus.enable = false;
};
outputs = {
"eDP-1" = {
mode = {
width = 1920;
height = 1080;
};
scale = 1.0;
position = {
x = 0;
y = 0;
};
};
"Microstep MSI MP161 E2 PB7H314B00225" = {
mode = {
width = 1920;
height = 1080;
};
scale = 1.0;
position = {
x = 0;
y = -1080;
};
};
};
cursor = {
size = 20;
theme = "Adwaita";
};
environment = {
CLUTTER_BACKEND = "wayland";
GDK_BACKEND = "wayland,x11";
MOZ_ENABLE_WAYLAND = "1";
NIXOS_OZONE_WL = "1";
QT_QPA_PLATFORM = "wayland";
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
ELECTRON_OZONE_PLATFORM_HINT = "auto";
XDG_SESSION_TYPE = "wayland";
XDG_CURRENT_DESKTOP = "niri";
DISPLAY = ":0";
};
};
};
}

View file

@ -0,0 +1,12 @@
# ✨ password manager
{pkgs, ...}: {
programs.password-store = {
enable = true;
package = pkgs.pass.withExtensions (exts: [exts.pass-otp]);
};
home.packages = with pkgs; [
tessen
zbar
];
}

View file

@ -0,0 +1,54 @@
# A customizable prompt for shells.
{
config,
lib,
...
}: let
accent = "#${config.lib.stylix.colors.base0D}";
background-alt = "#${config.lib.stylix.colors.base01}";
in {
programs.starship = {
enable = true;
enableZshIntegration = true;
settings = {
add_newline = true;
format = lib.concatStrings [
"$hostname"
"$directory"
"$git_branch"
"$git_state"
"$git_status"
"$character"
];
directory = {
style = accent;
};
character = {
success_symbol = "[](${accent})";
error_symbol = "[](red)";
vimcmd_symbol = "[](cyan)";
};
git_branch = {
symbol = "[](${background-alt}) ";
style = "fg:${accent} bg:${background-alt}";
format = "on [$symbol$branch]($style)[](${background-alt}) ";
};
git_status = {
format = "[[(*$conflicted$untracked$modified$staged$renamed$deleted)](218)($ahead_behind$stashed)]($style)";
style = "cyan";
conflicted = "";
renamed = "";
deleted = "";
stashed = "";
};
git_state = {
format = "([$state( $progress_current/$progress_total)]($style)) ";
style = "bright-black";
};
};
};
}

View file

@ -0,0 +1,126 @@
{ pkgs, ... }:
{
programs.yazi = {
enable = true;
enableZshIntegration = true;
shellWrapperName = "y";
plugins = {
starship = pkgs.yaziPlugins.starship;
full-border = pkgs.yaziPlugins.full-border;
chmod = pkgs.yaziPlugins.chmod;
compress = pkgs.yaziPlugins.compress;
smart-paste = pkgs.yaziPlugins.smart-paste;
smart-enter = pkgs.yaziPlugins.smart-enter;
smart-filter = pkgs.yaziPlugins.smart-filter;
};
settings = {
yazi = {
ratio = [
1
4
3
];
sort_by = "natural";
sort_sensitive = true;
sort_reverse = false;
sort_dir_first = true;
linemode = "none";
show_hidden = true;
show_symlink = true;
};
preview = {
image_filter = "lanczos3";
image_quality = 90;
tab_size = 1;
max_width = 600;
max_height = 900;
cache_dir = "";
ueberzug_scale = 1;
ueberzug_offset = [
0
0
0
0
];
};
tasks = {
micro_workers = 5;
macro_workers = 10;
bizarre_retry = 5;
};
};
initLua = ''
require("starship"):setup()
require("full-border"):setup()
require("smart-enter"):setup {
open_multi = true,
}
'';
keymap = {
mgr.prepend_keymap = [
{
on = [
"c"
"a"
"a"
];
run = "plugin compress";
desc = "Archive selected files";
}
{
on = [
"c"
"a"
"p"
];
run = "plugin compress -p";
desc = "Archive selected files (password)";
}
{
on = [
"c"
"a"
"h"
];
run = "plugin compress -ph";
desc = "Archive selected files (password+header)";
}
{
on = [
"c"
"a"
"l"
];
run = "plugin compress -l";
desc = "Archive selected files (compression level)";
}
{
on = [
"c"
"a"
"u"
];
run = "plugin compress -phl";
desc = "Archive selected files (password+header+level)";
}
{
on = "p";
run = "plugin smart-paste";
desc = "Paste into the hovered directory or CWD";
}
{
on = "l";
run = "plugin smart-enter";
desc = "Enter the child directory, or open the file";
}
{
on = "F";
run = "plugin smart-filter";
desc = "Smart filter";
}
];
};
};
}

View file

@ -0,0 +1,23 @@
{
config.dendritic.hosts.candlekeep = {
system = "x86_64-linux";
type = "laptop";
roles = [
"workstation"
"laptop"
];
primaryUser = "gwg313";
primaryUserExtraGroups = [
"wheel"
"networkmanager"
"audio"
];
nixosModules = [
../nixos/hardware/candlekeep.nix
../nixos/hosts/candlekeep/ssh.nix
../nixos/hosts/candlekeep/nfs.nix
../nixos/hosts/candlekeep/networking.nix
];
};
}

View file

@ -0,0 +1,17 @@
{
lib,
config,
...
}: {
config = lib.mkIf config.bluetooth.enable {
services.blueman.enable = true;
hardware.bluetooth = {
enable = true;
powerOnBoot = true;
};
services.upower = {
enable = true;
};
};
}

13
modules/nixos/clamav.nix Normal file
View file

@ -0,0 +1,13 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
clamav
];
services.clamav = {
daemon.enable = true;
updater.enable = true;
scanner.enable = true;
fangfrisch.enable = true;
};
}

5
modules/nixos/comma.nix Normal file
View file

@ -0,0 +1,5 @@
{_}: {
# Disable so comma can be installed
programs.command-not-found.enable = false;
programs.nix-index-database.comma.enable = true;
}

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