diff --git a/.sops.yaml b/.sops.yaml index 31130ff..af9d39b 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -1,12 +1,7 @@ keys: - &root age1y0tj3kt67pfnj38t9c8g2ghry3a0mhcq8rrqv5xr4jekwepxaelqzu3dkf - &user age16v8w7q4wmn22hhakq2uzaus2508rhldm7lcwh0kukshzjzyhuqesqz44ze - - &sandbox age1mr42xh9llvrggrvuawr5253qk7gygf4gcg9clqdvjecw3d6tj59qsqxswd creation_rules: - - path_regex: microvm/secrets/sandbox\.yaml$ - key_groups: - - age: - - *sandbox - path_regex: secrets/[^/]+\.yaml$ key_groups: - age: diff --git a/configuration.nix b/configuration.nix index 1fd0b01..7be81c3 100644 --- a/configuration.nix +++ b/configuration.nix @@ -15,6 +15,9 @@ path = "/root/.ssh/desktop"; mode = "0600"; }; + sops.secrets."deepseek_api_key" = { + owner = "agent"; + }; nix.settings.experimental-features = [ "nix-command" "flakes" @@ -93,16 +96,14 @@ enable = true; ports = [ 22 ]; settings = { - PasswordAuthentication = true; - KbdInteractiveAuthentication = true; + PasswordAuthentication = false; + KbdInteractiveAuthentication = false; PermitRootLogin = "no"; AllowUsers = [ "user" ]; }; }; - - ratbagd.enable = true; }; hardware = { @@ -170,10 +171,10 @@ }; systemd.tmpfiles.rules = [ - "d /home/user/dev 0770 user users -" - "d /home/user/pictures 0750 user users -" + "d /home/public 2775 root public - -" + "d /home/public/pictures 2775 root public - -" - "a+ /home/user/dev - - - - d:g:users:rwX,d:m::rwX" - "a+ /home/user/pictures - - - - d:g:users:rwX,d:m::rwX" + "a+ /home/public - - - - d:g:public:rwX,d:m::rwX" + "a+ /home/public/pictures - - - - d:g:public:rwX,d:m::rwX" ]; } diff --git a/executables/opencode.sh b/executables/opencode.sh deleted file mode 100644 index 8735693..0000000 --- a/executables/opencode.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SSH_TARGET="sandbox@vsock%3" - -if [[ "$PWD" == /home/user* ]]; then - project="${PWD/\/home\/user/\/home\/sandbox}" -else - project="$(ssh "$SSH_TARGET" 'mktemp -d -p /tmp opencode-XXXXXX')" -fi - -exec ssh -t "$SSH_TARGET" opencode "$project" "$@" diff --git a/firejail.nix b/firejail.nix deleted file mode 100644 index 7a95668..0000000 --- a/firejail.nix +++ /dev/null @@ -1,101 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: -let - agentProfile = pkgs.writeText "agent.profile" '' - whitelist /nix/store - whitelist /nix/var - read-only /nix/store - whitelist ''${HOME}/.cache/nix - whitelist ''${HOME}/.local/state/nix - whitelist /etc/nix - whitelist /etc/nixos - whitelist /nix/var/nix/daemon-socket - whitelist ''${HOME}/dev - whitelist ''${HOME}/work - whitelist ''${HOME}/.config - - blacklist ''${HOME} - blacklist /etc/nixos/secrets - blacklist /etc/shadow - blacklist /etc/sudoers - blacklist /etc/sudoers.d - blacklist /root - - caps.drop all - nonewprivs - noroot - seccomp - - no3d - nodvd - notv - nou2f - novideo - - - ignore net none - - machine-id - disable-mnt - private-dev - private-tmp - private-cache - ''; -in -{ - programs.firejail = { - enable = true; - wrappedBinaries = { - claude = { - executable = "${pkgs.claude-code}/bin/claude"; - profile = agentProfile; - extraArgs = [ - "--private=~/.local/state/claude-home" - ]; - }; - chromium-sandbox = { - executable = "${pkgs.chromium}/bin/chromium"; - profile = "${pkgs.firejail}/etc/firejail/chromium-browser.profile"; - extraArgs = [ - "--netns=wg0ns" - "--whitelist=~/downloads" - "--env=TGK_THEME=Adwaita:dark" - "--dns=10.2.0.1" - "--private=/home/user/.local/state/chromium-home" - ]; - }; - google-chrome-stable = { - # executable = "${chrome-argumented}/bin/google-chrome-stable"; - executable = "${pkgs.google-chrome}/bin/google-chrome-stable"; - profile = "${pkgs.firejail}/etc/firejail/google-chrome-stable.profile"; - extraArgs = [ - "--env=GTK_THEME=Adwaita:dark" - "--netns=wg-br0ns" - "--dns=10.2.0.1" - "--whitelist=/home/user/downloads" - "--whitelist=/home/user/pictures" - ]; - }; - 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" - ]; - }; - }; - }; -} diff --git a/flake.lock b/flake.lock index 819f475..66ebce0 100644 --- a/flake.lock +++ b/flake.lock @@ -24,14 +24,15 @@ "dms": { "inputs": { "flake-compat": "flake-compat", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "quickshell": "quickshell" }, "locked": { - "lastModified": 1781822553, - "narHash": "sha256-lINO2V/B5MxB6RXGahrPlaL07WvFiJur1WDF6rTYuyk=", + "lastModified": 1777675128, + "narHash": "sha256-2zuDs9Lju99dg8MsSPf1frKPPgCRakDn+CEGX71cHJ0=", "owner": "AvengeMedia", "repo": "DankMaterialShell", - "rev": "4203148cabb74abfb17e5c02f3b76c28b52601e7", + "rev": "c1cbd0994f5a3585dded85069f2c9103c54f5285", "type": "github" }, "original": { @@ -40,71 +41,6 @@ "type": "github" } }, - "fenix": { - "inputs": { - "nixpkgs": [ - "ferrosonic", - "nixpkgs" - ], - "rust-analyzer-src": "rust-analyzer-src" - }, - "locked": { - "lastModified": 1782550137, - "narHash": "sha256-XvgBjuAmdT7fvltu56lvZULtDHCr0BLVdEAdfQQlYqw=", - "owner": "nix-community", - "repo": "fenix", - "rev": "4febf815bd2c2f1181e027c5b07fb66d85317cc6", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "fenix", - "type": "github" - } - }, - "fenix_2": { - "inputs": { - "nixpkgs": [ - "ferrosonic", - "naersk", - "nixpkgs" - ], - "rust-analyzer-src": "rust-analyzer-src_2" - }, - "locked": { - "lastModified": 1752475459, - "narHash": "sha256-z6QEu4ZFuHiqdOPbYss4/Q8B0BFhacR8ts6jO/F/aOU=", - "owner": "nix-community", - "repo": "fenix", - "rev": "bf0d6f70f4c9a9cf8845f992105652173f4b617f", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "fenix", - "type": "github" - } - }, - "ferrosonic": { - "inputs": { - "fenix": "fenix", - "naersk": "naersk", - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1782822043, - "narHash": "sha256-UsStOiULt4i7hO2dasJI4MqwK0i8JzsJKgzqQHEW6mA=", - "owner": "jaidaken", - "repo": "ferrosonic", - "rev": "ac0a146b515979238b9577a4b13f30479b02b07c", - "type": "github" - }, - "original": { - "owner": "jaidaken", - "repo": "ferrosonic", - "type": "github" - } - }, "flake-compat": { "flake": false, "locked": { @@ -167,11 +103,11 @@ ] }, "locked": { - "lastModified": 1781906751, - "narHash": "sha256-6Ld1PqmptFtFKblE+SynhRgyBApUWcmrISetWqWHeeo=", + "lastModified": 1777679572, + "narHash": "sha256-egYNbRrkn+6SwTHinhdb6WUfzzdC3nXfCRqS321VylY=", "owner": "nix-community", "repo": "home-manager", - "rev": "37f21dfa5d27e71b75bacd9418b156f9265e312e", + "rev": "9cb587ade2aa1b4a7257f0238d41072690b0ca4f", "type": "github" }, "original": { @@ -204,7 +140,7 @@ "impermanence": { "inputs": { "home-manager": "home-manager_2", - "nixpkgs": "nixpkgs_3" + "nixpkgs": "nixpkgs_2" }, "locked": { "lastModified": 1769548169, @@ -220,49 +156,6 @@ "type": "github" } }, - "microvm": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ], - "spectrum": "spectrum" - }, - "locked": { - "lastModified": 1784320259, - "narHash": "sha256-9yPGZVcPV0W9Iq1qL4rfkNigKIIUk4jRk3YbJNr3pLA=", - "owner": "microvm-nix", - "repo": "microvm.nix", - "rev": "24ae5c9f140e4c4b06d132ea3fc7795b550dfe9e", - "type": "github" - }, - "original": { - "owner": "microvm-nix", - "repo": "microvm.nix", - "type": "github" - } - }, - "naersk": { - "inputs": { - "fenix": "fenix_2", - "nixpkgs": [ - "ferrosonic", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1782220280, - "narHash": "sha256-thLTFbp9D5Qknmh8q/v4FRpLGphUSijT3E86cbLYTXo=", - "owner": "nix-community", - "repo": "naersk", - "rev": "9aa07bb0256d300219b30622d2454e85f7f3667e", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "naersk", - "type": "github" - } - }, "niri-branch": { "inputs": { "nixpkgs": [ @@ -271,11 +164,11 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1781817881, - "narHash": "sha256-pRPtSWYy9XsVnvjHhXhaGX3uwqFdfAn2fXvxQ0xKXnk=", + "lastModified": 1771283045, + "narHash": "sha256-AgD3KAkrQ4cs34kKZE8v/+FyFTc1Vq2sOJaPrWiCRio=", "owner": "argosnothing", "repo": "niri", - "rev": "cd36d0374d6e66bc07248899d02478f42719ecc2", + "rev": "eab116015a5a4d8f027c915dbd7b0a90e1e9a5e1", "type": "github" }, "original": { @@ -310,11 +203,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1778443072, - "narHash": "sha256-zi7/fsqM/kFdNuED//4WOCUtezGtKKqRNORjMvfwjnA=", + "lastModified": 1776169885, + "narHash": "sha256-l/iNYDZ4bGOAFQY2q8y5OAfBBtrDAaPuRQqWaFHVRXM=", "owner": "nixos", "repo": "nixpkgs", - "rev": "da5ad661ba4e5ef59ba743f0d112cbc30e474f32", + "rev": "4bd9165a9165d7b5e33ae57f3eecbcb28fb231c9", "type": "github" }, "original": { @@ -325,22 +218,6 @@ } }, "nixpkgs_2": { - "locked": { - "lastModified": 1782467914, - "narHash": "sha256-pGvFkM8N0xEkIIXDe5YYfbEAvHrk4IxBrjB/x8OomhE=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "e73de5be04e0eff4190a1432b946d469c794e7b4", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_3": { "locked": { "lastModified": 1768564909, "narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=", @@ -356,7 +233,7 @@ "type": "github" } }, - "nixpkgs_4": { + "nixpkgs_3": { "locked": { "lastModified": 1744536153, "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", @@ -372,13 +249,13 @@ "type": "github" } }, - "nixpkgs_5": { + "nixpkgs_4": { "locked": { - "lastModified": 1781960011, - "narHash": "sha256-66fKJZTRbxFJ48dE3kDdCaHTbux6nmApvIQhtwcaI0E=", + "lastModified": 1777731324, + "narHash": "sha256-piLMdJYPP/9+/yiHxVMpqbAAoP8EnsqRO5921ilx0lk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c1b9ab3ad7c39b61915438b2222e3655b7d8a16f", + "rev": "38e436af6ec1a3b1c9b666ceea098bf5ef05fc66", "type": "github" }, "original": { @@ -387,13 +264,13 @@ "type": "github" } }, - "nixpkgs_6": { + "nixpkgs_5": { "locked": { - "lastModified": 1781577229, - "narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=", + "lastModified": 1777578337, + "narHash": "sha256-Ad49moKWeXtKBJNy2ebiTQUEgdLyvGmTeykAQ9xM+Z4=", "owner": "nixos", "repo": "nixpkgs", - "rev": "567a49d1913ce81ac6e9582e3553dd90a955875f", + "rev": "15f4ee454b1dce334612fa6843b3e05cf546efab", "type": "github" }, "original": { @@ -406,14 +283,14 @@ "nur": { "inputs": { "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_6" + "nixpkgs": "nixpkgs_5" }, "locked": { - "lastModified": 1781959811, - "narHash": "sha256-ZKWWQbvWnZwHU6YTWB7uoIgeXw70z82mJglH7DmCTDg=", + "lastModified": 1777729540, + "narHash": "sha256-tF5WMS4SSSmDvEZ7qgOosh8q0BVdz/ynb4Wnruc1rgY=", "owner": "nix-community", "repo": "NUR", - "rev": "8ccedaa4ba8b650594426145a6f67201b685359c", + "rev": "1091dd1d0f6589dc9a88d808052dda9b85835670", "type": "github" }, "original": { @@ -422,55 +299,41 @@ "type": "github" } }, + "quickshell": { + "inputs": { + "nixpkgs": [ + "dms", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1776854048, + "narHash": "sha256-lLbV66V3RMNp1l8/UelmR4YzoJ5ONtgvEtiUMJATH/o=", + "ref": "refs/heads/master", + "rev": "783c953987dc56ff0601abe6845ed96f1d00495a", + "revCount": 806, + "type": "git", + "url": "https://git.outfoxxed.me/quickshell/quickshell" + }, + "original": { + "rev": "783c953987dc56ff0601abe6845ed96f1d00495a", + "type": "git", + "url": "https://git.outfoxxed.me/quickshell/quickshell" + } + }, "root": { "inputs": { "disko": "disko", "dms": "dms", - "ferrosonic": "ferrosonic", "home-manager": "home-manager", "impermanence": "impermanence", - "microvm": "microvm", "niri-branch": "niri-branch", "niri-scratchpad": "niri-scratchpad", - "nixpkgs": "nixpkgs_5", + "nixpkgs": "nixpkgs_4", "nur": "nur", "sops-nix": "sops-nix" } }, - "rust-analyzer-src": { - "flake": false, - "locked": { - "lastModified": 1782469328, - "narHash": "sha256-EVrPvYr7VtAtiUWdKglwTSVT+KgQNcZ8EEWL/CnBC0o=", - "owner": "rust-lang", - "repo": "rust-analyzer", - "rev": "a77548188dbecc332bdc292b01a5077ec770cd98", - "type": "github" - }, - "original": { - "owner": "rust-lang", - "ref": "nightly", - "repo": "rust-analyzer", - "type": "github" - } - }, - "rust-analyzer-src_2": { - "flake": false, - "locked": { - "lastModified": 1752428706, - "narHash": "sha256-EJcdxw3aXfP8Ex1Nm3s0awyH9egQvB2Gu+QEnJn2Sfg=", - "owner": "rust-lang", - "repo": "rust-analyzer", - "rev": "591e3b7624be97e4443ea7b5542c191311aa141d", - "type": "github" - }, - "original": { - "owner": "rust-lang", - "ref": "nightly", - "repo": "rust-analyzer", - "type": "github" - } - }, "rust-overlay": { "inputs": { "nixpkgs": [ @@ -479,11 +342,11 @@ ] }, "locked": { - "lastModified": 1781752752, - "narHash": "sha256-kVG5tV9hddPviGAgqf9sGSuStvv+HAB9onfKqGptV0k=", + "lastModified": 1767322002, + "narHash": "sha256-yHKXXw2OWfIFsyTjduB4EyFwR0SYYF0hK8xI9z4NIn0=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "c06d86dabe5b92982b9d67acccb9990d58da3a0e", + "rev": "03c6e38661c02a27ca006a284813afdc461e9f7e", "type": "github" }, "original": { @@ -494,7 +357,7 @@ }, "rust-overlay_2": { "inputs": { - "nixpkgs": "nixpkgs_4" + "nixpkgs": "nixpkgs_3" }, "locked": { "lastModified": 1772075164, @@ -517,11 +380,11 @@ ] }, "locked": { - "lastModified": 1781943681, - "narHash": "sha256-NFHmA7H47adqiyp+0iEOyZOQhmigDqA/NBAlf4imB6U=", + "lastModified": 1777338324, + "narHash": "sha256-bc+ZZCmOTNq86/svGnw0tVpH7vJaLYvGLLKFYP08Q8E=", "owner": "Mic92", "repo": "sops-nix", - "rev": "420f8d2e9882911f65cfac15cc706f639ba96cca", + "rev": "8eaee5c45428b28b8c47a83e4c09dccec5f279b5", "type": "github" }, "original": { @@ -530,22 +393,6 @@ "type": "github" } }, - "spectrum": { - "flake": false, - "locked": { - "lastModified": 1783694892, - "narHash": "sha256-xO8f7Qng+18FK2UlB9vcrkxCaQMCt5WjCH24aW/11eg=", - "ref": "refs/heads/main", - "rev": "24c4346e30fdea8d8e80f34aec3554a15a667d24", - "revCount": 1410, - "type": "git", - "url": "https://spectrum-os.org/git/spectrum" - }, - "original": { - "type": "git", - "url": "https://spectrum-os.org/git/spectrum" - } - }, "systems": { "locked": { "lastModified": 1681028828, diff --git a/flake.nix b/flake.nix index a842bf2..a693e7d 100644 --- a/flake.nix +++ b/flake.nix @@ -7,10 +7,10 @@ url = "github:Mic92/sops-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; - microvm = { - url = "github:microvm-nix/microvm.nix"; - inputs.nixpkgs.follows = "nixpkgs"; - }; + # microvm = { + # url = "github:microvm-nix/microvm.nix/da28962a2ba84718895b7325f600686c3b4ee099"; + # inputs.nixpkgs.follows = "nixpkgs"; + # }; disko = { url = "github:nix-community/disko/latest"; inputs.nixpkgs.follows = "nixpkgs"; @@ -31,7 +31,6 @@ inputs.nixpkgs.follows = "nixpkgs"; }; dms.url = "github:AvengeMedia/DankMaterialShell"; - ferrosonic.url = "github:jaidaken/ferrosonic"; }; outputs = @@ -40,7 +39,6 @@ sops-nix, impermanence, home-manager, - microvm, ... }: let @@ -51,7 +49,7 @@ config.allowUnfree = true; # overlays = [ inputs.neovim-nightly-overlay.overlays.default ]; }; - microvm = inputs.microvm.nixosModules.host; + # microvm = inputs.microvm.nixosModules.host; in { nixosConfigurations."${hostname}" = nixpkgs.lib.nixosSystem { @@ -61,7 +59,7 @@ nixpkgs impermanence home-manager - microvm + # microvm sops-nix ; hostname = hostname; @@ -75,10 +73,9 @@ ./packages.nix ./kernel ./home - ./firejail.nix inputs.sops-nix.nixosModules.sops - inputs.microvm.nixosModules.host - (import ./microvm/sandbox.nix) + # inputs.microvm.nixosModules.host + # (import ./vms) inputs.disko.nixosModules.disko inputs.impermanence.nixosModules.impermanence inputs.home-manager.nixosModules.home-manager @@ -108,7 +105,6 @@ }); } ); - ferrosonic = inputs.ferrosonic.packages.${prev.stdenv.hostPlatform.system}.default; }) inputs.nur.overlays.default (_: prev: { diff --git a/home/agents.nix b/home/agents.nix index 27fb52f..630454b 100644 --- a/home/agents.nix +++ b/home/agents.nix @@ -227,7 +227,7 @@ let enable = true; setSessionVariables = false; extraConfig = { - XDG_CACHE_HOME = "${HOME}/.cache"; + XDG_CACHE_HOME = "$HOME/.cache"; }; }; }; @@ -236,8 +236,8 @@ in { home-manager.users = lib.mkMerge [ (home-manager-config { - uid = 1001; - username = "sandbox"; + uid = 1002; + username = "agent"; }) ]; } diff --git a/home/nvim/default.nix b/home/nvim/default.nix index ce34276..4e9cc2e 100644 --- a/home/nvim/default.nix +++ b/home/nvim/default.nix @@ -87,7 +87,7 @@ in less = { "prettierd" }, blade = { "blade-formatter" }, go = { "gofmt" }, - wgsl = { "wgslfmt" }, + wgsl = { "wgsl_fmt" }, odin = { "odinfmt" }, }, }) @@ -107,6 +107,14 @@ in ''; } leap-nvim + { + plugin = lsp_lines-nvim; + type = "lua"; + config = '' + require("lsp_lines").setup() + vim.keymap.set("n", "it", require("lsp_lines").toggle, { desc = "Toggle LSP lines" }) + ''; + } { plugin = mini-icons; type = "lua"; @@ -143,13 +151,13 @@ in # plugin = neotest-zig; # type = "lua"; # } - { - plugin = nvim-autopairs; - type = "lua"; - config = '' - require('nvim-autopairs').setup() - ''; - } + # { + # plugin = nvim-autopairs; + # type = "lua"; + # config = '' + # require('nvim-autopairs').setup() + # ''; + # } { plugin = nvim-dap; type = "lua"; @@ -372,12 +380,23 @@ in require("ts-autotag").setup() ''; } + # { + # plugin = toggleterm-nvim; + # type = "lua"; + # config = '' + # require("toggleterm").setup() + # vim.keymap.set("n", "nt", "ToggleTerm size=120 direction=tab name=ttermh", { desc = "Toggle tterm tab" }) + # vim.keymap.set("n", "ns", "ToggleTerm direction=vertical name=ttermv", { desc = "Toggle tterm vertical" }) + # vim.keymap.set("n", "", "ToggleTerm direction=float name=ttermf", { desc = "Toggle tterm float" }) + # ''; + # } { plugin = trouble-nvim; type = "lua"; config = '' require("trouble").setup({}) vim.keymap.set("n", "id", "Trouble diagnostics toggle", { desc = "Trouble project" }) + -- vim.keymap.set("n", "io", "Trouble diagnostics toggle filter.buf=0", { desc = "Trouble buffer" }) ''; } { diff --git a/home/nvim/plugins.lua b/home/nvim/plugins.lua index d68a383..a0ea9f2 100644 --- a/home/nvim/plugins.lua +++ b/home/nvim/plugins.lua @@ -152,3 +152,15 @@ vim.api.nvim_create_autocmd("CmdlineLeave", { vim.keymap.set({ "n", "x", "o" }, "s", "(leap)", { desc = "leap" }) vim.keymap.set({ "n", "x", "o" }, "S", "(leap-from-window)", { desc = "leap across window" }) + +require("neotest").setup({ + adapters = { + require("neotest-pest"), + }, +}) +vim.keymap.set("n", "pn", function() + require("neotest").run.run() +end, { desc = "test nearest" }) +vim.keymap.set("n", "pe", function() + require("neotest").run.run(vim.fn.expand("%")) +end, { desc = "test file" }) diff --git a/home/nvim/settings.lua b/home/nvim/settings.lua index e4caa0d..7cdbfb3 100644 --- a/home/nvim/settings.lua +++ b/home/nvim/settings.lua @@ -114,7 +114,7 @@ vim.diagnostic.config({ virtual_lines = true, signs = true, underline = true, - update_in_insert = true, + update_in_insert = false, severity_sort = true, }) diff --git a/home/root.nix b/home/root.nix index 77593f3..f601343 100644 --- a/home/root.nix +++ b/home/root.nix @@ -19,7 +19,7 @@ ssh = { enable = true; enableDefaultConfig = false; - settings = { + matchBlocks = { "icefox.sh" = { user = "git"; identityFile = "/root/.ssh/desktop"; diff --git a/home/user.nix b/home/user.nix index afe9204..bccadfe 100644 --- a/home/user.nix +++ b/home/user.nix @@ -27,12 +27,9 @@ sops.defaultSopsFile = ../secrets/home.yaml; sops.age.keyFile = "/.persist/${HOME}/.config/sops/age/keys.txt"; - sops.secrets = { - "user/ssh/desktop" = { - path = "${HOME}/.ssh/desktop"; - mode = "0600"; - }; - "navidrome/user" = { }; + sops.secrets."user/ssh/desktop" = { + path = "${HOME}/.ssh/desktop"; + mode = "0600"; }; home.file."/.ssh/desktop.pub".text = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILABd/iSJ4gn/ystDqNxLJTG0n0z5VIC9YXlmdUfOhHf desktop@icefox.sh"; @@ -62,16 +59,13 @@ systemd.user.services.waypipe-socket = { Unit = { Description = "start waypipe client"; - After = [ "niri.service" ]; - Requires = [ "niri.service" ]; }; Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { ExecStart = "${pkgs.waypipe}/bin/waypipe --socket /tmp/waypipe.sock client"; - ExecStartPost = "${pkgs.acl}/bin/setfacl -m g:sandbox:rw /tmp/waypipe.sock"; - ExecStopPost = "${pkgs.coreutils}/bin/rm /tmp/waypipe.sock"; + ExecStartPost = "${pkgs.acl}/bin/setfacl -m u:agent:rw /tmp/waypipe.sock"; RuntimeDirectory = "waypipe"; Type = "simple"; Restart = "on-failure"; @@ -106,24 +100,6 @@ }; }; - xdg.configFile."ferrosonic/config.toml".text = '' - BaseURL = "https://navidrome.icefox.sh" - Username = "user" - PasswordFile = "${config.sops.secrets."navidrome/user".path}" - Theme = "Catppuccin" - Cava = true - CavaSize = 40 - Daemon = false - AutoContinue = false - RepeatMode = "Off" - CoverArt = true - CoverArtSize = 16 - Scrobble = true - Notifications = true - RateSwitchDelayMs = 500 - MusicFolderId = 1 - ''; - xdg.desktopEntries = { google-chrome = { name = "Google Chrome"; @@ -253,17 +229,16 @@ extraConfig = { SCREENSHOTS = "$HOME/pictures/screenshots"; - XDG_CACHE_HOME = "${HOME}/.cache"; + XDG_CACHE_HOME = "$HOME/.cache"; }; }; programs = { - opencode.enable = true; dank-material-shell.enable = true; ssh = { enable = true; enableDefaultConfig = false; - settings = { + matchBlocks = { "*" = { serverAliveInterval = 60; serverAliveCountMax = 3; @@ -300,15 +275,15 @@ user = { name = "felipematos"; email = "5471818+fnzr@users.noreply.github.com"; - signingkey = "${HOME}/.ssh/desktop.pub"; + signingkey = "E6C30AB4CD83BB00"; }; }; } ]; settings = { user = { - email = "felipe@imatos.dev"; - name = "fmatos"; + email = "felipe@icefox.sh"; + name = "icefox"; signingkey = "${HOME}/.ssh/desktop.pub"; }; gpg.format = "ssh"; @@ -355,7 +330,7 @@ }; safe = { directory = [ - "/home/sandbox/*" + "/home/agent/*" ]; }; }; @@ -364,14 +339,9 @@ home.packages = with pkgs; [ xrdb - # (writeShellScriptBin "agent" '' - # machinectl shell agent@ ${waypipe}/bin/waypipe --socket /run/waypipe.sock server fish - # '') - (writeShellApplication { - name = "opencode-sandbox"; - runtimeInputs = [ openssh ]; - text = builtins.readFile ../executables/opencode.sh; - }) + (writeShellScriptBin "agent" '' + machinectl shell agent@ ${waypipe}/bin/waypipe --socket /run/waypipe.sock server fish + '') (writeShellApplication { name = "tmux-sessionizer"; runtimeInputs = [ diff --git a/impermanence.nix b/impermanence.nix index 7936f33..b018315 100644 --- a/impermanence.nix +++ b/impermanence.nix @@ -30,11 +30,11 @@ ]; }; - # users.agent = { - # files = [ - # ".config/sops/age/keys.txt" - # ]; - # }; + users.agent = { + files = [ + ".config/sops/age/keys.txt" + ]; + }; }; environment.persistence."/.nobackup" = { diff --git a/kernel/default.nix b/kernel/default.nix index 6edd722..404a84e 100644 --- a/kernel/default.nix +++ b/kernel/default.nix @@ -15,6 +15,7 @@ let "$@" ''; nsWrapper = pkgs.writeShellScriptBin "ns" '' + exec /run/wrappers/bin/doas ${nsExec}/bin/ns-raw "$@" ''; in @@ -23,16 +24,17 @@ in ./hardened.nix ./vfio.nix ./standard.nix + # ./apparmor.nix ]; custom.kernel.hardened.enable = true; custom.kernel.vfio.enable = false; custom.kernel.standard.enable = true; - security.apparmor.enable = false; + # security.apparmor.enable = false; specialisation.unhardened.configuration = { custom.kernel.hardened.enable = lib.mkForce false; - security.apparmor.enable = lib.mkForce false; + # security.apparmor.enable = lib.mkForce false; }; specialisation.vfio.configuration = { @@ -55,10 +57,6 @@ in runAs = "root"; keepEnv = true; persist = true; - setEnv = [ - "EDITOR" - "TERM" - ]; } { users = [ "user" ]; @@ -66,6 +64,23 @@ in noPass = true; keepEnv = false; } + { + users = [ "user" ]; + runAs = "agent"; + noPass = true; + keepEnv = true; + } + { + users = [ + "user" + "agent" + "work" + ]; + runAs = "root"; + noPass = true; + keepEnv = true; + cmd = "${nsExec}/bin/ns-raw"; + } ]; }; @@ -74,19 +89,6 @@ in security.pam.services.su.requireWheel = true; security.pam.services.newgrp.requireWheel = true; - security.polkit = { - enable = true; - extraConfig = '' - polkit.addRule(function(action, subject) { - if ((action.id == "org.freedesktop.machine1.host-shell" || - action.id == "org.freedesktop.machine1.login") && - subject.user == "user") { - return polkit.Result.YES; - } - }); - ''; - }; - boot = { loader = { systemd-boot.enable = true; diff --git a/microvm/sandbox.nix b/microvm/sandbox.nix deleted file mode 100644 index cd530ed..0000000 --- a/microvm/sandbox.nix +++ /dev/null @@ -1,234 +0,0 @@ -{ - impermanence, - sops-nix, - home-manager, - ... -}: -let - impermanenceModule = impermanence.nixosModules.impermanence; - sopsModule = sops-nix.nixosModules.sops; - homeManagerModule = home-manager.nixosModules.home-manager; -in -{ - microvm.host.useNotifySockets = true; - microvm.vms."sandbox" = { - config = - { - config, - pkgs, - lib, - ... - }: - { - imports = [ - impermanenceModule - sopsModule - homeManagerModule - ]; - - sops.defaultSopsFile = ./secrets/sandbox.yaml; - sops.age.keyFile = "/.persist/secrets/age-keys.txt"; - sops.secrets."root-password-hash" = { - neededForUsers = true; - }; - sops.secrets."sandbox-password-hash" = { - neededForUsers = true; - }; - sops.secrets."deepseek-api-key" = { - owner = "sandbox"; - mode = "0400"; - }; - - fileSystems."/.persist".neededForBoot = true; - - users.users.root = { - hashedPasswordFile = config.sops.secrets."root-password-hash".path; - openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILABd/iSJ4gn/ystDqNxLJTG0n0z5VIC9YXlmdUfOhHf desktop@icefox.sh" - ]; - }; - users.users.host = { - isNormalUser = true; - uid = 1000; - group = "users"; - }; - users.users.sandbox = { - isNormalUser = true; - uid = 1001; - group = "users"; - extraGroups = [ - "video" - "render" - ]; - hashedPasswordFile = config.sops.secrets."sandbox-password-hash".path; - openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILABd/iSJ4gn/ystDqNxLJTG0n0z5VIC9YXlmdUfOhHf desktop@icefox.sh" - ]; - }; - services.openssh.enable = true; - - boot.kernelModules = [ - "drm" - "virtio_gpu" - ]; - boot.blacklistedKernelModules = lib.mkForce [ ]; - - environment.sessionVariables = { - WAYLAND_DISPLAY = "wayland-1"; - DISPLAY = ":0"; - QT_QPA_PLATFORM = "wayland"; - GDK_BACKEND = "wayland"; - XDG_SESSION_TYPE = "wayland"; - }; - - hardware.graphics.enable = true; - system.stateVersion = lib.trivial.release; - - environment.systemPackages = with pkgs; [ - xdg-utils - tmux - waypipe - opencode - fd - ripgrep - podman-compose - ]; - - environment.persistence."/.persist" = { - enable = true; - hideMounts = true; - users.sandbox = { - directories = [ - ".local/share/opencode" - ".claude" - ]; - files = [ - ".claude.json" - ]; - }; - - }; - - home-manager = { - useGlobalPkgs = true; - users.sandbox = { - home.stateVersion = "26.11"; - xdg.configFile."containers/containers.conf".text = '' - [engine] - compose_warning_logs=false - events_logger="file" - - [containers] - log_driver="k8s-file" - ''; - xdg.configFile."opencode/opencode.json".text = builtins.toJSON { - "$schema" = "https://opencode.ai/config.json"; - provider = { - deepseek = { - npm = "@ai-sdk/openai-compatible"; - name = "DeepSeek"; - options = { - baseURL = "https://api.deepseek.com"; - apiKey = "{file:${config.sops.secrets."deepseek-api-key".path}}"; - }; - models = { - "deepseek-v4-pro" = { - name = "DeepSeek-V4-Pro"; - limit = { - context = 1048576; - output = 262144; - }; - options = { - reasoningEffort = "high"; - thinking.type = "enabled"; - }; - }; - "deepseek-v4-flash" = { - name = "DeepSeek-V4-Flash"; - limit = { - context = 1048576; - output = 262144; - }; - options = { - reasoningEffort = "high"; - thinking.type = "enabled"; - }; - }; - }; - }; - }; - }; - }; - }; - - virtualisation.containers.enable = true; - virtualisation.podman = { - enable = true; - dockerCompat = true; - defaultNetwork.settings.dns_enabled = true; - }; - microvm = { - vsock = { - cid = 3; - ssh.enable = true; - }; - writableStoreOverlay = "/nix/.rw-store"; - # graphics.enable = true; - mem = 4096; - interfaces = [ - { - type = "user"; - id = "vm-1"; - mac = "02:00:00:01:01:01"; - } - ]; - volumes = [ - { - mountPoint = "/var"; - image = "var.img"; - size = 256; - } - { - mountPoint = "/nix/.rw-store"; - image = "nix-store-overlay.img"; - size = 512; - } - { - mountPoint = "/.persist"; - image = "persist.img"; - size = 1; - } - ]; - shares = [ - { - proto = "virtiofs"; - tag = "projects"; - source = "/home/user/dev"; - mountPoint = "/home/sandbox/dev"; - } - { - proto = "virtiofs"; - tag = "work"; - source = "/home/user/work"; - mountPoint = "/home/sandbox/work"; - } - { - proto = "virtiofs"; - tag = "screenshots"; - source = "/home/user/pictures"; - mountPoint = "/home/sandbox/pictures"; - readOnly = true; - } - { - proto = "virtiofs"; - tag = "ro-store"; - source = "/nix/store"; - mountPoint = "/nix/.ro-store"; - readOnly = true; - } - ]; - hypervisor = "qemu"; - }; - }; - }; -} diff --git a/microvm/secrets/sandbox.yaml b/microvm/secrets/sandbox.yaml deleted file mode 100644 index 0b93259..0000000 --- a/microvm/secrets/sandbox.yaml +++ /dev/null @@ -1,18 +0,0 @@ -root-password-hash: ENC[AES256_GCM,data:YTQn1UGwgrlCD381u+Z7xXMgUoigKXp+Na1/Aj0GExikEeIs9SkBIcAyQ2Dw0FimL0wgG4z+AxFhdAnzRHcbecvvb3tRrTX3VjFt+CLPWscZar1jjNesPyV1inXI2IFW06twHbAl4oQHFQ==,iv:Va0B4aFUlavJd3AGzDbAnmAnAX3fEow4ByIQzfPbheM=,tag:OIjXY7ngZow7Y3tRFZ8iiA==,type:str] -sandbox-password-hash: ENC[AES256_GCM,data:bxVKDAsk6ao0D+xIgAR2Sh1msoPJGEE8P0+O9YGZS/F+DZl33r/JQbNFYJzZgbHDqzLDbab0tnzyRwbfepT2eV/KWaroQDFcBCLJ07t4lTOtdJ3mR/dB1UftrCvvmoPubVrguDPvftQLAg==,iv:tDErYBYhfPrOKyH7W41SUAFgT54bA7QvUYmo35GWMIs=,tag:vNJVKrlCwCuZl4z8KFby2Q==,type:str] -deepseek-api-key: ENC[AES256_GCM,data:pzg/7L92Ig+m3nhZBiYFSfdLuJFmamWWmPQwMxmctRS2kVQ=,iv:yCu+kPXkOxhfpVLlOvUpB/BwygedRaJviPe2D0tCW78=,tag:YTM7hx4UdZEsB9qfXs5LXQ==,type:str] -sops: - age: - - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzQXlvQWl3aWtSWjU5QWVN - K3JGSzg0RElZSkVxNWFmTDNMNzVHckFuZkM4CnJiVDFDTTZ3cDBrTG5RR2RTR3A0 - RmdDSVA1T1dDbUZTNWJQNzB1K0dhYnMKLS0tIDk3VVJBSUFLVjMrdzV5MTFzRXlF - N0ZZa3JnSXN2bHdLa1hoVFlmSUhXWWMK5JCznoaqS6svxcBl6UF9XqbfirZ9L2np - /CTlYyWRadRvRmxrNkYNdgGn4V+is9FG+Et0u8JHAMvI7x/+W99yGA== - -----END AGE ENCRYPTED FILE----- - recipient: age1mr42xh9llvrggrvuawr5253qk7gygf4gcg9clqdvjecw3d6tj59qsqxswd - lastmodified: "2026-07-18T18:23:56Z" - mac: ENC[AES256_GCM,data:d/vRaH5vFzTkb8WopwIDb9Ku7n0EXUR5PyE/fmYhDWcCGX71PcM23Y1DPX1SCY6ydnpxqtGxfRiJOZMfIAx+tCBKX5Szj2aPnKXpogtukZbWWT4pF5jYWnlXcA9R7b9CY0sSAXIetyKhAaH086PJ2i2tAx8TiqZNkUFyoR6g0+E=,iv:R+cOmhYJnVPMjaiL5J0zbFUR69sNR78Gz5ea3CV6X6Y=,tag:RlaTyampHdMtmzvHskM4Dw==,type:str] - unencrypted_suffix: _unencrypted - version: 3.13.1 diff --git a/networking.nix b/networking.nix index 72cb6ee..65c34eb 100644 --- a/networking.nix +++ b/networking.nix @@ -15,8 +15,9 @@ networking = { hostName = hostname; - networkmanager.enable = false; nameservers = [ "192.168.88.3" ]; + networkmanager.enable = false; + firewall.trustedInterfaces = [ "vlan66" ]; useDHCP = false; useNetworkd = true; @@ -71,28 +72,20 @@ linkConfig.RequiredForOnline = "routable"; }; - networks."30-vm-1" = { - matchConfig.Name = "vm-1"; - address = [ "10.0.0.1/24" ]; - networkConfig.IPMasquerade = "both"; - }; + # netdevs."30-vlan66" = { + # netdevConfig = { + # Kind = "vlan"; + # Name = "vlan66"; + # }; + # vlanConfig = { + # Id = 66; + # }; + # }; - }; - - networking.nat = { - enable = true; - internalInterfaces = [ "vm-*" ]; - externalInterface = "br0"; - }; - - services.resolved = { - enable = true; - settings = { - Resolve = { - Domains = [ "~." ]; - FallbackDNS = null; - }; - }; + # networks."30-vlan66" = { + # matchConfig.Name = "vlan66"; + # networkConfig.DHCP = "yes"; + # }; }; services.wireguard-netns = { @@ -120,4 +113,46 @@ }; }; }; + + # 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 + # echo "nameserver $(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 + # ''; + # }; + # }; } diff --git a/packages.nix b/packages.nix index 09b439f..3c863b3 100644 --- a/packages.nix +++ b/packages.nix @@ -14,12 +14,12 @@ bluetuith bluez bluez-tools - cava + cargo clang clang-tools clevis cliphist - ungoogled-chromium + chromium distrobox dos2unix dnsutils @@ -27,7 +27,6 @@ (import ./templates/extract.sh.nix { inherit pkgs; }) eza fd - ferrosonic ffmpeg file fira-code-symbols @@ -39,6 +38,7 @@ git gh ghostty + go google-chrome gopass gopass-jsonapi @@ -47,7 +47,6 @@ htmx-lsp2 imagemagick inkscape - # input-remapper pavucontrol pciutils poppler @@ -55,7 +54,16 @@ jq kitty lazygit - lf + (pkgs.writeShellScriptBin "lf" '' + cd_file="/tmp/lf-lastdir" + + ${pkgs.lf}/bin/lf "$@" + + if [ -f "$cd_file" ]; then + cd "$(cat "$cd_file")" + rm "$cd_file" + fi + '') libreoffice libvirt linux-firmware @@ -105,13 +113,11 @@ thunderbird tor-browser unzip - usbutils virt-manager virt-viewer vscode-langservers-extracted watchexec wayland - waypipe wgsl-analyzer # wineWowPackages.waylandFull wineWow64Packages.waylandFull @@ -179,6 +185,51 @@ localNetworkGameTransfers.openFirewall = true; }; + programs.firejail = { + enable = true; + wrappedBinaries = { + chromium-sandbox = { + executable = "${pkgs.chromium}/bin/chromium"; + profile = "${pkgs.firejail}/etc/firejail/chromium-browser.profile"; + extraArgs = [ + "--netns=wg0ns" + "--whitelist=/home/user/downloads" + "--env=TGK_THEME=Adwaita:dark" + "--dns=10.2.0.1" + "--private=/data/sandbox/chromium" + ]; + }; + google-chrome-stable = { + # executable = "${chrome-argumented}/bin/google-chrome-stable"; + executable = "${pkgs.google-chrome}/bin/google-chrome-stable"; + profile = "${pkgs.firejail}/etc/firejail/google-chrome-stable.profile"; + extraArgs = [ + "--env=GTK_THEME=Adwaita:dark" + "--netns=wg-br0ns" + "--dns=10.2.0.1" + "--whitelist=/home/user/downloads" + "--whitelist=/home/user/pictures" + ]; + }; + 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" + ]; + }; + }; + }; + services.ollama = { enable = true; package = pkgs.ollama-cuda; @@ -188,7 +239,6 @@ "glm-5.1" ]; }; - # services.input-remapper.enable = true; # services.open-webui = { # enable = true; # port = 11347; diff --git a/secrets/home.yaml b/secrets/home.yaml index a7269df..cfa4063 100644 --- a/secrets/home.yaml +++ b/secrets/home.yaml @@ -1,6 +1,4 @@ deepseek_api_key: ENC[AES256_GCM,data:HJXkEErncaOb2up0B45qisM+rIHoNmX9n6RZrdGN2JZlur8=,iv:4Dx5AjtDhWfYKlRiUrADT7HdHy/F2sfkzuPKuLhBRt4=,tag:AC3Zm+NHnnIQDCnlmBDUcQ==,type:str] -navidrome: - user: ENC[AES256_GCM,data:TkPLvX3AxC7Lbnh6s2j1q3XrQE1u16ykah9rSjlYPnuH,iv:dtjM4O4A4ABVyHQHPAUH5dVopgwLlKSUcbqFpCWV2eA=,tag:W2PVbIaLGbX4SR2ZNOGmsQ==,type:str] root: password: ENC[AES256_GCM,data:qA7sbNvWvfmWiLX4pIYOzDmuCwc3+7I1KvTHHYF5jDHR0CNRuya0XglP8TNK5qGLEJkdmD9WphdWvYY60NTOf5NFhDnqtm3ZIw==,iv:B42jl40hQbRqMRfV39fNne0E3KKCwriAQ5MQ0DF4QQA=,tag:hH/u0Qw6A2is4XOOQpnr2Q==,type:str] ssh: @@ -15,7 +13,8 @@ user: legacy_rsa: ENC[AES256_GCM,data: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,iv:oGGm7bveDXNmxqe5Zina03vSVLJx9P3VBC/DbuI6KzY=,tag:taEL0E4Uinv1MQPxeRbPzA==,type:str] sops: age: - - enc: | + - recipient: age1y0tj3kt67pfnj38t9c8g2ghry3a0mhcq8rrqv5xr4jekwepxaelqzu3dkf + enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOZ3dERmxMbEJmSVhVRmVw TUZZL0FzTHprci9ENHFodnRVWmRSbk1ab2xnCnZYeXN3MWRJZENlYmtWeFM0azdR @@ -23,8 +22,8 @@ sops: bFhna3RyY1kxK0IyVWlnR2FpMXk3UjQKvJaecXqAecBljJ9cNcHX13nxSxVey3LG NdvJaMfEV4m3SqRF7YUoTzGYhucYjtX58E5SuvHnaP2qa21aDF+AZQ== -----END AGE ENCRYPTED FILE----- - recipient: age1y0tj3kt67pfnj38t9c8g2ghry3a0mhcq8rrqv5xr4jekwepxaelqzu3dkf - - enc: | + - recipient: age16v8w7q4wmn22hhakq2uzaus2508rhldm7lcwh0kukshzjzyhuqesqz44ze + enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSZnV1T0JKTXoyeUlZQ3o4 QkR4OHZUbzQrbjdSK2VLTDNzMU9qdlUvVVUwClI4SDhMZTRDRXY3NlJSZ3REdmpJ @@ -32,8 +31,7 @@ sops: NVlzQlQvMVc2dHZNK2pEWk80MStwY1UK38mxk1dJWi6XRKSwzcDA9qt8i1Grw2KJ ac2EbJIFwYLOaMNOKF9hu+NrMdruRpU/2B8HlYYZjpNWmLb9jwI4wQ== -----END AGE ENCRYPTED FILE----- - recipient: age16v8w7q4wmn22hhakq2uzaus2508rhldm7lcwh0kukshzjzyhuqesqz44ze - lastmodified: "2026-07-05T22:42:52Z" - mac: ENC[AES256_GCM,data:La8bfH1u7pmukx9OZTUS9gdZODiYcY07dMU08kEkEeojHGoh/VAUrBK3Sj5W33WnbqpXnuiRKgF34mqVav5T9TE0ds31PMc/VceWkd5pJ2crCjbmlR6Zm/XCHgilIO4IoGlCO5Zz+LXpsPbD3vv1AwmzYBRwgik69vyWiXwT0UA=,iv:vSzK3eE+Jpy//dzdOT+PHmdOOKmNlbiFDeDdtZ9Lz9o=,tag:Fo6IUvyyMxWy1gsa7faV7w==,type:str] + lastmodified: "2026-05-04T12:41:30Z" + mac: ENC[AES256_GCM,data:OxKBSbx/NrkprIHTdI+iM2yMh1lhTMYuS7UO09NzxXHkyEoXtacDm7XtWIrELIxDIpqQGkousKcNRDmfiejzkpD6aLpdR1S0exXe1A+heWUMB9D+I+an51Nuv/LBGKeelK71RAq2H0VQZQgZd6OuzDECsK07lxnxUAWo8rxhScs=,iv:0cREbkAyUz1a6ze74MKmfeX8RJjMIrwgRoTPeGADEiE=,tag:DJaNf7gckCDoYLzzw+SRUg==,type:str] unencrypted_suffix: _unencrypted - version: 3.13.1 + version: 3.12.2 diff --git a/secrets/vpn.yaml b/secrets/vpn.yaml index 49dcd36..e2601b7 100644 --- a/secrets/vpn.yaml +++ b/secrets/vpn.yaml @@ -6,14 +6,15 @@ wg-br0: private_key: ENC[AES256_GCM,data:y8djTiZ00DIhdN1YNUNmjqCPeSUrS+YWKfr4iLT8h54fSlgDn1OPAoyJllM=,iv:Wz/EiISOlaiSXSIa4h8L2wJPm34rxpQkErpuqAR/uC8=,tag:RS100jf8INb12q6+hGQDiw==,type:str] conf: ENC[AES256_GCM,data:3TJ34y3NI1wO2Oyh7D72t2WmlOq/pMS43Ck3gDFV9QPSC7E3GHtc86aZqRQm8qbRqnkJco1+nlJZmsC+BQdmW+U5RkRL7vUyDmrCyeDyJvEkNIJLzcFi4lppbYXG3A+fRO2l5guQA5qNSQmnyux51yY11/OCahoFEEenL1wH+R0ugMK/LIPwK0/Y2u7c+7SvNwwtK9xQUlb4azqUsdLX0xkUFbBje2BgN50BB2TxLZJexUNjOTW9TE57tw3yI4VjYEvIyBXOK4uuuST+TcNJY5B45tjd8PmO9vPYDw==,iv:BdNVbiMjzGtX0rzkLBb/YCDxqBv15L7bJcLTPzvt/yM=,tag:NmEMTPasBSsg1GSkYi/HxA==,type:str] wg-us0: - private_key: ENC[AES256_GCM,data:rouU6q7Qn8wu93YL+uAWKsItXK2d21rRbTLLURk15wmC8YUytt/Hx8XNCbk=,iv:6m4+yS1LIZMfwZrWkb/4I4ABFLca24G8Nz3UTMQw8Q8=,tag:eTR7MW7Y9m34S5CRKIWsLw==,type:str] - conf: ENC[AES256_GCM,data:QTc6Y4VOT0UQKY9il4p4dCGYiGRYYF6Pi80ytwMweMWr1aHNl3RyFfSkAtCW3GErO6Y2OUdiwukSBKpmP6DDmBMZfhH/bQzWTFX+bAbcMBD6Ql3rMYl3rZ7pfbAZpa5a/tnzsfK+0ee8GfAo9IKci5gq7ic6E5zD9IsNPNxUH4HWNWfpSfnQo4Z6V/S05/Yb+GH4gQuX/K/eLh1b/8oWePpcRSKaQSSDzEd2NtvAv8S2LUwJxg/QYSC0CxrOGWXGdaDE,iv:05MM/v8OjjwSijhLAqlLeohYMbyV932QvgWsPhaCXLI=,tag:qpgaYyb4jkEhJTI46RMvhA==,type:str] + private_key: ENC[AES256_GCM,data:PWzeqoYLICXjYL5AV+dxUxYn6RL/tUMkfTMYhm+OdC85cPBPU135Ov15nUk=,iv:1CdiayG3F4xp3eid/ilboFUOL4Y92RUqipASOPT8Jl0=,tag:cJulFquSHjmKF+lUegp37Q==,type:str] + conf: ENC[AES256_GCM,data:x4bpjE/icVqe3lXHRNWf5W9w8EVAiNyqmFUR2LslSrEz0ekmJ4YDKDuU//+VoomsZzHhY6GhKtEVJ4Me/xY0G1+dSBBgpZlO8UyZVg8aydsVmA09fHYgwKovzHXc0XM9cbbovf2yyK8kO+X8e3ODy1dSu+a1SA3YsEp2G46kbRRxTdYazeHMJ+hJdmCONEvx0p0NcPlPAW8eZWEsAbVT/eQzB3TnF2THy/t4oWrn4r/MVvcsWgc1LJ3rVJ6L8RREU/PYBJoyDMgAs3DP79E8iOQS+bwdJj0+gcrP,iv:Ngqn/EA3QpOnBxz+slSyn+oOO33hLZlGhAg+RIlN+wI=,tag:BZFjGxI0nRsdPn99rvijdA==,type:str] wg-uk0: private_key: ENC[AES256_GCM,data:r1BEMvO+Q/6VTuC7N/iqWf1Cyp4WZsUitVF14n5QXPzYK9PoWgPGylQQpmg=,iv:wR1gsHzzu0C629bs7yGW6evjdieONyzMnc9vvtTEh2Q=,tag:lMk4DuTDFtOW0heIJ0Ef2A==,type:str] conf: ENC[AES256_GCM,data:tCQaQEJ1Pa0jw96q/LRtqhAWes04GkGOUYAlZu3W3C9EGHj123dYZiWXcUgymSsi999M3RbO2mWNllSl17zkV1iGZAkA23aQLKDUU0/m/SSCLm2ohJOdLKkGeRK41TMGFRRydfYZJ9rg0iJdacfXrX2t4RGWgtprSlS2crOcrAQ+jhMjCNxKuAg0gaJyUh1lcTmOohe0aBiqxGJE+mc4mKMwCiUytNoprAc2TrnKUTQ7/eyIv9hn0PeRvLL59KFNrcVpCb7VRkufYpYlNtO1zyl2oczYzw+IXCHt,iv:S74FbQLM5sXhvoSaUD0wuMeAd7U4rL/dneaVS3ah8Bo=,tag:0U/k1Cyy4XbvmnlApg2BYg==,type:str] sops: age: - - enc: | + - recipient: age1y0tj3kt67pfnj38t9c8g2ghry3a0mhcq8rrqv5xr4jekwepxaelqzu3dkf + enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtOHZSRkpBVVdUUk9OYUFH cVBra014WXJyRTJ0QWFKallLQlc0SXhNSlFBCmpwME92M2lCN2liVjZBRndlSVBk @@ -21,8 +22,8 @@ sops: OWhIdUxDcHB4Z3dTdDkyZWF6NEJCYzAKfPB9AZFQ08yqil+4AhIi6EMy8PXI4CAz lK4ON/M67T0UrlWN/m3pryOOr4Lj4oiZvdOR0BCO3kn4Pj0nq5jQOA== -----END AGE ENCRYPTED FILE----- - recipient: age1y0tj3kt67pfnj38t9c8g2ghry3a0mhcq8rrqv5xr4jekwepxaelqzu3dkf - - enc: | + - recipient: age16v8w7q4wmn22hhakq2uzaus2508rhldm7lcwh0kukshzjzyhuqesqz44ze + enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMSC9Td1NTMzk2NlJDTDNM UVUzTSt1dGkrUVRGT1UzeXcwR1REN1U0dW5JCnNJRzdKZHVyR0dzaUw2TlVzQnQ2 @@ -30,8 +31,7 @@ sops: OEZ4WUp1QlVrTkVTN1BHMG0yaXFuSk0KLw3ZuvWTurJDTpyoq5YafLm8YFT4v4Vh s+ay8ju3kA1CKjMF3gBQF08EoCdP/jU6tZerNwwcs17el5zIvRmG7Q== -----END AGE ENCRYPTED FILE----- - recipient: age16v8w7q4wmn22hhakq2uzaus2508rhldm7lcwh0kukshzjzyhuqesqz44ze - lastmodified: "2026-07-12T15:08:29Z" - mac: ENC[AES256_GCM,data:RiyjNVLep6kPx8oNno+v/GSCXQ0mo4SJFo54+KUyP/up79mPYTxLiuRsEZXO5P3d5pzMqMubQntDaMj8h6C4IJjojPIFvl4AeOveXkOeFz50ufeNBkwKEsDJgNNQfw/3vgq5rTR5WegsLzEMagXuDGwEJPA3uQQf0Ea2pXFO/Nw=,iv:YpTw0+Q+tBK3j3uEYiHLUzwygUFPrUanH8apNwpJwDM=,tag:o5opSInF5D9Q0OgB/7uf7Q==,type:str] + lastmodified: "2026-02-08T19:15:21Z" + mac: ENC[AES256_GCM,data:IxRNC13NPMIhVon0vCH3df+JxQlIPzv79H6JQzj8hkQNLxbFtPzk9DlHW1PWX90UAQbaXnzUM9uyHZhg4TypVsuKiEhpGyE4LXn/O7wD3U66YMkbqGrpKtnWbCQNdj///N5nDf71QwdLTEAzH+Kn9zRmiZ60rEu3w1Wm5vitB78=,iv:jWQvvO8kJDULepEUbWRym57whNpd23Q2PkXCDNQeJLo=,tag:wPBtn7Onr3S9ksEmdCZFzg==,type:str] unencrypted_suffix: _unencrypted - version: 3.13.1 + version: 3.11.0 diff --git a/storage.nix b/storage.nix index edb6a45..8ecc9fd 100644 --- a/storage.nix +++ b/storage.nix @@ -32,13 +32,6 @@ "noatime" ]; }; - "@downloads" = { - mountpoint = "/home/user/downloads"; - mountOptions = [ - "compress=zstd" - "noatime" - ]; - }; }; }; }; diff --git a/tailscale.nix b/tailscale.nix deleted file mode 100644 index af1693e..0000000 --- a/tailscale.nix +++ /dev/null @@ -1,273 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: - -with lib; - -let - cfg = config.services.tailscale-netns; - - instanceOptions = - { name, ... }: - { - options = { - authKeyFile = mkOption { - type = types.nullOr types.path; - default = null; - description = "Path to file containing a Tailscale auth key."; - }; - - hostname = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Tailscale hostname for this instance. - Defaults to "-". - ''; - }; - - advertiseRoutes = mkOption { - type = types.listOf types.str; - default = [ ]; - description = "Subnet routes to advertise (e.g. [ \"10.0.0.0/24\" ])."; - }; - - dns = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Bootstrap DNS server for the namespace before Tailscale is connected. - Defaults to `1.1.1.1`. Only used for the initial coordination server - connection; once Tailscale is up it manages DNS inside the namespace. - ''; - }; - - advertiseExitNode = mkOption { - type = types.bool; - default = false; - description = "Whether to advertise this node as an exit node."; - }; - - acceptRoutes = mkOption { - type = types.bool; - default = false; - description = "Whether to accept routes advertised by other nodes."; - }; - - exitNode = mkOption { - type = types.nullOr types.str; - default = null; - description = "Tailscale IP or hostname of exit node to use."; - }; - - extraUpFlags = mkOption { - type = types.listOf types.str; - default = [ ]; - description = "Extra flags passed to `tailscale up`."; - }; - - extraDaemonFlags = mkOption { - type = types.listOf types.str; - default = [ ]; - description = "Extra flags passed to `tailscaled`."; - }; - }; - }; - - mkUpFlags = - instanceCfg: - let - hostFlag = optional ( - instanceCfg.hostname != null - ) "--hostname=${escapeShellArg instanceCfg.hostname}"; - routeFlags = map (r: "--advertise-routes=${escapeShellArg r}") instanceCfg.advertiseRoutes; - exitFlag = optional instanceCfg.advertiseExitNode "--advertise-exit-node"; - acceptFlag = optional instanceCfg.acceptRoutes "--accept-routes"; - exitNodeFlag = optional ( - instanceCfg.exitNode != null - ) "--exit-node=${escapeShellArg instanceCfg.exitNode}"; - in - hostFlag ++ routeFlags ++ exitFlag ++ acceptFlag ++ exitNodeFlag ++ instanceCfg.extraUpFlags; - - mkAutoconnectScript = - name: instanceCfg: - pkgs.writers.writeBash "tailscale-autoconnect-${name}" '' - set -euo pipefail - - TS="${pkgs.tailscale}/bin/tailscale" - SOCKET="/run/tailscale-${name}/tailscaled.sock" - TS_ARGS="--socket $SOCKET" - - get_state() { - $TS $TS_ARGS status --json --peers=false 2>/dev/null | ${pkgs.jq}/bin/jq -r '.BackendState // "NoState"' - } - - last_state="" - while state="$(get_state)"; do - if [[ "$state" != "$last_state" ]]; then - case "$state" in - NeedsLogin|NeedsMachineAuth|Stopped) - echo "[tailscale-netns:${name}] server needs authentication, sending auth key" - $TS $TS_ARGS up \ - --auth-key "$(cat ${instanceCfg.authKeyFile})" \ - ${escapeShellArgs (mkUpFlags instanceCfg)} - ;; - Running) - echo "[tailscale-netns:${name}] tailscale is running" - ${pkgs.systemd}/bin/systemd-notify --ready - exit 0 - ;; - NoState) - echo "[tailscale-netns:${name}] tailscaled not ready yet" - ;; - *) - echo "[tailscale-netns:${name}] waiting for Running (state=$state)" - ;; - esac - fi - last_state="$state" - sleep 1 - done - ''; - - mkNetnsSetup = - index: name: instanceCfg: - let - ns = "ts-${name}ns"; - hostIP = "10.201.${toString index}.1/24"; - nsIP = "10.201.${toString index}.2/24"; - vethHost = "veth-ts-${name}"; - vethNS = "veth-ts-${name}-ns"; - in - { - "netns@ts-${name}" = { - description = "Network namespace for Tailscale instance ${name}"; - before = [ "network.target" ]; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - ExecStart = pkgs.writers.writeBash "ts-${name}-netns-up" '' - set -euo pipefail - ${pkgs.coreutils}/bin/mkdir -p /etc/netns/${ns} - - # Build resolv.conf for the netns. Skip loopback addresses - # (systemd-resolved stub at 127.0.0.53 is not reachable from the netns). - NS_DNS="${if instanceCfg.dns != null then instanceCfg.dns else "1.1.1.1"}" - { - ${pkgs.gawk}/bin/awk '$1 == "nameserver" && $2 !~ /^127\./ && $2 != "::1" {print}' /etc/resolv.conf - echo "nameserver $NS_DNS" - } > /etc/netns/${ns}/resolv.conf - - ${pkgs.iproute2}/bin/ip netns add ${ns} - ${pkgs.iproute2}/bin/ip link add ${vethHost} type veth peer name ${vethNS} - ${pkgs.iproute2}/bin/ip link set ${vethNS} netns ${ns} - - ${pkgs.iproute2}/bin/ip addr add ${hostIP} dev ${vethHost} - ${pkgs.iproute2}/bin/ip link set ${vethHost} up - - ${pkgs.iproute2}/bin/ip -n ${ns} addr add ${nsIP} dev ${vethNS} - ${pkgs.iproute2}/bin/ip -n ${ns} link set ${vethNS} up - ${pkgs.iproute2}/bin/ip -n ${ns} link set lo up - - ${pkgs.iptables}/bin/iptables -t nat -C POSTROUTING -s ${nsIP} -j MASQUERADE 2>/dev/null \ - || ${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s ${nsIP} -j MASQUERADE - ''; - ExecStop = pkgs.writers.writeBash "ts-${name}-netns-down" '' - set -euo pipefail - ${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s ${nsIP} -j MASQUERADE 2>/dev/null || true - ${pkgs.iproute2}/bin/ip link del ${vethHost} 2>/dev/null || true - ${pkgs.iproute2}/bin/ip netns del ${ns} 2>/dev/null || true - ''; - }; - }; - - "tailscaled-${name}" = { - description = "Tailscale daemon for instance ${name}"; - bindsTo = [ "netns@ts-${name}.service" ]; - after = [ "netns@ts-${name}.service" ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - ExecStart = pkgs.writers.writeBash "tailscaled-${name}-start" '' - exec ${pkgs.iproute2}/bin/ip netns exec ${ns} \ - ${pkgs.tailscale}/bin/tailscaled \ - --statedir=/var/lib/tailscale-${name} \ - --socket=/run/tailscale-${name}/tailscaled.sock \ - --tun=ts-${name} \ - --port=41641 \ - ${escapeShellArgs instanceCfg.extraDaemonFlags} - ''; - ExecStopPost = pkgs.writers.writeBash "tailscaled-${name}-stop" '' - ${pkgs.iproute2}/bin/ip netns exec ${ns} \ - ${pkgs.tailscale}/bin/tailscaled --cleanup \ - --statedir=/var/lib/tailscale-${name} \ - --socket=/run/tailscale-${name}/tailscaled.sock \ - 2>/dev/null || true - ''; - Restart = "on-failure"; - RuntimeDirectory = "tailscale-${name}"; - RuntimeDirectoryMode = "0755"; - StateDirectory = "tailscale-${name}"; - StateDirectoryMode = "0700"; - CacheDirectory = "tailscale-${name}"; - CacheDirectoryMode = "0750"; - - AmbientCapabilities = "CAP_NET_ADMIN CAP_NET_RAW"; - LimitNOFILE = "infinity"; - }; - }; - }; - -in -{ - options.services.tailscale-netns = { - enable = mkEnableOption "Tailscale instances in isolated network namespaces"; - - instances = mkOption { - type = types.attrsOf (types.submodule instanceOptions); - default = { }; - description = "Tailscale instances configured in separate network namespaces."; - example = literalExpression '' - { - work = { - authKeyFile = "/run/secrets/ts-work/authkey"; - acceptRoutes = true; - }; - } - ''; - }; - }; - - config = mkIf cfg.enable { - systemd.services = listToAttrs ( - flatten ( - imap1 ( - index: elem: - let - name = elem.name; - instanceCfg = elem.value; - units = mkNetnsSetup index name instanceCfg; - in - [ - units."netns@ts-${name}" - units."tailscaled-${name}" - ] - ++ optional (instanceCfg.authKeyFile != null) { - "tailscaled-autoconnect-${name}" = { - description = "Tailscale autoconnect for instance ${name}"; - after = [ "tailscaled-${name}.service" ]; - requires = [ "tailscaled-${name}.service" ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - Type = "notify"; - }; - script = "${mkAutoconnectScript name instanceCfg}"; - }; - } - ) (attrsToList cfg.instances) - ) - ); - }; -} diff --git a/users.nix b/users.nix index 4dc3158..b56284c 100644 --- a/users.nix +++ b/users.nix @@ -7,7 +7,7 @@ imports = [ ./home/user.nix ./home/root.nix - # ./home/agents.nix + ./home/agents.nix ]; sops.secrets."user/password" = { neededForUsers = true; @@ -41,25 +41,26 @@ # ]; # linger = true; # }; - # agent = { - # uid = 1002; + agent = { + uid = 1002; + homeMode = "770"; + home = "/home/agent"; + shell = pkgs.fish; + isNormalUser = true; + group = "agent"; + extraGroups = [ "public" ]; + linger = true; + }; + # sandbox = { + # uid = 1003; # homeMode = "770"; - # home = "/home/agent"; + # home = "/home/sandbox"; # shell = pkgs.fish; # isNormalUser = true; - # group = "agent"; + # group = "sandbox"; # extraGroups = [ "public" ]; # linger = true; # }; - sandbox = { - uid = 1001; - homeMode = "770"; - home = "/home/sandbox"; - shell = pkgs.fish; - isNormalUser = true; - group = "users"; - linger = true; - }; user = { uid = 1000; homeMode = "700"; @@ -71,11 +72,12 @@ "libvirt" "systemd-journal" "kvm" + "public" + "agent" + "sandbox" "audio" "video" - "render" "bluetooth" - "users" # "work" ]; hashedPasswordFile = config.sops.secrets."user/password".path; @@ -84,6 +86,9 @@ }; groups = { user.gid = 1000; + agent.gid = 1002; + public.gid = 777; + # sandbox.gid = 1003; }; }; }