initial commit

This commit is contained in:
root 2025-12-22 16:46:52 -03:00
commit 120dbdbc64
No known key found for this signature in database
21 changed files with 2413 additions and 0 deletions

9
.sops.yaml Normal file
View file

@ -0,0 +1,9 @@
keys:
- &root age1y0tj3kt67pfnj38t9c8g2ghry3a0mhcq8rrqv5xr4jekwepxaelqzu3dkf
- &user age16v8w7q4wmn22hhakq2uzaus2508rhldm7lcwh0kukshzjzyhuqesqz44ze
creation_rules:
- path_regex: secrets/[^/]+\.yaml$
key_groups:
- age:
- *root
- *user

143
configuration.nix Normal file
View file

@ -0,0 +1,143 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{
config,
lib,
pkgs,
hostname,
...
}:
{
sops.age.keyFile = "/.persist/root/.config/sops/age/keys.txt";
nix.settings.experimental-features = [
"nix-command"
"flakes"
];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
boot.initrd.systemd.enable = true;
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# Set your time zone.
time.timeZone = "America/Sao_Paulo";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
#console = {
# # font = "Lat2-Terminus16";
# keyMap = "us";
# useXkbConfig = true; # use xkb.options in tty.
#};
# services.xserver.xkb.layout = "us";
# services.xserver.xkb.options = "eurosign:e,caps:escape";
services.printing.enable = true;
services = {
xserver.xkb = {
layout = "us";
variant = "altgr-intl";
};
pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
# jack.enable = true;
};
xserver.videoDrivers = [
"nvidia"
"amdgpu"
];
logind.settings.Login = {
HandlePowerKey = "ignore";
HandlePowerKeyLongPress = "ignore";
HandleRebootKey = "ignore";
HandleRebootKeyLongPress = "ignore";
HandleHibernateKey = "ignore";
HandleHibernateKeyLongPress = "ignore";
};
getty = {
autologinUser = "user";
autologinOnce = true;
};
# greetd = {
# enable = true;
# settings = rec {
# initial_session = {
# command = "${pkgs.niri}/bin/niri-session";
# user = "user";
# };
# default_session = initial_session;
# };
# };
tailscale.enable = true;
};
# systemd.services.greetd.serviceConfig = {
# Type = "idle";
# StandardInput = "tty";
# StandardOutput = "tty";
# StandardError = "journal";
# TTYReset = true;
# TTYVHangup = true;
# TTYVTDisallocate = true;
# Restart = "no";
# };
hardware = {
graphics = {
enable = true;
enable32Bit = true;
};
nvidia = {
modesetting.enable = true;
powerManagement.enable = false;
powerManagement.finegrained = false;
open = true;
nvidiaSettings = false;
package = config.boot.kernelPackages.nvidiaPackages.stable;
};
bluetooth = {
enable = true;
powerOnBoot = true;
settings = {
General = {
Enable = "Source,Sink,Media,Socket";
};
};
};
};
xdg.portal = {
enable = true;
xdgOpenUsePortal = true;
# config.common.default = [ "*" ];
extraPortals = [
pkgs.xdg-desktop-portal-gnome
# pkgs.gnome-keyring
pkgs.xdg-desktop-portal-gtk
];
};
qt = {
enable = true;
};
fonts.packages = with pkgs; [
fira-code-symbols
nerd-fonts.monaspace
];
environment.sessionVariables = {
NIXOS_OZONE_WL = "1";
EDITOR = "nvim";
QT_FONT_DPI = "144";
};
system.stateVersion = "25.11";
}

320
flake.lock generated Normal file
View file

@ -0,0 +1,320 @@
{
"nodes": {
"disko": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1746728054,
"narHash": "sha256-eDoSOhxGEm2PykZFa/x9QG5eTH0MJdiJ9aR00VAofXE=",
"owner": "nix-community",
"repo": "disko",
"rev": "ff442f5d1425feb86344c028298548024f21256d",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "latest",
"repo": "disko",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"neovim-nightly-overlay",
"nixpkgs"
]
},
"locked": {
"lastModified": 1765835352,
"narHash": "sha256-XswHlK/Qtjasvhd1nOa1e8MgZ8GS//jBoTqWtrS1Giw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "a34fae9c08a15ad73f295041fec82323541400a9",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": [
"nur",
"nixpkgs"
]
},
"locked": {
"lastModified": 1733312601,
"narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1765980955,
"narHash": "sha256-rB45jv4uwC90vM9UZ70plfvY/2Kdygs+zlQ07dGQFk4=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "89c9508bbe9b40d36b3dc206c2483ef176f15173",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"impermanence": {
"locked": {
"lastModified": 1737831083,
"narHash": "sha256-LJggUHbpyeDvNagTUrdhe/pRVp4pnS6wVKALS782gRI=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "4b3e914cdf97a5b536a889e939fb2fd2b043a170",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "impermanence",
"type": "github"
}
},
"microvm": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"spectrum": "spectrum"
},
"locked": {
"lastModified": 1766005889,
"narHash": "sha256-UCFkQ37BKDmPEHDkW1BaqJo6AZFoVcogtuyxTg4/a8M=",
"owner": "microvm-nix",
"repo": "microvm.nix",
"rev": "bb9e99bdb3662354299605cc1a75a2b1a86bd29a",
"type": "github"
},
"original": {
"owner": "microvm-nix",
"repo": "microvm.nix",
"type": "github"
}
},
"neovim-nightly-overlay": {
"inputs": {
"flake-parts": "flake-parts",
"neovim-src": "neovim-src",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1766102654,
"narHash": "sha256-F2g1gDd88D5KI6j2YIfXn0Vcug+wNqcwFyKWQ/CnPUY=",
"owner": "nix-community",
"repo": "neovim-nightly-overlay",
"rev": "f5c873a02a0607bf5847d85af629dbb86dd75f4e",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "neovim-nightly-overlay",
"type": "github"
}
},
"neovim-src": {
"flake": false,
"locked": {
"lastModified": 1766102038,
"narHash": "sha256-17Rz4usR1sLsj0IhMU+GuVViwqRmgDOHGyaOAhLfJis=",
"owner": "neovim",
"repo": "neovim",
"rev": "04357f2eff750ca7cb32f19d43bf7dd64249a0f9",
"type": "github"
},
"original": {
"owner": "neovim",
"repo": "neovim",
"type": "github"
}
},
"niri-branch": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1766290957,
"narHash": "sha256-BW0AVMiN2juvEiUdu6MpTwjQKWg/jdoz30ecwacy1sQ=",
"owner": "argosnothing",
"repo": "niri",
"rev": "0cb2199a527892d73ec749a7ed4f113b9d1c8299",
"type": "github"
},
"original": {
"owner": "argosnothing",
"ref": "hidden-workspaces",
"repo": "niri",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1766025857,
"narHash": "sha256-Lav5jJazCW4mdg1iHcROpuXqmM94BWJvabLFWaJVJp0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "def3da69945bbe338c373fddad5a1bb49cf199ce",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1765779637,
"narHash": "sha256-KJ2wa/BLSrTqDjbfyNx70ov/HdgNBCBBSQP3BIzKnv4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "1306659b587dc277866c7b69eb97e5f07864d8c4",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1766070988,
"narHash": "sha256-G/WVghka6c4bAzMhTwT2vjLccg/awmHkdKSd2JrycLc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "c6245e83d836d0433170a16eb185cefe0572f8b8",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nur": {
"inputs": {
"flake-parts": "flake-parts_2",
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1766201826,
"narHash": "sha256-j9CFs4N5z4sFnAwiuGoAZk6t9eEGF4Ukb/VFqsZcnOY=",
"owner": "nix-community",
"repo": "NUR",
"rev": "4479648d80a1650a0338d79fd3ed9f02ec662d9c",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "NUR",
"type": "github"
}
},
"root": {
"inputs": {
"disko": "disko",
"home-manager": "home-manager",
"impermanence": "impermanence",
"microvm": "microvm",
"neovim-nightly-overlay": "neovim-nightly-overlay",
"niri-branch": "niri-branch",
"nixpkgs": "nixpkgs_2",
"nur": "nur",
"sops-nix": "sops-nix"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": [
"niri-branch",
"nixpkgs"
]
},
"locked": {
"lastModified": 1757989933,
"narHash": "sha256-9cpKYWWPCFhgwQTww8S94rTXgg8Q8ydFv9fXM6I8xQM=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "8249aa3442fb9b45e615a35f39eca2fe5510d7c3",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"sops-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1765836173,
"narHash": "sha256-hWRYfdH2ONI7HXbqZqW8Q1y9IRbnXWvtvt/ONZovSNY=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "443a7f2e7e118c4fc63b7fae05ab3080dd0e5c63",
"type": "github"
},
"original": {
"owner": "Mic92",
"repo": "sops-nix",
"type": "github"
}
},
"spectrum": {
"flake": false,
"locked": {
"lastModified": 1759482047,
"narHash": "sha256-H1wiXRQHxxPyMMlP39ce3ROKCwI5/tUn36P8x6dFiiQ=",
"ref": "refs/heads/main",
"rev": "c5d5786d3dc938af0b279c542d1e43bce381b4b9",
"revCount": 996,
"type": "git",
"url": "https://spectrum-os.org/git/spectrum"
},
"original": {
"type": "git",
"url": "https://spectrum-os.org/git/spectrum"
}
}
},
"root": "root",
"version": 7
}

80
flake.nix Normal file
View file

@ -0,0 +1,80 @@
{
description = "NixOS flake";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
sops-nix = {
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
microvm = {
url = "github:microvm-nix/microvm.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
disko = {
url = "github:nix-community/disko/latest";
inputs.nixpkgs.follows = "nixpkgs";
};
impermanence.url = "github:nix-community/impermanence";
neovim-nightly-overlay.url = "github:nix-community/neovim-nightly-overlay";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
nur.url = "github:nix-community/NUR";
niri-branch = {
url = "github:argosnothing/niri/hidden-workspaces";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
inputs@{ nixpkgs, ... }:
let
hostname = "amelia";
system = "x86_64-linux";
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;
overlays = [ inputs.neovim-nightly-overlay.overlays.default ];
};
in
{
nixosConfigurations."${hostname}" = nixpkgs.lib.nixosSystem {
inherit system pkgs;
specialArgs = {
# inherit quickshell;
hostname = hostname;
};
modules = [
./users.nix
./storage.nix
./configuration.nix
./impermanence.nix
./networking.nix
./packages.nix
./kernel
./home
inputs.sops-nix.nixosModules.sops
inputs.microvm.nixosModules.host
inputs.disko.nixosModules.disko
inputs.impermanence.nixosModules.impermanence
inputs.home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.sharedModules = [
inputs.sops-nix.homeManagerModules.sops
];
nixpkgs.overlays = [
inputs.nur.overlays.default
(_: prev: {
niri = inputs.niri-branch.packages.${prev.system}.niri;
})
];
}
# ./networking/wireguard
];
};
};
}

31
home/bin/tmux-sessionizer Executable file
View file

@ -0,0 +1,31 @@
#!/usr/bin/env bash
if [[ $# -eq 1 ]]; then
selected=$1
else
selected=$(
(
find ~/work -mindepth 1 -maxdepth 1 -type d
find ~/dev -mindepth 1 -maxdepth 1 -type d
) | fzf
)
fi
if [[ -z $selected ]]; then
exit 0
fi
selected_name=$(basename "$selected" | tr . _)
tmux_running=$(pgrep tmux)
if [[ -z $TMUX ]] && [[ -z $tmux_running ]]; then
tmux new-session -s "$selected_name" -c "$selected"
exit 0
fi
if ! tmux has-session -t="$selected_name" 2> /dev/null; then
tmux new-session -ds "$selected_name" -c "$selected"
fi
tmux switch-client -t "$selected_name"

7
home/default.nix Normal file
View file

@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./user.nix
./root.nix
];
}

180
home/nvim/default.nix Normal file
View file

@ -0,0 +1,180 @@
{
config,
pkgs,
lib,
...
}:
with lib;
let
cfg = config.custom.neovim;
in
{
options.custom.neovim = {
enable = mkEnableOption "Custom Neovim";
colorscheme = mkOption {
type = types.str;
default = "unokai";
};
hostname = mkOption {
type = types.str;
};
};
config = mkIf cfg.enable {
programs.neovim = {
enable = true;
defaultEditor = true;
viAlias = true;
vimAlias = false;
vimdiffAlias = true;
plugins = with pkgs.vimPlugins; [
{
plugin = blink-cmp;
type = "lua";
config = ''
require("blink.cmp").setup({
keymap = {
preset = "default",
["<C-y>"] = { "select_and_accept", "snippet_forward", "fallback" },
["<C-S-y>"] = { "snippet_backward", "fallback" },
},
})
'';
}
{
plugin = conform-nvim;
type = "lua";
config = ''
require("conform").setup({
formatters_by_ft = {
lua = { "stylua" },
javascript = { "prettierd" },
nix = { "nixfmt" },
python = { "black" },
php = { "php_cs_fixer" },
zig = { "zigfmt" },
css = { "prettierd" },
scss = { "prettierd" },
less = { "prettierd" },
blade = { "blade-formatter" },
go = { "go fmt" },
},
})
vim.api.nvim_create_autocmd("BufWritePre", {
pattern = "*",
callback = function(args)
require("conform").format({ bufnr = args.buf })
end,
})
vim.keymap.set("n", "<leader>c", function()
require("conform").format({
lsp_fallback = true,
async = true,
timeout_ms = 500,
})
end, { desc = "conform format" })
'';
}
# (codecompanion-nvim.overrideAttrs (_: {
# src = pkgs.fetchFromGitHub {
# owner = "olimorris";
# repo = "codecompanion.nvim";
# tag = "v18.2.1";
# sha256 = "sha256-94uX1Ie+BiKSPGCYcUwoZ6DZwSz8tUxaNsa+xTv1ejw=";
# };
# }))
kanagawa-nvim
leap-nvim
{
plugin = mini-icons;
type = "lua";
config = ''require("mini.icons").setup()'';
}
{
plugin = nvim-treesitter.withAllGrammars;
type = "lua";
config = ''
require("nvim-treesitter").setup({
highlight = {
enable = true,
additional_vim_regex_highlighting = false,
},
indent = { enable = true },
refactor = {
highlight_definitions = { enable = true },
},
})
'';
}
{
plugin = nvim-treesitter-context;
type = "lua";
config = ''require("treesitter-context").setup()'';
}
{
plugin = nvim-treesitter-textobjects;
# type = "lua";
# config = ''
# vim.g.no_plugin_maps = true
# require("treesitter-textobjects").setup()
# '';
}
nvim-lspconfig
{
plugin = nvim-surround;
type = "lua";
config = ''require("nvim-surround").setup()'';
}
{
plugin = nvim-web-devicons;
type = "lua";
config = ''require("nvim-web-devicons").setup()'';
}
{
plugin = oil-nvim;
type = "lua";
config = ''
require("oil").setup()
vim.keymap.set("n", "<leader>o", "<cmd>Oil<cr>", { desc = "Oil" })
'';
}
phpactor
{
plugin = render-markdown-nvim;
type = "lua";
config = ''require("render-markdown").setup()'';
}
snacks-nvim
tokyonight-nvim
{
plugin = undotree;
type = "lua";
config = ''vim.keymap.set("n", "<leader>u", vim.cmd.UndotreeToggle, { desc = "undotree" })'';
}
{
plugin = vimtex;
type = "lua";
config = ''
vim.g.vimtex_view_method = "zathura"
vim.g.vimtex_compiler_method = "latexmk"
'';
}
{
plugin = which-key-nvim;
type = "lua";
config = ''require("which-key").setup()'';
}
];
extraConfig = ''
colorscheme ${cfg.colorscheme}
'';
extraLuaConfig = ''
${builtins.readFile ./settings.lua}
${builtins.replaceStrings [ "@HOSTNAME@" ] [ cfg.hostname ] (builtins.readFile ./plugins.lua)}
require("custom")
'';
};
};
}

148
home/nvim/plugins.lua Normal file
View file

@ -0,0 +1,148 @@
local hostname = "@HOSTNAME@"
local servers = {
textlab = {},
lua_ls = {},
rust_analyzer = {},
nixd = {
nixpkgs = {
expr = 'import (builtins.getFlake "/etc/nixos").inputs.nixpkgs {}',
},
formatting = { command = { "nixfmt" } },
options = {
nixos = {
expr = '(builtins.getFlake "/etc/nixos").nixosConfigurations.' .. hostname .. ".options",
},
home_manager = {
expr = '(builtins.getFlake "/etc/nixos").homeConfigurations.' .. hostname .. ".options",
},
},
},
phpactor = {},
zls = {
settings = {
zls = {
enable_build_on_save = true,
semantic_tokens = "partial",
},
},
},
css = {},
scss = {},
less = {},
blade = {},
html = { filetypes = { "html", "blade" } },
htmx = { filetypes = { "html", "blade" } },
gopls = {},
}
for server, config in pairs(servers) do
vim.lsp.config(server, config)
vim.lsp.enable(server)
end
vim.api.nvim_create_autocmd("LspAttach", {
group = vim.api.nvim_create_augroup("UserConfigLsp", {}),
callback = function(ev)
vim.keymap.set("n", "gD", vim.lsp.buf.declaration, { buffer = ev.buf, desc = "go to declaration" })
vim.keymap.set("n", "gd", vim.lsp.buf.definition, { buffer = ev.buf, desc = "go to definition" })
-- vim.keymap.set("n", "gi", vim.lsp.buf.implementaion, { buffer = ev.buf, desc = "go to implementation" })
vim.keymap.set("n", "<leader>rn", vim.lsp.buf.rename, { buffer = ev.buf, desc = "lsp rename" })
vim.keymap.set("n", "<leader>a", vim.lsp.buf.code_action, { buffer = ev.buf, desc = "code action" })
vim.keymap.set({ "n", "i" }, "<C-k>", vim.lsp.buf.signature_help, { buffer = ev.buf, desc = "signature help" })
vim.keymap.set("n", "gr", vim.lsp.buf.references, { buffer = ev.buf, desc = "references" })
end,
})
local snacks = require("snacks")
snacks.setup({
bigfile = {},
dim = {},
image = {},
indent = {},
lazygit = {},
picker = {},
quickfile = {},
notifier = {},
})
vim.keymap.set("n", "<leader>tf", function()
snacks.picker.grep()
end, { desc = "grep picker" })
vim.keymap.set("n", "<leader>te", snacks.picker.files, { desc = "file picker" })
vim.keymap.set("n", "<leader>lg", function()
snacks.lazygit()
end, { desc = "lazygit" })
local leap = require("leap")
leap.opts.preview = function(ch0, ch1, ch2)
return not (ch1:match("%s") or (ch0:match("%a") and ch1:match("%a") and ch2:match("%a")))
end
leap.opts.equivalence_classes = {
" \t\r\n",
"([{",
")]}",
"'\"`",
}
vim.api.nvim_set_hl(0, "LeapBackdrop", { link = "Comment" })
do
-- Return an argument table for `leap()`, tailored for f/t-motions.
local function as_ft(key_specific_args)
local common_args = {
inputlen = 1,
inclusive = true,
-- To limit search scope to the current line:
-- pattern = function (pat) return '\\%.l'..pat end,
opts = {
labels = "", -- force autojump
safe_labels = vim.fn.mode(1):match("[no]") and "" or nil, -- [1]
},
}
return vim.tbl_deep_extend("keep", common_args, key_specific_args)
end
local clever = require("leap.user").with_traversal_keys -- [2]
local clever_f = clever("f", "F")
local clever_t = clever("t", "T")
for key, key_specific_args in pairs({
f = { opts = clever_f },
F = { backward = true, opts = clever_f },
t = { offset = -1, opts = clever_t },
T = { backward = true, offset = 1, opts = clever_t },
}) do
vim.keymap.set({ "n", "x", "o" }, key, function()
require("leap").leap(as_ft(key_specific_args))
end)
end
end
vim.api.nvim_create_autocmd("CmdlineLeave", {
group = vim.api.nvim_create_augroup("LeapOnSearch", {}),
callback = function()
local ev = vim.v.event
local is_search_cmd = (ev.cmdtype == "/") or (ev.cmdtype == "?")
local cnt = vim.fn.searchcount().total
if is_search_cmd and not ev.abort and (cnt > 1) then
-- Allow CmdLineLeave-related chores to be completed before
-- invoking Leap.
vim.schedule(function()
-- We want "safe" labels, but no auto-jump (as the search
-- command already does that), so just use `safe_labels`
-- as `labels`, with n/N removed.
local labels = require("leap").opts.safe_labels:gsub("[nN]", "")
-- For `pattern` search, we never need to adjust conceallevel
-- (no user input). We cannot merge `nil` from a table, but
-- using the option's current value has the same effect.
local vim_opts = { ["wo.conceallevel"] = vim.wo.conceallevel }
require("leap").leap({
pattern = vim.fn.getreg("/"), -- last search pattern
windows = { vim.fn.win_getid() },
opts = { safe_labels = "", labels = labels, vim_opts = vim_opts },
})
end)
end
end,
})
vim.keymap.set({ "n", "x", "o" }, "s", "<Plug>(leap)", { desc = "leap" })
vim.keymap.set({ "n", "x", "o" }, "S", "<Plug>(leap-from-window)", { desc = "leap across window" })

151
home/nvim/settings.lua Normal file
View file

@ -0,0 +1,151 @@
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.cursorline = true
vim.opt.wrap = false
vim.opt.scrolloff = 10
vim.opt.sidescrolloff = 8
vim.opt.tabstop = 4
vim.opt.shiftwidth = 4
vim.opt.softtabstop = 4
vim.opt.expandtab = true
vim.opt.smartindent = true
vim.opt.autoindent = true
vim.opt.ignorecase = true
vim.opt.smartcase = true
vim.opt.hlsearch = false
vim.opt.incsearch = true
vim.opt.termguicolors = true
vim.opt.signcolumn = "yes"
vim.opt.colorcolumn = "120"
vim.opt.showmatch = false
--- vim.opt.matchtime = 2
vim.opt.conceallevel = 0
vim.opt.concealcursor = ""
vim.opt.synmaxcol = 1000
vim.opt.isfname:append("@-@")
vim.opt.backup = false
vim.opt.writebackup = false
vim.opt.swapfile = false
vim.opt.undofile = true
vim.opt.undodir = vim.fn.expand("~/.cache/vim/undodir")
vim.opt.updatetime = 100
vim.opt.timeoutlen = 500
vim.opt.ttimeoutlen = 0
vim.opt.autoread = true
vim.opt.autowrite = false
vim.opt.hidden = true
--- vim.opt.errorbells = false
vim.opt.backspace = "indent,eol,start"
vim.opt.autochdir = false
vim.opt.path:append("**")
vim.opt.selection = "exclusive"
vim.opt.mouse = "a"
vim.opt.modifiable = true
vim.opt.encoding = "UTF-8"
-- Split behavior
vim.opt.splitbelow = true
vim.opt.splitright = true
vim.g.mapleader = " "
vim.g.maplocalleader = " "
vim.o.exrc = true
vim.cmd("set title")
vim.cmd("set ic")
-- Delete without yanking
vim.keymap.set({ "n", "v" }, "<leader>d", '"_d', { desc = "Delete without yanking" })
vim.keymap.set({ "n", "v" }, "<C-c>", '"+y', { desc = "Copy to clipboard" })
-- Wayland clipboard mappings
vim.keymap.set({ "n", "v" }, "<leader>y", '"+y', { desc = "Yank to system clipboard" })
vim.keymap.set("n", "<leader>Y", '"+Y', { desc = "Yank line to system clipboard" })
vim.keymap.set({ "n", "v" }, "<leader>p", '"+p', { desc = "Paste from system clipboard" })
vim.keymap.set({ "n", "v" }, "<leader>P", '"+P', { desc = "Paste from system clipboard before cursor" })
-- Better J behavior
vim.keymap.set("n", "J", "mzJ`z", { desc = "Join lines and keep cursor position" })
--- center when jumping
vim.keymap.set("n", "n", "nzzzv", { desc = "Next search result (centered)" })
vim.keymap.set("n", "N", "Nzzzv", { desc = "Previous search result (centered)" })
vim.keymap.set("n", "<C-d>", "<C-d>zz", { desc = "Half page down (centered)" })
vim.keymap.set("n", "<C-u>", "<C-u>zz", { desc = "Half page up (centered)" })
--- window navigation
vim.keymap.set("n", "<C-h>", "<C-w>h", { desc = "Move to left window" })
vim.keymap.set("n", "<C-l>", "<C-w>l", { desc = "Move to right window" })
vim.keymap.set("n", "<C-k>", "<C-w>k", { desc = "Move to top window" })
vim.keymap.set("n", "<C-j>", "<C-w>j", { desc = "Move to bottom window" })
--- indenting in visual mode
-- vim.keymap.set("v", "<", "<gv", { desc = "Indent left and reselect" })
-- vim.keymap.set("v", ">", ">gv", { desc = "Indent right and reselect" })
local augroup = vim.api.nvim_create_augroup("UserConfig", {})
-- Highlight yanked text
vim.api.nvim_create_autocmd("TextYankPost", {
group = augroup,
callback = function()
vim.highlight.on_yank()
end,
})
--- return to last edit position when opening files
vim.api.nvim_create_autocmd("BufReadPost", {
group = augroup,
callback = function()
local mark = vim.api.nvim_buf_get_mark(0, '"')
local lcount = vim.api.nvim_buf_line_count(0)
if mark[1] > 0 and mark[1] <= lcount then
pcall(vim.api.nvim_win_set_cursor, 0, mark)
end
end,
})
--- close terminal when process exits
vim.api.nvim_create_autocmd("TermClose", {
group = augroup,
callback = function()
if vim.v.event.status == 0 then
vim.api.nvim_buf_delete(0, {})
end
end,
})
-- Disable syntax highlighting for large files
vim.api.nvim_create_autocmd("BufReadPre", {
pattern = "*",
callback = function()
local size = vim.fn.getfsize(vim.fn.expand("<afile>"))
if size > 1024 * 1024 then -- 1MB threshold
vim.cmd("syntax off")
vim.opt_local.wrap = false
vim.opt_local.number = false
vim.opt_local.relativenumber = false
end
end,
})
--- create directory when saving files
-- vim.api.nvim_create_autocmd("BufWritePre", {
-- group = augroup,
-- callback = function()
-- local dir = vim.fn.expand("<afile>:p:h")
-- if vim.fn.isdirectory(dir) == 0 and dir ~= "oil:" then
-- vim.fn.mkdir(dir, "p")
-- end
-- end,
-- })
--- command line completion
vim.opt.wildmenu = true
vim.opt.wildmode = "longest:full,full"
vim.opt.wildignore:append({ "*.o", "*.obj", "*.pyc", "*.class", "*.jar" })

87
home/root.nix Normal file
View file

@ -0,0 +1,87 @@
{ hostname, ... }:
{
home-manager.users.root =
{ config, ... }:
{
imports = [ ./nvim ];
custom.neovim = {
enable = true;
hostname = hostname;
colorscheme = "unokai";
};
home.stateVersion = "25.11";
sops.defaultSopsFile = ../secrets/home.yaml;
sops.age.keyFile = "/.persist/${config.home.homeDirectory}/.config/sops/age/keys.txt";
sops.secrets."root/ssh/desktop" = {
path = "${config.home.homeDirectory}/.ssh/desktop";
mode = "0600";
};
home.file."/.ssh/desktop.pub".text =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILquARrJ3Vyh5z6aeVoiYrkLpgiMts+V/JzFEvs3Cnth root@icefox.sh";
programs = {
ssh = {
enable = true;
enableDefaultConfig = false;
matchBlocks = {
"icefox.sh" = {
user = "git";
identityFile = config.sops.secrets."root/ssh/desktop".path;
};
};
};
delta = {
enable = true;
options = {
navigate = true;
line-numbers = true;
side-by-side = true;
};
enableGitIntegration = true;
};
git = {
enable = true;
lfs.enable = true;
settings = {
user = {
email = "root@icefox.sh";
name = "root";
};
gpg.format = "ssh";
user.signingkey = "${config.home.homeDirectory}/.ssh/desktop.pub";
commit.gpgsign = true;
tag.gpgsign = true;
core = {
editor = "nvim";
whitespace = "fix,only-indent-error,trailing-space,space-before-tab";
quotepath = false;
};
diff = {
algorithm = "histogram";
renames = "copies";
};
merge = {
conflictstyle = "zdiff3";
};
init = {
defaultBranch = "master";
};
push = {
autoSetupRemote = true;
default = "current";
};
pull = {
rebase = true;
};
fetch = {
prune = true;
};
help = {
autocorrect = "prompt";
};
};
};
};
};
}

355
home/user.nix Normal file
View file

@ -0,0 +1,355 @@
{ hostname, lib, ... }:
{
home-manager.users.user =
{
config,
pkgs,
...
}:
{
home.username = "user";
home.homeDirectory = "/home/user";
home.stateVersion = "25.11";
home.enableNixpkgsReleaseCheck = false;
sops.defaultSopsFile = ../secrets/home.yaml;
sops.age.keyFile = "/.persist/${config.home.homeDirectory}/.config/sops/age/keys.txt";
sops.secrets."user/ssh/desktop" = {
path = "${config.home.homeDirectory}/.ssh/desktop";
mode = "0600";
};
home.file."/.ssh/desktop.pub".text =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILABd/iSJ4gn/ystDqNxLJTG0n0z5VIC9YXlmdUfOhHf desktop@icefox.sh";
sops.secrets."user/ssh/legacy_ed25519" = {
path = "${config.home.homeDirectory}/.ssh/legacy_ed25519";
mode = "0600";
};
home.file."/.ssh/legacy_ed25519.pub".text =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILkchxtY21PzSLHJ5SoYPrl03+NRzRqznbdCqNyGuOX/ master@michizure.net";
dconf.settings = {
"org/gnome/desktop/interface" = {
text-scaling-factor = 1.5;
};
};
xresources.properties = {
"Xcursor.size" = 18;
"Xft.dpi" = 144;
"Xft.autohint" = 0;
"Xft.lcdfilter" = "lcddefault";
"Xft.hintstyle" = "hintfull";
"Xft.hinting" = 1;
"Xft.antialias" = 1;
"Xft.rgba" = "rgb";
};
systemd.user.services.xrdb-configure = {
Unit = {
Description = "Load Xresources";
};
Intall = {
WantedBy = [ "graphical-session.target" ];
};
Service = {
ExecStart = "${pkgs.xorg.xrdb}/bin/xrdb -merge ${config.home.homeDirectory}/.Xresources";
Type = "oneshot";
};
};
sops.secrets."user/gpg/legacy_fnzr" = { };
home.activation.importGpgKey = config.lib.dag.entryAfter [ "writeBoundary" ] ''
if [[ -f "${config.sops.secrets."user/gpg/legacy_fnzr".path}" ]]; then
${pkgs.gnupg}/bin/gpg --batch --import "${
config.sops.secrets."user/gpg/legacy_fnzr".path
}" || true
echo "YOUR_KEY_FINGERPRINT:6:" | ${pkgs.gnupg}/bin/gpg --import-ownertrust || true
fi
'';
xdg.configFile."containers/containers.conf".text = ''
[engine]
compose_warning_logs=false
'';
# xdg.configFile."mimeapps.list".force = true;
xdg.userDirs = {
enable = true;
createDirectories = true;
download = "${config.home.homeDirectory}/downloads";
documents = "${config.home.homeDirectory}/documents";
desktop = "${config.home.homeDirectory}/desktop";
pictures = "${config.home.homeDirectory}/pictures";
music = "${config.home.homeDirectory}/music";
videos = "${config.home.homeDirectory}/videos";
templates = "${config.home.homeDirectory}";
publicShare = "${config.home.homeDirectory}";
extraConfig = {
XDG_SCREENSHOTS_DIR = "${config.home.homeDirectory}/pictures/screenshots";
};
};
programs = {
ssh = {
enable = true;
enableDefaultConfig = false;
matchBlocks = {
"github.com" = {
identityFile = config.sops.secrets."user/ssh/legacy_ed25519".path;
};
"icefox.sh" = {
user = "git";
identityFile = config.sops.secrets."user/ssh/desktop".path;
};
};
};
delta = {
enable = true;
options = {
navigate = true;
line-numbers = true;
side-by-side = true;
};
enableGitIntegration = true;
};
git = {
enable = true;
lfs.enable = true;
settings = {
user = {
email = "felipe@icefox.sh";
name = "icefox";
};
gpg.format = "ssh";
user.signingkey = "${config.home.homeDirectory}/.ssh/desktop.pub";
commit.gpgsign = true;
tag.gpgsign = true;
core = {
editor = "nvim";
whitespace = "fix,only-indent-error,trailing-space,space-before-tab";
quotepath = false;
};
diff = {
algorithm = "histogram";
renames = "copies";
};
merge = {
conflictstyle = "zdiff3";
};
init = {
defaultBranch = "master";
};
push = {
autoSetupRemote = true;
default = "current";
};
pull = {
rebase = true;
};
fetch = {
prune = true;
};
help = {
autocorrect = "prompt";
};
url."git@github.com:".insteadOf = "https://github.com/";
};
};
};
programs.tmux = {
enable = true;
baseIndex = 1;
keyMode = "vi";
mouse = true;
plugins = with pkgs.tmuxPlugins; [
sensible
yank
pain-control
tmux-powerline
tmux-which-key
{
plugin = resurrect;
extraConfig = "set -g @ressurect-strategy-nvim 'session'";
}
{
plugin = continuum;
extraConfig = ''
set -g @continuum-restore 'on'
set -g @continuum-save-interval '60'
'';
}
];
extraConfig = ''
set -g status-position top
set -g focus-events on
set -g allow-passthrough on
bind -n M-n select-window -t 1
bind -n M-e select-window -t 2
bind -n M-i select-window -t 3
bind -n M-a select-window -t 4
bind -n M-, run-shell "tmux neww tmux-sessionizer"
bind -n M-/ run-shell "tmux switch-client -t default"
bind -n M-. run-shell "tmux switchc -l"
'';
};
home.packages = with pkgs; [
xorg.xrdb
(writeShellApplication {
name = "tmux-sessionizer";
runtimeInputs = [
tmux
fzf
];
text = builtins.readFile ./bin/tmux-sessionizer;
})
];
imports = [ ./nvim ];
custom.neovim = {
enable = true;
colorscheme = "tokyonight";
hostname = hostname;
};
programs.fish = {
enable = true;
plugins = [
{
name = "puffer";
src = pkgs.fetchFromGitHub {
owner = "nickeb96";
repo = "puffer-fish";
rev = "83174b0";
sha256 = "sha256-Dhx5+XRxJvlhdnFyimNxFyFiASrGU4ZwyefsDwtKnSg=";
};
}
];
interactiveShellInit = ''
set fish_greeting
'';
};
programs.starship = {
enable = true;
};
programs.zoxide = {
enable = true;
enableFishIntegration = true;
};
programs.chromium = {
enable = true;
package = pkgs.symlinkJoin {
name = "chromium-firejail-hm";
paths = [ pkgs.chromium ];
buildInputs = [ pkgs.makeWrapper ];
postBuild = ''
rm $out/bin/chromium
ln -s /run/current-system/sw/bin/chromium $out/bin/chromium
'';
};
};
programs.ghostty = {
enable = true;
settings = {
font-family = "MonaspiceNe Nerd Font Mono";
"font-family " = "Fire Code Symbol";
font-size = "14";
font-feature = "+calt, +liga, +dlig, +ss01, +ss02, +ss03, +ss04, +ss05, +ss06, +ss07, +ss08, +ss09, +ss10";
};
enableFishIntegration = true;
systemd.enable = true;
};
programs.librewolf = {
enable = true;
package = pkgs.librewolf;
nativeMessagingHosts = [
pkgs.browserpass
pkgs.tridactyl-native
];
profiles.default = {
id = 0;
name = "default";
isDefault = true;
containersForce = true;
containers = {
personal = {
id = 1;
color = "blue";
icon = "fingerprint";
};
google = {
id = 2;
color = "pink";
icon = "briefcase";
};
};
search = {
force = true;
default = "ddg";
order = [
"ddg"
"Kagi"
"NixOS"
];
engines = {
"Kagi" = {
urls = [ { template = "https://kagi.com/search?q={searchTerms}"; } ];
icon = "https://kagi.com/favicon.ico";
updateInterval = 24 * 60 * 60 * 1000;
definedAliases = [ "kg" ];
};
"nx" = {
urls = [ { template = "https://mynixos.com/search?q={searchTerms}"; } ];
icon = "https://mynixos.com/favicon.ico";
updateInterval = 24 * 60 * 60 * 1000;
definedAliases = [ "nx" ];
};
"ddg" = {
metaData.alias = "dd";
};
"google".metaData.hidden = true;
"bing".metaData.hidden = true;
"amazondotcom-us".metaData.hidden = true;
"ebay".metaData.hidden = true;
};
};
settings = {
"layout.css.prefers-color-scheme.content-override" = 2;
"privacy.resistFingerprinting" = true;
"privacy.resistFingerprinting.exemptions" = "prefers-color-scheme";
"browser.theme.dark-private-windows" = true;
};
extensions = {
packages = with pkgs.nur.repos.rycee.firefox-addons; [
ublock-origin
tridactyl
gopass-bridge
multi-account-containers
foxyproxy-standard
];
# force = true;
# settings."uBlock0@raymondhill.net".settings = {
# selectedFilterLists = [
# "ublock-filters"
# "ublock-badware"
# "ublock-privacy"
# "ublock-unbreak"
# "ublock-quick-fixes"
# ];
# };
};
};
};
};
}

54
impermanence.nix Normal file
View file

@ -0,0 +1,54 @@
{
environment.persistence."/.persist" = {
enable = true;
hideMounts = true;
directories = [
"/etc/nixos"
"/var/lib/nixos"
];
users.root = {
home = "/root";
files = [
".config/sops/age/keys.txt"
];
};
files = [
#
];
users.user = {
files = [
".config/sops/age/keys.txt"
];
directories = [
".config/nvim"
".config/niri"
".config/ghostty"
".config/tmux"
".config/tmux-powerline"
".ssh"
];
};
};
environment.persistence."/.nobackup" = {
enable = true;
hideMounts = true;
directories = [
"/var/log"
"/var/cache"
"/var/lib/docker"
];
users.root = {
home = "/root";
directories = [
".cache"
];
};
users.user = {
directories = [
".cache"
];
};
};
}

77
kernel/default.nix Normal file
View file

@ -0,0 +1,77 @@
{
lib,
pkgs,
...
}:
{
imports = [
./hardened.nix
./vfio.nix
# ./apparmor.nix
];
custom.kernel.hardened.enable = true;
custom.kernel.vfio.enable = false;
# security.apparmor.enable = false;
specialisation.unhardened.configuration = {
custom.kernel.hardened.enable = lib.mkForce false;
# security.apparmor.enable = lib.mkForce false;
};
specialisation.vfio.configuration = {
custom.kernel.vfio.enable = lib.mkForce true;
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.enableRedistributableFirmware = true;
hardware.cpu.amd.updateMicrocode = true;
security.rtkit.enable = true;
security.sudo.enable = false;
security.doas = {
enable = true;
extraRules = [
{
users = [ "user" ];
keepEnv = true;
persist = true;
}
];
};
boot = {
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
kernelPackages = pkgs.linuxPackages_zen;
kernelParams = [
"amd_iommu=on"
];
initrd.availableKernelModules = [
"nvme"
"xhci_pci"
"ahci"
"usbhid"
"sd_mod"
"uas"
"usbcore"
"usb_storage"
"vfat"
"nls_cp437"
"nls_iso8859_1"
"virtio_pci"
"virtio_blk"
"virtio_net"
"virtio_ring"
];
initrd.kernelModules = [
"amdgpu"
"nvidia"
"nvidia_modeset"
"nvidia_drm"
];
};
}

207
kernel/hardened.nix Normal file
View file

@ -0,0 +1,207 @@
{
lib,
config,
pkgs,
...
}:
let
cfg = config.custom.kernel.hardened;
in
{
options.custom.kernel.hardened = {
enable = lib.mkEnableOption "hardened kernel options";
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [
pkgs.kernel-hardening-checker
pkgs.lynis
];
security = {
auditd.enable = true;
audit.enable = true;
audit.rules = [ "-a always,exit -F arch=b64 -S execve" ];
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 = config.virtualisation.containers.enable;
allowSimultaneousMultithreading = true;
};
boot.kernel.sysctl = {
"fs.suid_dumpable" = 0;
# prevent pointer leaks
"kernel.kptr_restrict" = 2;
# restrict kernel log to CAP_SYSLOG capability
"kernel.dmesg_restrict" = 1;
# Note: certian container runtimes or browser sandboxes might rely on the following
# restrict eBPF to the CAP_BPF capability
"kernel.unprivileged_bpf_disabled" = 1;
# should be enabled along with bpf above
# "net.core.bpf_jit_harden" = 2;
# 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;
# disable unprivileged user namespaces, Note: Docker, NH, and other apps may need this
"kernel.unprivileged_userns_clone" = 1;
# restrict all usage of performance events to the CAP_PERFMON capability
"kernel.perf_event_paranoid" = 3;
# Network
# 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;
# Userspace
# restrict usage of ptrace
"kernel.yama.ptrace_scope" = 2;
# 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;
## TCP optimization
# TCP Fast Open is a TCP extension that reduces network latency by packing
# data in the senders initial TCP SYN. Setting 3 = enable TCP Fast Open for
# both incoming and outgoing connections:
"net.ipv4.tcp_fastopen" = 3;
# Bufferbloat mitigations + slight improvement in throughput & latency
"net.ipv4.tcp_congestion_control" = "bbr";
"net.core.default_qdisc" = "cake";
};
boot.kernelParams = [
"audit=1"
# 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" # Datagram Congestion Control Protocol
"sctp" # Stream Control Transmission Protocol
"rds" # Reliable Datagram Sockets
"tipc" # Transparent Inter-Process Communication
"n-hdlc" # High-level Data Link Control
"ax25" # Amateur X.25
"netrom" # NetRom
"x25" # X.25
"rose"
"decnet"
"econet"
"af_802154" # IEEE 802.15.4
"ipx" # Internetwork Packet Exchange
"appletalk"
"psnap" # SubnetworkAccess Protocol
"p8023" # Novell raw IEE 802.3
"p8022" # IEE 802.3
"can" # Controller Area Network
"atm"
# Various rare filesystems
"cramfs"
"freevxfs"
"jffs2"
"hfs"
"hfsplus"
# "udf"
# "nfs" # Network File System
# "nfsv3"
# "nfsv4"
"gfs2" # Global File System 2
# vivid driver is only useful for testing purposes and has been the
# cause of privilege escalation vulnerabilities
"vivid"
];
};
}

47
kernel/vfio.nix Normal file
View file

@ -0,0 +1,47 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.custom.kernel.vfio;
in
{
options.custom.kernel.vfio = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
};
};
config = lib.mkIf cfg.enable {
boot = {
extraModulePackages = [ config.boot.kernelPackages.kvmfr ];
extraModprobeConfig = ''
options kvmfr static_size_mb=128
'';
kernelParams = [
"vfio-pci.ids=10de:2204,10de:1aef"
];
kernelModules = [ "kvmfr" ];
initrd.kernelModules = [
"kvmfr"
"kvm-amd"
"vfio_pci"
"vfio_iommu_type1"
"vfio"
];
};
services = {
udev.extraRules = ''
SUBSYSTEM=="kvmfr", OWNER="master", GROUP="kvm", MODE="0660"
'';
};
environment.systemPackages = [
pkgs.looking-glass-client
];
};
}

116
networking.nix Normal file
View file

@ -0,0 +1,116 @@
{
config,
hostname,
pkgs,
...
}:
let
inetInterface = "enp1s0";
in
{
sops.secrets = {
"wg0/address".sopsFile = ./secrets/vpn.yaml;
"wg0/dns".sopsFile = ./secrets/vpn.yaml;
"wg0/conf".sopsFile = ./secrets/vpn.yaml;
};
networking = {
hostName = hostname;
networkmanager.enable = false;
firewall.trustedInterfaces = [ "vlan66" ];
useDHCP = false;
useNetworkd = true;
# vlans.vlan66 = {
# id = 66;
# interface = "br0";
# };
# interfaces = {
# br0.useDHCP = true;
# vlan66.useDHCP = true;
# };
# bridges.br0 = {
# interfaces = [ inetInterface ];
# };
# firewall.allowedTCPPorts = [ 8080 12000 12001 12002 12003 12004 12005 ];
};
systemd.network = {
netdevs."20-br0" = {
netdevConfig = {
Kind = "bridge";
Name = "br0";
};
};
netdevs."30-vlan66" = {
netdevConfig = {
Kind = "vlan";
Name = "vlan66";
};
vlanConfig = {
Id = 66;
};
};
networks."10-lan-up-link" = {
matchConfig.Name = "en* eth*";
networkConfig.Bridge = "br0";
};
networks."20-br0" = {
matchConfig.Name = "br0";
networkConfig = {
VLAN = [ "vlan66" ];
DHCP = "yes";
};
};
networks."30-vlan66" = {
matchConfig.Name = "vlan66";
networkConfig.DHCP = "yes";
};
};
systemd.services."netns@wg0ns" = {
description = "wg0 network namespace";
before = [ "network.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = pkgs.writers.writeBash "wg0ns-up" ''
${pkgs.coreutils}/bin/mkdir -p /etc/netns/wg0ns
cat ${config.sops.secrets."wg0/dns".path} >> /etc/netns/wg0ns/resolv.conf
${pkgs.iproute2}/bin/ip netns add wg0ns
'';
ExecStop = "${pkgs.iproute2}/bin/ip netns del wg0ns";
};
};
systemd.services.wg0 = {
description = "wg0 network interface";
bindsTo = [ "netns@wg0ns.service" ];
requires = [ "network-online.target" ];
after = [ "netns@wg0ns.service" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = pkgs.writers.writeBash "wg-up" ''
${pkgs.iproute2}/bin/ip link add wg0 type wireguard
${pkgs.iproute2}/bin/ip link set wg0 netns wg0ns
${pkgs.iproute2}/bin/ip -n wg0ns address add $(< ${config.sops.secrets."wg0/address".path}) dev wg0
${pkgs.iproute2}/bin/ip netns exec wg0ns \
${pkgs.wireguard-tools}/bin/wg setconf wg0 ${config.sops.secrets."wg0/conf".path}
${pkgs.iproute2}/bin/ip -n wg0ns link set lo up
${pkgs.iproute2}/bin/ip -n wg0ns link set wg0 up
${pkgs.iproute2}/bin/ip -n wg0ns route add default dev wg0
'';
ExecStop = pkgs.writers.writeBash "wg-down" ''
${pkgs.iproute2}/bin/ip -n wg0ns route del default dev wg0
${pkgs.iproute2}/bin/ip -n wg0ns link del wg0
'';
};
};
}

210
packages.nix Normal file
View file

@ -0,0 +1,210 @@
{ pkgs, lib, ... }:
{
environment.systemPackages = with pkgs; [
bat
black
blade-formatter
cmake
cifs-utils
coreutils
bluetuith
bluez
bluez-tools
cargo
claude-code
clevis
cliphist
dunst
eza
fd
ffmpeg
fira-code-symbols
fish
freetube
fuzzel
fzf
git
gh
ghostty
gopass
gopass-jsonapi
gopls
hyprpicker
htmx-lsp
imagemagick
inkscape
pavucontrol
pciutils
poppler
jetbrains.datagrip
jq
lazygit
lf
libreoffice
libvirt
linux-firmware
lua-language-server
luarocks
lutris
mpv
nerd-fonts.monaspace
neovim
niri
nixd
nixfmt-rfc-style
(wrapOBS {
plugins = with obs-studio-plugins; [
wlrobs
obs-pipewire-audio-capture
];
})
php
php84Packages.composer
php84Packages.php-cs-fixer
phpactor
podman-compose
podman-tui
prettierd
playerctl
qemu_full
qmk
resvg
ripgrep
rust-analyzer
sshfs
starship
stow
stylua
sops
superhtml
swayimg
texlab
texlive.combined.scheme-full
tmux
thunderbird
tor-browser
unzip
virt-manager
virt-viewer
vscode-langservers-extracted
wineWow64Packages.waylandFull
winetricks
wl-clipboard
xdg-user-dirs
xwayland-satellite
yazi
zathura
zig_0_15
zls_0_15
zoxide
];
hardware.keyboard.qmk.enable = true;
programs = {
fish.enable = true;
virt-manager.enable = true;
direnv.enable = true;
gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
nix-ld.enable = true;
niri.enable = true;
dconf.enable = true;
};
virtualisation.containers.enable = true;
virtualisation.podman = {
enable = true;
dockerCompat = true;
defaultNetwork.settings.dns_enabled = true;
};
virtualisation.spiceUSBRedirection.enable = true;
virtualisation.libvirtd = {
enable = true;
extraConfig = ''
user="user"
'';
onBoot = "ignore";
onShutdown = "shutdown";
qemu = {
package = pkgs.qemu_full;
verbatimConfig = ''
cgroup_device_acl = [
"/dev/null", "/dev/full", "/dev/zero",
"/dev/random", "/dev/urandom", "/dev/ptmx",
"/dev/kvm", "/dev/kvmfr0"
]
'';
runAsRoot = false;
};
};
programs.steam = {
enable = true;
remotePlay.openFirewall = true;
dedicatedServer.openFirewall = true;
localNetworkGameTransfers.openFirewall = true;
};
programs.firejail = {
enable = true;
wrappedBinaries = {
chromium = {
executable = "${pkgs.chromium}/bin/chromium";
profile = "${pkgs.firejail}/etc/firejail/chromium.profile";
extraArgs = [
"--env=GTK_THEME=Adwaita:dark"
"--netns=wg0ns"
"--dns=1.1.1.1"
];
};
mpv = {
executable = "${lib.getBin pkgs.mpv}/bin/mpv";
profile = "${pkgs.firejail}/etc/firejail/mpv.profile";
};
claude = {
executable = "${pkgs.claude-code}/bin/claude";
# profile = "${pkgs.firejail}/etc/firejail/nodejs-common.profile";
extraArgs = [
"--netns=wg0ns"
"--dns=1.1.1.1"
"--whitelist=~/.cargo"
"--whitelist=$${HOME}/.claude"
"--whitelist=$${HOME}/.config/claude-code"
"--whitelist=$${HOME}/dev"
"--whitelist=$${HOME}/work"
"--whitelist=/tmp"
"--read-only=/nix"
"--caps.drop=all"
"--ipc-namespace"
"--seccomp"
"--seccomp.block-secondary"
"--nodvd"
"--nogroups"
"--notv"
"--nou2f"
"--protocol=unix,inet,inet6,netlink"
];
};
tor-browser = {
executable = "${pkgs.tor-browser}/bin/tor-browser";
profile = "${pkgs.firejail}/etc/firejail/tor-browser-en-us.profile";
extraArgs = [
"--netns=wg0ns"
"--dns=1.1.1.1"
];
};
freetube = {
executable = "${pkgs.freetube}/bin/freetube";
profile = "${pkgs.firejail}/etc/firejail/freetube.profile";
extraArgs = [
"--netns=wg0ns"
"--dns=1.1.1.1"
];
};
};
};
}

36
secrets/home.yaml Normal file
View file

@ -0,0 +1,36 @@
root:
password: ENC[AES256_GCM,data:qA7sbNvWvfmWiLX4pIYOzDmuCwc3+7I1KvTHHYF5jDHR0CNRuya0XglP8TNK5qGLEJkdmD9WphdWvYY60NTOf5NFhDnqtm3ZIw==,iv:B42jl40hQbRqMRfV39fNne0E3KKCwriAQ5MQ0DF4QQA=,tag:hH/u0Qw6A2is4XOOQpnr2Q==,type:str]
ssh:
desktop: ENC[AES256_GCM,data:mjenzt2rI9vZ4VnpWttAmojzEaGDgDTO0Tc5ICTZzKRC8fDIWc/YH81mCkU8BpPJGPiCQSCPz+/r7MEjcfjC0Xhf5xnSxespw/2eiCoeR4qWGMC4SlizusR+DBxwvW71MBn8icZkJyWc9zKPAfDyZQhtVUthvcQYTVsJEvMkRYSkTQgKJI0iEpq2x4j8fKr/FY4EQsidm5BFykOYOFejECWkkcMf0i+FBS60EsH3aZV+5c5fNNlj9GIdmX5rMp8iHa/RlGfxiu0QIaZRa+Q9h+h/d2Utf5qRFv2qpq+Fk7tI9JErtwwB+tKdXbavPjgWt3YtqI4O0f+01BWKRTPzFeiRANoONuGRgcx+b/GkAaHV4P+7uqIgmWgkwqCliYkgdwFtE2dWS6M/DEO+KP+GyKUykusdx2xODp+gA/CpiJM5OWPxmsgkDkuM/aLr3cBdzUHSJ028RCWBkTO/LsUOKNBpQ/9ePM5AoGVG7//gPlPEqURh5QrsJRJnr75E1qAI1Eu5XVIFrprPx3lxJEDWv6YPjUm6Aj6g2+b9,iv:rvJGN0ha+cACzf8u9dBRu1HOMx1jyx8Gwe2MJpJ6pb4=,tag:wkbymeExmj98vzDMSG5uTQ==,type:str]
user:
password: ENC[AES256_GCM,data:s5U1eR8aM4AM4J8j1VcRM8eSS/V6iJY/Dj9Ggis466Yxg+eUYWEimY1IWWVvFReRZ8WkbACysA56YZrLdEDowc1+lzeZQvPwYg==,iv:T7W1APCEozr7Eck06cDb3+VdVwjhQ3QoOrp7t+Hr2/4=,tag:MCH47JYaLyNEboW1oHC1kQ==,type:str]
gpg:
legacy_fnzr: ENC[AES256_GCM,data:aokSG2rHR6iX94GCcCmCxcz1lXSRvO03uhaUVGrNJT5aDjNjrjLya4TpUEVLvZXy87VaZobfuR+KQIcyi5zFHNCberq3q7h2zmtKhCEsnuy97oam7X39o/Jker/36geFxkDW5kvYAtcYL16Zi6cMB2+VvI7Sv0YGawGvvFfYjHjaV/wl0QPv+jyvM/HT9V7EMqJ7CER2QQVdkPuJHQSy/LsZqtcFGEDTuiGY7jZO4wWPByQ6PNPg4SiGeRfHz9rPvKO4LxQGt6keynM7VApZjTKOMcmaTgdOEgop5Sa9nZ+b5J7BJuP69vwnyREiP6u5T5l7QSxhFei+2K9iBMke+nbwM468lwnV9pUlpbBNxMwqVIRKiAGkcyZilmhlQd9Q4Dy5LwszItOM97+gN70IFkrzf6sO3nKsQWRr7kSwOAwvn1EQGEjj+KE1KM+cu+Y31PBBzkxtWBISJA1qzGcO35aeKNv8wGDGFliecg0Dz4SmtPXwP5Cd46U5XM/w8GMGRFg0b6anink1se7hOuYYSm9PzfJKbDOEL7eV5mhAGC2Qwv1q3Vwss+r1l6/b4myesP+OeVyeGCDMhCqO9VA6sQuBuddS2hYzh7tjI+p+0VXW7wonApNCKAMY90QLu2+8f33twYncWETbK/PkTz1jr4VVQIzh65kDclGPePfC2QMMRlT8eAL8y7u2RvDl6jteeQKiLsG7sz1NCXg484GfD8l9eMW3slLtY0b+9XHuCv09kkGkoktSw2udjoF4s9iJsGKOFRGZ/nLnpoXh0ftlKHvohhfqrTmwwvbPLYg9rn59dO6ZgIwH8hVi+ERWTtfpPERYPbIGLh7iRQf6iPI2d5oiE4wVjOsidiR5fhrb+0S8oALAV1Jhm5Y5Md0ePLrnPJxOXvAqCE1WXpjmZzl37qj+1FV/FFyh3Pq+GfmSN4fEllj7rkFppGBOQ19+8mV1JFkOVfkzwqV4NP8c08FigeO3T4vyvxu4jfMbovjS6Mi8Olia7pNGB6kZogHQXIGH7WE1tqmGFnEOvOHz+YKJ48apCtZ/ePo02lu/xZM4GNO5Q1LXpZtO67tpuepBjtmSGhBhUtt2ssdLpJVsDNbuLKDrT8ZA1wD7gA2C9wx+ycT5+JqE3o99J3unxVI=,iv:o3mrSYQINgMTaQBleo9hdNZZaPC4/OFf7RaJIvDVjv0=,tag:5v0SZBOpjdkFAezrKzQfLQ==,type:str]
ssh:
desktop: ENC[AES256_GCM,data:BXzI4BQmwunDe+PnmRjeDdZgaDVaJCqErhfUiDPtgOtx0+y1wPSTQoHBWM0+qnPTo0GtK2LmjlDGSoXUUl/aavwGyHG+/XMZcRs3LLGZqAOCWCAoA4N8nJIv2PFPCDdboK99HSR70eqHWgHk8McRrqpwDUaCsTaizU+e7R7bKX08kBp+k02fE2OW7OJHTfK6H+qH8yV8PpBXGpiPG/8OMsLa9m+1burb0KeMVRVk8Jd+kQ9meYj0xUH05l/VV7jeZ5XmZQOCtNxIRDnALjfWDJ44QLcdt1OoA8WZCoUV1437u88hYi45vo8IvFK46DBMnQGnGioITkOoIzBYAPFf/RWzyJZChrQ8qgCIfoOszbGrjXu5j1upa0KvLe4EkOBCeGNi+vPG75Q6Ma25jBLXxIq+xBeoSZyW5w9GLNEjXT7D6hXiVpypBQK3AW4JjOLywXDYG5dJzqrS4QQvilKIqj/EWSGiYkrHNJd+jVaBx/M6HrgW9Vfs0JuSz1bWgzASjqn/3zx6UzbaREm+j5Is6t1PPsix+zPKAo09,iv:gmtvM+6auTFlH3fxtq+HXq5PuzGTnIRgLIVfvPuk3hw=,tag:d0kpvr12rA/HcYOw7hDBUw==,type:str]
legacy_ed25519: ENC[AES256_GCM,data:0VbcLU1XtHfgi5mM+qYZ74ZE48DiKc2lzw2Ro13XyLvQMHP6fiTKZkrPFA/LQW+sQBG2Ax5dbAYaf4Gxe5wIWKn0kU8uai17//IS2ahN91fQ2GKC3ofURfwmTEZXnQPHXjK1Kygb6uMGWYOjjiY4JCXsEr2Ur5OTH5Cn7wrOPLFp4V7rK66RlrUuYoB52uGC8ds/KZWSRKZKSRJ2fIJkAZtOFUTzU1nbScKC7pVjt1pZmCI2dYzVD3xo/p90wZAXTTq6B6pprtnApHnzEW8kP5RVUdc9euMQm/HlQUh0RexUlfJCkloVxYD0RRiGL9RFABxQCdeyK6VNcgRZ32M6cUji0FSDgE04qTz0HN062Um/ebB65zFmTAN4GZLClIUqJVa9qXweESGkzbUV5t1J7IXDtG+ZdJmPokX31ozF69Vtcf53LQOee1d4zseP+niOR63tYOkZWkthRRLx4yxXSODyZcVe7ASbwICnxmf3bh1Qbn/4LU3NSBF1DZXiVIKR9COMdO8vqx4H2zZLrkn06I33J9sjoI4ejEFX,iv:Tjts8BRYhE+Nn9dyAL2yNpvPF8oMTwyVvoQkmwAsjrA=,tag:PuHmgIvHt+Dv85EI2WFxng==,type:str]
legacy_rsa: ENC[AES256_GCM,data:PWBAlpIUbxVGDZlxJGvYRiUgeGnR7Bl1hXjzVC6MIt4hLPmc5SksBj5TmW+i6j312RLaFzYTb6SerFlFs6vn3Rtmk5Q7p/IO4JSKondJrsw1xw52YePP29FfIe7gtOxDK/F9YJhHb1VJQghQoWTN++iZjjg80iNVofBtAcrPPkyfH43Yw8In6jMla/p2w6vAhXAJS+8SpEdmdILOQT4OnDvkzi4Nwae2uFEWcGJI/kxstgAL97MTmu06qK9/zt8vuq6bTYeBOOFnasoIL+V/0A5dAz3aw8QwdSoRrN5+PEHmeB9y4+WCf10MTv8P2JxJ9ul4pCwZd2IEdg2gWSQa/vbSJdG7ZjaCih+blNEf8DTVtRQT9soTvti7MYYYziLfHw8LUT+c3nt+c0nXxVxOgRx0sGSuHsHT5HHGBOjw9PsZ+arZuwnIyrmfkm8TkvD+j7je2fqLACRBkp3CXg8a647To4GQXK0Y0yuJUpt18YSbVak9etGj5z7+PWs86NKHQ+gOrMxeirRuHGIa53FQSORYlpBZnM9FCAs4g5Fs4IZard/0LkX1lrhVUOk7OokRstiIWKJMOqRFuN+toZbCWMNVX4Hd8otSFG3U/vo3vK08TEF+HDIhp4rStPjJpOdyZStKyol6sKlHcVdMcgk79fmzesMZoSpITP/GTYe46xZ6vMQ2tvqvd0QcVJfBZuy4q2UUgjY+r8zgVRKw+Wo37YUUr4UFK2W5E23cLFkr+H9nV/cz08V1vUXk2eCi62czFXpjkpubQXysK246wHtdVFGpOmtDxicS4Zn3iqm/UxF5vKKguRaTdejXxfkRbsFhwn6/GrRAW6nxJLLVnSIzJEnNivt88m9cxmb1VYAHRZDNlGDK7ca8IhCb5yzPalRI0KqUMKen3MDLae+eEjcZH/lgGdhsZJg6Kxg/v0XC4dCJxNW+/ckIs5bjYMoQRfJ6OknAVFLwZcY0QZ+5EWrWNDkBEfPKub/r+KcF2sxIrv7KB0qXDsW4pCEcE+85i8xEiFs49ebeV4d42tsLzdYi9iVdZO4I1gzi929rbUFJLzVJCfkyn7Eic1u92UgBAa58lUFZ5LMEH9+P1V4Gm0GPIwXYvd4X+LIGhbqGDjGel+YeeLUHVRj4qeuoz1aLUCF8Cv0e3djBuhJ+tRSKdZM2aSz6PNrK2THfdFSiaHZmfH7McVXNum8TD8lhbkKIPDYdb2La3MVgvvgRN8Gw8L/Xkp/ivuFWXJ8Gc41AIUI2gY2mWbq1YAiwEuMeDJCXXAROKLQrd2rJYI7epbcw2EyLgtc90zsjWa1gFrHfBJVh23B69vWc5uEVyt/ryg3n4tp9QLjNpg0DRMjPTR+vEbsEHl7oLJdPO3XKof0h6QXXJ1ZtgHkSFS9MoXCnNhiC9ZKWA6PM31Yftp82RKiy5CSpf2AIVIOa3p9GUhVI0YlEN5tfejZuhybUL44JZ2FcVlhbC+zzLPIhROguHF0Az4Qg7tzKM9poin4xVV3HXs/mvXAcA8qnlQxnpuei3Lob4Iq1MUb9oNoA0QJ7nKIybSYUhKnGOq0Cv4ZVmxlk+RkXfTS4si3qEg3UxXjonP/e2oU334CsdSS32taP0KNTQzEP6j3AM4Zv/iEobz6XvRsKXHzbrG4UQefuQ+ZDw1DGlr/BKDLq9T+adGCWaCTKJChOIwoEQvij6rxtnGOJu9XC+/Tk8FVuzI/gPnRBOia0uUwaYskgoXmNjMgT+P8yNkdqx7MFJVdrFADyGhSaefVNszQlxfJlpAZtKazEltxmUdW6/pPoG42dfIcX+HxhbX1GqQa3japO7NrPQwLIw4LusBXd/ShLMyxkkYCcAidSgaSWgTWCzEIO5RbxRoxFA4qnEd6fqH61Y6W5Wg0Yk4DwWW/KcKn8xkgPdNk4hPq7IPL/x6Z1Dwb9zYf3T0G+97iezI9ZCNImd82aDOT5UcMZGYDD9yW9sEfohniaJcbu5DocNLTJDBa3UgiWluY7u+q4I/zPKN+9chA7h8p5BYAZJc03d1UBvHL8Mv2D7JIb/GlLhseRoV3A+b2qm6uwcxHA6zksAAx1XOZYlU88ls9ykeKKIB+AmlZEx4EuZG+E98DFp5dndMCYzL/1uy+LEsmTNrdmG+gl7bQlbYq5hOHaqtOAEsft/0VFzteRjg5Lagh0cqB1Rc92EGzQq84G5QYQb/DDZLC4i17SZEvwJoo3Ai476B6JpKefcQ5pPNf219mD/V/rodHMxm5vMC3hBQLpaSQ7ZtZ2jmwsxsWkrVaMU+NGBShqVLV+wsPlIWrSybnZC7hOLawZLev1CJ9Udiy82U1SyL9vB4dfHnhEra85nzdNvKwKzAwnr5mG2w1leJOzdg5kz8I0D98GFxmgrnOeQZ6S7/pjD7Qcw38exvEtCI8fpreAb7djbZN2sUNaSe8oitgukqNajBHlFA2z75P4dZ+IH+tTH25Inem/COojWnVQHsic03eus8x4jinbU6fxgZ6sT0SlyItTFgAAv3XqT3oHBiXIvF8DCcw7EtOeW1aZx6wR6D8JFLXTkMiXeug2wvQxV7MMXt7DBNUPqWLYnsrzAY+UaGkQtlnGiffDjCwbWkDfRpHMutMoYMk9o4yD26XTv3oV79Rod4+R39A8WEQhiHKPKFBS7TW+NttKMQVGgcmWvfRFeem4Iqy6JG22xxQqM9GK8gsUKa8MmEuLAQCGenXHIj+dOVWJugjG4IOdaQR3nB4LgwWIXHciYD9KmjlDsvd0MjQTc1bUBkS3aqOF6uvnWJ5LlWv5gs+OsFRMTe8wyqwCOLkj1EmmfJW3leEl/ONMkuaKCJTl7Yw1gto9itnC7rXFSIuGtLfW+4BSJQDYNRBskBkf81t1b6qejkS/3FFKEl8CzLdnuZU5WM5EOkR8ReAYTF/c4LYQjKDYbTAkXsuf9I8QbJXNwwJrP0C7zR4MgZQ5csKyxMNhxy5prTol5TIfCtwjy9UWOurI8WRwfqf6dyq31HtIDxD+elAJOlnZ+yHYH0Al/AETNhzWej35XJTMpYAK5wyBInM3enzBDqzEXQh4OLBwFMP0RaaZYnGTjbjyTUjmOj6GnMSbjwKECCEJFXfmpGsaxIG5RXIU71eu1x7k/Ifm3HgvQ9Q5Jw+EF6vYo1WNjOf9UbQhEhI1+uKEYEkwD/qFu07l9/WqLp3/nDNS66lnyag8jGKeO9WDb07WBBpxywtlN0vE8q9VmY7wXDdkaf5Gb13VwpaAyStANeP2Mp7XlmvYIFudzAY6kxkxCBA5rCY5guI0ebREHnJgR9ARzK3MD85X5abk8sY7Urx01tVdmx7eqVVrjBsEq65SUg8Z0jA7uVHTpOkVxboxJEWsdQN3JYYXz7Tg7M0t1PEYlxhUFIlIyvD8hrmUfxyZB0YgVI3faTezb+1I6xqAyxGFEVKPBzjyv36V9eMJmGB1wiZv3mNFqMUI9AMUHJAmIg==,iv:oGGm7bveDXNmxqe5Zina03vSVLJx9P3VBC/DbuI6KzY=,tag:taEL0E4Uinv1MQPxeRbPzA==,type:str]
sops:
age:
- recipient: age1y0tj3kt67pfnj38t9c8g2ghry3a0mhcq8rrqv5xr4jekwepxaelqzu3dkf
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOZ3dERmxMbEJmSVhVRmVw
TUZZL0FzTHprci9ENHFodnRVWmRSbk1ab2xnCnZYeXN3MWRJZENlYmtWeFM0azdR
ZDFFYSsxRE9pdGZWV05hWnlacDlKbWcKLS0tIGNveTkwWEN2ajhaZ1JiaXRENzk0
bFhna3RyY1kxK0IyVWlnR2FpMXk3UjQKvJaecXqAecBljJ9cNcHX13nxSxVey3LG
NdvJaMfEV4m3SqRF7YUoTzGYhucYjtX58E5SuvHnaP2qa21aDF+AZQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age16v8w7q4wmn22hhakq2uzaus2508rhldm7lcwh0kukshzjzyhuqesqz44ze
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSZnV1T0JKTXoyeUlZQ3o4
QkR4OHZUbzQrbjdSK2VLTDNzMU9qdlUvVVUwClI4SDhMZTRDRXY3NlJSZ3REdmpJ
L2Y1N1p1VDFuK3VhbjJLaEVaenNQbWMKLS0tIEZGN3VlRFZqUFZQR1hCMTA5SEZN
NVlzQlQvMVc2dHZNK2pEWk80MStwY1UK38mxk1dJWi6XRKSwzcDA9qt8i1Grw2KJ
ac2EbJIFwYLOaMNOKF9hu+NrMdruRpU/2B8HlYYZjpNWmLb9jwI4wQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-12-22T18:37:14Z"
mac: ENC[AES256_GCM,data:BQj7pieRocXUP7as5/coL76WrpBPOwEzHlR+vTEOkBTD89hOnfUo0f2gJi/Ho4KldnCHKjQVGoLhA7l/NIuKXGs8OQ+0IYW9EOoEROi01EePW++Nw7rtOLBRQWojO9HpOmrOz8/fqMHq/vxrdrLql5gomNHJgPllBoAcALCUl2E=,iv:sPB13YhGgDO+KA+azVBqtIPrqRuoPpRfEljV5Xg4ig4=,tag:BnCePF7ii63Glq6dCI7YDg==,type:str]
unencrypted_suffix: _unencrypted
version: 3.11.0

28
secrets/vpn.yaml Normal file
View file

@ -0,0 +1,28 @@
wg0:
address: ENC[AES256_GCM,data:9Tnph2SHKeEt9Ss=,iv:CPR1N7fqqlaThGltSpfqeAOc5bAe13KWskGWj3jI8LQ=,tag:xha/hQOVqfUoGyfKbHhnuQ==,type:str]
dns: ENC[AES256_GCM,data:fXJG1uVYXcM=,iv:6FeSHSHMZHrXo3HLhR0Rpl2PI/9LDYHJwMkNwJv4QGk=,tag:KmuMHk2LgUW5TLAeQkqcMw==,type:str]
conf: ENC[AES256_GCM,data:SRDnI+2PvK7Zz1L5XBvrBNejgJEg8DK+qVO5XEtx6Nal+f7IeB3Ascp8Bkit5fd5myn/RxiK80wYmvLkDmcJAk46UjHKOpbxJl1s5FmKDuZJ3c3MXLwH7k2PeZP14VDDlyQqlcyGBrSu74L64ZMh/6EWGKbONTD1Wt3Ykg+/RegzQFDr2CPbj6XQeXsNS2p0ugicP5ffBMTUa9KSYDMQVV80mjSZ246aeY0owU1VUsitdvsCbfxtFd5gr/9zdfOXOvGY/BKxAlvVbszCalNs9DgJDHt/,iv:FP90SvUGnsZJS7F/uxtbOqTvGOgtC4+r2+YgF5FBoQY=,tag:9G1tkXHTpbytmG9T6sTpMw==,type:str]
sops:
age:
- recipient: age1y0tj3kt67pfnj38t9c8g2ghry3a0mhcq8rrqv5xr4jekwepxaelqzu3dkf
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtOHZSRkpBVVdUUk9OYUFH
cVBra014WXJyRTJ0QWFKallLQlc0SXhNSlFBCmpwME92M2lCN2liVjZBRndlSVBk
OEpUU1YyakdCa0xVaHdhRlpXbGxYdUEKLS0tIDFlV1k0Qkx1UDd2NUVHTTI3NDZE
OWhIdUxDcHB4Z3dTdDkyZWF6NEJCYzAKfPB9AZFQ08yqil+4AhIi6EMy8PXI4CAz
lK4ON/M67T0UrlWN/m3pryOOr4Lj4oiZvdOR0BCO3kn4Pj0nq5jQOA==
-----END AGE ENCRYPTED FILE-----
- recipient: age16v8w7q4wmn22hhakq2uzaus2508rhldm7lcwh0kukshzjzyhuqesqz44ze
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMSC9Td1NTMzk2NlJDTDNM
UVUzTSt1dGkrUVRGT1UzeXcwR1REN1U0dW5JCnNJRzdKZHVyR0dzaUw2TlVzQnQ2
SHhSSGlDWUNBSXZiME5GM0JPTFRseDQKLS0tIEFnOXgzWFo2Rmo2THN4VFFIY1h0
OEZ4WUp1QlVrTkVTN1BHMG0yaXFuSk0KLw3ZuvWTurJDTpyoq5YafLm8YFT4v4Vh
s+ay8ju3kA1CKjMF3gBQF08EoCdP/jU6tZerNwwcs17el5zIvRmG7Q==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-12-17T22:57:50Z"
mac: ENC[AES256_GCM,data:xsXO2t9IyEvuWbz+eYvtcJ6qLdkiKZKnn1wJxbdm6D4A3piAuja0GaS5frahGiEo2jhNMZfm3lVeYvbFCttO5qJjagfT2CIFH3c9kVQO6R9MtbDDi620vrctv9YsLydIulDdEYB1J3JWXIcmyd8yaSIlu9532NqV2Bog3zwq4Io=,iv:50FOOKQkXDq8N3qpAlaE0dtidhscC/DvzOv4aJ/u7Uk=,tag:KaP6Yhf/aMxEAtg6c5w0JQ==,type:str]
unencrypted_suffix: _unencrypted
version: 3.11.0

90
storage.nix Normal file
View file

@ -0,0 +1,90 @@
{ ... }:
{
disko.devices.disk = {
main = {
type = "disk";
device = "/dev/vda";
content = {
type = "gpt";
partitions = {
ESP = {
size = "2G";
type = "EF00";
start = "1M";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
root = {
size = "100%";
content = {
type = "btrfs";
extraArgs = [ "-f" ];
mountpoint = "/.root-disk";
mountOptions = [
"compress=zstd"
"noatime"
];
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@home" = {
mountpoint = "/home";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@nix" = {
mountpoint = "/nix";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@persist" = {
mountpoint = "/.persist";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@nobackup" = {
mountpoint = "/.nobackup";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@snapshots" = {
mountpoint = "/.snapshots";
mountOptions = [
"compress=zstd"
"noatime"
];
};
};
};
};
};
};
};
};
fileSystems."/.persist".neededForBoot = true;
fileSystems."/.nobackup".neededForBoot = true;
swapDevices = [
{
device = "/.nobackup/swapfile";
size = 64 * 1024;
}
];
}

37
users.nix Normal file
View file

@ -0,0 +1,37 @@
{
config,
pkgs,
...
}:
{
sops.secrets."user/password" = {
neededForUsers = true;
sopsFile = ./secrets/home.yaml;
};
sops.secrets."root/password" = {
neededForUsers = true;
sopsFile = ./secrets/home.yaml;
};
users = {
mutableUsers = false;
users = {
root = {
homeMode = "700";
hashedPasswordFile = config.sops.secrets."root/password".path;
};
user = {
uid = 1000;
homeMode = "700";
shell = pkgs.fish;
isNormalUser = true;
group = "user";
extraGroups = [ "libvirt" ];
hashedPasswordFile = config.sops.secrets."user/password".path;
};
};
groups = {
user.gid = 1000;
};
};
}