commit 2dec42d4872efd04c543fc95dc7b7a672f186af8 Author: Thary Date: Wed Aug 20 18:24:02 2025 +0300 Initial commit diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1a9853a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +root=true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..275ae70 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +./results diff --git a/README.md b/README.md new file mode 100644 index 0000000..5fd20d2 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# Structure +|Directory|Usage| +|:--:|--| +|hosts/|Configuration for | +|modules/|Classical modules and configurations| +|lib/|Functions| +|assets/|Extra files| +|secrets/|Rekeyd secrets| +|users/|todo: User configuration and dotfiles| + +# Hosts +|Hostname|Device|Description| +|:--:|--|:--:| +|Phoenix|Asus TUF Gaming FX505DT|My main laptop| +|Tureis|Thinkpad X240|My second laptop| +|Cepheus|Contabo VPS| +|Naos|todo: homeserver| + +# Thanks to... +oddlama, sodiboo, nhnn diff --git a/assets/Wallpaper.jpg b/assets/Wallpaper.jpg new file mode 100644 index 0000000..14d5b6b Binary files /dev/null and b/assets/Wallpaper.jpg differ diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..c97b3cd --- /dev/null +++ b/flake.lock @@ -0,0 +1,1316 @@ +{ + "nodes": { + "agenix": { + "inputs": { + "darwin": "darwin", + "home-manager": "home-manager", + "nixpkgs": "nixpkgs", + "systems": "systems" + }, + "locked": { + "lastModified": 1754433428, + "narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=", + "owner": "ryantm", + "repo": "agenix", + "rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "agenix-rekey": { + "inputs": { + "devshell": "devshell", + "flake-parts": "flake-parts", + "nixpkgs": [ + "nixpkgs" + ], + "pre-commit-hooks": "pre-commit-hooks", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1754492276, + "narHash": "sha256-cCtleJZQY5eWPYRGl5x63BZ2rfOik4pLveCveH+tmvM=", + "owner": "oddlama", + "repo": "agenix-rekey", + "rev": "69ed7833c0e4e6a677a20894d8f12876b9e2bedb", + "type": "github" + }, + "original": { + "owner": "oddlama", + "repo": "agenix-rekey", + "type": "github" + } + }, + "ags": { + "inputs": { + "astal": "astal", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1754932414, + "narHash": "sha256-V8c+68Axn5AGDCaG9Zv+EqNU4D6xWPHNXLIapq6AGiM=", + "owner": "Aylur", + "repo": "ags", + "rev": "9e6912b51d7bc58f35d10b11be1a126b926b56d3", + "type": "github" + }, + "original": { + "owner": "Aylur", + "repo": "ags", + "type": "github" + } + }, + "arkenfox": { + "inputs": { + "flake-compat": "flake-compat_2", + "nixpkgs": [ + "nixpkgs" + ], + "pre-commit": "pre-commit" + }, + "locked": { + "lastModified": 1751321356, + "narHash": "sha256-7vrKgcIg7jOHVEJrpfjNjcqZnsAoXnJvKK8NuV1x2kU=", + "owner": "dwarfmaster", + "repo": "arkenfox-nixos", + "rev": "3f04af64f37dad55446417fc2f8c6cf754fde879", + "type": "github" + }, + "original": { + "owner": "dwarfmaster", + "repo": "arkenfox-nixos", + "type": "github" + } + }, + "astal": { + "inputs": { + "nixpkgs": [ + "ags", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1752404970, + "narHash": "sha256-XULTToDUkIshNXEO+YP2mAHdQv8bxWDvKjbamBfOC8E=", + "owner": "aylur", + "repo": "astal", + "rev": "2c5eb54f39e1710c6e2c80915a240978beb3269a", + "type": "github" + }, + "original": { + "owner": "aylur", + "repo": "astal", + "type": "github" + } + }, + "base16": { + "inputs": { + "fromYaml": "fromYaml" + }, + "locked": { + "lastModified": 1746562888, + "narHash": "sha256-YgNJQyB5dQiwavdDFBMNKk1wyS77AtdgDk/VtU6wEaI=", + "owner": "SenchoPens", + "repo": "base16.nix", + "rev": "806a1777a5db2a1ef9d5d6f493ef2381047f2b89", + "type": "github" + }, + "original": { + "owner": "SenchoPens", + "repo": "base16.nix", + "type": "github" + } + }, + "base16-fish": { + "flake": false, + "locked": { + "lastModified": 1622559957, + "narHash": "sha256-PebymhVYbL8trDVVXxCvZgc0S5VxI7I1Hv4RMSquTpA=", + "owner": "tomyun", + "repo": "base16-fish", + "rev": "2f6dd973a9075dabccd26f1cded09508180bf5fe", + "type": "github" + }, + "original": { + "owner": "tomyun", + "repo": "base16-fish", + "type": "github" + } + }, + "base16-helix": { + "flake": false, + "locked": { + "lastModified": 1752979451, + "narHash": "sha256-0CQM+FkYy0fOO/sMGhOoNL80ftsAzYCg9VhIrodqusM=", + "owner": "tinted-theming", + "repo": "base16-helix", + "rev": "27cf1e66e50abc622fb76a3019012dc07c678fac", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-helix", + "type": "github" + } + }, + "base16-vim": { + "flake": false, + "locked": { + "lastModified": 1732806396, + "narHash": "sha256-e0bpPySdJf0F68Ndanwm+KWHgQiZ0s7liLhvJSWDNsA=", + "owner": "tinted-theming", + "repo": "base16-vim", + "rev": "577fe8125d74ff456cf942c733a85d769afe58b7", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-vim", + "rev": "577fe8125d74ff456cf942c733a85d769afe58b7", + "type": "github" + } + }, + "crane": { + "locked": { + "lastModified": 1754269165, + "narHash": "sha256-0tcS8FHd4QjbCVoxN9jI+PjHgA4vc/IjkUSp+N3zy0U=", + "owner": "ipetkov", + "repo": "crane", + "rev": "444e81206df3f7d92780680e45858e31d2f07a08", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1744478979, + "narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "43975d782b418ebf4969e9ccba82466728c2851b", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "deploy-rs": { + "inputs": { + "flake-compat": "flake-compat_4", + "nixpkgs": "nixpkgs_4", + "utils": "utils" + }, + "locked": { + "lastModified": 1749105467, + "narHash": "sha256-hXh76y/wDl15almBcqvjryB50B0BaiXJKk20f314RoE=", + "owner": "serokell", + "repo": "deploy-rs", + "rev": "6bc76b872374845ba9d645a2f012b764fecd765f", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "deploy-rs", + "type": "github" + } + }, + "devshell": { + "inputs": { + "nixpkgs": [ + "agenix-rekey", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1728330715, + "narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=", + "owner": "numtide", + "repo": "devshell", + "rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "firefox-gnome-theme": { + "flake": false, + "locked": { + "lastModified": 1748383148, + "narHash": "sha256-pGvD/RGuuPf/4oogsfeRaeMm6ipUIznI2QSILKjKzeA=", + "owner": "rafaelmardojai", + "repo": "firefox-gnome-theme", + "rev": "4eb2714fbed2b80e234312611a947d6cb7d70caf", + "type": "github" + }, + "original": { + "owner": "rafaelmardojai", + "repo": "firefox-gnome-theme", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1747046372, + "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_3": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_4": { + "flake": false, + "locked": { + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_5": { + "flake": false, + "locked": { + "lastModified": 1747046372, + "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "agenix-rekey", + "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" + } + }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "lanzaboote", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1754091436, + "narHash": "sha256-XKqDMN1/Qj1DKivQvscI4vmHfDfvYR2pfuFOJiCeewM=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "67df8c627c2c39c41dbec76a1f201929929ab0bd", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_3": { + "inputs": { + "nixpkgs-lib": [ + "nixpak", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1754487366, + "narHash": "sha256-pHYj8gUBapuUzKV/kN/tR3Zvqc7o6gdFB9XKXIp1SQ8=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "af66ad14b28a127c5c0f3bbb298218fc63528a18", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_4": { + "inputs": { + "nixpkgs-lib": [ + "stylix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1751413152, + "narHash": "sha256-Tyw1RjYEsp5scoigs1384gIg6e0GoBVjms4aXFfRssQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "77826244401ea9de6e3bac47c2db46005e1f30b5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flakey-profile": { + "locked": { + "lastModified": 1712898590, + "narHash": "sha256-FhGIEU93VHAChKEXx905TSiPZKga69bWl1VB37FK//I=", + "owner": "lf-", + "repo": "flakey-profile", + "rev": "243c903fd8eadc0f63d205665a92d4df91d42d9d", + "type": "github" + }, + "original": { + "owner": "lf-", + "repo": "flakey-profile", + "type": "github" + } + }, + "fromYaml": { + "flake": false, + "locked": { + "lastModified": 1731966426, + "narHash": "sha256-lq95WydhbUTWig/JpqiB7oViTcHFP8Lv41IGtayokA8=", + "owner": "SenchoPens", + "repo": "fromYaml", + "rev": "106af9e2f715e2d828df706c386a685698f3223b", + "type": "github" + }, + "original": { + "owner": "SenchoPens", + "repo": "fromYaml", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "agenix-rekey", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_2": { + "inputs": { + "nixpkgs": [ + "arkenfox", + "pre-commit", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_3": { + "inputs": { + "nixpkgs": [ + "lanzaboote", + "pre-commit-hooks-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gnome-shell": { + "flake": false, + "locked": { + "lastModified": 1748186689, + "narHash": "sha256-UaD7Y9f8iuLBMGHXeJlRu6U1Ggw5B9JnkFs3enZlap0=", + "owner": "GNOME", + "repo": "gnome-shell", + "rev": "8c88f917db0f1f0d80fa55206c863d3746fa18d0", + "type": "github" + }, + "original": { + "owner": "GNOME", + "ref": "48.2", + "repo": "gnome-shell", + "type": "github" + } + }, + "hercules-ci-effects": { + "inputs": { + "flake-parts": [ + "nixpak", + "flake-parts" + ], + "nixpkgs": [ + "nixpak", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1752595130, + "narHash": "sha256-CNBgr4OZSuklGtNOa9CnTNo9+Xceqn/EDAC1Tc43fH8=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "5f2e09654b2e70ba643e41609d9f9b6640f22113", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1745494811, + "narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1755313937, + "narHash": "sha256-pQb7bNcolxYGRiylUCrTddiF+qW2wsUiM9+eRIDUrVU=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "2a749f4790a14f7168be67cdf6e548ef1c944e10", + "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" + } + }, + "lanzaboote": { + "inputs": { + "crane": "crane", + "flake-compat": "flake-compat_5", + "flake-parts": "flake-parts_2", + "nixpkgs": [ + "nixpkgs" + ], + "pre-commit-hooks-nix": "pre-commit-hooks-nix", + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1754297745, + "narHash": "sha256-aD6/scLN3L4ZszmNbhhd3JQ9Pzv1ScYFphz14wHinfs=", + "owner": "nix-community", + "repo": "lanzaboote", + "rev": "892cbdca865d6b42f9c0d222fe309f7720259855", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "lanzaboote", + "type": "github" + } + }, + "lix": { + "flake": false, + "locked": { + "lastModified": 1737234286, + "narHash": "sha256-pgDJZjj4jpzkFxsqBTI/9Yb0n3gW+DvDtuv9SwQZZcs=", + "rev": "079528098f5998ba13c88821a2eca1005c1695de", + "type": "tarball", + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/079528098f5998ba13c88821a2eca1005c1695de.tar.gz?rev=079528098f5998ba13c88821a2eca1005c1695de" + }, + "original": { + "type": "tarball", + "url": "https://git.lix.systems/lix-project/lix/archive/release-2.92.tar.gz" + } + }, + "lix-module": { + "inputs": { + "flake-utils": "flake-utils", + "flakey-profile": "flakey-profile", + "lix": "lix", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1742943028, + "narHash": "sha256-fprwZKE1uMzO9tiWWOrmLWBW3GPkMayQfb0xOvVFIno=", + "rev": "868d97695bab9d21f6070b03957bcace249fbe3c", + "type": "tarball", + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/868d97695bab9d21f6070b03957bcace249fbe3c.tar.gz?rev=868d97695bab9d21f6070b03957bcace249fbe3c" + }, + "original": { + "type": "tarball", + "url": "https://git.lix.systems/lix-project/nixos-module/archive/2.92.0-3.tar.gz" + } + }, + "niri": { + "inputs": { + "niri-stable": "niri-stable", + "niri-unstable": "niri-unstable", + "nixpkgs": "nixpkgs_5", + "nixpkgs-stable": "nixpkgs-stable", + "xwayland-satellite-stable": "xwayland-satellite-stable", + "xwayland-satellite-unstable": "xwayland-satellite-unstable" + }, + "locked": { + "lastModified": 1755337977, + "narHash": "sha256-enrs40LRu+hbnKF7bcZL1uCgUflTmzJM1HUx1q2Pg8I=", + "owner": "sodiboo", + "repo": "niri-flake", + "rev": "b634336507cb4cace8170f71063cc81a3eb225e5", + "type": "github" + }, + "original": { + "owner": "sodiboo", + "repo": "niri-flake", + "type": "github" + } + }, + "niri-stable": { + "flake": false, + "locked": { + "lastModified": 1748151941, + "narHash": "sha256-z4viQZLgC2bIJ3VrzQnR+q2F3gAOEQpU1H5xHtX/2fs=", + "owner": "YaLTeR", + "repo": "niri", + "rev": "8ba57fcf25d2fc9565131684a839d58703f1dae7", + "type": "github" + }, + "original": { + "owner": "YaLTeR", + "ref": "v25.05.1", + "repo": "niri", + "type": "github" + } + }, + "niri-unstable": { + "flake": false, + "locked": { + "lastModified": 1755333728, + "narHash": "sha256-XJdE2XgTrstjV5Uh1mdGfjaKF6cawnBH8ybMRMlR8tQ=", + "owner": "YaLTeR", + "repo": "niri", + "rev": "af30cc8df68b29973c8b9eec290f9e6b93463929", + "type": "github" + }, + "original": { + "owner": "YaLTeR", + "repo": "niri", + "type": "github" + } + }, + "nixpak": { + "inputs": { + "flake-parts": "flake-parts_3", + "hercules-ci-effects": "hercules-ci-effects", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1755139484, + "narHash": "sha256-gCMJp0indBuBXnog2C86aby5Pz268gUMZD0ORahulO8=", + "owner": "nixpak", + "repo": "nixpak", + "rev": "ae70d05017be7e0aa6c1cf5f267fe6953eb027e6", + "type": "github" + }, + "original": { + "owner": "nixpak", + "repo": "nixpak", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1754028485, + "narHash": "sha256-IiiXB3BDTi6UqzAZcf2S797hWEPCRZOwyNThJIYhUfk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "59e69648d345d6e8fef86158c555730fa12af9de", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1755274400, + "narHash": "sha256-rTInmnp/xYrfcMZyFMH3kc8oko5zYfxsowaLv1LVobY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ad7196ae55c295f53a7d1ec39e4a06d922f3b899", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1754214453, + "narHash": "sha256-Q/I2xJn/j1wpkGhWkQnm20nShYnG7TI99foDBpXm1SY=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "5b09dc45f24cf32316283e62aec81ffee3c3e376", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1730768919, + "narHash": "sha256-8AKquNnnSaJRXZxc5YmF/WfmxiHX6MMZZasRP6RRQkE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a04d33c0c3f1a59a2c1cb0c6e34cd24500e5a1dc", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1743014863, + "narHash": "sha256-jAIUqsiN2r3hCuHji80U7NNEafpIMBXiwKlSrjWMlpg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "bd3bac8bfb542dbde7ffffb6987a1a1f9d41699f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1755186698, + "narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { + "locked": { + "lastModified": 1755186698, + "narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_7": { + "locked": { + "lastModified": 1751792365, + "narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nur": { + "inputs": { + "flake-parts": [ + "stylix", + "flake-parts" + ], + "nixpkgs": [ + "stylix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1751906969, + "narHash": "sha256-BSQAOdPnzdpOuCdAGSJmefSDlqmStFNScEnrWzSqKPw=", + "owner": "nix-community", + "repo": "NUR", + "rev": "ddb679f4131e819efe3bbc6457ba19d7ad116f25", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "NUR", + "type": "github" + } + }, + "pre-commit": { + "inputs": { + "flake-compat": "flake-compat_3", + "gitignore": "gitignore_2", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1750779888, + "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": [ + "agenix-rekey", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1735882644, + "narHash": "sha256-3FZAG+pGt3OElQjesCAWeMkQ7C/nB1oTHLRQ8ceP110=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "a5a961387e75ae44cc20f0a57ae463da5e959656", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks-nix": { + "inputs": { + "flake-compat": [ + "lanzaboote", + "flake-compat" + ], + "gitignore": "gitignore_3", + "nixpkgs": [ + "lanzaboote", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1750779888, + "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "agenix": "agenix", + "agenix-rekey": "agenix-rekey", + "ags": "ags", + "arkenfox": "arkenfox", + "deploy-rs": "deploy-rs", + "home-manager": "home-manager_2", + "impermanence": "impermanence", + "lanzaboote": "lanzaboote", + "lix-module": "lix-module", + "niri": "niri", + "nixpak": "nixpak", + "nixpkgs": "nixpkgs_6", + "stylix": "stylix", + "website": "website" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "lanzaboote", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1754189623, + "narHash": "sha256-fstu5eb30UYwsxow0aQqkzxNxGn80UZjyehQVNVHuBk=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "c582ff7f0d8a7ea689ae836dfb1773f1814f472a", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "stylix": { + "inputs": { + "base16": "base16", + "base16-fish": "base16-fish", + "base16-helix": "base16-helix", + "base16-vim": "base16-vim", + "firefox-gnome-theme": "firefox-gnome-theme", + "flake-parts": "flake-parts_4", + "gnome-shell": "gnome-shell", + "nixpkgs": "nixpkgs_7", + "nur": "nur", + "systems": "systems_4", + "tinted-foot": "tinted-foot", + "tinted-kitty": "tinted-kitty", + "tinted-schemes": "tinted-schemes", + "tinted-tmux": "tinted-tmux", + "tinted-zed": "tinted-zed" + }, + "locked": { + "lastModified": 1755211397, + "narHash": "sha256-kw6iLWUj6+fiEpuc8ntrIzJ2gdS36wIcRINbKU0AIbA=", + "owner": "danth", + "repo": "stylix", + "rev": "928ca832d22ab3167b49dc5f4d52ff5d26b0b52a", + "type": "github" + }, + "original": { + "owner": "danth", + "repo": "stylix", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "tinted-foot": { + "flake": false, + "locked": { + "lastModified": 1726913040, + "narHash": "sha256-+eDZPkw7efMNUf3/Pv0EmsidqdwNJ1TaOum6k7lngDQ=", + "owner": "tinted-theming", + "repo": "tinted-foot", + "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "tinted-foot", + "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4", + "type": "github" + } + }, + "tinted-kitty": { + "flake": false, + "locked": { + "lastModified": 1735730497, + "narHash": "sha256-4KtB+FiUzIeK/4aHCKce3V9HwRvYaxX+F1edUrfgzb8=", + "owner": "tinted-theming", + "repo": "tinted-kitty", + "rev": "de6f888497f2c6b2279361bfc790f164bfd0f3fa", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "tinted-kitty", + "type": "github" + } + }, + "tinted-schemes": { + "flake": false, + "locked": { + "lastModified": 1750770351, + "narHash": "sha256-LI+BnRoFNRa2ffbe3dcuIRYAUcGklBx0+EcFxlHj0SY=", + "owner": "tinted-theming", + "repo": "schemes", + "rev": "5a775c6ffd6e6125947b393872cde95867d85a2a", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "schemes", + "type": "github" + } + }, + "tinted-tmux": { + "flake": false, + "locked": { + "lastModified": 1751159871, + "narHash": "sha256-UOHBN1fgHIEzvPmdNMHaDvdRMgLmEJh2hNmDrp3d3LE=", + "owner": "tinted-theming", + "repo": "tinted-tmux", + "rev": "bded5e24407cec9d01bd47a317d15b9223a1546c", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "tinted-tmux", + "type": "github" + } + }, + "tinted-zed": { + "flake": false, + "locked": { + "lastModified": 1751158968, + "narHash": "sha256-ksOyv7D3SRRtebpXxgpG4TK8gZSKFc4TIZpR+C98jX8=", + "owner": "tinted-theming", + "repo": "base16-zed", + "rev": "86a470d94204f7652b906ab0d378e4231a5b3384", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-zed", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "agenix-rekey", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1735135567, + "narHash": "sha256-8T3K5amndEavxnludPyfj3Z1IkcFdRpR23q+T0BVeZE=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "9e09d30a644c57257715902efbb3adc56c79cf28", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "website": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1755650275, + "narHash": "sha256-U5i5OjtABXhddF6mmbAofJWvK/UKAlvO0gLyeTOqWdk=", + "ref": "main", + "rev": "92a0078b8bb8817be55ddea960ee091e4fa05c84", + "revCount": 11, + "type": "git", + "url": "https://tea.nothing.run/nothing.run/website" + }, + "original": { + "ref": "main", + "type": "git", + "url": "https://tea.nothing.run/nothing.run/website" + } + }, + "xwayland-satellite-stable": { + "flake": false, + "locked": { + "lastModified": 1748488455, + "narHash": "sha256-IiLr1alzKFIy5tGGpDlabQbe6LV1c9ABvkH6T5WmyRI=", + "owner": "Supreeeme", + "repo": "xwayland-satellite", + "rev": "3ba30b149f9eb2bbf42cf4758d2158ca8cceef73", + "type": "github" + }, + "original": { + "owner": "Supreeeme", + "ref": "v0.6", + "repo": "xwayland-satellite", + "type": "github" + } + }, + "xwayland-satellite-unstable": { + "flake": false, + "locked": { + "lastModified": 1755219541, + "narHash": "sha256-yKV6xHaPbEbh5RPxAJnb9yTs1wypr7do86hFFGQm1w8=", + "owner": "Supreeeme", + "repo": "xwayland-satellite", + "rev": "5a184d435927c3423f0ad189ea2b490578450fb7", + "type": "github" + }, + "original": { + "owner": "Supreeeme", + "repo": "xwayland-satellite", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100755 index 0000000..23e8cbc --- /dev/null +++ b/flake.nix @@ -0,0 +1,144 @@ +{ + description = "Thary and nothing.run`s NixOS configuration"; + + inputs = { + # NixOS stuff + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + lix-module = { + url = "https://git.lix.systems/lix-project/nixos-module/archive/2.92.0-3.tar.gz"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + lanzaboote = { + url = "github:nix-community/lanzaboote"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + deploy-rs.url = "github:serokell/deploy-rs"; + impermanence.url = "github:nix-community/impermanence"; + agenix.url = "github:ryantm/agenix"; + agenix-rekey = { + url = "github:oddlama/agenix-rekey"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + nixpak = { + url = "github:nixpak/nixpak"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + # User stuff + niri.url = "github:sodiboo/niri-flake"; + ags.url = "github:Aylur/ags"; + stylix.url = "github:danth/stylix"; + arkenfox = { + url = "github:dwarfmaster/arkenfox-nixos"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + website = { + url = "git+https://tea.nothing.run/nothing.run/website?ref=main"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + }; + + outputs = { + self, + nixpkgs, + ... + } @ inputs: let + system = "x86_64-linux"; + + l = nixpkgs.lib.extend (import ./lib); + getModules = dir: l.pipe (l.filterAttrs (_: type: type == "directory") (builtins.readDir ./${dir})) [ + (x: builtins.mapAttrs (name: _: builtins.readDir ./${dir}/${name}) x) # Get all types and their files + (x: builtins.mapAttrs (name: value: (l.pipe value [ + (y: l.filterAttrs (n: _: n != "secrets") y) # Exclude agenix secrets directory + (y: l.filterAttrs (n: _: n != "containers") y) # Exclude containers directory + (y: l.mapAttrsToList (n: _: ./${dir}/${name}/${n}) y) # Make phoenix."default.nix" = "regular" phoenix = [ "default.nix" ] + ])) x) + ]; + + modulesList = { + hosts = getModules "hosts"; + # profiles = getModules "profiles"; + modules = getModules "modules"; + # users = getModules "users"; + }; + + hosts = builtins.mapAttrs ( + host: modules: + let + cfg = import ./hosts/${host}/default.nix { lib = l; pkgs = {}; config = {}; }; + in l.nixosSystem { + inherit system; + specialArgs = { + inherit inputs; + inherit host; + username = cfg.n.host.defaultUser; + }; + + modules = + modules + ++ l.flatten (builtins.map (x: modulesList.modules.${x}) (cfg.n.host.types + ++ [ + "global" + "n" + ] + )); + }) modulesList.hosts; + + externals = l.pipe hosts [ + # (x: builtins.mapAttrs (_: v: (l.filterAttrs (n: _: n == "global" || n == "nodes") v.config)) x) # Get `global` and `nodes` + (x: builtins.mapAttrs (_: v: (l.filterAttrs (n: _: n == "nodes") v.config)) x) # Get `nodes` + (x: builtins.attrValues x) + ]; + + hosts' = builtins.mapAttrs ( + name: system: system.extendModules { + modules = map (n: if l.hasAttr "${name}" n.nodes then n.nodes.${name} else {}) externals; + } + ) hosts; + + in { + nixosConfigurations = hosts'; + + deploy = { + # sudo = "doas -u"; + sshOpts = [ "-p" "22" ]; + autoRollback = false; + magicRollback = false; + remoteBuild = false; + + # KOSTYL' + nodes.cepheus = { + hostname = "nothing.run"; + user = "root"; + profiles.system = { + sshUser = "root"; + path = inputs.deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.cepheus; + }; + }; + nodes.naos = { + hostname = "192.168.1.115"; + user = "root"; + profiles.system = { + sshUser = "root"; + path = inputs.deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.cepheus; + }; + }; + }; + # This is highly advised, and will prevent many possible mistakes + checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) inputs.deploy-rs.lib; + + agenix-rekey = inputs.agenix-rekey.configure { + userFlake = self; + nixosConfigurations = self.nixosConfigurations; + }; + + formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.alejandra; + }; +} diff --git a/hosts/cepheus/caddy.nix b/hosts/cepheus/caddy.nix new file mode 100644 index 0000000..b0e48ae --- /dev/null +++ b/hosts/cepheus/caddy.nix @@ -0,0 +1,17 @@ +{ inputs, ... }: { + services.caddy = { + enable = true; + + virtualHosts."nothing.run, www.nothing.run".extraConfig = '' + header /.well-known/matrix/* Content-Type application/json + header /.well-known/matrix/* Access-Control-Allow-Origin * + respond /.well-known/matrix/server `{"m.server": "matrix.nothing.run:443"}` + respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://matrix.nothing.run"},"org.matrix.msc3575.proxy":{"url":"https://matrix.nothing.run"}}` + + root * ${inputs.website.website} + file_server + ''; + + }; + networking.firewall.allowedTCPPorts = [ 80 443 ]; +} diff --git a/hosts/cepheus/couchdb.nix b/hosts/cepheus/couchdb.nix new file mode 100644 index 0000000..00196b4 --- /dev/null +++ b/hosts/cepheus/couchdb.nix @@ -0,0 +1,37 @@ +{ pkgs, lib, ... }: { + containers.couchdb = { + autoStart = true; + bindMounts = { + "/var/lib/couchdb" = { hostPath = "/nix/persist/services/couchdb"; isReadOnly = false; }; + }; + hostAddress = "192.168.105.10"; + localAddress = "192.168.105.11"; + privateNetwork = true; + + config = { ... }: { + services.couchdb = { + enable = true; + bindAddress = "192.168.105.11"; + port = 5984; + databaseDir = "/var/lib/couchdb"; + viewIndexDir = "/var/lib/couchdb"; + + adminUser = lib.removeSuffix "\n" ("admin_" + pkgs.lib.readFile "${pkgs.runCommand "timestamp" {} "echo `head -c 12 /dev/urandom | base64 | sed 's/[+=\\/A-Z]//g'` > $out"}"); + adminPass = pkgs.lib.readFile "${pkgs.runCommand "timestamp" {} "echo `head -c 32 /dev/urandom | base64 | sed 's/[+=\\/A-Z]//g'` > $out"}"; + }; + + networking.firewall = { + enable = true; + allowedTCPPorts = [ 5984 ]; + }; + system.stateVersion = "25.05"; + }; + }; + + services.caddy.virtualHosts = { + "couchdb.nothing.run".extraConfig = '' + reverse_proxy http://192.168.105.11:5984 + ''; + }; + +} diff --git a/hosts/cepheus/default.nix b/hosts/cepheus/default.nix new file mode 100644 index 0000000..e60555c --- /dev/null +++ b/hosts/cepheus/default.nix @@ -0,0 +1,37 @@ +{ lib, config, ... }: { + nixpkgs.hostPlatform = "x86_64-linux"; + hardware.enableRedistributableFirmware = true; + boot.initrd.availableKernelModules = [ + "nvme" + "xhci_pci" + "usb_storage" + "sd_mod" + "ata_piix" + "virtio_pci" + "virtio_scsi" + "sr_mod" + ]; + + age.secrets.cepheus_userhjkl_password = { + rekeyFile = ./secrets/password.age; + owner = "userhjkl"; + group = "users"; + mode = "0400"; + }; + + n.host = { + hardware.cpu = "virt"; + bootloader = "grub"; + + domain = "nothing.run"; + hostId = "0b6ce634"; + users."userhjkl" = lib.mkUser config.age.secrets.cepheus_userhjkl_password.path true; + defaultUser = "userhjkl"; + types = [ "server" ]; + }; + + imports = [ + (lib.fs.ext4 "/" "/dev/disk/by-uuid/8c2eee33-ab23-42b5-b22c-777fbede1ccf" null) + (lib.fs.vfat "/boot" "/dev/disk/by-uuid/8B83-5678" null) + ]; +} diff --git a/hosts/cepheus/gitea.nix b/hosts/cepheus/gitea.nix new file mode 100644 index 0000000..fdea1d3 --- /dev/null +++ b/hosts/cepheus/gitea.nix @@ -0,0 +1,195 @@ +{ config, pkgs, lib, ... }: { + age.secrets.kanidm-oauth2-gitea = lib.mkSecret "kanidm"; + services.kanidm.provision = { + groups."gitea.access" = {}; + groups."gitea.admins" = {}; + systems.oauth2.gitea = { + displayName = "gitea"; + originUrl = "https://tea.nothing.run/user/oauth2/kanidm/callback"; + originLanding = "https://tea.nothing.run/"; + basicSecretFile = config.age.secrets.kanidm-oauth2-gitea.path; + scopeMaps."gitea.access" = [ + "openid" + "email" + "profile" + ]; + allowInsecureClientDisablePkce = true; + preferShortUsername = true; + claimMaps.groups = { + joinType = "array"; + valuesByGroup."gitea.admins" = [ "admins" ]; + }; + }; + }; + + containers.gitea = let host-config = config; in { + autoStart = true; + bindMounts = { + "/var/lib/gitea" = { hostPath = "/nix/persist/services/gitea"; isReadOnly = false; }; + # "${config.age.secretsDir}" = { hostPath = config.age.secretsDir; isReadOnly = true; }; + "/run/agenix" = { hostPath = "/run/agenix"; isReadOnly = false; }; + }; + # tmpfs = [ "/" ]; + hostAddress = "192.168.102.10"; + localAddress = "192.168.102.11"; + + # forwardPorts = [ + # { + # containerPort = 22; + # hostPort = 9922; + # protocol = "tcp"; + # } + # ]; + privateNetwork = true; + + config = { lib, config, ... }: { + imports = [ + ../../modules/global/dnscrypt-proxy.nix + ]; + + users.groups.kanidm = {}; + users.groups.git = { }; + users.users.git = { + isSystemUser = true; + useDefaultShell = true; + group = "git"; + extraGroups = [ "kanidm" ]; + home = config.services.gitea.stateDir; + openssh.authorizedKeys.keys = lib.mkForce host-config.users.users.root.openssh.authorizedKeys.keys; + }; + services.openssh = { + enable = true; + # settings = { + # PasswordAuthentication = false; + # KbdInteractiveAuthentication = false; + # PermitRootLogin = "prohibit-password"; + # }; + # openFirewall = true; + # ports = [ 22 ]; + # settings.AcceptEnv = "GIT_PROTOCOL"; + }; + + services.gitea = { + enable = true; + package = pkgs.gitea; + user = "git"; + group = "git"; + settings = { + DEFAULT.APP_NAME = "Hollow Tea"; + mailer.ENABLED = false; + metrics.ENABLED = false; + oauth2_client = { + ACCOUNT_LINKING = "login"; + USERNAME = "nickname"; + ENABLE_AUTO_REGISTRATION = false; + REGISTER_EMAIL_CONFIRM = false; + UPDATE_AVATAR = true; + }; + repository = { + DEFAULT_PRIVATE = "private"; + ENABLE_PUSH_CREATE_USER = true; + ENABLE_PUSH_CREATE_ORG = true; + }; + server = { + HTTP_ADDR = "0.0.0.0"; + HTTP_PORT = 3000; + DOMAIN = "tea.nothing.run"; + ROOT_URL = "https://tea.nothing.run"; + LANDING_PAGE = "login"; + SSH_PORT = 9922; + SSH_USER = "git"; + }; + service = { + DISABLE_REGISTRATION = false; + ALLOW_ONLY_INTERNAL_REGISTRATION = false; + ALLOW_ONLY_EXTERNAL_REGISTRATION = true; + SHOW_REGISTRATION_BUTTON = false; + REGISTER_EMAIL_CONFIRM = false; + ENABLE_NOTIFY_MAIL = false; + }; + "service.explore" = { + REQUIRE_SIGNIN_VIEW = true; + DISABLE_USERS_PAGE = false; + DISABLE_ORGANIZATIONS_PAGE = true; + DISABLE_CODE_PAGE = true; + }; + admin.DISABLE_REGULAR_ORG_CREATION = true; # Prohibit creation of organizations by non-admin users + session.COOKIE_SECURE = true; + }; + }; + + systemd.services.gitea = { + enable = true; + wantedBy = [ "multi-user.target" ]; + serviceConfig.RestartSec = "60"; # Retry every minute + preStart = + let + exe = lib.getExe config.services.gitea.package; + providerName = "kanidm"; + clientId = "gitea"; + args = lib.escapeShellArgs ( + lib.concatLists [ + [ + "--name" + providerName + ] + [ + "--provider" + "openidConnect" + ] + [ + "--key" + clientId + ] + [ + "--auto-discover-url" + "https://idm.nothing.run/oauth2/openid/${clientId}/.well-known/openid-configuration" + ] + [ + "--scopes" + "email" + ] + [ + "--scopes" + "profile" + ] + [ + "--group-claim-name" + "groups" + ] + [ + "--admin-group" + "admin" + ] + [ "--skip-local-2fa" ] + ] + ); + in + lib.mkAfter '' + provider_id=$(${exe} admin auth list | ${pkgs.gnugrep}/bin/grep -w '${providerName}' | cut -f1) + SECRET="$(< ${host-config.age.secrets.kanidm-oauth2-gitea.path})" + if [[ -z "$provider_id" ]]; then + ${exe} admin auth add-oauth ${args} --secret "$SECRET" + else + ${exe} admin auth update-oauth --id "$provider_id" ${args} --secret "$SECRET" + fi + ''; + }; + + networking.firewall = { + enable = true; + allowedTCPPorts = [ 3000 22 ]; + }; + system.stateVersion = "25.05"; + }; + }; + + networking.firewall.allowedTCPPorts = [ 9922 ]; + + services.caddy.virtualHosts = { + "tea.nothing.run".extraConfig = '' + reverse_proxy http://192.168.102.11:3000 + ''; + }; + +} diff --git a/hosts/cepheus/hedgedoc.nix b/hosts/cepheus/hedgedoc.nix new file mode 100755 index 0000000..8a1f764 --- /dev/null +++ b/hosts/cepheus/hedgedoc.nix @@ -0,0 +1,36 @@ +{ config, ... }: +let + inherit (config.networking) domain; + service_port = 8259; + db = "hedgedoc"; +in { + services.hedgedoc = { + # enable = true; # TODO + enable = false; + settings = { + # TODO: kanidm auth + port = service_port; + protocolUseSSL = true; + domain = "pad.${domain}"; + host = "127.0.0.1"; + allowGravatar = false; + allowPDFExport = true; + dbURL = "postgres://${db}:${db}@localhost:${toString config.services.postgresql.settings.port}/${db}"; + + allowEmailRegister = false; + allowAnonymous = false; + + loglevel = "none"; + }; + }; + + imp.dirs = [ + { directory = "/var/lib/hedgedoc"; user = "hedgedoc"; group = "hedgedoc"; mode = "u=rwx,g=rx,o="; } + ]; + + services.caddy.virtualHosts = { + "pad.${domain}".extraConfig = '' + reverse_proxy http://127.0.0.1:${toString service_port} + ''; + }; +} diff --git a/hosts/cepheus/kanidm.nix b/hosts/cepheus/kanidm.nix new file mode 100644 index 0000000..e32fe80 --- /dev/null +++ b/hosts/cepheus/kanidm.nix @@ -0,0 +1,107 @@ +{ config, pkgs, lib, ... }: +let + kanidmPort = 1888; +in { + age.secrets.kanidm-admin-password = lib.mkSecret "kanidm"; + age.secrets.kanidm-idm-admin-password = lib.mkSecret "kanidm"; + users.groups.kanidm = {}; + users.users.kanidm.group = "kanidm"; + users.users.kanidm.isSystemUser = true; + + containers.kanidm = { + autoStart = true; + bindMounts = { + "/certs" = { hostPath = "/nix/persist/services/kanidm/certs"; isReadOnly = false; }; + "/var/lib/kanidm" = { hostPath = "/nix/persist/services/kanidm/db"; isReadOnly = false; }; + # "${config.age.secretsDir}" = { hostPath = config.age.secretsDir; isReadOnly = true; }; + "/run/agenix" = { hostPath = "/run/agenix"; isReadOnly = false; }; + }; + # tmpfs = [ "/" ]; + hostAddress = "192.168.101.10"; + localAddress = "192.168.101.11"; + privateNetwork = true; + # privateNetwork = false; + + config = { lib, ... }: { + imports = [ + # ../../modules/global/nix.nix + ../../modules/global/dnscrypt-proxy.nix + ]; + + services.kanidm = { + enableServer = true; + package = pkgs.kanidmWithSecretProvisioning; + enableClient = true; + serverSettings = { + domain = "idm.nothing.run"; + origin = "https://idm.nothing.run"; + # bindaddress = "127.0.0.1:${toString kanidmPort}"; + bindaddress = "0.0.0.0:${toString kanidmPort}"; + log_level = "trace"; + trust_x_forward_for = true; + + tls_chain = "/certs/chain.pem"; + tls_key = "/certs/key.pem"; + }; + clientSettings = { + uri = "https://127.0.0.1:${toString kanidmPort}"; + verify_ca = false; + verify_hostnames = false; + }; + provision = lib.mkMerge [ + { enable = lib.mkForce true; } + config.services.kanidm.provision + ]; + }; + + networking.firewall = { + enable = true; + allowedTCPPorts = [ kanidmPort ]; + }; + system.stateVersion = "25.05"; + }; + }; + + services.kanidm.provision = { + acceptInvalidCerts = true; + instanceUrl = "https://127.0.0.1:${toString kanidmPort}"; + + adminPasswordFile = config.age.secrets.kanidm-admin-password.path; + idmAdminPasswordFile = config.age.secrets.kanidm-idm-admin-password.path; + groups.admins = {}; + + persons = { + "thary" = { + "displayName" = "Thary"; + "mailAddresses" = [ + "thary@riseup.net" + "thary@nothing.run" + ]; + groups = [ + "gitea.access" "gitea.admins" + "miniflux.access" + ]; + }; + }; + }; + + imp.home.dirs = [ ".cache/kanidm_tokens" ]; + services.kanidm.enableClient = true; + services.kanidm.clientSettings = { + uri = "https://idm.nothing.run"; + verify_ca = true; + verify_hostnames = true; + }; + + services.caddy.virtualHosts = { + "idm.nothing.run".extraConfig = '' + reverse_proxy https://192.168.101.11:${toString kanidmPort} { + transport http { + tls + tls_insecure_skip_verify + } + } + ''; + }; + +} diff --git a/hosts/cepheus/matrix-web-clients.nix b/hosts/cepheus/matrix-web-clients.nix new file mode 100644 index 0000000..a6d4f49 --- /dev/null +++ b/hosts/cepheus/matrix-web-clients.nix @@ -0,0 +1,34 @@ +{ pkgs, ... }: { + services.caddy = { + enable = true; + + virtualHosts."cinny.nothing.run".extraConfig = '' + root * ${pkgs.cinny.override {conf = { + defaultHomeserver = 0; + homeserverList = [ "matrix.nothing.run" "matrix.inex.rocks" ]; + allowCustomHomeservers = false; + };}} + file_server + ''; + virtualHosts."element.nothing.run".extraConfig = '' + root * ${pkgs.element-web.override { + conf = { + default_server_config = { + "m.homeserver".base_url = "https://nothing.run"; + "m.identity_server" = {}; + }; + disable_custom_urls = true; + brand = "Nothing Chat"; + default_theme = "dark"; + jitsi.preferred_domain = "https://jitsi.inex.rocks"; # TODO: host jitsi + };}} + file_server + ''; + virtualHosts."riot.nothing.run".extraConfig = '' + redir https://element.nothing.run + ''; + +# TODO: schildichat-web (there is no package in nixpkgs) + }; + networking.firewall.allowedTCPPorts = [ 80 443 ]; +} diff --git a/hosts/cepheus/miniflux.nix b/hosts/cepheus/miniflux.nix new file mode 100644 index 0000000..c288540 --- /dev/null +++ b/hosts/cepheus/miniflux.nix @@ -0,0 +1,76 @@ +{ config, pkgs, lib, ... }: { + age.secrets.kanidm-oauth2-miniflux = lib.mkSecret "kanidm"; + services.kanidm.provision = { + groups."miniflux.access" = {}; + systems.oauth2.miniflux = { + displayName = "miniflux"; + originUrl = "https://rss.nothing.run/oauth2/oidc/callback"; + originLanding = "https://rss.nothing.run/"; + basicSecretFile = config.age.secrets.kanidm-oauth2-miniflux.path; + scopeMaps."miniflux.access" = [ + "openid" + "email" + "profile" + ]; + allowInsecureClientDisablePkce = true; + preferShortUsername = true; + }; + }; + + age.secrets.miniflux-admin-credentials = { + generator.script = _: '' + echo "ADMIN_USERNAME = 'admin_fmA4ei32f'" + echo "ADMIN_PASSWORD = '$(head -c 32 /dev/urandom | base64)'" + ''; + group = "kanidm"; + mode = "444"; + }; + + containers.miniflux = { + autoStart = true; + bindMounts = { + "/run/postgresql" = { hostPath = "/nix/persist/services/miniflux"; isReadOnly = false; }; + "/run/agenix" = { hostPath = "/run/agenix"; isReadOnly = false; }; + }; + hostAddress = "192.168.103.10"; + localAddress = "192.168.103.11"; + privateNetwork = true; + + config = { ... }: { + imports = [ ../../modules/global/dnscrypt-proxy.nix ]; + + users.groups.kanidm = {}; + users.users.postgres.extraGroups = [ "kanidm" ]; + + services.miniflux = { + enable = true; + createDatabaseLocally = true; + adminCredentialsFile = config.age.secrets.miniflux-admin-credentials.path; + config = { + LISTEN_ADDR = "192.168.103.11:8080"; + CREATE_ADMIN = 1; + + OAUTH2_PROVIDER = "oidc"; + OAUTH2_CLIENT_ID = "miniflux"; + OAUTH2_CLIENT_SECRET = config.age.secrets.kanidm-oauth2-miniflux.path; + OAUTH2_REDIRECT_URL = "https://rss.nothing.run/oauth2/oidc/callback"; + OAUTH2_OIDC_DISCOVERY_ENDPOINT = "https://idm.nothing.run/oauth2/openid/miniflux"; + OAUTH2_USER_CREATION = 1; + }; + }; + + networking.firewall = { + enable = true; + allowedTCPPorts = [ 8080 ]; + }; + system.stateVersion = "25.05"; + }; + }; + + services.caddy.virtualHosts = { + "rss.nothing.run".extraConfig = '' + reverse_proxy http://192.168.103.11:8080 + ''; + }; + +} diff --git a/hosts/cepheus/postgres.nix b/hosts/cepheus/postgres.nix new file mode 100644 index 0000000..d037688 --- /dev/null +++ b/hosts/cepheus/postgres.nix @@ -0,0 +1,4 @@ +{ ... }: { + services.postgresql.enable = true; + imp.dirs = [ "/var/lib/postgresql" ]; +} diff --git a/hosts/cepheus/secrets/matrix_admin_api_token.age b/hosts/cepheus/secrets/matrix_admin_api_token.age new file mode 100644 index 0000000..f54128f --- /dev/null +++ b/hosts/cepheus/secrets/matrix_admin_api_token.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 8IT6eg yX9WPef2jwkv9rsWS1Zz37qNwP/7AXVwwR3y7sy5/0k +d6IIsuuPi+ZZA/HDyDYgbjL7AiFtEEx+Ez3IWeVYo5Y +-> d6L4.Y&D-grease *z=Q"@Cb f{ VN +3IcbB/YPlZaTqaKIYjkvYmxlLVSBkOnLPMm3uPQrzA2i9bTNH6tjGVG0c64jYif4 +GXbSIKn1wkTmkYBX3FQAPsPwBQ +--- u4kYHCN4Flk12expFXLzogEmv0LleaTExylppjkLdJg +k6\Z,oVOOh+" \N)&M8&x1g&Zxn!Aȅ,\飩-omriD1De_4 \ No newline at end of file diff --git a/hosts/cepheus/secrets/password.age b/hosts/cepheus/secrets/password.age new file mode 100644 index 0000000..82b45dd --- /dev/null +++ b/hosts/cepheus/secrets/password.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 8IT6eg OGouWD06nC1BworHWu+bhrnwb5Q4skSrOKU703Rqr2E +/T0+bnhxRzgry7nVdlHFoYGEXc/6Q3dIxtvlATMl/3s +-> `-grease ++LfEGtXt+5BOYK5njRUFRhQix/yPMIs +--- Hxczp2zWnEqT0MQYjPc3O7Dva8r9pUOXkXHuv2DuIP4 +`FF#g֗t ŖK:)g\gCR3*0 Vvt:t70wND)x"מIPu6@hfag[ ܺ \ No newline at end of file diff --git a/hosts/cepheus/synapse-admin.nix b/hosts/cepheus/synapse-admin.nix new file mode 100755 index 0000000..de82945 --- /dev/null +++ b/hosts/cepheus/synapse-admin.nix @@ -0,0 +1,9 @@ +{ pkgs, config, ... }: { + services.caddy = { + virtualHosts."synapse-admin.${config.networking.domain}".extraConfig = '' + encode zstd gzip + root * ${pkgs.synapse-admin-etkecc} + file_server + ''; + }; +} diff --git a/hosts/cepheus/synapse-revitalization.nix b/hosts/cepheus/synapse-revitalization.nix new file mode 100644 index 0000000..0ababb6 --- /dev/null +++ b/hosts/cepheus/synapse-revitalization.nix @@ -0,0 +1,37 @@ +{ pkgs, config, ... }: { + age.secrets.matrix_admin_api_token = { + rekeyFile = ./secrets/matrix_admin_api_token.age; + owner = "matrix-synapse"; + group = "matrix-synapse"; + mode = "0400"; + }; + + systemd.services."synapse-revitalization" = + let pkg = "${pkgs.synapse-revitalization}/bin/synapse-revitalization"; + script = pkgs.writeShellScript "synapse-revitalization-script" '' + journalctl -f -u matrix-synapse -o cat | + while read -r line; do + echo "$line" | grep "as we're not in the room" && ${pkg} "$line" & + echo "$line" | grep "Ignoring PDU for unknown room_id" && ${pkg} "$line" & + done + ''; + in { + enable = true; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "simple"; + # User = "matrix-synapse"; + # Group = "matrix-synapse"; + User = "root"; + Group = "root"; + ExecStart = script; + Restart = "always"; + }; + environment = { + "SYNAPSE_REVITALIZATION_ADMIN_AUTH_TOKEN_FILE" = config.age.secrets.matrix_admin_api_token.path; + "SYNAPSE_REVITALIZATION_SERVER_KEY_FILE" = "/var/lib/matrix-synapse/homeserver.signing.key"; + "SYNAPSE_REVITALIZATION_SERVER_NAME" = "nothing.run"; + "SYNAPSE_REVITALIZATION_SERVER_ADDRESS" = "matrix.nothing.run"; + }; + }; +} diff --git a/hosts/cepheus/synapse.nix b/hosts/cepheus/synapse.nix new file mode 100755 index 0000000..7fd4c50 --- /dev/null +++ b/hosts/cepheus/synapse.nix @@ -0,0 +1,216 @@ +{ lib, config, pkgs, ... }: +let + domain = "nothing.run"; + ulid = "01K2FWKJXXG713J0PERVHJ54S3"; +in { + environment.systemPackages = with pkgs; [ synapse synadm ]; + + age.secrets.kanidm-oauth2-mas = lib.mkSecret "kanidm"; + services.kanidm.provision = { + groups."matrix.access" = {}; + # groups."matrix.admins" = {}; + systems.oauth2.matrix = { + displayName = "matrix"; + originUrl = "https://mas.nothing.run/upstream/callback/${ulid}"; + originLanding = "https://mas.nothing.run/"; + basicSecretFile = config.age.secrets.kanidm-oauth2-mas.path; + scopeMaps."matrix.access" = [ + "openid" + "email" + "profile" + ]; + allowInsecureClientDisablePkce = false; + # enableLegacyCrypto = true; + preferShortUsername = true; + # claimMaps.groups = { + # joinType = "array"; + # valuesByGroup."matrix.admins" = [ "admins" ]; + # }; + }; + }; + + # containers.matrix-synapse = { + # autoStart = true; + # bindMounts = { + # "/var/lib/matrix-synapse" = { hostPath = "/nix/persist/services/synapse/data"; isReadOnly = false; }; + # "/var/lib/postgresql" = { hostPath = "/nix/persist/services/synapse/db"; isReadOnly = false; }; + # "/run/agenix" = { hostPath = "/run/agenix"; isReadOnly = false; }; + # }; + # hostAddress = "192.168.107.10"; + # localAddress = "192.168.107.11"; + # + # privateNetwork = true; + # + # config = { ... }: { + systemd.services.matrix-authentication-service = + let config = pkgs.writeText "mas-configuration.json" (builtins.toJSON { + upstream_oauth2.providers = [ + { + id = ulid; + issuer = "https://idm.nothing.run/oauth2/openid/matrix"; + token_endpoint_auth_method = "client_secret_basic"; + human_name = "matrix"; + client_id = "matrix"; + scope = "openid email profile"; + pkce_method = "always"; + + claims_imports.localpart.action = "require"; + claims_imports.displayname.action = "ignore"; + claims_imports.email.action = "require"; + } + ]; + + http = { + public_base = "https://mas.nothing.run"; + listeners = [{ + name = "web"; + resources = [ + { name = "discovery"; } + { name = "human"; } + { name = "oauth"; } + { name = "compat"; } + { name = "graphql"; } + { + name = "assets"; + path = "${pkgs.matrix-authentication-service}/share/matrix-authentication-service/assets"; + } # What is it? + ]; + + binds = [{ + host = "127.0.0.1"; + port = 8086; + }]; + proxy_protocol = false; + }]; + }; + # database.uri = "postgresql:///matrix-authentication-service?host=/run/postgresql"; + database.uri = "postgresql://matrix-authentication-service@127.0.0.1:5432/matrix-authentication-service"; + matrix = { + kind = "synapse"; + homeserver = "nothing.run"; + endpoint = "https://matrix.nothing.run:443"; + }; + passwords = { + enabled = true; + schemes = [ + { + version = 2; + algorithm = "argon2id"; + } + { + version = 1; + algorithm = "bcrypt"; + unicode_normalization = true; + } + ]; + minimum_complexity = 8; + }; + + }); + in { + enable = true; + description = "Matrix Authentication Service"; + # wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "simple"; + ExecStart = "${lib.getExe pkgs.matrix-authentication-service} --config ${config}"; + Restart = "on-failure"; + RestartSec = "10s"; + }; + }; + + services.postgresql = { + ensureDatabases = [ "matrix-authentication-service" ]; + ensureUsers = [ + { + name = "matrix-authentication-service"; + ensureDBOwnership = true; + } + ]; + }; + + services.matrix-synapse = { + enable = true; + settings = { + server_name = domain; + enable_metrics = true; + listeners = [ + { port = 8008; + bind_addresses = [ "0.0.0.0" ]; + type = "http"; + tls = false; + x_forwarded = true; + resources = [ { + names = [ "client" "federation" ]; + compress = true; + } ]; + } + + # { port = 3002; # Metrics + # bind_addresses = [ "0.0.0.0" ]; + # # type = "metrics"; + # type = "http"; + # tls = false; + # x_forwarded = true; + # resources = [ { + # names = [ "metrics" ]; + # compress = true; + # } ]; + # } + ]; + database = { + name = "psycopg2"; + args = let db = "matrix-synapse"; in { + user = db; + database = db; + }; + }; + # registration_shared_secret = secrets.matrix.shared_secret; + registration_shared_secret = pkgs.lib.readFile "${pkgs.runCommand "timestamp" {} "echo `cat /dev/random | head -c 50 | base64` > $out"}"; + max_upload_size = "20M"; + enable_authenticated_media = true; + require_auth_for_profile_requests = true; + enable_registration_captcha = false; + enable_registration = false; + }; + + # log.root.level = "ERROR"; + log.root.level = "INFO"; + }; + # networking.firewall.allowedTCPPorts = [ 8008 8080 ]; + # }; + # }; + + # services.caddy = { + # virtualHosts = { + # "matrix.${domain}".extraConfig = '' + # reverse_proxy /_matrix/* http://192.168.107.11:8008 + # reverse_proxy /_synapse/client/* http://192.168.107.11:8008 + # reverse_proxy /client/* http://192.168.107.11:8008 + # reverse_proxy /_matrix/client/unstable/org.matrix.msc3575/sync/* http://192.168.107.11:8008 + # reverse_proxy /_synapse/admin/* http://192.168.107.11:8008 + # ''; + # # Add `reverse_proxy /_synapse/admin/* http://127.0.0.1:8008` to allow access to the admin API + # + # "mas.${domain}".extraConfig = '' + # reverse_proxy http://192.168.107.11:8080 + # ''; + # }; + # }; + services.caddy = { + virtualHosts = { + "matrix.${domain}".extraConfig = '' + reverse_proxy /_matrix/* http://127.0.0.1:8008 + reverse_proxy /_synapse/client/* http://127.0.0.1:8008 + reverse_proxy /client/* http://127.0.0.1:8008 + reverse_proxy /_matrix/client/unstable/org.matrix.msc3575/sync/* http://127.0.0.1:8008 + reverse_proxy /_synapse/admin/* http://127.0.0.1:8008 + ''; + # Add `reverse_proxy /_synapse/admin/* http://127.0.0.1:8008` to allow access to the admin API + + "mas.${domain}".extraConfig = '' + reverse_proxy http://127.0.0.1:8086 + ''; + }; + }; +} diff --git a/hosts/naos/caddy.nix b/hosts/naos/caddy.nix new file mode 100644 index 0000000..a3383ad --- /dev/null +++ b/hosts/naos/caddy.nix @@ -0,0 +1,6 @@ +{ ... }: { + # services.caddy = { + # enable = true; + # }; + # networking.firewall.allowedTCPPorts = [ 80 443 ]; +} diff --git a/hosts/naos/default.nix b/hosts/naos/default.nix new file mode 100644 index 0000000..af3f21e --- /dev/null +++ b/hosts/naos/default.nix @@ -0,0 +1,38 @@ +{ lib, config, ... }: { + nixpkgs.hostPlatform = "x86_64-linux"; + hardware.enableRedistributableFirmware = true; + boot.initrd.availableKernelModules = [ + "ata_piix" + "usb_storage" + "usbhid" + "sd_mod" + ]; + + age.secrets.naos_userasdf_password = { + rekeyFile = ./secrets/password.age; + owner = "userasdf"; + group = "users"; + mode = "0400"; + }; + + n.host = { + hardware.cpu = "intel"; + bootloader = "sysdboot"; + + hostId = "553fb274"; + users."userasdf" = lib.mkUser config.age.secrets.naos_userasdf_password.path true; + defaultUser = "userasdf"; + types = [ "server" ]; + }; + + imports = [ + (lib.fs.zfs "/nix" "rpool/nix" null) + (lib.fs.luks "cryptroot" + "/dev/disk/by-partuuid/ed673238-50b1-4ebf-b6fc-4a25568917c6" + { allowDiscards = true; # Used if primary device is a SSD + preLVM = true; }) + + (lib.fs.tmpfs "/" "none" [ "mode=755" "size=30%" ]) + (lib.fs.vfat "/boot" "/dev/disk/by-uuid/CDA1-7D4A" null) + ]; +} diff --git a/hosts/naos/jellyfin.nix b/hosts/naos/jellyfin.nix new file mode 100644 index 0000000..850d1f9 --- /dev/null +++ b/hosts/naos/jellyfin.nix @@ -0,0 +1,16 @@ +{ pkgs, ... }: { + # imp.dirs = [ "/nix/persist/services/jellyfin" ]; + # services.jellyfin = { + # enable = true; + # dataDir = "/nix/persist/films"; + # configDir = "/nix/persist/services/jellyfin/cfg"; + # cacheDir = "/nix/persist/services/jellyfin/cache"; + # logDir = "/nix/persist/services/jellyfin/log"; + # openFirewall = false; + # }; + # environment.systemPackages = [ + # pkgs.jellyfin + # pkgs.jellyfin-web + # pkgs.jellyfin-ffmpeg + # ]; +} diff --git a/hosts/naos/luks.nix b/hosts/naos/luks.nix new file mode 100644 index 0000000..405c917 --- /dev/null +++ b/hosts/naos/luks.nix @@ -0,0 +1,19 @@ +{ ... }: { + # boot.kernelParams = [ "ip=dhcp" ]; + boot.initrd = { + availableKernelModules = [ "r8169" ]; + network = { + enable = true; + udhcpc.enable = true; + ssh = { + enable = true; + port = 22; + authorizedKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDEDqpSiQpbSsClh6UGb7Z2DA1Hy+EyePzTy+5hEVD/A" ]; + hostKeys = [ "/nix/keys/identity" ]; + }; + postCommands = '' + echo 'cryptsetup-askpass || echo "Unlock was successful; exiting SSH session" && exit 1' >> /root/.profile + ''; + }; + }; +} diff --git a/hosts/naos/secrets/password.age b/hosts/naos/secrets/password.age new file mode 100644 index 0000000..e7b3608 --- /dev/null +++ b/hosts/naos/secrets/password.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 8IT6eg a5gQkLDKM9tbEe0ZSqRKjLz7u0iOUwaxVeetTjTkbDU +w4V3IBC/MC7Pxn/92aTLNp24uZz623vEUa9wK5pS0wk +-> @Mkd`z-grease ?mx2I=/d +XDeroqJTqWJmt+aS2vLar9WtRzG3a2SlKoTwCx6s +--- ml0i3EekhNXcxocnc5Z+RQp4t9bo8qUZRAQJeWw4soE +7 +VqY{fpԭsbG iuqW{D0'<6<.M@&"r͠ %[[3UF1[ \ No newline at end of file diff --git a/hosts/phoenix/chromium.nix b/hosts/phoenix/chromium.nix new file mode 100644 index 0000000..ba103be --- /dev/null +++ b/hosts/phoenix/chromium.nix @@ -0,0 +1,41 @@ +{ pkgs, ... }: { + hm = { + programs.chromium = { + enable = true; + package = pkgs.ungoogled-chromium; + commandLineArgs = [ + "--enable-features=WebUIDarkMode,OzonePlatform,EncryptedClientHello,TouchpadOverscrollHistoryNavigation,VaapiVideoDecoder,WebAssembly" + "--disable-features=UserAgentClientHint" + "--force-webrtc-ip-handling-policy=default_public_interface_only" + "--force-dark-mode" + "--disable-beforeunload" + "--disable-search-engine-collection" + "--extension-mime-request-handling=download-as-regular-file" + "--disable-top-sites" + "--disable-file-system" + "--disable-default-apps" + "--disable-grease-tls" + "--ozone-platform=wayland" + # ''--js-flags="--jitless"'' + '' + --user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"'' + '' + --http-accept-header="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"'' + "--fingerprinting-canvas-image-data-noise" + "--fingerprinting-canvas-measuretext-noise" + "--fingerprinting-client-rects-noise" + "--enable-quic" + "--gtk-version=4" + ]; + # extensions = [ + # + # ]; + }; + }; + imp.home.dirs = [ ".config/chromium" ]; + + nodes.phoenix.hardware.graphics.extraPackages = with pkgs; [ + nvidia-vaapi-driver + libvdpau-va-gl + ]; +} diff --git a/hosts/phoenix/default.nix b/hosts/phoenix/default.nix new file mode 100644 index 0000000..8936544 --- /dev/null +++ b/hosts/phoenix/default.nix @@ -0,0 +1,35 @@ +{ lib, config, ... }: { + nixpkgs.hostPlatform = "x86_64-linux"; + hardware.enableRedistributableFirmware = true; + boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "usb_storage" "sd_mod" ]; + + age.secrets.phoenix_user_password = { + rekeyFile = ./secrets/password.age; + owner = "user"; + group = "users"; + mode = "0400"; + }; + + n.host = { + hardware.cpu = "amd"; + bootloader = "lanzaboote"; + + hostId = "053c9578"; + users."user" = lib.mkUser config.age.secrets.phoenix_user_password.path true; + defaultUser = "user"; + types = [ "desktop" ]; + }; + + imports = [ + (lib.fs.zfs "/nix" "rpool/nix" null) + (lib.fs.luks "crypted" + "/dev/disk/by-partuuid/0f262ab8-0aad-5f42-8ee5-493f68465aff" + { header = "/dev/disk/by-partuuid/11ca2df8-17c3-47a2-8ba0-49976273008f"; + allowDiscards = true; # Used if primary device is a SSD + preLVM = true; }) + + (lib.fs.tmpfs "/" "none" [ "mode=755" "size=40%" ]) + (lib.fs.vfat "/boot" "/dev/disk/by-uuid/6D12-D841" null) + (lib.fs.swap "/dev/disk/by-uuid/391c74f2-8703-4d17-af3b-1f8087f8ad0a") + ]; +} diff --git a/hosts/phoenix/games.nix b/hosts/phoenix/games.nix new file mode 100644 index 0000000..94aec49 --- /dev/null +++ b/hosts/phoenix/games.nix @@ -0,0 +1,100 @@ +{ pkgs, lib, inputs, username, ... }: { + hm.home.packages = (with pkgs; [ + # steam-tui + steamcmd + steam-run + xwayland-satellite + # wineWow64Packages.waylandFull + bottles + + glfw3-minecraft + prismlauncher + + openspades + # zeroad + superTuxKart + wine64Packages.waylandFull + (pkgs.writeShellScriptBin "rungame" + ''export __NV_PRIME_RENDER_OFFLOAD=1 + export __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0 + export __GLX_VENDOR_LIBRARY_NAME=nvidia + export __VK_LAYER_NV_optimus=NVIDIA_only + exec "${pkgs.gamemode}/bin/gamemoderun" "$@"'' + ) + ]) ++ ( + let + mkNixPak = inputs.nixpak.lib.nixpak { inherit pkgs; inherit lib; }; + mkGameRunner' = name: rw': exe: network: mkNixPak { + config = { sloth, ... }: + let runfile = pkgs.writeScriptBin name '' + ${exe} + ''; + in { + dbus.enable = false; + gpu.enable = true; + gpu.provider = "nixos"; + bubblewrap = { + inherit network; + sockets.pulse = true; + sockets.wayland = true; + bind.rw = rw'; + bind.ro = [ "/etc" "/sys" "/lib64" "${runfile}" "/bin" ]; + tmpfs = [ "/tmp" ]; + bind.dev = [ "/dev/nvidia0" "/dev/nvidiactl" "/dev/nvidia-modeset" ]; + }; + app.package = runfile; + }; + }; + + mkWineGameRunner' = name: workdir: exe: network: (mkGameRunner' name [workdir] + ''WINEPREFIX="${workdir}/wineprefix" ${lib.getExe pkgs.wine64Packages.waylandFull} ${workdir}/${exe}'' network); + mkSteamrunGameRunner' = name: workdir: exe: network: (mkGameRunner' name [workdir] + ''DISPLAY=:0 ${lib.getExe pkgs.steam-run} ${workdir}/${exe}'' network); + mkWineGameRunner = name: workdir: exe: [ + ((mkWineGameRunner' "${name}-run" workdir exe false).config.script) + ((mkWineGameRunner' "${name}-run-inet" workdir exe true).config.script) + ]; + mkSteamrunGameRunner = name: workdir: exe: [ + (mkSteamrunGameRunner' "${name}-run" workdir exe false).config.script + (mkSteamrunGameRunner' "${name}-run-inet" workdir exe true).config.script + ]; + + dirs = ["/home/${username}/Games" "/mnt/gd" "/home/${username}/.wine"]; + in + (mkWineGameRunner "littlenighmares" "/home/${username}/Games/LittleNightmares/1" "game_info/data/Atlas/Binaries/Win64/LittleNightmares.exe") + + # (mkGameRunner' "wine-basic-run" dirs "${lib.getExe pkgs.wine64Packages.waylandFull} $@" false ).config.script + # (mkGameRunner' "wine-basic-run-inet" dirs "${lib.getExe pkgs.wine64Packages.waylandFull} $@" true ).config.script + ); + + programs = { + steam = { + enable = true; + remotePlay.openFirewall = false; # Open ports in the firewall for Steam Remote Play + # extest.enable = true; + }; + + gamemode = { + enable = true; + settings = { + + }; + }; + }; + boot.kernel.sysctl."kernel.unprivileged_userns_clone" = true; + + imp.home.dirs = [ + ".local/share/Steam" ".steam" + ".local/share/bottles" + ".local/share/PrismLauncher" + ".local/share/Paradox Interactive" + ".local/share/openspades" + ]; + + n.misc.unfreePackages = [ + "steam" + "steam-unwrapped" + "steamcmd" + "steam-run" + ]; +} diff --git a/hosts/phoenix/gnome.nix b/hosts/phoenix/gnome.nix new file mode 100644 index 0000000..e1b1f0e --- /dev/null +++ b/hosts/phoenix/gnome.nix @@ -0,0 +1,139 @@ +{ pkgs, lib, ... }: { + services.xserver.desktopManager.gnome.enable = true; + environment.gnome.excludePackages = (with pkgs; [ + gnome-tour + yelp # Help view + # ]) ++ (with pkgs.gnome; [ + tali # poker game + iagno # go game + hitori # sudoku game + atomix # puzzle game + ]); + programs.dconf.enable = true; + + imp.home.dirs = [ ".local/share/keyrings" ]; + + hm = let + extensions = with pkgs.gnomeExtensions; [ + # gnomeExtensions.user-themes + blur-my-shell + pop-shell + vitals + ]; + # inherit (lib.hm.gvariant) mkTuple; + in { + dconf.settings = { + "org/gnome/desktop/input-sources" = { + # sources = [ (mkTuple [ "xkb" "us" ]) (mkTuple [ "xkb" "by+ru" ]) ]; + xkb-options = [ "grp:caps_toggle" "compose:rctrl" ]; + }; + + "org/gnome/desktop/interface" = { + color-scheme = "prefer-dark"; + enable-hot-corners = false; + # gtk-theme = "adw-gtk3-dark"; + show-battery-percentage = true; + toolkit-accessibility = false; + }; + + "org/gnome/desktop/peripherals/touchpad" = { + tap-to-click = true; + two-finger-scrolling-enabled = true; + }; + + "org/gnome/desktop/wm/keybindings" = let + binds = map (x: { "switch-to-workspace-${toString x}" = [ "${toString x}" ]; + "move-to-workspace-${toString x}" = [ "${toString x}" ]; }) [1 2 3 4 5 6 7 8 9]; + in lib.mkMerge (binds ++ [{ + close = [ "q" ]; + minimize = [ "minus" ]; + switch-input-source = []; + switch-input-source-backward = []; + toggle-fullscreen = [ "F11" ]; + }]); + + "org/gnome/mutter" = { + dynamic-workspaces = false; + }; + + "org/gnome/settings-daemon/plugins/color" = { + night-light-enabled = true; + night-light-schedule-automatic = true; + night-light-schedule-from = 20.0; + night-light-schedule-to = 9.0; + night-light-temperature = 3469; + }; + + "org/gnome/settings-daemon/plugins/media-keys" = { + calculator = [ "Calculator" ]; + custom-keybindings = [ "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/" ]; + mic-mute = [ "AudioMicMute" ]; + screensaver = [ "ScreenSaver" ]; + volume-down = [ "AudioLowerVolume" ]; + volume-mute = [ "AudioMute" ]; + volume-up = [ "AudioRaiseVolume" ]; + www = [ "b" ]; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0" = { + binding = "Return"; + command = lib.getExe pkgs.gnome-terminal; + name = "GNOME Terminal"; + }; + + "org/gnome/shell/extensions/pop-shell" = { + active-hint = false; + fullscreen-launcher = false; + mouse-cursor-follows-active-window = true; + show-skip-taskbar = true; + show-title = true; + smart-gaps = true; + snap-to-grid = true; + stacking-with-mouse = true; + tile-by-default = true; + tile-enter = [ "r" ]; + }; + + "org/gnome/shell/extensions/vitals" = { + alphabetize = false; + fixed-widths = true; + hide-icons = false; + hide-zeros = true; + hot-sensors = [ "_memory_usage_" "_processor_usage_" "_storage_free_" ]; + memory-measurement = 1; + menu-centered = false; + position-in-panel = 2; + }; + + "org/gnome/shell/keybindings" = { + toggle-application-view = [ "d" ]; + toggle-quick-settings = [ "d" ]; + }; + + # "org/gnome/shell.favorite-apps" = [ + # # "chromium.desktop" + # "org.gnome.terminal.desktop" + # "org.gnome.nautilus.desktop" + # ]; + + "org/gnome/shell" = { + disable-user-extensions = false; + enabled-extensions = map (x: x.extensionUuid) extensions; + }; + }; + + home = { + packages = (with pkgs; [ + # pinentry-gnome # maybe I'll delete it + # cava + adw-gtk3 + dconf + gnome-tweaks + ]) ++ extensions; + + sessionVariables.GTK_THEME = "adw-gtk3-dark"; + }; + }; + + environment.etc."lemurs/wayland/gnome".source = pkgs.writeShellScript "gnome.sh" "${pkgs.gnome-shell}/bin/niri"; +} diff --git a/hosts/phoenix/gpu.nix b/hosts/phoenix/gpu.nix new file mode 100644 index 0000000..986e754 --- /dev/null +++ b/hosts/phoenix/gpu.nix @@ -0,0 +1,41 @@ +{ lib, config, ... }: { + boot.initrd.kernelModules = [ "nvidia" ]; + boot.extraModulePackages = [ config.boot.kernelPackages.nvidia_x11 ]; + services.xserver.videoDrivers = [ "nvidia" "modesetting" ]; + + hardware = { + nvidia = { + modesetting.enable = true; + powerManagement.enable = false; + powerManagement.finegrained = false; + open = false; # Use open kernel module, not nouveau + nvidiaSettings = true; + package = config.boot.kernelPackages.nvidiaPackages.stable; + # package = config.boot.kernelPackages.nvidiaPackages.stable.override { + # disable32Bit = true; + # }; + + + prime = { + amdgpuBusId = "PCI:5:0:0"; + nvidiaBusId = "PCI:1:0:0"; + + offload = { + enable = true; + enableOffloadCmd = true; + }; + reverseSync.enable = lib.mkForce false; + sync.enable = lib.mkForce false; + }; + }; + + graphics.enable = true; # OpenGL + }; + + nixpkgs.config.nvidia.acceptLicense = true; + n.misc.unfreePackages = [ + "nvidia-x11" + "nvidia-settings" + "nvidia-persistenced" + ]; +} diff --git a/hosts/phoenix/obsidian.nix b/hosts/phoenix/obsidian.nix new file mode 100644 index 0000000..478f55f --- /dev/null +++ b/hosts/phoenix/obsidian.nix @@ -0,0 +1,12 @@ +{ pkgs, ... }: { + # nixpkgs.overlays = [ + # (final: prev: { + # electron = final.electron_33-bin; + # electron_34 = final.electron_33-bin; + # }) + # ]; + + n.misc.unfreePackages = [ "obsidian" ]; + hm.home.packages = [ pkgs.obsidian ]; + imp.home.dirs = [ ".config/obsidian" "Knowledge" ]; +} diff --git a/hosts/phoenix/postgres.nix b/hosts/phoenix/postgres.nix new file mode 100644 index 0000000..d037688 --- /dev/null +++ b/hosts/phoenix/postgres.nix @@ -0,0 +1,4 @@ +{ ... }: { + services.postgresql.enable = true; + imp.dirs = [ "/var/lib/postgresql" ]; +} diff --git a/hosts/phoenix/secrets/password.age b/hosts/phoenix/secrets/password.age new file mode 100644 index 0000000..cb123d0 --- /dev/null +++ b/hosts/phoenix/secrets/password.age @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 8IT6eg zOyK3R9L2wLc3j24BeClZfV0qreGhCUEAKe5I/ek/RQ +p8Cs+J6Wr2gqbuxk9pBHzswsVu3hFBsi69fkxvGxNIE +-> zh:p3}L;-grease 0r+81 g +Fd+eCNxUNT6oCVS+ljiPObC9d0oIZQSwkXIhIaEyugAdMBRIfvniO9nkHiHn +--- TsFWr7WQ1ublsHFf0In5XgH+THVqE9w7B3AWv4WthTo ++, + +ձ7>f<5^YwȀ9m|\͉?\kaVkWܒoS*q.]`[65,MϟZƊBdi4җNd \ No newline at end of file diff --git a/hosts/tureis/default.nix b/hosts/tureis/default.nix new file mode 100644 index 0000000..437955e --- /dev/null +++ b/hosts/tureis/default.nix @@ -0,0 +1,36 @@ +{ lib, config, ... }: { + nixpkgs.hostPlatform = "x86_64-linux"; + hardware.enableRedistributableFirmware = true; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ]; + boot.initrd.kernelModules = [ "usb_storage" ]; + boot.kernelModules = [ "usb_storage" ]; + boot.extraModulePackages = [ ]; + + # age.secrets.tureis_user_password = { + # rekeyFile = ./secrets/password.age; + # owner = "user"; + # group = "users"; + # mode = "0400"; + # }; + + n.host = { + # hardware.cpu = "intel"; # TODO + bootloader = "lanzaboote"; + + hostId = "db4713ee"; + users."user" = lib.mkUser "" true; + defaultUser = "user"; + types = [ "desktop" ]; + }; + + imports = [ + (lib.fs.luks "nix" "/dev/sda4" {}) + + (lib.fs.tmpfs "/" "none" [ "mode=755" "size=40%" ]) + (lib.fs.vfat "/boot" "/dev/disk/by-uuid/5B0A-68EA" [ "fmask=0022" "dmask=0022" ]) + (lib.fs.ext4 "/nix" "/dev/mapper/nix" null) + ]; + + boot.initrd.supportedFilesystems.vfat = true; +} diff --git a/hosts/tureis/secrets/password.age b/hosts/tureis/secrets/password.age new file mode 100644 index 0000000..cb123d0 --- /dev/null +++ b/hosts/tureis/secrets/password.age @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 8IT6eg zOyK3R9L2wLc3j24BeClZfV0qreGhCUEAKe5I/ek/RQ +p8Cs+J6Wr2gqbuxk9pBHzswsVu3hFBsi69fkxvGxNIE +-> zh:p3}L;-grease 0r+81 g +Fd+eCNxUNT6oCVS+ljiPObC9d0oIZQSwkXIhIaEyugAdMBRIfvniO9nkHiHn +--- TsFWr7WQ1ublsHFf0In5XgH+THVqE9w7B3AWv4WthTo ++, + +ձ7>f<5^YwȀ9m|\͉?\kaVkWܒoS*q.]`[65,MϟZƊBdi4җNd \ No newline at end of file diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..520a4f3 --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,5 @@ +final: prev: { + fs = import ./fs.nix final prev; + mkSecret = import ./mkSecret.nix; +} + // (import ./mkUser.nix { lib = final; }) diff --git a/lib/fs.nix b/lib/fs.nix new file mode 100644 index 0000000..7388a3f --- /dev/null +++ b/lib/fs.nix @@ -0,0 +1,24 @@ +final: prev: +let + filesystem = fsType: path: device: options: { + fileSystems.${path} = + { inherit device fsType; } + // final.optionalAttrs (options != null) { inherit options; }; + }; + +in { + btrfs = filesystem "btrfs"; + ntfs = filesystem "ntfs-3g"; + ext4 = filesystem "ext4"; + vfat = filesystem "vfat"; + zfs = filesystem "zfs"; + tmpfs = filesystem "tmpfs"; + + swap = device: {swapDevices = [{inherit device;}];}; + + luks = mapper: device: additional: { + boot.initrd.luks.devices.${mapper} = { + inherit device; + } // additional; + }; +} diff --git a/lib/mkSecret.nix b/lib/mkSecret.nix new file mode 100644 index 0000000..832468c --- /dev/null +++ b/lib/mkSecret.nix @@ -0,0 +1,5 @@ +group: { + generator.script = "alnum"; + mode = "440"; + inherit group; +} diff --git a/lib/mkUser.nix b/lib/mkUser.nix new file mode 100644 index 0000000..796a650 --- /dev/null +++ b/lib/mkUser.nix @@ -0,0 +1,8 @@ +{ lib }: { + mkUser = password: wheel: { + isNormalUser = true; + extraGroups = [ "video" "libvirtd" "lp" (if wheel then "wheel" else "") ]; + } // (if (lib.hasPrefix "/" password) + then {hashedPasswordFile = password;} + else {hashedPassword = password;}); +} diff --git a/modules/desktop/apps.nix b/modules/desktop/apps.nix new file mode 100644 index 0000000..2d40de2 --- /dev/null +++ b/modules/desktop/apps.nix @@ -0,0 +1,35 @@ +{ pkgs, ... }: { + hm.home.packages = with pkgs; [ + # qtox + # jami + # session-desktop + # briar-desktop + dino + # retroshare + # mumble + telegram-desktop + thunderbird + # fractal + + keepassxc + monero-gui + libreoffice-fresh + anki + + playerctl + android-tools + libqalculate + deploy-rs + + mpv + ]; + + imp.home.dirs = [ + ".local/share/TelegramDesktop" + ".local/share/fractal" ".cache/fractal" + ".cache/keepassxc" ".config/keepassxc" + ".config/qalculate" + ".local/share/Anki2" ".local/share/Anki" + ".local/share/dino" + ]; +} diff --git a/modules/desktop/avahi.nix b/modules/desktop/avahi.nix new file mode 100644 index 0000000..7bfa1e3 --- /dev/null +++ b/modules/desktop/avahi.nix @@ -0,0 +1,7 @@ +{ ... }: { + services.avahi = { + enable = true; + nssmdns4 = true; + nssmdns6 = true; + }; +} diff --git a/modules/desktop/bluetooth.nix b/modules/desktop/bluetooth.nix new file mode 100644 index 0000000..c795dec --- /dev/null +++ b/modules/desktop/bluetooth.nix @@ -0,0 +1,29 @@ +{ pkgs, ... }: { + hardware.bluetooth = { + enable = true; + settings = { + General = { + Enable = "Source,Sink,Media,Socket"; + }; + Policy = { + AutoEnable = "true"; + }; + }; + }; + + imp.dirs = [ "/var/lib/bluetooth" ]; + + hm = { + home.packages = with pkgs; [ bluetuith ]; + systemd.user.enable = true; + systemd.user.services.mpris-proxy = { + Unit = { + Description = "Mpris proxy"; + After = [ "bluetooth.target" "sound.target" ]; + }; + Service.ExecStart = "${pkgs.bluez}/bin/mpris-proxy"; + Install.WantedBy = [ "default.target" ]; + }; + }; + imp.home.files = [ ".cache/.bluetoothctl_history" ]; +} diff --git a/modules/desktop/cinny.nix b/modules/desktop/cinny.nix new file mode 100755 index 0000000..a7a6bcd --- /dev/null +++ b/modules/desktop/cinny.nix @@ -0,0 +1,29 @@ +{ lib, pkgs, ... }: { + services.caddy = { + enable = lib.mkDefault true; + virtualHosts."http://localhost:1989".extraConfig = '' + encode zstd gzip + root * ${pkgs.cinny} + + + file_server + @index { + not path /index.html + not path /public/* + not path /assets/* + + not path /config.json + + not path /manifest.json + not path /pdf.worker.min.js + not path /olm.wasm + not path /sw.js + + path /* + } + + rewrite /*/olm.wasm /olm.wasm + rewrite @index /index.html + ''; + }; +} diff --git a/modules/desktop/cups.nix b/modules/desktop/cups.nix new file mode 100644 index 0000000..2896486 --- /dev/null +++ b/modules/desktop/cups.nix @@ -0,0 +1,36 @@ +{ pkgs, username, ... }: { + services.printing = { + enable = true; + drivers = [ + pkgs.splix # Xerox Phaser 3117 + pkgs.pantum-driver # Pantum M6500W + ]; + }; + hardware.printers = { + ensurePrinters = [ + { + name = "Pantum"; + location = "Home"; + deviceUri = "ipps://pantum._ipps._tcp.local/"; + model = "Pantum/Pantum-M6500W-Series.ppd"; + ppdOptions = { + PageSize = "A4"; + }; + } + ]; + ensureDefaultPrinter = "Pantum"; + }; + + services.saned.enable = true; + hardware.sane = { + enable = true; + extraBackends = [ pkgs.pantum-driver pkgs.sane-airscan ]; + }; + services.udev.packages = [ pkgs.sane-airscan ]; + + n.misc.unfreePackages = [ + "pantum-driver-1.1.123" + "pantum-driver" + ]; + users.users.${username}.extraGroups = [ "scanner" "lp" ]; +} diff --git a/modules/desktop/firefox.nix b/modules/desktop/firefox.nix new file mode 100644 index 0000000..2c3fa9b --- /dev/null +++ b/modules/desktop/firefox.nix @@ -0,0 +1,133 @@ +{ inputs, pkgs, ... }: { + n.misc.defaults.firefox = [ + "text/html" + "x-scheme-handler/http" + "x-scheme-handler/https" + "application/pdf" + ]; + + hm = { + imports = [ inputs.arkenfox.hmModules.arkenfox ]; + stylix.targets.firefox = { + enable = true; + profileNames = [ "default" ]; + }; + + programs.firefox = { + enable = true; + # arkenfox.enable = true; # TODO: configure arkenfox + + profiles.default = { + id = 0; + isDefault = true; + + search = { + default = "ddg"; + engines = + let + getIcon = url: sha256: pkgs.fetchurl { inherit url sha256; }; + nixicon = getIcon "https://nixos.org/favicon.ico" "sha256-58CkYxFA9Baioz3+avCQocft/AW9sgOLTPV71gxKD2g="; + in { + + # Github + "GitHub" = { + urls = [ { template = "https://github.com/search?q={searchTerms}"; } ]; + icon = getIcon "https://github.githubassets.com/favicons/favicon-dark.svg" "sha256-qu/d9ftvsntplFuxw9RFL8BpI9b2g5b6xfeGw6Ekh6w="; + definedAliases = [ "@github" "@gh" ]; + }; + + # Knihi.com + "Knihi.com" = { + urls = [ { template = "https://knihi.com/search.html#{searchTerms}"; } ]; + icon = getIcon "https://knihi.com/img/logo.svg" "sha256-wTpuVFhstRE6HXSWvrom49Wl0NNEw7jB+3dQDcLEWFI="; + definedAliases = [ "@knihi" "@knihi.com" ]; + }; + + # NixOS Packages + "NixOS Packages" = { + urls = [ { template = "https://search.nixos.org/packages?channel=unstable&query={searchTerms}"; } ]; + icon = nixicon; + definedAliases = [ "@nixpkgs" "@np" "@pkg" ]; + }; + + # NixOS Options + "NixOS Options" = { + urls = [ { template = "https://search.nixos.org/options?channel=unstable&query={searchTerms}"; } ]; + icon = nixicon; + definedAliases = [ "@nixopts" "@no" "@opt" ]; + }; + + # NixOS Wiki + "NixOS Wiki" = { + urls = [ { template = "https://nixos.wiki/index.php?search={searchTerms}"; } ]; + icon = getIcon "https://nixos.wiki/favicon.png" "sha256-Sw3Sysk6x/xDTwz6q2/HWaCZtffapsAuMMFjYN0FhIk="; + definedAliases = [ "@nixoswiki" "@nw" ]; + }; + + # Home Manager options + "Home Manager Options" = { + urls = [ { template = "https://home-manager-options.extranix.com/?query={searchTerms}"; } ]; + icon = getIcon "https://nixos.wiki/favicon.png" "sha256-Sw3Sysk6x/xDTwz6q2/HWaCZtffapsAuMMFjYN0FhIk="; + definedAliases = [ "@hm" ]; + }; + + # Noogle (nix-functions search) + "Noogle" = { + urls = [ { template = "https://noogle.dev/q?term={searchTerms}"; } ]; + icon = getIcon "https://noogle.dev/favicon.png" "sha256-5VjB+MeP1c25DQivVzZe77NRjKPkrJdYAd07Zm0nNVM="; + definedAliases = [ "@noogle" "@f" "@l" "@func" ]; + }; + + # Rutracker + "Rutracker" = { + urls = [ { template = "https://rutracker.org/forum/tracker.php?nm={searchTerms}"; } ]; + icon = getIcon "https://rutracker.org/favicon.ico" "sha256-p6PGZMIvLUX38QL5LnHGDr0X1SfNes5JiRdh4WNj6Zg="; + definedAliases = [ "@rutracker" "@rutr" "@torrent" "@tr" ]; + }; + + # Flibusta + "Flibusta" = { + urls = [ { template = "https://flibusta.is/booksearch?ask={searchTerms}"; } ]; + icon = getIcon "https://flibusta.is/sites/default/files/bluebreeze_favicon.ico" "sha256-Ksq+eviBPAVULOXOPAxhJJ5jx9iQqIiQ4dak9twng+I="; + definedAliases = [ "@rutracker" "@rutr" "@torrent" "@tr" ]; + }; + + # Wiktionary + "Wiktionary" = { + urls = [ { template = "https://en.wiktionary.org/w/index.php?title=Special:Search&search={searchTerms}"; } ]; + icon = getIcon "https://en.wiktionary.org/static/favicon/piece.ico" "sha256-Mz5Z9nz+gPlNqo8SerFgQSAMN76557yWZp4rgbjkPv8="; + definedAliases = [ "@wiktionary" "@w" ]; + }; + + # Verbum + "Verbum" = { + urls = [ { template = "https://verbum.by/?q={searchTerms}"; } ]; + icon = getIcon "https://verbum.by/statics/favicon.png" "sha256-/P3zuoHbL5Rb7MYxPeehVCmfoB/V73edTvGrHTA8hJ4="; + definedAliases = [ "@verbum" "@v" ]; + }; + + # Sloŭnik.org + "Slounik.org" = { + urls = [ { template = "https://slounik.org/search?dict=&search={searchTerms}"; } ]; + icon = getIcon "https://slounik.org/icon.svg" "sha256-jDvQ0iNMZ8pFp6+uvzTBuEOuVstZP2t1+hzDDx7oCAk="; + definedAliases = [ "@slounik" "@sl" ]; + }; + + # Youtube + "Youtube" = { + urls = [ { template = "https://www.youtube.com/results?search_query={searchTerms}"; } ]; + icon = getIcon "https://www.youtube.com/s/desktop/280a3f09/img/favicon.ico" "sha256-i7HQ+kOhdDbVndVG9vdMdtxEc13vdSLCLYAxFm24kR0="; + definedAliases = [ "@youtube" "@yt" "@y" ]; + }; + + # Disable crap + "bing".metaData.hidden = true; + "google".metaData.hidden = true; + }; + }; + }; + }; + }; + + imp.home.dirs = [ ".mozilla" ]; +} diff --git a/modules/desktop/fish.nix b/modules/desktop/fish.nix new file mode 100644 index 0000000..fcc0ee9 --- /dev/null +++ b/modules/desktop/fish.nix @@ -0,0 +1,54 @@ +{ pkgs, config, ...}: { + globals.hm = { + programs.carapace = { + enableFishIntegration = true; + enable = true; + }; + home.packages = with pkgs; [ grc fzf ]; + + # home.file.".config/fish/config.fish".force = lib.mkForce true; + programs.fish = { + enable = true; + shellAliases = config.n.misc.aliases; + + interactiveShellInit = '' + set fish_greeting + fish_vi_key_bindings + ''; + + plugins = with pkgs.fishPlugins; [ + # Colorized command output + { name = "grc"; src = grc.src; } + # Fzf integration + { name = "fzf"; src = fzf-fish.src; } + { name = "forgit"; src = forgit.src; } + # Usage frequency-based directory jumping + { name = "z"; src = z.src; } + ]; + + functions = { + fish_prompt = "string join '' -- (set_color --bold green) (prompt_login) (set_color normal) ' ['(prompt_pwd)']' (set_color green) (fish_git_prompt) ' '(fish_default_mode_prompt)\\n(set_color blue)'> '(set_color normal)"; + fish_mode_prompt = ""; + fish_default_mode_prompt = '' + switch $fish_bind_mode + case default + set_color red + echo '[N]' + case insert + set_color green + echo '[I]' + case replace_one + set_color green + echo '[R]' + case visual + set_color brmagenta + echo '[V]' + end + ''; + }; + }; + }; + imp.home.dirs = [ ".local/share/fish" ]; + users.defaultUserShell = pkgs.fish; + programs.fish.enable = true; +} diff --git a/modules/desktop/fonts.nix b/modules/desktop/fonts.nix new file mode 100644 index 0000000..88dcd13 --- /dev/null +++ b/modules/desktop/fonts.nix @@ -0,0 +1,28 @@ +{ pkgs, ... }: { + fonts = { + packages = with pkgs; ([ + # fira-code + # fira-code-symbols + noto-fonts-emoji + ] + ++ (with nerd-fonts; [ + fira-code + fira-sans + fira-mono + noto + font-awesome + cozette + source-han-sans + ubuntu + ])); + + fontconfig = { + defaultFonts = { + monospace = ["FiraCode Nerd Font Mono" "Noto Color Emoji"]; + sansSerif = ["FiraCode Nerd Font" "Noto Color Emoji"]; + serif = ["FiraCode Nerd Font" "Noto Color Emoji"]; + emoji = ["Noto Color Emoji"]; + }; + }; + }; +} diff --git a/modules/desktop/foot.nix b/modules/desktop/foot.nix new file mode 100644 index 0000000..90b36a7 --- /dev/null +++ b/modules/desktop/foot.nix @@ -0,0 +1,6 @@ +{ ... }: { + hm.programs.foot = { + enable = true; + server.enable = true; + }; +} diff --git a/modules/desktop/gpg.nix b/modules/desktop/gpg.nix new file mode 100644 index 0000000..a85d1e8 --- /dev/null +++ b/modules/desktop/gpg.nix @@ -0,0 +1,10 @@ +{ pkgs, ... }: { + hm.programs.gpg.enable = true; + + hm.services.gpg-agent = { + enable = true; + enableSshSupport = false; + pinentry.package = pkgs.pinentry-tty; + enableFishIntegration = true; + }; +} diff --git a/modules/desktop/gvfs.nix b/modules/desktop/gvfs.nix new file mode 100644 index 0000000..76ecf07 --- /dev/null +++ b/modules/desktop/gvfs.nix @@ -0,0 +1,3 @@ +{ ... }: { + services.gvfs.enable = true; +} diff --git a/modules/desktop/loupe.nix b/modules/desktop/loupe.nix new file mode 100644 index 0000000..b1a5f16 --- /dev/null +++ b/modules/desktop/loupe.nix @@ -0,0 +1,20 @@ +{ pkgs, ... }: { + hm.home.packages = with pkgs; [ loupe ]; + n.misc.defaults."org.gnome.Loupe" = [ + "image/avif" + "image/bmp" + "image/gif" + "image/jp2" + "image/jpeg" + "image/jpg" + "image/jpm" + "image/jpx" + "image/jxl" + "image/png" + "image/tiff" + "image/vnd.microsoft.icon" + "image/webp" + "image/webp" + "image/x-tga" + ]; +} diff --git a/modules/desktop/network-manager.nix b/modules/desktop/network-manager.nix new file mode 100644 index 0000000..5e05e6b --- /dev/null +++ b/modules/desktop/network-manager.nix @@ -0,0 +1,5 @@ +{ username, ... }: { + networking.networkmanager.enable = true; + users.users.${username}.extraGroups = [ "networkmanager" "netdev" ]; + imp.dirs = [ "/etc/NetworkManager" "/var/lib/NetworkManager" ]; +} diff --git a/modules/desktop/niri.nix b/modules/desktop/niri.nix new file mode 100644 index 0000000..c4f620e --- /dev/null +++ b/modules/desktop/niri.nix @@ -0,0 +1,290 @@ +{ lib, pkgs, config, inputs, username, ... }: { + imports = [ inputs.niri.nixosModules.niri ]; + hm.imports = [ inputs.ags.homeManagerModules.ags ]; + + nixpkgs.overlays = [ + inputs.niri.overlays.niri + (final: prev: { + c.niri = final.niri-unstable; + }) + ]; + + programs.light.enable = true; + programs.niri = { + enable = true; + package = pkgs.c.niri; + }; + + hm.home.packages = with pkgs; [ mako wofi wl-clipboard wl-clipboard-x11 swaybg swayidle swaylock yambar ]; + hm.programs.niri.settings = { + environment = { + QT_QPA_PLATFORM = "wayland"; + NIXOS_OZONE_WL = "1"; + GSK_RENDERER = "gl"; + }; + + input = { + touchpad = { + natural-scroll = false; + scroll-method = "two-finger"; + tap = true; + }; + + keyboard = { + xkb = { + layout = "pl,by(ru)"; + options = "grp:caps_toggle,compose:menu"; + }; + }; + }; + + spawn-at-startup = [ + { command = [ "${lib.getExe pkgs.mako}" ]; } + { command = [ "${lib.getExe pkgs.xwayland-satellite}" ]; } + { command = [ "${lib.getExe pkgs.swaybg}" "--image" "/home/${username}/Pictures/Wallpapers/1.png" ]; } + { command = let + swaylock = "${lib.getExe pkgs.swaylock} -f -c 000000"; + niri = lib.getExe pkgs.niri; + light = lib.getExe pkgs.light; + script = pkgs.writeShellScript "lockscript.sh" + '' + ${lib.getExe pkgs.swayidle} -w \ + lock '${swaylock} && ${niri} msg action power-off-monitors' \ + unlock '${niri} msg action power-on-monitors' \ + timeout 200 '${swaylock}' \ + timeout 210 '${niri} msg action power-off-monitors' \ + resume '${niri} msg action power-on-monitors' \ + timeout 195 '${light} -U 50' \ + resume '${light} -A 50' \ + before-sleep '${swaylock}' + ''; + in [ "sh" "-e" "${script}" ]; + } + { command = [ "${lib.getExe pkgs.yambar}" ]; } + ]; + binds = with config.hm.lib.niri.actions; let + workspaces = [1 2 3 4 5 6 7 8 9]; + tags-binds = map (x: { "Mod+${toString x}".action = focus-workspace x; + "Mod+Shift+${toString x}".action = move-column-to-index x; + }) workspaces; + in lib.mkMerge (tags-binds ++ [{ + # Volume + "XF86AudioRaiseVolume" = { + action = spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.01+"; + allow-when-locked = true; + }; + "XF86AudioLowerVolume".action = spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.01-"; + "XF86AudioMute".action = spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; + "XF86AudioMicMute".action = spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; + + "XF86Calculator".action = spawn "foot" "-e" "qalc"; + + "XF86MonBrightnessUp".action = spawn "${lib.getExe pkgs.light}" "-A" "2"; + "XF86MonBrightnessDown".action = spawn "${lib.getExe pkgs.light}" "-U" "2"; + "XF86ScreenSaver".action = let session = "loginctl session-status | awk '{ print $1 }' | head -n 1"; + in spawn "loginctl lock-session $(${session})"; + + + "Mod+Shift+Q".action = close-window; + "Mod+Shift+E".action = quit; + "Mod+Space".action = toggle-window-floating; + "Mod+O".action = toggle-overview; + "Mod+Slash".action = show-hotkey-overlay; + "Mod+P".action = toggle-window-rule-opacity; + + "Mod+Minus".action = set-column-width "-10%"; + "Mod+Equal".action = set-column-width "+10%"; + "Mod+Shift+Minus".action = set-window-height "-10%"; + "Mod+Shift+Equal".action = set-window-height "+10%"; + + "Mod+W".action = toggle-column-tabbed-display; + "Mod+Ctrl+H".action = consume-or-expel-window-left; + "Mod+Ctrl+L".action = consume-or-expel-window-right; + + "Mod+R".action = switch-preset-column-width; + "Mod+Shift+R".action = reset-window-height; + "Mod+F".action = maximize-column; + "Mod+Shift+F".action = fullscreen-window; + "Mod+C".action = center-column; + + # Mouse + "Mod+WheelScrollUp".action = focus-workspace-up; + "Mod+WheelScrollDown".action = focus-workspace-down; + + "Mod+Shift+WheelScrollDown".action = focus-column-right; + "Mod+Shift+WheelScrollUp".action = focus-column-left; + "Mod+Ctrl+Shift+WheelScrollDown".action = move-column-right; + "Mod+Ctrl+Shift+WheelScrollUp".action = move-column-left; + + # Focus window or workspace + "Mod+Left".action = focus-column-left; + "Mod+Down".action = focus-window-or-workspace-down; + "Mod+Up".action = focus-window-or-workspace-up; + "Mod+Right".action = focus-column-right; + + "Mod+H".action = focus-column-left; + "Mod+J".action = focus-window-or-workspace-down; + "Mod+K".action = focus-window-or-workspace-up; + "Mod+L".action = focus-column-right; + + # Move window or workspace + "Mod+Shift+Left".action = move-column-left; + "Mod+Shift+Down".action = move-window-down-or-to-workspace-down; + "Mod+Shift+Up".action = move-window-up-or-to-workspace-up; + "Mod+Shift+Right".action = move-column-right; + + "Mod+Shift+H".action = move-column-left; + "Mod+Shift+J".action = move-window-down-or-to-workspace-down; + "Mod+Shift+K".action = move-window-up-or-to-workspace-up; + "Mod+Shift+L".action = move-column-right; + + # Move workspace + "Mod+U".action = move-workspace-down; + "Mod+I".action = move-workspace-up; + + "Mod+Ctrl+J".action = move-workspace-down; + "Mod+Ctrl+K".action = move-workspace-up; + + "Mod+Ctrl+Down".action = move-workspace-down; + "Mod+Ctrl+Up".action = move-workspace-up; + + # Screenshots + "Print".action = screenshot; + # "Ctrl+Print".action = screenshot-screen; # Only on niri-stable + "Alt+Print".action = screenshot-window; + + # "Mod+B".action = spawn "${lib.getExe pkgs.ungoogled-chromium}"; + "Mod+B".action = spawn "${lib.getExe pkgs.firefox}"; + "Mod+Shift+B".action = spawn "${lib.getExe pkgs.ungoogled-chromium}"; + "Mod+D".action = spawn "${lib.getExe pkgs.wofi}" "--show" "drun"; + # "Mod+Return".action = spawn "footclient"; + "Mod+Return".action = spawn "${lib.getExe pkgs.foot}"; + }]); + + window-rules = [ + { + matches = [ + { title = "Cinny"; } + { title = "cinny"; } + { title = "Element"; } + { title = "element"; } + { title = "Library"; } + { title = "YouTube"; } + { title = "Invidious"; } + { title = "Piped"; } + { app-id = "org\.keepassxc\.KeePassXC"; } + { app-id = "org\.gnome\.World\.Secrets"; } + { app-id = "org\.gnome\.Nautilus"; } + + { title = "File Upload"; } + { title = "Open File"; } + { title = "Open Folder"; } + { app-id = "xdg-desktop-portal-gnome"; } + + { title = "Telegram"; } + { app-id= "io\.github\.tdesktop_x64\.TDesktop"; } + ]; + block-out-from = "screencast"; + } + + { matches = [ + { app-id = "librewolf"; } + { app-id = "firefox"; } + ]; + open-maximized = true; } + { matches = [ + { app-id = "alacritty"; } + { app-id = "foot"; } + { app-id = "footclient"; } + ]; + default-column-width = { proportion = 0.50; }; } + + { + matches = [ + { is-active = false; } + ]; + opacity = 0.9; + } + { + matches = [ + { is-active = true; } + ]; + opacity = 1.0; + } + + { + matches = [ + { is-window-cast-target = true; } + ]; + focus-ring.active.gradient = { # TODO: set colors using stylix + from = "#f38ba8"; + to = "#7d0d2d70"; + }; + focus-ring.inactive.color = "#7d0d2d"; + shadow = { + enable = true; + color = "#7d0d2d70"; + }; + } + + { geometry-corner-radius = { + top-left = 3.0; + top-right = 3.0; + bottom-left = 0.0; + bottom-right = 0.0; + }; + clip-to-geometry = true; + } + ]; + + layer-rules = [ + { + matches = [ + { namespace = "waybar"; } + { namespace = "yambar"; } + ]; + + opacity = 0.8; + shadow = { + enable = true; + softness = 40; + spread = 5; + offset.x = 0; + offset.y = 5; + draw-behind-window = true; + color = "#00000064"; + }; + } + ]; + + hotkey-overlay.skip-at-startup = true; + + prefer-no-csd = true; + animations = { + workspace-switch.spring = { + damping-ratio = 1.000000; + epsilon = 0.000100; + stiffness = 1000; + }; + }; + + layout = { + border.enable = false; + focus-ring = { + enable = true; + width = 2; + active.color = config.lib.stylix.colors.base0D; + }; + + tab-indicator = { + enable = true; + gap = 5; + width = 4; + gaps-between-tabs = 3; + active.color = config.lib.stylix.colors.base05; + }; + }; + }; + + environment.etc."lemurs/wayland/niri".source = pkgs.writeShellScript "niri.sh" "${pkgs.niri}/bin/niri-session"; +} diff --git a/modules/desktop/nvim/default.nix b/modules/desktop/nvim/default.nix new file mode 100644 index 0000000..27bd032 --- /dev/null +++ b/modules/desktop/nvim/default.nix @@ -0,0 +1,121 @@ +{ pkgs, config, ...}: { + hm = { + imports = [ + ./lsp.nix + ./oil.nix + ]; + + programs.neovim = { + enable = true; + defaultEditor = true; + viAlias = true; + vimAlias = true; + + extraLuaConfig = '' + require "nvim.icons" + require "nvim.keybinds" + require "nvim.bufferline" + require "nvim.cyrillic" + ------------------- + local bind = vim.keymap.set + local opt = vim.opt + local g = vim.g + local o = vim.o + local cmd = vim.cmd + ------------------- + + -- cmd [[colorscheme gruvbox]] + + o.expandtab = true + o.smarttab = true + o.cindent = true + o.autoindent = true + + o.ignorecase = true + o.smartcase = true + + o.backup = false + o.writebackup = false + o.undofile = true + o.swapfile = false + + opt.relativenumber = true + opt.number = true + opt.tabstop = 2 + opt.shiftwidth = 2 + opt.spelllang = { "en_us", "ru", "by" } + opt.mouse = "a" + opt.termguicolors = true + opt.clipboard = "unnamedplus" + ''; + + plugins = with pkgs.vimPlugins; [ + nvim-tree-lua + gruvbox-nvim + which-key-nvim + nvim-autopairs + { plugin = nvim-highlight-colors; type = "lua"; + config = "require('nvim-highlight-colors').setup({})"; } + { plugin = comment-nvim; type = "lua"; + config = "require('Comment').setup()"; } + { plugin = nvim-autopairs; type = "lua"; + config = ''require("nvim-autopairs").setup{}''; } + { plugin = lualine-nvim; type = "lua"; + config = ''require "nvim.lualine"''; } + nvim-web-devicons + vim-startuptime + { plugin = nvim-tree-lua; type = "lua"; + config = ''require "nvim.filemanager"''; } + + { plugin = telescope-nvim; type = "lua"; + config = '' + require('telescope').load_extension('fzf') + local telescope = require('telescope.builtin') + -- Old keybinds + bind('n', 'gfc', telescope.find_files, {}) + bind('n', 'gfs', telescope.live_grep, {}) + bind('n', 'gfb', telescope.buffers, {}) + -- New keybinds + bind('n', '/', telescope.live_grep, {}) + bind('n', 'h', telescope.help_tags, {}) + bind('n', 'b', telescope.buffers, {}) + bind('n', 'e', telescope.buffers, {}) + bind('n', 'f', telescope.find_files, {}) + ''; } + { plugin = editorconfig-nvim; type = "lua"; + config = ''require "editorconfig"''; } + telescope-fzf-native-nvim + bufferline-nvim # ./lua/nvim/bufferline.lua + ]; + }; + + home = { + file.".config/nvim/lua" = { + enable = true; + source = ./lua; + target = ".config/nvim/lua"; + recursive = true; + }; + }; + + editorconfig = { + enable = true; + settings = { + "*" = { + charset = "utf-8"; + end_of_line = "lf"; + trim_trailing_whitespace = true; + insert_final_newline = true; + max_line_width = 78; + indent_style = "space"; + indent_size = 2; + }; + }; + }; + + home.sessionVariables = { + # EDITOR = lib.mkForce lib.getExe pkgs.neovim; + MANPAGER = "${config.hm.home.sessionVariables.EDITOR} +Man!"; + }; + }; +} diff --git a/modules/desktop/nvim/lsp.nix b/modules/desktop/nvim/lsp.nix new file mode 100755 index 0000000..6710aea --- /dev/null +++ b/modules/desktop/nvim/lsp.nix @@ -0,0 +1,24 @@ +{ pkgs, ... }: { + home.packages = with pkgs; [ + rust-analyzer + pyright + nixd + lua-language-server + nodePackages.typescript-language-server + nodePackages.vscode-langservers-extracted + gopls + nimlsp + clang-tools + ]; + + programs.neovim.plugins = with pkgs.vimPlugins; [ + { plugin = nvim-lspconfig; type = "lua"; + config = ''require "nvim.lsp"''; } + nvim-cmp + luasnip + cmp-nvim-lsp + cmp_luasnip + cmp-path + cmp-buffer + ]; +} diff --git a/modules/desktop/nvim/lua/nvim/bufferline.lua b/modules/desktop/nvim/lua/nvim/bufferline.lua new file mode 100755 index 0000000..3727046 --- /dev/null +++ b/modules/desktop/nvim/lua/nvim/bufferline.lua @@ -0,0 +1,43 @@ +require("bufferline").setup{ + options = { + diagnostics = "nvim_lsp", + diagnostics_indicator = function(count, level, diagnostics_dict, context) + local icon = level:match("error") and " " or " " + return " " .. icon .. count + end, + + numbers = function(opts) + return string.format('%s)', opts.ordinal, opts.id) + end, + + -- groups = { + -- options = { + -- toggle_hidden_on_enter = true -- when you re-enter a hidden group this options re-opens that group so the buffer is visible + -- }, + -- items = { + -- { + -- name = "Code", -- Mandatory + -- highlight = {underline = true, sp = "blue"}, -- Optional + -- priority = 1, + -- icon = "", + -- matcher = function(buf) + -- return buf.filename:match('%.rs') or buf.filename:match('%.py') or buf.filename:match('%.nix') or buf.filename:match('%.lua') + -- end, + -- }, + -- { + -- name = "Docs", + -- highlight = {undercurl = true, sp = "green"}, + -- auto_close = false, + -- icon = "", -- Optional + -- priority = 2, + -- matcher = function(buf) + -- return buf.filename:match('%.md') or buf.filename:match('%.txt') or buf.filename:match('LICENSE') + -- end, + -- separator = { -- Optional + -- style = require('bufferline.groups').separator.tab + -- }, + -- } + -- } + -- } + } +} diff --git a/modules/desktop/nvim/lua/nvim/cyrillic.lua b/modules/desktop/nvim/lua/nvim/cyrillic.lua new file mode 100644 index 0000000..f0ebef9 --- /dev/null +++ b/modules/desktop/nvim/lua/nvim/cyrillic.lua @@ -0,0 +1,612 @@ +-- Author: nrv +-- Version: 1.0 +-- License: GPLv3 +-- URL: http://github.com/nativerv/cyrillic.nvim +-- Description: Adds some support for Cyrillic keyboard +-- layouts (Ukrainian, Russian) in Neovim + +vim.cmd [[ +cabbrev ив getcmdtype()==':' && getcmdline()=="ив" ? "bd" : "ив" +cabbrev ит getcmdtype()==':' && getcmdline()=="ит" ? "bn" : "ит" +cabbrev й getcmdtype()==':' && getcmdline()=="й" ? "q" : "й" +cabbrev йф getcmdtype()==':' && getcmdline()=="йф" ? "qa" : "йф" +cabbrev ц getcmdtype()==':' && getcmdline()=="ц" ? "w" : "ц" +cabbrev цй getcmdtype()==':' && getcmdline()=="цй" ? "wq" : "цй" +]] + +vim.keymap.set('', 'ё', '`', { desc = 'which_key_ignore' }) +vim.keymap.set('', '’', '`', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'й', 'q', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ц', 'w', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'у', 'e', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'к', 'r', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'е', 't', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'н', 'y', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'г', 'u', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ш', 'i', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'щ', 'o', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'з', 'p', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'х', '[', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъ', ']', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ї', ']', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ф', 'a', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ы', 's', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'і', 's', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'в', 'd', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'а', 'f', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'п', 'g', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'р', 'h', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'о', 'j', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'л', 'k', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'д', 'l', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ж', ';', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'э', "'", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'є', "'", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'я', 'z', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ч', 'x', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'с', 'c', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'м', 'v', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'и', 'b', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'т', 'n', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ь', 'm', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'б', ',', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ю', '.', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ё', '~', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Й', 'Q', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ц', 'W', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'У', 'E', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'К', 'R', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Е', 'T', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Н', 'Y', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Г', 'U', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ш', 'I', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Щ', 'O', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'З', 'P', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Х', '{', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ъ', '}', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ї', '}', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ф', 'A', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ы', 'S', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'І', 'S', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'В', 'D', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'А', 'F', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'П', 'G', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Р', 'H', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'О', 'J', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Л', 'K', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Д', 'L', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ж', ':', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Э', '"', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Є', '"', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Я', 'Z', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ч', 'X', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'С', 'C', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'М', 'V', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'И', 'B', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Т', 'N', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ь', 'M', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Б', '<', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ю', '>', { desc = 'which_key_ignore' }) + +vim.keymap.set('', 'ЯЯ', 'ZZ', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЯЙ', 'ZQ', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'йЖ', 'q:', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'й.', 'q/', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'й,', 'q?', { desc = 'which_key_ignore' }) + +vim.keymap.set('', 'ёё', '``', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёБ', '`<', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёЮ', '`>', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёх', '`[', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёъ', '`]', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёХ', '`{', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёЪ', '`}', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ээ', "''", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эБ', "'<", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эЮ', "'>", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эх', "'[", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эъ', "']", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эХ', "'{", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эЪ', "'}", { desc = 'which_key_ignore' }) + +vim.keymap.set('', 'хэ', "['", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хё', '[`', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хВ', '[D', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хШ', '[I', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хЗ', '[P', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хх', '[[', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хъ', '[]', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хс', '[c', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хв', '[d', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ха', '[f', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хш', '[i', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хь', '[m', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хз', '[p', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хы', '[s', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хя', '[z', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'хХ', '[{', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъэ', "]'", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъё', ']`', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъВ', ']D', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъШ', ']I', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъЗ', ']P', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъх', '][', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъъ', ']]', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъс', ']c', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъв', ']d', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъа', ']f', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъш', ']i', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъь', ']m', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъз', ']p', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъы', ']s', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъя', ']z', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъХ', ']{', { desc = 'which_key_ignore' }) + +vim.keymap.set('', 'ьФ', 'mA', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёФ', '`A', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эФ', "'A", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёФ', 'g`A', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэФ', "g'A", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьИ', 'mB', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёИ', '`B', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эИ', "'B", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёИ', 'g`B', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэИ', "g'B", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьС', 'mC', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёС', '`C', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эС', "'C", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёС', 'g`C', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэС', "g'C", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьВ', 'mD', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёВ', '`D', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эВ', "'D", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёВ', 'g`D', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэВ', "g'D", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьУ', 'mE', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёУ', '`E', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эУ', "'E", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёУ', 'g`E', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэУ', "g'E", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьА', 'mF', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёА', '`F', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эА', "'F", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёА', 'g`F', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэА', "g'F", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьП', 'mG', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёП', '`G', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эП', "'G", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёП', 'g`G', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэП', "g'G", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьР', 'mH', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёР', '`H', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эР', "'H", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёР', 'g`H', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэР', "g'H", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьШ', 'mI', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёШ', '`I', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эШ', "'I", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёШ', 'g`I', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэШ', "g'I", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьО', 'mJ', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёО', '`J', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эО', "'J", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёО', 'g`J', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэО', "g'J", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьЛ', 'mK', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёЛ', '`K', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эЛ', "'K", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёЛ', 'g`K', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэЛ', "g'K", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьД', 'mL', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёД', '`L', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эД', "'L", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёД', 'g`L', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэД', "g'L", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьЬ', 'mM', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёЬ', '`M', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эЬ', "'M", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёЬ', 'g`M', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэЬ', "g'M", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьТ', 'mN', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёТ', '`N', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эТ', "'N", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёТ', 'g`N', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэТ', "g'N", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьЩ', 'mO', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёЩ', '`O', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эЩ', "'O", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёЩ', 'g`O', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэЩ', "g'O", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьЗ', 'mP', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёЗ', '`P', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эЗ', "'P", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёЗ', 'g`P', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэЗ', "g'P", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьЙ', 'mQ', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёЙ', '`Q', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эЙ', "'Q", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёЙ', 'g`Q', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэЙ', "g'Q", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьК', 'mR', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёК', '`R', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эК', "'R", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёК', 'g`R', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэК', "g'R", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьЫ', 'mS', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёЫ', '`S', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эЫ', "'S", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёЫ', 'g`S', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэЫ', "g'S", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьЕ', 'mT', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёЕ', '`T', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эЕ', "'T", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёЕ', 'g`T', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэЕ', "g'T", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьГ', 'mU', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёГ', '`U', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эГ', "'U", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёГ', 'g`U', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэГ', "g'U", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьМ', 'mV', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёМ', '`V', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эМ', "'V", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёМ', 'g`V', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэМ', "g'V", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьЦ', 'mW', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёЦ', '`W', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эЦ', "'W", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёЦ', 'g`W', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэЦ', "g'W", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьЧ', 'mX', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёЧ', '`X', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эЧ', "'X", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёЧ', 'g`X', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэЧ', "g'X", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьН', 'mY', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёН', '`Y', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эН', "'Y", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёН', 'g`Y', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэН', "g'Y", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьЯ', 'mZ', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёЯ', '`Z', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эЯ', "'Z", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёЯ', 'g`Z', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэЯ', "g'Z", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьф', 'ma', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёф', '`a', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эф', "'a", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёф', 'g`a', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэф', "g'a", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьи', 'mb', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёи', '`b', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эи', "'b", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёи', 'g`b', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэи', "g'b", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьс', 'mc', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёс', '`c', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эс', "'c", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёс', 'g`c', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэс', "g'c", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьв', 'md', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёв', '`d', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эв', "'d", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёв', 'g`d', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэв', "g'd", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьу', 'me', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёу', '`e', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эу', "'e", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёу', 'g`e', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэу', "g'e", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьа', 'mf', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёа', '`f', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эа', "'f", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёа', 'g`f', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэа', "g'f", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьп', 'mg', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёп', '`g', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эп', "'g", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёп', 'g`g', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэп', "g'g", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьр', 'mh', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёр', '`h', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эр', "'h", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёр', 'g`h', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэр', "g'h", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьш', 'mi', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёш', '`i', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эш', "'i", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёш', 'g`i', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэш', "g'i", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьо', 'mj', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёо', '`j', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эо', "'j", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёо', 'g`j', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэо', "g'j", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьл', 'mk', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёл', '`k', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эл', "'k", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёл', 'g`k', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэл', "g'k", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьд', 'ml', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёд', '`l', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эд', "'l", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёд', 'g`l', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэд', "g'l", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьь', 'mm', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёь', '`m', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эь', "'m", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёь', 'g`m', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэь', "g'm", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьт', 'mn', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёт', '`n', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эт', "'n", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёт', 'g`n', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэт', "g'n", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьщ', 'mo', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёщ', '`o', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эщ', "'o", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёщ', 'g`o', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэщ', "g'o", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьз', 'mp', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёз', '`p', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эз', "'p", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёз', 'g`p', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэз', "g'p", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьй', 'mq', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёй', '`q', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эй', "'q", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёй', 'g`q', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэй', "g'q", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьк', 'mr', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёк', '`r', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эк', "'r", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёк', 'g`r', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэк', "g'r", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьы', 'ms', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёы', '`s', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эы', "'s", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёы', 'g`s', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэы', "g's", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ье', 'mt', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёе', '`t', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эе', "'t", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёе', 'g`t', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэе', "g't", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьг', 'mu', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёг', '`u', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эг', "'u", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёг', 'g`u', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэг', "g'u", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьм', 'mv', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ём', '`v', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эм', "'v", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пём', 'g`v', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэм', "g'v", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьц', 'mw', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёц', '`w', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эц', "'w", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёц', 'g`w', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэц', "g'w", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьч', 'mx', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёч', '`x', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эч', "'x", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёч', 'g`x', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэч', "g'x", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ьн', 'my', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ён', '`y', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эн', "'y", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пён', 'g`y', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэн', "g'y", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ья', 'mz', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ёя', '`z', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'эя', "'z", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пёя', 'g`z', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пэя', "g'z", { desc = 'which_key_ignore' }) + +vim.keymap.set('', 'ЭЭ', '""', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭЖ', '":', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эю', '".', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭФ', '"A', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭИ', '"B', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭС', '"C', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭВ', '"D', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭУ', '"E', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭА', '"F', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭП', '"G', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭР', '"H', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭШ', '"I', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭО', '"J', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭЛ', '"K', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭД', '"L', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭЬ', '"M', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭТ', '"N', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭЩ', '"O', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭЗ', '"P', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭЙ', '"Q', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭК', '"R', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭЫ', '"S', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭЕ', '"T', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭГ', '"U', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭМ', '"V', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭЦ', '"W', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭЧ', '"X', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭН', '"Y', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ЭЯ', '"Z', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эф', '"a', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эи', '"b', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эс', '"c', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эв', '"d', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эу', '"e', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эа', '"f', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эп', '"g', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эр', '"h', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эш', '"i', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эо', '"j', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эл', '"k', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эд', '"l', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эь', '"m', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эт', '"n', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эщ', '"o', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эз', '"p', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эй', '"q', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эк', '"r', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эы', '"s', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эе', '"t', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эг', '"u', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эм', '"v', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эц', '"w', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эч', '"x', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эн', '"y', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Эя', '"z', { desc = 'which_key_ignore' }) + +vim.keymap.set('', 'пБ', 'g<', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пВ', 'gD', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пУ', 'gE', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пР', 'gH', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пШ', 'gI', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пО', 'gJ', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пТ', 'gN', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пЗ', 'gP', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пЙ', 'gQ', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пК', 'gR', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пЕ', 'gT', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пГ', 'gU', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пМ', 'gV', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пъ', 'g]', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пф', 'ga', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пв', 'gd', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пу', 'ge', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'па', 'gf', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пА', 'gF', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пп', 'gg', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пр', 'gh', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пш', 'gi', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'по', 'gj', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пл', 'gk', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пт', 'gn', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пь', 'gm', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пщ', 'go', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пз', 'gp', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пй', 'gq', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пк', 'gr', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пы', 'gs', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пе', 'gt', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пг', 'gu', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пм', 'gv', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пц', 'gw', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пч', 'gx', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пЁ', 'g~', { desc = 'which_key_ignore' }) + +vim.keymap.set('', 'яю', 'z.', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яФ', 'zA', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яС', 'zC', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яВ', 'zD', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яУ', 'zE', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яА', 'zF', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яП', 'zG', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яР', 'zH', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яД', 'zL', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яЬ', 'zM', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яТ', 'zN', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яЩ', 'zO', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яК', 'zR', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яЦ', 'zW', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яЧ', 'zX', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яф', 'za', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яи', 'zb', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яс', 'zc', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яв', 'zd', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яу', 'ze', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яа', 'zf', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яп', 'zg', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яр', 'zh', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яш', 'zi', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яо', 'zj', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ял', 'zk', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яд', 'zl', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яь', 'zm', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ят', 'zn', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ящ', 'zo', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'як', 'zr', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яы', 'zs', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яе', 'zt', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ям', 'zv', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яц', 'zw', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яч', 'zx', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'яя', 'zz', { desc = 'which_key_ignore' }) + +vim.keymap.set('', 'фЭ', 'a"', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шЭ', 'i"', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фэ', "a'", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шэ', "i'", { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фБ', 'a<', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шБ', 'i<', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фЮ', 'a>', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шЮ', 'i>', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фИ', 'aB', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шИ', 'iB', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фЦ', 'aW', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шЦ', 'iW', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фх', 'a[', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шх', 'i[', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фъ', 'a]', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шъ', 'i]', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фё', 'a`', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шё', 'i`', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фи', 'ab', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ши', 'ib', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фз', 'ap', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шз', 'ip', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фы', 'as', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шы', 'is', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фе', 'at', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ше', 'it', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фц', 'aw', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шц', 'iw', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фХ', 'a{', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шХ', 'i{', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'фЪ', 'a}', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'шЪ', 'i}', { desc = 'which_key_ignore' }) + +vim.keymap.set('', 'Б', '<', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ю', '>', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Р', 'H', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'О', 'J', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Л', 'K', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Д', 'L', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'З', 'P', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'К', 'R', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ы', 'S', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Е', 'T', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ц', 'W', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ъ', ']', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'и', 'b', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'с', 'c', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'в', 'd', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'а', 'f', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'А', 'F', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'п', 'g', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пъ', 'g]', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пЪ', 'g}', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'па', 'gf', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'пА', 'gF', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'р', 'h', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ш', 'i', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'о', 'j', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'л', 'k', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'д', 'l', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'т', 'n', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'щ', 'o', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'з', 'p', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'й', 'q', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'к', 'r', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ы', 's', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'е', 't', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'м', 'v', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ц', 'w', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'ч', 'x', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'я', 'z', { desc = 'which_key_ignore' }) +vim.keymap.set('', 'Ъ', '}', { desc = 'which_key_ignore' }) + +vim.keymap.set('n', '№', '#', { desc = 'which_key_ignore' }) +vim.keymap.set('n', ';', '$', { desc = 'which_key_ignore' }) diff --git a/modules/desktop/nvim/lua/nvim/filemanager.lua b/modules/desktop/nvim/lua/nvim/filemanager.lua new file mode 100755 index 0000000..34dcc27 --- /dev/null +++ b/modules/desktop/nvim/lua/nvim/filemanager.lua @@ -0,0 +1,13 @@ +local g = vim.g +local bind = vim.keymap.set +local nvimTree = require('nvim-tree.api') + +g.loaded_netrw = 1 +g.loaded_netrwPlugin = 1 +g.netrw_banner = 0 +g.netrw_liststyle = 3 +g.netrw_browse_split = 3 + +require("nvim-tree").setup() + +bind('n', 'tt', nvimTree.tree.toggle, {}) diff --git a/modules/desktop/nvim/lua/nvim/icons.lua b/modules/desktop/nvim/lua/nvim/icons.lua new file mode 100755 index 0000000..5d64ce1 --- /dev/null +++ b/modules/desktop/nvim/lua/nvim/icons.lua @@ -0,0 +1,27 @@ +require'nvim-web-devicons'.setup { + override = { + zsh = { + icon = "", + color = "#428850", + cterm_color = "65", + name = "Zsh" + } + }; + color_icons = true; + default = true; + strict = true; + override_by_filename = { + [".gitignore"] = { + icon = "", + color = "#f1502f", + name = "Gitignore" + } + }; + -- override_by_extension = { + -- ["log"] = { + -- icon = "", + -- color = "#81e043", + -- name = "Log" + -- } + -- }; +} diff --git a/modules/desktop/nvim/lua/nvim/keybinds.lua b/modules/desktop/nvim/lua/nvim/keybinds.lua new file mode 100755 index 0000000..80c85be --- /dev/null +++ b/modules/desktop/nvim/lua/nvim/keybinds.lua @@ -0,0 +1,8 @@ +local bind = vim.keymap.set +---------------------------- + +bind('n', '1', ':b 1', {}) +bind('n', '2', ':b 2', {}) +bind('n', '3', ':b 3', {}) +bind('n', '4', ':b 4', {}) +bind('n', '5', ':b 5', {}) diff --git a/modules/desktop/nvim/lua/nvim/lsp.lua b/modules/desktop/nvim/lua/nvim/lsp.lua new file mode 100755 index 0000000..fd74cfc --- /dev/null +++ b/modules/desktop/nvim/lua/nvim/lsp.lua @@ -0,0 +1,108 @@ +local lspconfig = require('lspconfig') +-- local luasnip = require 'luasnip' +local cmp = require 'cmp' +local capabilities = require("cmp_nvim_lsp").default_capabilities() + +local servers = { 'pyright', 'rust_analyzer', 'nixd', 'lua_ls', 'ts_ls', 'html', 'cssls', 'gopls', 'nimls', 'clangd' } +for _, lsp in ipairs(servers) do + lspconfig[lsp].setup { + -- on_attach = my_custom_on_attach, + capabilities = capabilities, + } +end + +-- lspconfig.lua_ls.setup { +-- settings = { +-- Lua = { +-- runtime = { +-- version = 'LuaJIT', +-- }, +-- diagnostics = { +-- globals = {'vim'}, +-- }, +-- workspace = { +-- library = vim.api.nvim_get_runtime_file("", true), +-- }, +-- telemetry = { +-- enable = false, +-- }, +-- }, +-- }, +-- } + +-- Global mappings. +-- See `:help vim.diagnostic.*` for documentation on any of the below functions +vim.keymap.set('n', 'd', vim.diagnostic.open_float) +vim.keymap.set('n', '[d', vim.diagnostic.goto_prev) +vim.keymap.set('n', ']d', vim.diagnostic.goto_next) +vim.keymap.set('n', 'q', vim.diagnostic.setloclist) + +-- Use LspAttach autocommand to only map the following keys +-- after the language server attaches to the current buffer +vim.api.nvim_create_autocmd('LspAttach', { +group = vim.api.nvim_create_augroup('UserLspConfig', {}), +callback = function(ev) + -- Enable completion triggered by + vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc' + + -- Buffer local mappings. + -- See `:help vim.lsp.*` for documentation on any of the below functions + local opts = { buffer = ev.buf } + vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts) + vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts) + vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts) + vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts) + vim.keymap.set('n', '', vim.lsp.buf.signature_help, opts) + vim.keymap.set('n', 'wa', vim.lsp.buf.add_workspace_folder, opts) + vim.keymap.set('n', 'wr', vim.lsp.buf.remove_workspace_folder, opts) + vim.keymap.set('n', 'wl', function() + print(vim.inspect(vim.lsp.buf.list_workspace_folders())) + end, opts) + vim.keymap.set('n', 'D', vim.lsp.buf.type_definition, opts) + vim.keymap.set('n', 'rn', vim.lsp.buf.rename, opts) + vim.keymap.set({ 'n', 'v' }, 'ca', vim.lsp.buf.code_action, opts) + vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts) +end, +}) + +cmp.setup { +-- snippet = { +-- expand = function(args) +-- luasnip.lsp_expand(args.nody) +-- end, +-- }, +mapping = cmp.mapping.preset.insert({ + [''] = cmp.mapping.scroll_docs(-4), -- Up + [''] = cmp.mapping.scroll_docs(4), -- Down + -- C-b (back) C-f (forward) for snippet placeholder navigation. + [''] = cmp.mapping.complete(), + [''] = cmp.mapping.confirm { + behavior = cmp.ConfirmBehavior.Replace, + select = true, + }, + -- [''] = cmp.mapping(function(fallback) + -- if cmp.visible() then + -- cmp.select_next_item() + -- elseif luasnip.expand_or_jumpable() then + -- luasnip.expand_or_jump() + -- else + -- fallback() + -- end + -- end, { 'i', 's' }), + -- [''] = cmp.mapping(function(fallback) + -- if cmp.visible() then + -- cmp.select_prev_item() + -- elseif luasnip.jumpable(-1) then + -- luasnip.jump(-1) + -- else + -- fallback() + -- end + -- end, { 'i', 's' }), +}), +sources = { + { name = 'nvim_lsp' }, + -- { name = 'luasnip' }, + { name = 'path' }, + { name = 'buffer' }, +}, +} diff --git a/modules/desktop/nvim/lua/nvim/lualine.lua b/modules/desktop/nvim/lua/nvim/lualine.lua new file mode 100755 index 0000000..25e041a --- /dev/null +++ b/modules/desktop/nvim/lua/nvim/lualine.lua @@ -0,0 +1,24 @@ +require('lualine').setup { + options = { + theme = "everforest", + component_separators = '|', + }, + sections = { + lualine_a = { 'mode' }, + lualine_b = { 'filename', 'location' }, + lualine_c = { 'branch', 'diff', 'diagnostics'}, + lualine_x = { 'filetype' }, + lualine_y = { 'progress' }, + lualine_z = {{ 'fileformat', left_padding = 2 },}, + }, + inactive_sections = { + lualine_a = { 'filename' }, + lualine_b = {}, + lualine_c = {}, + lualine_x = {}, + lualine_y = {}, + lualine_z = { 'location' }, + }, + tabline = {}, + extensions = { 'nvim-tree' }, +} diff --git a/modules/desktop/nvim/oil.nix b/modules/desktop/nvim/oil.nix new file mode 100755 index 0000000..a3af6ef --- /dev/null +++ b/modules/desktop/nvim/oil.nix @@ -0,0 +1,162 @@ +{ pkgs, ... }: { + programs.neovim.plugins = with pkgs.vimPlugins; [ + { plugin = oil-nvim; type = "lua"; + config = '' + require("oil").setup({ + -- Oil will take over directory buffers (e.g. `vim .` or `:e src/`) + -- Set to false if you still want to use netrw. + default_file_explorer = true, + -- Id is automatically added at the beginning, and name at the end + -- See :help oil-columns + columns = { + "icon", + -- "permissions", + -- "size", + -- "mtime", + }, + -- Buffer-local options to use for oil buffers + buf_options = { + buflisted = false, + bufhidden = "hide", + }, + -- Window-local options to use for oil buffers + win_options = { + wrap = false, + signcolumn = "no", + cursorcolumn = false, + foldcolumn = "0", + spell = false, + list = false, + conceallevel = 3, + concealcursor = "nvic", + }, + -- Send deleted files to the trash instead of permanently deleting them (:help oil-trash) + delete_to_trash = false, + -- Skip the confirmation popup for simple operations (:help oil.skip_confirm_for_simple_edits) + skip_confirm_for_simple_edits = false, + -- Selecting a new/moved/renamed file or directory will prompt you to save changes first + -- (:help prompt_save_on_select_new_entry) + prompt_save_on_select_new_entry = true, + -- Oil will automatically delete hidden buffers after this delay + -- You can set the delay to false to disable cleanup entirely + -- Note that the cleanup process only starts when none of the oil buffers are currently displayed + cleanup_delay_ms = 2000, + lsp_file_methods = { + -- Time to wait for LSP file operations to complete before skipping + timeout_ms = 1000, + -- Set to true to autosave buffers that are updated with LSP willRenameFiles + -- Set to "unmodified" to only save unmodified buffers + autosave_changes = false, + }, + -- Constrain the cursor to the editable parts of the oil buffer + -- Set to `false` to disable, or "name" to keep it on the file names + constrain_cursor = "editable", + -- Set to true to watch the filesystem for changes and reload oil + experimental_watch_for_changes = false, + -- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap + -- options with a `callback` (e.g. { callback = function() ... end, desc = "", mode = "n" }) + -- Additionally, if it is a string that matches "actions.", + -- it will use the mapping at require("oil.actions"). + -- Set to `false` to remove a keymap + -- See :help oil-actions for a list of all available actions + keymaps = { + ["g?"] = "actions.show_help", + [""] = "actions.select", + [""] = "actions.select_vsplit", + [""] = "actions.select_split", + [""] = "actions.select_tab", + [""] = "actions.preview", + [""] = "actions.close", + [""] = "actions.refresh", + ["-"] = "actions.parent", + ["_"] = "actions.open_cwd", + ["`"] = "actions.cd", + ["~"] = "actions.tcd", + ["gs"] = "actions.change_sort", + ["gx"] = "actions.open_external", + ["g."] = "actions.toggle_hidden", + ["g\\"] = "actions.toggle_trash", + }, + -- Configuration for the floating keymaps help window + keymaps_help = { + border = "rounded", + }, + -- Set to false to disable all of the above keymaps + use_default_keymaps = true, + view_options = { + -- Show files and directories that start with "." + show_hidden = false, + -- This function defines what is considered a "hidden" file + is_hidden_file = function(name, bufnr) + return vim.startswith(name, ".") + end, + -- This function defines what will never be shown, even when `show_hidden` is set + is_always_hidden = function(name, bufnr) + return false + end, + sort = { + -- sort order can be "asc" or "desc" + -- see :help oil-columns to see which columns are sortable + { "type", "asc" }, + { "name", "asc" }, + }, + }, + -- Configuration for the floating window in oil.open_float + float = { + -- Padding around the floating window + padding = 2, + max_width = 0, + max_height = 0, + border = "rounded", + win_options = { + winblend = 0, + }, + -- This is the config that will be passed to nvim_open_win. + -- Change values here to customize the layout + override = function(conf) + return conf + end, + }, + -- Configuration for the actions floating preview window + preview = { + -- Width dimensions can be integers or a float between 0 and 1 (e.g. 0.4 for 40%) + -- min_width and max_width can be a single value or a list of mixed integer/float types. + -- max_width = {100, 0.8} means "the lesser of 100 columns or 80% of total" + max_width = 0.9, + -- min_width = {40, 0.4} means "the greater of 40 columns or 40% of total" + min_width = { 40, 0.4 }, + -- optionally define an integer/float for the exact width of the preview window + width = nil, + -- Height dimensions can be integers or a float between 0 and 1 (e.g. 0.4 for 40%) + -- min_height and max_height can be a single value or a list of mixed integer/float types. + -- max_height = {80, 0.9} means "the lesser of 80 columns or 90% of total" + max_height = 0.9, + -- min_height = {5, 0.1} means "the greater of 5 columns or 10% of total" + min_height = { 5, 0.1 }, + -- optionally define an integer/float for the exact height of the preview window + height = nil, + border = "rounded", + win_options = { + winblend = 0, + }, + -- Whether the preview window is automatically updated when the cursor is moved + update_on_cursor_moved = true, + }, + -- Configuration for the floating progress window + progress = { + max_width = 0.9, + min_width = { 40, 0.4 }, + width = nil, + max_height = { 10, 0.9 }, + min_height = { 5, 0.1 }, + height = nil, + border = "rounded", + minimized_border = "none", + win_options = { + winblend = 0, + }, + }, +}) + ''; } + ]; +} diff --git a/modules/desktop/openssh.nix b/modules/desktop/openssh.nix new file mode 100644 index 0000000..d55c1d8 --- /dev/null +++ b/modules/desktop/openssh.nix @@ -0,0 +1,62 @@ +{ config, lib, pkgs, username, ... }: +let socket = "/run/${username}/1000/ssh-agent"; +in { + hm = { + programs.ssh = { + enable = true; + hashKnownHosts = true; + + matchBlocks = { + "cepheus" = { + hostname = "nothing.run"; + user = "root"; + port = 22; + }; + }; + + extraConfig = "ObscureKeystrokeTiming yes"; + forwardAgent = true; + addKeysToAgent = "yes"; + }; + services.ssh-agent.enable = true; + home.sessionVariables = { + # SSH_ASKPASS = lib.mkForce pkgs.kdePackages.ksshaskpass; + SSH_AUTH_SOCK = socket; + }; + }; + imp.home.dirs = [ ".ssh" ]; + services.openssh = { + enable = lib.mkDefault false; + openFirewall = lib.mkDefault false; + }; + + systemd.user.services.ssh-agent-delete-keys = + let + ssh-add = "${pkgs.openssh}/bin/ssh-add"; + script = pkgs.writeShellScript "ssh-agent-delete-keys" '' +while true; do + state="$(${ssh-add} -l)" + # if (echo $state | grep -i "The agent has no identities"); then + if [[ $state != *"The agent has no identities"* ]]; then + echo "Detected adding of key: $(${ssh-add} -l)" + sleep $SSH_AGENT_KEY_LIFETIME + ${ssh-add} -D + echo "Deleted the key: $(${ssh-add} -l)" + fi + sleep 2 +done + ''; + in { + enable = true; + after = [ "ssh-agent.service" ]; + wantedBy = [ "default.target" ]; + serviceConfig = { + Type = "simple"; + ExecStart = script; + }; + environment = { + SSH_AUTH_SOCK = socket; + SSH_AGENT_KEY_LIFETIME = "180"; + }; + }; +} diff --git a/modules/desktop/pipewire.nix b/modules/desktop/pipewire.nix new file mode 100644 index 0000000..489a932 --- /dev/null +++ b/modules/desktop/pipewire.nix @@ -0,0 +1,19 @@ +{ pkgs, ... }: { + services.pulseaudio.enable = false; + services.pipewire = { + enable = true; + alsa = { + enable = true; + support32Bit = true; + }; + pulse.enable = true; + jack.enable = true; + wireplumber.enable = true; + }; + + hm.home.packages = with pkgs; [ + pavucontrol + helvum + pulseaudio + ]; +} diff --git a/modules/desktop/qbittorrent.nix b/modules/desktop/qbittorrent.nix new file mode 100644 index 0000000..0dd0095 --- /dev/null +++ b/modules/desktop/qbittorrent.nix @@ -0,0 +1,35 @@ +{ username, pkgs, ... }: { + systemd.services.qbittorrent-nox = let + port = 1999; + in { + enable = true; + description = "QBitTorrent server"; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + serviceConfig = { + Type = "exec"; + User = username; + ExecStart = "${pkgs.qbittorrent-nox}/bin/qbittorrent-nox --profile=\"/home/${username}/Torrent\" --configuration=\"/home/${username}/Torrent/config\" --webui-port=${toString port}"; + }; + wantedBy = [ "multi-user.target" ]; + }; +# WebUI\LocalHostAuth=false + + imp.home.dirs = [ "Torrent" ]; + + systemd.services.gdisk = { + enable = true; + description = "Automounting additional disk"; + serviceConfig = { + Type = "oneshot"; + User = "root"; + ExecStart = pkgs.writeShellScript "mount-gdisk.sh" '' + systemd-cryptsetup attach gd /dev/sda /nix/disks/gd/key header=/nix/disks/gd/header + mkdir -p /mnt/gd + mount /dev/mapper/gd /mnt/gd -o compress=zstd:2 + ''; + RemainAfterExit = true; + ExecStop = "umount /dev/gd && systemd-cryptsetup detach gd"; + }; + }; +} diff --git a/modules/desktop/stylix.nix b/modules/desktop/stylix.nix new file mode 100644 index 0000000..998a6c4 --- /dev/null +++ b/modules/desktop/stylix.nix @@ -0,0 +1,18 @@ +{ inputs, pkgs, config, ... }: { + imports = [ inputs.stylix.nixosModules.stylix ]; + stylix = { + enable = true; + base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-dark-hard.yaml"; + polarity = "dark"; + image = ../../assets/Wallpaper.jpg; + + fonts = { + serif = config.stylix.fonts.monospace; + sansSerif = config.stylix.fonts.monospace; + monospace = { + package = pkgs.nerd-fonts.fira-code; + name = "FiraCode Nerd Font"; + }; + }; + }; +} diff --git a/modules/desktop/xcompose.nix b/modules/desktop/xcompose.nix new file mode 100644 index 0000000..bbd4438 --- /dev/null +++ b/modules/desktop/xcompose.nix @@ -0,0 +1,51 @@ +{ lib, pkgs, ... }: +let + makebinds = attrs: lib.pipe attrs [ + (attr: builtins.mapAttrs (_: keys: (builtins.map (key: "<${key}>") keys)) attr) + (attr: (builtins.mapAttrs (_: keys: (builtins.concatStringsSep " " keys)) attr)) + (attr: (lib.attrsets.mapAttrsToList (sum: keys: '' ${keys} : "${sum}"'') attr)) + (attr: builtins.concatStringsSep "\n" attr) + ]; + + binds = lib.concatStringsSep "\n" [ + # ''include "%L"'' + (makebinds { + "ě" = [ "e" "j" ]; + + "ѣ" = [ "Cyrillic_ie" "Cyrillic_ie" ]; + "Ѣ" = [ "Cyrillic_IE" ]; + "ѳ" = [ "Cyrillic_ef" ]; + "ѵ" = [ "Cyrillic_i" ]; + "ґ" = [ "Cyrillic_ghe" ]; + "є" = [ "Cyrillic_ie" "Cyrillic_e" ]; + + "љ" = [ "Cyrillic_el" "Cyrillic_el" ]; + "њ" = [ "Cyrillic_en" "Cyrillic_en" ]; + + "ѧ" = [ "Cyrillic_e" "Cyrillic_en" ]; + "ѩ" = [ "Cyrillic_ie" "Cyrillic_en" ]; + "ѫ" = [ "Cyrillic_o" "Cyrillic_en" ]; + "ѭ" = [ "Cyrillic_io" "Cyrillic_en" ]; + + "¨" = [ "Colon" ]; + + "α" = [ "g" "a" ]; + "β" = [ "g" "b" ]; + "γ" = [ "g" "g" ]; + "λ" = [ "g" "l" ]; + }) + ]; + +in { + environment.variables.XCOMPOSEFILE = ".XCompose"; + hm = { + home.file.".XCompose" = { + enable = true; + target = ".XCompose"; + recursive = false; + text = binds; + }; + + programs.niri.settings.input.keyboard.xkb.file = toString (pkgs.writeText "compose.xkb" binds); + }; +} diff --git a/modules/desktop/yambar.nix b/modules/desktop/yambar.nix new file mode 100644 index 0000000..a0ec741 --- /dev/null +++ b/modules/desktop/yambar.nix @@ -0,0 +1,690 @@ +{ + pkgs, + lib, + config, + host, + ... +}: let + niri = lib.getExe pkgs.c.niri; + jq = lib.getExe pkgs.jq; + workspaces_script = pkgs.writeShellScript "workspaces.sh" '' + workspaces_num () { + IFS=$'\n' + local r=$(${niri} msg -j workspaces | ${jq} '.[].idx' | sort -nr | head -n1) + echo $r + } + + get_idx () { + local r=$(${niri} msg -j workspaces) + for (( i=0; i<$(workspaces_num); i+=1 )) + do + local act=$(echo $r | ${jq} .[$i].id) + if [ $act -eq $1 ]; then + local idx=$(echo $r | ${jq} .[$i].idx) + echo $idx + break + fi + done + } + + get_before () { + if [ $1 -eq "1" ]; then + echo "" + else + a= + for (( i=1; i<$1; i++ )) do + a="$a $i" + done + echo $a + fi + } + + get_after () { + if [ $1 -eq $2 ]; then + echo "" + else + a= + for (( i=$1+1; i<=$2; i++ )) do + a="$a $i" + done + echo $a + fi + } + + ret_add () { + echo "before|string|$(get_before $1)" + echo "after|string|$(get_after $1 $2)" + } + + bnum=$(workspaces_num) + echo "number|int|$bnum" + + beg=$(${niri} msg -j workspaces) + + cf () { + for (( i=0; i<$2; i+=1 )) + do + bact=$(echo $1 | ${jq} .[$i].is_active) + if [[ "$bact" == "true" ]]; then + bf=$(echo $1 | ${jq} .[$i].idx) + echo "$bf" + break + fi + done + } + + sf=`cf "$beg" "$bnum"` + echo "focused|int|$sf" + ret_add $sf $bnum + + echo "" + + ${niri} msg -j event-stream | while read -r line; do + current=$(echo $line | ${jq} .WorkspaceActivated.id) + if [[ "$current" != "null" ]]; then + cn=$(workspaces_num) + idx=$(get_idx $current) + echo "number|int|$cn" + echo "focused|int|$idx" + ret_add $idx $cn + echo "" + fi + + current=$(echo $line | ${jq} .WorkspacesChanged.workspaces) + if [[ "$current" != "null" ]]; then + cn=$(workspaces_num) + c=$(cf "$current" "$cn") + idx=$c + echo "number|int|$cn" + echo "focused|int|$idx" + ret_add $c $cn + echo "" + fi + done + ''; + + lang_script = pkgs.writeShellScript "current_layout.sh" '' + startl=$(${niri} msg -j keyboard-layouts | ${jq} .current_idx) + echo "lang|int|$startl" + echo "" + + ${niri} msg -j event-stream | while read -r line; do + + current=$(echo $line | ${jq} .KeyboardLayoutSwitched.idx) + if [[ "$current" != "null" ]]; then + echo "lang|string|$current" + echo "" + fi + done + ''; +in { + hm.programs.yambar = { + enable = true; + settings.bar = let + # std_underline = { + # underline = { + # size = 2; + # color = "ff0000ff"; + # }; + # }; + red = config.lib.stylix.colors.base08 + "ff"; + orange = config.lib.stylix.colors.base09 + "ff"; + yellow = config.lib.stylix.colors.base0A + "ff"; + white = config.lib.stylix.colors.base05 + "ff"; + grey = "999999ff"; + + awesome = "Font Awesome 6 Free:style=solid:pixelsize=14"; + in { + font = "FiraCode Nerd Font:pixelsize=12"; + height = 26; + location = "top"; + spacing = 8; + margin = 7; + foreground = white; + background = config.lib.stylix.colors.base00 + "cc"; + left = [ + { + script = { + path = workspaces_script; + args = [ + ]; + content = [ + { + string = { + text = "{before}"; + }; + } + { + string = { + text = " {focused} "; + foreground = orange; + }; + } + { + string = { + text = "{after}"; + }; + } + ]; + }; + } + { + foreign-toplevel = { + content = { + map = { + conditions = { + "~activated" = { + empty = { + }; + }; + activated = [ + { + string = { + text = "{app-id}"; + foreground = orange; + }; + } + ]; + }; + }; + }; + }; + } + ]; + + center = [ + { + clock = { + time-format = "%H:%M"; + content = [ + { + string = { + text = "{time}"; + on-click = "${lib.getExe pkgs.playerctl} play-pause"; + }; + } + ]; + }; + } + ]; + + right = [ + { + network = { + content = { + map = { + default = { + empty = { + }; + }; + conditions = { + "name == enp2s0" = { + map = { + conditions = { + "~carrier" = { + empty = { + }; + }; + carrier = { + map = { + default = { + string = { + text = ""; + font = awesome; + foreground = white; + }; + }; + conditions = { + "state == up && ipv4 != \"\"" = { + string = { + text = ""; + foreground = red; + font = awesome; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + } + { + network = { + poll-interval = 1000; + content = { + map = { + default = { + empty = { + }; + }; + conditions = { + "name == wlan0" = { + map = { + default = { + string = { + text = ""; + font = awesome; + foreground = white; + }; + }; + conditions = { + "state == down" = { + string = { + text = ""; + font = awesome; + foreground = red; + }; + }; + "state == up" = { + map = { + default = [ + { + string = { + text = ""; + font = awesome; + }; + } + ]; + conditions = { + "ipv4 == \"\"" = [ + { + string = { + text = ""; + font = awesome; + foreground = red; + }; + } + ]; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + } + { + pipewire = let + volume.conditions = { + muted = { + string = { + text = "{cubic_volume}%"; + foreground = "999999ff"; + }; + }; + "~muted" = { + string = { + text = "{cubic_volume}%"; + }; + }; + }; + in { + content.list.items = [ + { + map.conditions = { + "type == \"sink\"".map.conditions = { + "bus == \"bluetooth\"" = { + string = { + text = "󰂯 "; + font = awesome; + }; + }; + muted = { + string = { + text = " "; + font = awesome; + foreground = grey; + }; + }; + "~muted" = [ + { + ramp = { + tag = "cubic_volume"; + items = [ + { + string = { + text = " "; + font = awesome; + }; + } + { + string = { + text = " "; + font = awesome; + }; + } + ]; + }; + } + ]; + }; + "type == \"source\"" = { + map.conditions = { + muted = { + string = { + text = "  "; + font = awesome; + foreground = grey; + }; + }; + "~muted" = { + string = { + text = " 🎙"; + font = awesome; + foreground = yellow; + }; + }; + }; + }; + }; + } + {map."<<" = volume;} + ]; + }; + } + { + backlight = { + name = "amdgpu_bl2"; + content = [ + { + string = { + text = ""; + font = awesome; + }; + } + { + string = { + text = "{percent}%"; + }; + } + ]; + }; + } + { + battery = let + discharging = { + list = { + items = [ + { + ramp = { + tag = "capacity"; + items = [ + { + string = { + text = ""; + foreground = "ff0000ff"; + font = awesome; + }; + } + { + string = { + text = ""; + foreground = "ff0000ff"; + font = awesome; + }; + } + { + string = { + text = ""; + foreground = "ffa600ff"; + font = awesome; + }; + } + { + string = { + text = ""; + font = awesome; + }; + } + { + string = { + text = ""; + font = awesome; + }; + } + { + string = { + text = ""; + font = awesome; + }; + } + { + string = { + text = ""; + font = awesome; + }; + } + { + string = { + text = ""; + font = awesome; + }; + } + { + string = { + text = ""; + font = awesome; + }; + } + { + string = { + text = ""; + foreground = "00ff00ff"; + font = awesome; + }; + } + ]; + }; + } + { + string = { + text = "{capacity}%"; + }; + } + ]; + }; + }; + in { + name = if host == "tureis" then "BAT1" else "BAT0"; + poll-interval = 250; + content = { + map = { + conditions = { + "state == unknown" = { + "<<" = discharging; + }; + "state == discharging" = { + "<<" = discharging; + }; + "state == charging" = [ + { + string = { + text = "󱐋"; + foreground = "00ff00ff"; + font = awesome; + }; + } + { + string = { + text = "{capacity}%"; + }; + } + ]; + "state == full" = [ + { + string = { + text = ""; + foreground = "00ff00ff"; + font = awesome; + }; + } + { + string = { + text = "{capacity}%"; + }; + } + ]; + "state == \"not charging\"" = [ + { + ramp = { + tag = "capacity"; + items = [ + { + string = { + text = " "; + foreground = "ff0000ff"; + font = awesome; + }; + } + { + string = { + text = " "; + foreground = "ffa600ff"; + font = awesome; + }; + } + { + string = { + text = " "; + foreground = "00ff00ff"; + font = awesome; + }; + } + { + string = { + text = " "; + foreground = "00ff00ff"; + font = awesome; + }; + } + { + string = { + text = " "; + foreground = "00ff00ff"; + font = awesome; + }; + } + { + string = { + text = " "; + foreground = "00ff00ff"; + font = awesome; + }; + } + { + string = { + text = " "; + foreground = "00ff00ff"; + font = awesome; + }; + } + { + string = { + text = " "; + foreground = "00ff00ff"; + font = awesome; + }; + } + { + string = { + text = " "; + foreground = "00ff00ff"; + font = awesome; + }; + } + { + string = { + text = " "; + foreground = "00ff00ff"; + font = awesome; + }; + } + ]; + }; + } + { + string = { + text = "{capacity}%"; + }; + } + ]; + }; + }; + }; + }; + } + { + clock = { + date-format = "%d %B, %A"; + content = [ + { + string = { + text = ""; + font = awesome; + }; + } + { + string = { + text = "{date}"; + right-margin = 5; + }; + } + ]; + }; + } + { + script = { + path = lang_script; + args = [ + ]; + content = { + map = { + default = { + string = { + text = "{lang}"; + }; + }; + conditions = { + "lang == 0" = [ + { + string = { + text = ""; + font = awesome; + }; + } + { + string = { + text = "en"; + }; + } + ]; + "lang == 1" = [ + { + string = { + text = ""; + font = awesome; + }; + } + { + string = { + text = "ru"; + }; + } + ]; + }; + }; + }; + }; + } + ]; + }; + }; +} diff --git a/modules/global/bash.nix b/modules/global/bash.nix new file mode 100644 index 0000000..75afa14 --- /dev/null +++ b/modules/global/bash.nix @@ -0,0 +1,45 @@ +{ config, pkgs, ... }: { + globals.hm.programs.carapace = { + enable = true; + enableBashIntegration = true; + }; + + globals.hm.programs.bash = { + enable = true; + shellAliases = config.n.misc.aliases; + enableCompletion = true; + + initExtra = '' + #colorscript -e square + _fix_cursor() { + echo -ne '\e[5 q' + } + precmd_functions+=(_fix_cursor) + export TERM="xterm-256color" + PS1="\e[1;32m\u@\h\e[m \e[1;34m[\t]\e[m [\w]\n\e[0;34m-> %\e[m \e[0;32m" + ''; + }; + + environment.systemPackages = with pkgs; [ + wget + curl + tree + htop + killall + jq + p7zip + tldr + unzip + mtr + iperf3 + lsd + bat + ncdu + ripgrep + dig + pwgen + inxi + alejandra + tokei + ]; +} diff --git a/modules/global/dnscrypt-proxy.nix b/modules/global/dnscrypt-proxy.nix new file mode 100644 index 0000000..64f5c84 --- /dev/null +++ b/modules/global/dnscrypt-proxy.nix @@ -0,0 +1,17 @@ +{ ... }: { + services.dnscrypt-proxy2 = { + enable = true; + settings = { + # listen_addresses = [ "127.0.0.1:53" ]; + listen_addresses = [ "0.0.0.0:53" ]; + max_clients = 200; + force_tcp = true; + netprobe_address = "192.168.1.1:53"; + server_names = [ "libredns-noads" "njalla-doh" ]; + }; + }; + + networking = { + nameservers = [ "127.0.0.1" ]; + }; +} diff --git a/modules/global/firewall.nix b/modules/global/firewall.nix new file mode 100644 index 0000000..b5f244a --- /dev/null +++ b/modules/global/firewall.nix @@ -0,0 +1,6 @@ +{ ... }: { + networking.firewall = { + allowedTCPPorts = []; + allowedUDPPorts = []; + }; +} diff --git a/modules/global/git.nix b/modules/global/git.nix new file mode 100644 index 0000000..876ea23 --- /dev/null +++ b/modules/global/git.nix @@ -0,0 +1,29 @@ +{ pkgs, lib, ... }: { + hm.programs.git.enable = true; + environment.systemPackages = [ pkgs.git ]; + + hm.programs.git = { + userEmail = "thary@riseup.net"; + userName = "Thary"; + signing = { + signByDefault = true; + }; + }; + + nodes.phoenix.hm = { + programs.git.extraConfig = { + commit.gpgsign = true; + gpg.format = "ssh"; + gpg.ssh.allowedSignersFile = "~/.ssh/allowed_signers"; + user.signingkey = "~/.ssh/id_ed25519.pub"; + }; + home.file.".ssh/allowed_signers".text = + # "* ${builtins.readFile /home/${username}/.ssh/id_ed25519.pub}"; + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDEDqpSiQpbSsClh6UGb7Z2DA1Hy+EyePzTy+5hEVD/A"; + }; + + lib.n.misc.shellAliases = { + gc = "${lib.getExe pkgs.git} commit -m"; + ga = "${lib.getExe pkgs.git} add"; + }; +} diff --git a/modules/global/home-manager.nix b/modules/global/home-manager.nix new file mode 100755 index 0000000..e9237bd --- /dev/null +++ b/modules/global/home-manager.nix @@ -0,0 +1,26 @@ +{ lib, username, config, inputs, ... }: +with lib; +{ + imports = [ + inputs.home-manager.nixosModules.home-manager + (lib.mkAliasOptionModule [ "hm" ] [ + "home-manager" + "users" + username + ]) + ]; + + options.globals.hm = mkOption { type = types.attrs; }; + config = { + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + # backupFileExtension = "hm-backup-" + pkgs.lib.readFile "${pkgs.runCommand "timestamp" {} "echo -n `date '+%Y%m%d%H%M%S'` > $out"}"; + backupFileExtension = "hm-backup-$(date \"+%Y%m%d%H%M%S\")"; + sharedModules = [ config.globals.hm ]; + }; + hm.home = { + inherit (config.system) stateVersion; + }; + }; +} diff --git a/modules/global/locales.nix b/modules/global/locales.nix new file mode 100755 index 0000000..99b97d8 --- /dev/null +++ b/modules/global/locales.nix @@ -0,0 +1,23 @@ +{ ... }: +let + locales = "en_US.UTF-8"; + timezone = "Europe/Minsk"; +in { + time.timeZone = timezone; + + i18n = { + defaultLocale = locales; + extraLocaleSettings = { + # LC_ADDRESS = locales; + # LC_MEASUREMENT = locales; + # LC_MONETARY = locales; + # LC_NAME = locales; + # LC_NUMERIC = locales; + # LC_PAPER = locales; + # LC_TELEPHONE = locales; + # LC_TIME = locales; + LANGUAGE = locales; + LC_ALL = locales; + }; + }; +} diff --git a/modules/global/networking.nix b/modules/global/networking.nix new file mode 100644 index 0000000..6e43199 --- /dev/null +++ b/modules/global/networking.nix @@ -0,0 +1,8 @@ +{ ... }: { + # nodes.cepheus.networking.interfaces.ens18 = { + # ipv4.addresses = [{ + # address = "158.220.126.56"; + # prefixLength = 24; + # }]; + # }; +} diff --git a/modules/global/nix.nix b/modules/global/nix.nix new file mode 100644 index 0000000..eb7dcce --- /dev/null +++ b/modules/global/nix.nix @@ -0,0 +1,29 @@ +{ pkgs, lib, inputs, username, config, ... }: { + # imp.home.dirs = [ ".local/share/nix" ]; # Nix Repl history + nix = { + package = pkgs.lix; + settings = { + allowed-users = ["root" "@wheel"]; + trusted-users = [ "root" username ]; + experimental-features = ["nix-command" "flakes"]; + build-dir = "/nix/builds"; + }; + registry = lib.mapAttrs (_: value: {flake = value;}) inputs // { n.flake = inputs.nixpkgs; }; + nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry; + }; + + system.stateVersion = "23.05"; # My first nixos was 22.11 + + nixpkgs.overlays = [ + (import ../../pkgs) + ]; + + # documentation = { + # enable = true; + # doc.enable = true; + # dev.enable = true; + # info.enable = true; + # nixos.enable = true; + # man.enable = true; + # }; +} diff --git a/modules/global/nvim.nix b/modules/global/nvim.nix new file mode 100644 index 0000000..8dcee2e --- /dev/null +++ b/modules/global/nvim.nix @@ -0,0 +1,44 @@ +{ config, ...}: { + globals.hm = { + programs.neovim = { + enable = true; + defaultEditor = true; + viAlias = true; + vimAlias = true; + + extraLuaConfig = '' + local bind = vim.keymap.set + local opt = vim.opt + local g = vim.g + local o = vim.o + local cmd = vim.cmd + + o.expandtab = true + o.smarttab = true + o.cindent = true + o.autoindent = true + + o.ignorecase = true + o.smartcase = true + + o.backup = false + o.writebackup = false + o.undofile = true + o.swapfile = false + + opt.relativenumber = true + opt.number = true + opt.tabstop = 2 + opt.shiftwidth = 2 + opt.mouse = "a" + opt.termguicolors = true + opt.clipboard = "unnamedplus" + ''; + + home.sessionVariables = { + # EDITOR = lib.mkForce lib.getExe pkgs.neovim; + MANPAGER = "${config.hm.home.sessionVariables.EDITOR} +Man!"; + }; + }; + }; +} diff --git a/modules/global/secrets.nix b/modules/global/secrets.nix new file mode 100644 index 0000000..23e6b96 --- /dev/null +++ b/modules/global/secrets.nix @@ -0,0 +1,38 @@ +{ inputs, host, lib, ... }: +let + keys = { + phoenix = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBsrEEXQwcu4i7hOqCbpwd4EdC/+v9fAWm30MUXhVpp5"; + cepheus = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGm1PymMJ2JnE973UCaezWQFKyZi7lsAzHshUUwafa8F"; + naos = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIcR9C753wDWjg/oJxn6p9kLMaiaOPJFNT0xYPICXK52"; + }; +in { + environment.systemPackages = [ inputs.agenix-rekey.packages.x86_64-linux.default ]; + imports = [ + inputs.agenix.nixosModules.default + inputs.agenix-rekey.nixosModules.default + ]; + + age.identityPaths = [ "/nix/keys/identity" ]; # default key path + age.rekey = { + masterIdentities = [ + { identity = "/home/user/.ssh/id_ed25519"; + pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDEDqpSiQpbSsClh6UGb7Z2DA1Hy+EyePzTy+5hEVD/A"; } + ]; + storageMode = "local"; + generatedSecretsDir = ../../secrets/generated/${host}; + localStorageDir = ../../secrets/rekeyed/${host}; + }; + + # services.openssh.enable = true; + services.openssh.hostKeys = [{ + path = "/nix/keys/identity"; + type = "ed25519"; + }]; + +# TODO: define key via hosts//default.nix + + nodes.phoenix.age.rekey.hostPubkey = keys.phoenix; + nodes.cepheus.age.rekey.hostPubkey = keys.cepheus; + # nodes.tureis.age.rekey.hostPubkey = ""; # TODO + nodes.naos.age.rekey.hostPubkey = keys.naos; +} diff --git a/modules/global/security.nix b/modules/global/security.nix new file mode 100644 index 0000000..810e2ff --- /dev/null +++ b/modules/global/security.nix @@ -0,0 +1,26 @@ +{ username, pkgs, ... }: { + security = { + doas = { + enable = true; + wheelNeedsPassword = true; + }; + sudo.enable = false; + + # polkit.enable = lib.mkForce false; + polkit.enable = true; + }; + + + n.misc.aliases.sudo = "doas"; + + security.tpm2 = { + enable = true; + pkcs11.enable = true; + pkcs11.package = pkgs.tpm2-pkcs11-fapi; + tctiEnvironment.enable = true; + }; + users.users.${username}.extraGroups = [ "tss" "admin" ]; + + environment.systemPackages = with pkgs; [ tpm2-pkcs11-fapi clevis tpm2-tools ]; + environment.variables.TPM2_PKCS11_BACKEND = "fapi"; +} diff --git a/modules/n/aliases.nix b/modules/n/aliases.nix new file mode 100644 index 0000000..cf8c2f8 --- /dev/null +++ b/modules/n/aliases.nix @@ -0,0 +1,15 @@ +{ lib, pkgs, ... }: +with lib; { + options.n.misc.aliases = mkOption { + type = types.attrs; + }; + config.n.misc.aliases = { + ls = "${lib.getExe pkgs.lsd} --group-directories-first"; + la = "${lib.getExe pkgs.lsd} -l"; + cat = "${lib.getExe pkgs.bat}"; + dcat = "${lib.getExe pkgs.bat} --plain"; + list-generations = "nix-env -p /nix/var/nix/profiles/system --list-generations"; + delete-generations = "nix-env -p /nix/var/nix/profiles/system --delete-generations"; + myip = "${lib.getExe pkgs.curl} ipwho.de/json | ${lib.getExe pkgs.jq} ."; + }; +} diff --git a/modules/n/bootloader.nix b/modules/n/bootloader.nix new file mode 100644 index 0000000..c2691da --- /dev/null +++ b/modules/n/bootloader.nix @@ -0,0 +1,42 @@ +{ lib, pkgs, config, inputs, ... }: +with lib; +let + cfg = config.n.host.bootloader; +in { + options.n.host.bootloader = mkOption { type = types.str; }; + + imports = [ inputs.lanzaboote.nixosModules.lanzaboote ]; + config = mkMerge [ + (mkIf (cfg == "lanzaboote") { + environment.systemPackages = [ pkgs.sbctl ]; + + boot = { + loader = { + systemd-boot.enable = lib.mkForce false; + grub.enable = lib.mkForce false; + efi.canTouchEfiVariables = true; + }; + bootspec.enable = true; + lanzaboote = { + enable = true; + pkiBundle = "/var/lib/sbctl"; + }; + }; + + imp.dirs = [ { directory = "/var/lib/sbctl"; mode = "0400"; } ]; + }) + + (mkIf (cfg == "grub") { + boot.loader.grub = { + enable = true; + efiSupport = lib.mkDefault false; + # efiInstallAsRemovable = true; # TODO: what's it? + device = "nodev"; + }; + boot.loader.systemd-boot.enable = lib.mkForce false; + }) + (mkIf (cfg == "sysdboot") { + boot.loader.systemd-boot.enable = true; + }) + ]; +} diff --git a/modules/n/default.nix b/modules/n/default.nix new file mode 100644 index 0000000..0ad4e07 --- /dev/null +++ b/modules/n/default.nix @@ -0,0 +1,23 @@ +{ lib, config, pkgs, host, ... }: +with lib; +let + cfg = config.n.host; +in { + options.n.host = { + kernel = mkOption { + type = types.raw; + default = pkgs.linuxKernel.packages.linux_6_1_hardened; + }; + + users = mkOption { type = with types; attrs; default = {}; }; + defaultUser = mkOption { type = type.str; }; + extras = mkOption { type = with types; listOf path; }; + types = mkOption { type = with types; listOf str; }; + }; + options.nodes = mkOption { type = with types; attrsOf attrs; }; + + config = { + boot.kernelPackages = cfg.kernel; + users.users = cfg.users; + }; +} diff --git a/modules/n/defaults.nix b/modules/n/defaults.nix new file mode 100644 index 0000000..a26c17d --- /dev/null +++ b/modules/n/defaults.nix @@ -0,0 +1,16 @@ +{ lib, config, ... }: +with lib; { # Thanks to azahi! + options.n.misc.defaults = mkOption { + description = "Default applications."; + type = with types; attrsOf (listOf str); + default = {}; + }; + + config.hm.xdg = { + enable = true; + mimeApps = { + enable = true; + defaultApplications = mkMerge (mapAttrsToList (n: v: genAttrs v (_: [ "${n}.desktop" ])) config.n.misc.defaults); + }; + }; +} diff --git a/modules/n/hardware.nix b/modules/n/hardware.nix new file mode 100644 index 0000000..4fbb728 --- /dev/null +++ b/modules/n/hardware.nix @@ -0,0 +1,41 @@ +{ lib, config, ... }: +with lib; +let + cfg = config.n.host.hardware; +in { + options.n.host.hardware = { + cpu = mkOption { type = types.str; default = ""; }; + }; + config = mkMerge [ + (mkIf (cfg.cpu == "amd") + { + boot.kernelModules = [ "kvm-amd" ]; + hardware.cpu.amd.updateMicrocode = true; + } + ) + (mkIf (cfg.cpu == "intel") + { + hardware.cpu.intel.updateMicrocode = true; + } + ) + (mkIf (cfg.cpu == "virt") + { + boot.initrd.availableKernelModules = [ + "virtio_net" + "virtio_pci" + "virtio_mmio" + "virtio_blk" + "virtio_scsi" + "9p" + "9pnet_virtio" + ]; + boot.initrd.kernelModules = [ + "virtio_balloon" + "virtio_console" + "virtio_rng" + "virtio_gpu" + ]; + } + ) + ]; +} diff --git a/modules/n/impermanence.nix b/modules/n/impermanence.nix new file mode 100644 index 0000000..94eea30 --- /dev/null +++ b/modules/n/impermanence.nix @@ -0,0 +1,64 @@ +{ lib, config, inputs, username, ... }: +with lib; +let + cfg = config.imp; +in { + imports = [ + inputs.impermanence.nixosModules.impermanence + (mkAliasOptionModule [ "imp" "dirs" ] [ + "environment" + "persistence" + "/nix/persist" + "directories" + ]) + ]; + + options.imp.home = { + files = mkOption { + type = with types; listOf str; + default = []; + }; + dirs = mkOption { + type = with types; listOf str; + default = []; + }; + }; + + config = { + environment.persistence."/nix/persist" = { + enable = true; + directories = [ + "/var/lib/systemd/coredump" + "/var/lib/nixos" + ]; + files = [ + "/etc/machine-id" + ]; + }; + + environment.persistence."/nix/persist".users."${username}" = { + # environment.persistence."/nix/persist".users."user" = { + directories = builtins.map (x: { directory = x; mode = "0700"; }) + [ + "Audiobooks" + "Books" + "Desktop" + "Documents" + # "Downloads" + "Extensions" + "Forks" + "Games" + "IdeaProjects" + "Keybase" + "Library" + "Monero" + "Music" + "Phone" + "Pictures" + "Projects" + "Videos" + ] ++ cfg.home.dirs; + files = builtins.map (x: { file = x; parentDirectory = { mode = "0700"; }; }) cfg.home.files; + }; + }; +} diff --git a/modules/n/networking.nix b/modules/n/networking.nix new file mode 100644 index 0000000..12e326e --- /dev/null +++ b/modules/n/networking.nix @@ -0,0 +1,22 @@ +{ host, lib, config, ... }: +with lib; +let cfg = config.n.host; +in { + options.n.host = { + hostId = mkOption { type = types.str; }; + domain = mkOption { type = types.str; default = "${host}.local"; }; + }; + + config = { + networking = { + hostName = host; + hostId = cfg.hostId; + domain = cfg.domain; + dhcpcd.enable = true; + useDHCP = lib.mkDefault true; + }; + systemd.network.wait-online.enable = lib.mkForce false; + boot.initrd.systemd.network.wait-online.enable = lib.mkForce false; + systemd.services.NetworkManager-wait-online.enable = lib.mkForce false; + }; +} diff --git a/modules/n/unfree.nix b/modules/n/unfree.nix new file mode 100644 index 0000000..796833a --- /dev/null +++ b/modules/n/unfree.nix @@ -0,0 +1,13 @@ +{ lib, config, ... }: +with lib; +let + cfg = config.n.misc.unfreePackages; +in { + options.n.misc.unfreePackages = mkOption { + type = with types; listOf str; + }; + + config = { + nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) cfg; + }; +} diff --git a/modules/server/containers.nix b/modules/server/containers.nix new file mode 100644 index 0000000..d6b7aa9 --- /dev/null +++ b/modules/server/containers.nix @@ -0,0 +1,36 @@ +{ host, lib, config, ... }: { + networking.nat = { + enable = true; + # Use "ve-*" when using nftables instead of iptables + internalInterfaces = ["ve-+"]; + externalInterface = "ens18"; + enableIPv6 = false; + }; + + containers = + if builtins.pathExists ../../hosts/${host}/containers + then let + containers_files' = builtins.readDir ../../hosts/${host}/containers; + containers_files = lib.concatMapAttrs + (container: _: { + ${lib.removeSuffix ".nix" container} = {}; + }) containers_files'; + + in builtins.mapAttrs (container: _: { + autoStart = true; + bindMounts = builtins.mapAttrs (_: value: { hostPath = value; isReadOnly = false; }) config.container.${container}.config.binds; + tmpfs = [ "/" ]; + config = { lib, ... }: with lib; { + imports = [ + ../../hosts/${host}/containers/${container}.nix + # ../containers + ../global/nix.nix + ../global/dnscrypt-proxy.nix + ]; + options = { + binds = mkOption { type = types.attrs; default = {}; }; + }; + }; + }) containers_files + else {}; +} diff --git a/modules/server/openssh.nix b/modules/server/openssh.nix new file mode 100644 index 0000000..26163e0 --- /dev/null +++ b/modules/server/openssh.nix @@ -0,0 +1,19 @@ +{ username, ... }: let + keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINkHOpdBpYV3KJV+AtBK3jD6MLDZzAwh9HFt0LsLxBV0" # Old key + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDEDqpSiQpbSsClh6UGb7Z2DA1Hy+EyePzTy+5hEVD/A" # Main key + ]; +in { + users.users.${username}.openssh.authorizedKeys.keys = keys; + users.users.root.openssh.authorizedKeys.keys = keys; + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + KbdInteractiveAuthentication = false; + PermitRootLogin = "prohibit-password"; + }; + ports = [ 22 ]; + openFirewall = true; + }; +} diff --git a/pkgs/SynapseRevitalization/.editorconfig b/pkgs/SynapseRevitalization/.editorconfig new file mode 100644 index 0000000..74d6498 --- /dev/null +++ b/pkgs/SynapseRevitalization/.editorconfig @@ -0,0 +1,3 @@ +[*.py] +indent_style = space +indent_size = 4 diff --git a/pkgs/SynapseRevitalization/.gitignore b/pkgs/SynapseRevitalization/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/pkgs/SynapseRevitalization/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/pkgs/SynapseRevitalization/default.nix b/pkgs/SynapseRevitalization/default.nix new file mode 100644 index 0000000..d50f43e --- /dev/null +++ b/pkgs/SynapseRevitalization/default.nix @@ -0,0 +1,27 @@ +{ + python313Packages, + python313, + writeShellScript, +}: +python313Packages.buildPythonApplication rec { + projectDir = ./.; + pname = "synapse-revitalization"; + version = "0.1.0"; + pyproject = false; + + src = ./.; + + installPhase = + let python = python313.withPackages (ps: with ps; [ requests signedjson systemd ]); + script = writeShellScript "synapse-revitalization" "${python}/bin/python $out/main.py '$1'"; + in '' + mkdir -p $out/bin + cp $src/* $out + # cp ${script} $out/bin + cat > $out/bin/synapse-revitalization << EOF +#!/bin/sh +exec ${python}/bin/python $out/main.py "\$1" +EOF + chmod +x $out/bin/synapse-revitalization + ''; +} diff --git a/pkgs/SynapseRevitalization/flake.lock b/pkgs/SynapseRevitalization/flake.lock new file mode 100644 index 0000000..ade50e6 --- /dev/null +++ b/pkgs/SynapseRevitalization/flake.lock @@ -0,0 +1,58 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1692799911, + "narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1750776420, + "narHash": "sha256-/CG+w0o0oJ5itVklOoLbdn2dGB0wbZVOoDm4np6w09A=", + "path": "/nix/store/1l4nm55xcq55cdp1xz3x5mfgr4c24058-source", + "rev": "30a61f056ac492e3b7cdcb69c1e6abdcf00e39cf", + "type": "path" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/pkgs/SynapseRevitalization/flake.nix b/pkgs/SynapseRevitalization/flake.nix new file mode 100644 index 0000000..25e4c75 --- /dev/null +++ b/pkgs/SynapseRevitalization/flake.nix @@ -0,0 +1,20 @@ +{ + description = "my project description"; + inputs.flake-utils.url = "github:numtide/flake-utils"; + + outputs = { + self, + nixpkgs, + flake-utils, + }: + flake-utils.lib.eachDefaultSystem + ( + system: let + pkgs = nixpkgs.legacyPackages.${system}; + in { + devShells.default = pkgs.mkShell { + packages = with pkgs; [python313Full python313Packages.signedjson python313Packages.requests python313Packages.systemd python313Packages.setuptools black]; + }; + } + ); +} diff --git a/pkgs/SynapseRevitalization/get_config.py b/pkgs/SynapseRevitalization/get_config.py new file mode 100644 index 0000000..acd854c --- /dev/null +++ b/pkgs/SynapseRevitalization/get_config.py @@ -0,0 +1,20 @@ +import os + +def read_vars(): + if os.environ.get("SYNAPSE_REVITALIZATION_AUTH_TOKEN_TERM") == None: + auth_token_term = 180 + else: + auth_token_term = os.environ["SYNAPSE_REVITALIZATION_AUTH_TOKEN_TERM"] + + admin_auth_token_file = os.environ["SYNAPSE_REVITALIZATION_ADMIN_AUTH_TOKEN_FILE"] + + with open(admin_auth_token_file, "r") as file: + admin_auth_token = file.read().split("\n")[0] + + return { + "auth_token_term": auth_token_term, + "admin_auth_token": admin_auth_token, + "server_key_file": os.environ["SYNAPSE_REVITALIZATION_SERVER_KEY_FILE"], + "origin_server_name": os.environ["SYNAPSE_REVITALIZATION_SERVER_NAME"], + "origin_server": os.environ["SYNAPSE_REVITALIZATION_SERVER_ADDRESS"], + } diff --git a/pkgs/SynapseRevitalization/main.py b/pkgs/SynapseRevitalization/main.py new file mode 100644 index 0000000..f34d6a6 --- /dev/null +++ b/pkgs/SynapseRevitalization/main.py @@ -0,0 +1,35 @@ +from systemd import journal +from revitalize import revitalize, parse_roomid +import sys + +if len(sys.argv) != 2: # 2, because running the script looks like 'python [1]main.py [2]"..."' + print("synapse-revitalization accepts only 1 argument") + exit() +else: + message = sys.argv[1] + +if "Ignoring PDU for unknown room_id" in message: + journal.send("[info] Got error message: %s" % message) + roomid = message.rsplit(maxsplit=1)[1] + x = revitalize(roomid, parse_roomid(roomid)) + if x == True: + journal.send("[info] Successfully made all users rejoin {roomid} via {server}") + journal.send("[info] {roomid} is available now") + elif x == False: + journal.send("ERROR! Couldn't make {roomid} available via {parse_roomid(roomid)}") + + +elif "as we're not in the room" in message: + journal.send("[info] Got error message: %s" % message) + roomid = message.split("'")[1] + server = message.split("from server ")[1].split(" ")[0] + for i in [server, parse_roomid(roomid)]: + x = revitalize(roomid, i) + if x == True: + journal.send(f"[info] Successfully made all users rejoin {roomid} via {server}") + journal.send(f"[info] {roomid} is available now") + break + elif x == False: + journal.send(f"[WARNING] Couldn't make users rejoin {roomid} via {server}") + if i == parse_roomid(roomid): + journal.send(f"ERROR! Couldn't make {roomid} available via {server} nor {parse_roomid(roomid)}") diff --git a/pkgs/SynapseRevitalization/revitalize.py b/pkgs/SynapseRevitalization/revitalize.py new file mode 100644 index 0000000..8792ea4 --- /dev/null +++ b/pkgs/SynapseRevitalization/revitalize.py @@ -0,0 +1,198 @@ +from signedjson.key import read_signing_keys +from signedjson.sign import sign_json +import json + +import requests +from systemd import journal +from get_config import read_vars + +import datetime + +# Importing configuration from environment variables +config = read_vars() + + +# Getting signing key +with open(config["server_key_file"]) as f: + skey = read_signing_keys(f)[0] + + +# Defining additional functions +def current_time(): + now = datetime.datetime.now() + return int(now.timestamp() * 1000) + +def parse_roomid(roomid): + return roomid.split(":")[1] + +def serveraddr(servername): + x = requests.get("https://%s/.well-known/matrix/server" % servername) + if x.status_code == 200: + j = json.loads(x.text) + return j["m.server"] + else: + journal.send(f"[WARNING] Got {x.status_code} discovering server address of {servername}") + return False + + +# Function for getting users' access tokens +def get_access_token(userid): + time = current_time() + config["auth_token_term"] * 1000 + x = requests.post( + f"https://{config['origin_server']}/_synapse/admin/v1/users/{userid}/login", + json={"valid_until_ms": time}, + headers={ + "Authorization": "Bearer %s" % config["admin_auth_token"], + "Content-Type": "application/json", + }, + ).text + if "You are not a server admin" in x: + journal.send("ERROR! The given token doesn't belogn to the server admin!") + exit() + y = json.loads(x) + return y["access_token"] + + +# Sign Matrix federation API requests +## From Matrix protocol documentation +def authorization_headers( + destination_name, request_method, request_target, content=None +): + origin_name = config["origin_server_name"] + request_json = { + "method": request_method, + "uri": request_target, + "origin": origin_name, + "destination": destination_name, + } + + if content is not None: + request_json["content"] = content + + signed_json = sign_json(request_json, origin_name, skey) + + for key, sig in signed_json["signatures"][origin_name].items(): + return 'X-Matrix origin="%s",destination="%s",key="%s",sig="%s"' % ( + origin_name, + destination_name, + key, + sig, + ) + + +# Request the last event +def request_last_event(destination, roomid): + servers = [destination, "matrix.org", "inex.rocks", "sibnsk.net", "kde.org"] + for i in servers: + journal.send(f"[info] Trying access event_to_timestamp via {i}") + try: + server = serveraddr(i) + except requests.exceptions.ConnectionError: + journal.send(f"[WARNING] {i}'s well-known's are unreachable") + continue + except: + journal.send(f"[WARNING] Can't request {i}'s well-known's for unknown reason. Likely {i} is unreachable or ssl certs expired") + continue + if server == False: + continue + + res = current_time() + auth = authorization_headers( + i, + "GET", + f"/_matrix/federation/v1/timestamp_to_event/{roomid}?dir=b&ts={res}", + ) + try: + x = requests.get( + f"https://{server}/_matrix/federation/v1/timestamp_to_event/{roomid}", + params={"dir": "b", "ts": res}, + headers={"Authorization": auth}, + ).text + except requests.exceptions.ConnectionError: + journal.send(f"[WARNING] {server} is unreachable") + continue + except: + journal.send(f"[WARNING] Couldn't request timestamp_to_event from {server} for unknown reason. Likely {server} is unreachable or ssl certs expired") + continue + + if "M_UNRECOGNIZED" in x: + journal.send(f"[WARNING] Trying request {server} timestamp_to_event for {roomid}: got M_UNRECOGNIZED error") + continue + elif "M_NOT_FOUND" in x: + journal.send(f"[WARNING] Unable to get the last event from {roomid}. {i} doesn't know room {roomid}") + journal.send(f"{i} says: '{x}'") + continue + elif "event_id" in x: + j = json.loads(x) + return (i, server, j["event_id"]) + else: + journal.send(f"[WARNING] Unable to get the last event from {roomid}. Unknown error from {server}: '{x}'") + continue + + journal.send(f"ERROR! Unable to get the last event from {roomid}. All {servers} don't know room {roomid} or support timestamp_to_event") + return False + + +# Request states of specified room +def get_states(destination, server, roomid, last_event_id): + auth = authorization_headers( + destination, "GET", "/_matrix/federation/v1/state/%s?event_id=%s" % (roomid, last_event_id) + ) + return requests.get( + f"https://{server}/_matrix/federation/v1/state/{roomid}?event_id={last_event_id}", + headers={"Authorization": auth}, + ).text + + +# Get users list from states +def get_users(states): + x = json.loads(states) + # jq .pdus.[].type + users = [] + x = x["pdus"] + for i in x: + if i["type"] == "m.room.member": + users.append(i["sender"]) + return users + +def filter_users(users): + x = [] + for i in users: + if f":{config["origin_server_name"]}" in i: + x.append(i) + return x + + +# Make a user join a room +def mkjoins(roomid, users, server1, server2): + for i in users: + token = get_access_token(i) + x = requests.post( + f"https://{config['origin_server']}/_matrix/client/v3/join/{roomid}", + params={"via": server1, "via": server2}, + headers={"Authorization": "Bearer %s" % token}, + ).text + if roomid in x: + journal.send(f"[info] Joined {i} to {roomid}") + journal.send(x) + return True + else: + journal.send(f"[info] Failed to join {i} to {roomid}") + journal.send(x) + return False + + +def revitalize(roomid, server): + journal.send(f"Got new roomid {roomid}") + fe = request_last_event(server, roomid) + if fe == False: + return False + else: + x = get_states(fe[0], fe[1], roomid, fe[2]) + y = get_users(x) + z = filter_users(y) + journal.send(f"Trying to add {z} to {roomid}") + if mkjoins(roomid, z, server, fe[0]): + return True + else: + return False diff --git a/pkgs/default.nix b/pkgs/default.nix new file mode 100644 index 0000000..3bee389 --- /dev/null +++ b/pkgs/default.nix @@ -0,0 +1,3 @@ +final: prev: { + synapse-revitalization = final.callPackage ./SynapseRevitalization {}; +} diff --git a/secrets/generated/cepheus/kanidm-admin-password.age b/secrets/generated/cepheus/kanidm-admin-password.age new file mode 100644 index 0000000..ed6287f --- /dev/null +++ b/secrets/generated/cepheus/kanidm-admin-password.age @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 8IT6eg 2CqxQLqOp8pDeo5eoNo+cqhqb/aIKmYH+UrDog+uxSQ +r9Cftc3XAgq0dcK/LBBO6roQ7kNq0Y9MtIqSXftlmTw +-> 1-f2@=I3-CG!^v{ \ No newline at end of file diff --git a/secrets/generated/cepheus/kanidm-idm-admin-password.age b/secrets/generated/cepheus/kanidm-idm-admin-password.age new file mode 100644 index 0000000..1421428 --- /dev/null +++ b/secrets/generated/cepheus/kanidm-idm-admin-password.age @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 8IT6eg EUNesC2x4iOXvLxKdp4ma5NjmG+UYBniS2FwiwfOzig +Rg0H0XgDu8KwMwDH1taEzHujcmFynL+THnGQcc2f/zM +-> E-grease +arbRndcaz9H3+VX0KEPQKIQjCuf+Acjjg53DN9r9SUh1iwuy1D1xKAqJIQ/tQNnp +pKsvCPvsFRKylpsSID2grW+xgPixPol1yd82dFX7mzeMWY3YqQZCy9JibgKj207L +TGk +--- Gif1LntverRvEz/dS54Pr9XXBSjc+9wG3UgAV+JC1n4 +LFA=iv(=<Vg&~LDw)ZG_6uoXnuOzz~fc \ No newline at end of file diff --git a/secrets/generated/cepheus/kanidm-oauth2-gitea.age b/secrets/generated/cepheus/kanidm-oauth2-gitea.age new file mode 100644 index 0000000..f8a6bb3 Binary files /dev/null and b/secrets/generated/cepheus/kanidm-oauth2-gitea.age differ diff --git a/secrets/generated/cepheus/kanidm-oauth2-mas.age b/secrets/generated/cepheus/kanidm-oauth2-mas.age new file mode 100644 index 0000000..b694aa5 Binary files /dev/null and b/secrets/generated/cepheus/kanidm-oauth2-mas.age differ diff --git a/secrets/generated/cepheus/kanidm-oauth2-miniflux.age b/secrets/generated/cepheus/kanidm-oauth2-miniflux.age new file mode 100644 index 0000000..4e09177 --- /dev/null +++ b/secrets/generated/cepheus/kanidm-oauth2-miniflux.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 8IT6eg /PWQMo9+wNssMkIEffcV1q7vjljoqwbUO7YDt5JXqyQ +FBmmr4QUAGvqaa3+oqlqOchZQXmJqJvnj4OY173h8/Q +-> DXr6?'-grease Eh88zNV 4`;(F +DxR1JWHh5df5gW9vTuDyR1EH +--- To7Bsp7eZS5Eum60GFmcumq0C+Qh+tZhoRK6qY13Bqs +f'|? јY.6 [g_ȏULY50k5;cZ@\cZ&Fz m7k4_c \ No newline at end of file diff --git a/secrets/generated/cepheus/miniflux-admin-credentials.age b/secrets/generated/cepheus/miniflux-admin-credentials.age new file mode 100644 index 0000000..a0cd66f --- /dev/null +++ b/secrets/generated/cepheus/miniflux-admin-credentials.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 8IT6eg jDON1VKXuP/2nC8s+zdiM7YdWOIOSVfIlTzaa6sXFg8 +ObFOVNkFt3F9cmwoG2TmX24tyG5juJzJGZSgt1hO8EA +-> &_{#!-grease ;[! wNI+ +cpwN8W8Pa5L+aL5u/2G2Y8EQAFyG13AO4ROacpLJWw +--- Wo4nhP3/m9H9/kWttHBf2Igtvf8aGtinmriZelP4ZMY +Y S6Y!2g341Ҁ5n}Yo~@6i +_ 6T2J8{ΎfziF0g&1Y5CRAQ \ No newline at end of file diff --git a/secrets/rekeyed/cepheus/0a4a9e99dbbfa504b1f6cea3122eff30-matrix_admin_api_token.age b/secrets/rekeyed/cepheus/0a4a9e99dbbfa504b1f6cea3122eff30-matrix_admin_api_token.age new file mode 100644 index 0000000..f717176 --- /dev/null +++ b/secrets/rekeyed/cepheus/0a4a9e99dbbfa504b1f6cea3122eff30-matrix_admin_api_token.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 xe4i4g Hi7bYD2iTYHXZJ41aoU/enLCzQh33TW+XFy62qsoeE0 +8r1Tf5avaYYh6uhkU7IRELeWlqWqrYTKTX4yI7H2Ssc +-> x%wK\\-grease _$f *EAi= +uT6C6V4T +--- oE0ZFEyogNtK/wm+amLxzLuDzhEbd/0eY0fTw3YykuQ +SA/o0jO- *1ٳD`dSK۶YwIO){޺j늊rAM"!a:[k?$.FHC + \ No newline at end of file diff --git a/secrets/rekeyed/cepheus/270efbe40201f1ae49b3c6ef30142de4-cepheus_userhjkl_password.age b/secrets/rekeyed/cepheus/270efbe40201f1ae49b3c6ef30142de4-cepheus_userhjkl_password.age new file mode 100644 index 0000000..fe1a4fa --- /dev/null +++ b/secrets/rekeyed/cepheus/270efbe40201f1ae49b3c6ef30142de4-cepheus_userhjkl_password.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 xe4i4g yQginPj8wQLfq+GHQFad4JDOY6g822eJpCBLkkPLXnk +AotlrDtpYuqhOIfh7rw1jXzKQE2ftvKirlpy/n69nEI +-> 25|mGXDw-grease dFD + +j+z1VwaPHwx3eBybIJ0NslbCxIzq1i7fAg +--- EMWnjBa7TYjSY/6OiwGNb2BBeN3TI7jePYmSGjUHlQQ +"z ?80܏j=kb;U%N§;xD@:eV7w\kZ!X1{Uz*Ic8ʸ&ԶAq+:B \ No newline at end of file diff --git a/secrets/rekeyed/cepheus/a0215752e371e480cb53631bad8bbd8d-kanidm-admin-password.age b/secrets/rekeyed/cepheus/a0215752e371e480cb53631bad8bbd8d-kanidm-admin-password.age new file mode 100644 index 0000000..893af86 Binary files /dev/null and b/secrets/rekeyed/cepheus/a0215752e371e480cb53631bad8bbd8d-kanidm-admin-password.age differ diff --git a/secrets/rekeyed/cepheus/a0758da2f115a6248396a0844c73c751-kanidm-oauth2-mas.age b/secrets/rekeyed/cepheus/a0758da2f115a6248396a0844c73c751-kanidm-oauth2-mas.age new file mode 100644 index 0000000..f4cd335 --- /dev/null +++ b/secrets/rekeyed/cepheus/a0758da2f115a6248396a0844c73c751-kanidm-oauth2-mas.age @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 xe4i4g BhdWl4PFd7k6zUJVH+7Kl8896SPNNIQdlDacmSx3rGo +haPrFYsS95G0Wrmp+wYUZzrzMP/vEfSDeNqcjhCQ3h8 +-> 1}:Gbk=;-grease +pNDtikCNcq6iq/Ulk8JqVEf1ed8e7VWYWG2vJwCLfPKRda9zvQtAbbJol/V0aBrE +pdB9haQeuyNEOgGYX2g4UXjAMNMUeOsJxW2kR/qetSSVAC0 +--- srlG7TzKiMgQuIJl46BGX0fz7IoS8ZH4hwmnjYND6dY + \f iCAziat3[v.F$cm8=t0Uy cRdg9ϯ?_ +2NJ \ No newline at end of file diff --git a/secrets/rekeyed/cepheus/a466b38a1f2972f386ac8f64b0cb10e0-kanidm-oauth2-gitea.age b/secrets/rekeyed/cepheus/a466b38a1f2972f386ac8f64b0cb10e0-kanidm-oauth2-gitea.age new file mode 100644 index 0000000..f6d5a5b Binary files /dev/null and b/secrets/rekeyed/cepheus/a466b38a1f2972f386ac8f64b0cb10e0-kanidm-oauth2-gitea.age differ diff --git a/secrets/rekeyed/cepheus/a55e804940695c077263501a186f001d-miniflux-admin-credentials.age b/secrets/rekeyed/cepheus/a55e804940695c077263501a186f001d-miniflux-admin-credentials.age new file mode 100644 index 0000000..d9ab520 --- /dev/null +++ b/secrets/rekeyed/cepheus/a55e804940695c077263501a186f001d-miniflux-admin-credentials.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 xe4i4g ccm7czGT4kWYarmSoXIpj0YG+QORvYKls2/M0w2kRTE +U62wao9ns8EEMwonvGdsh648l3jVIf6zd9Trb3behyA +-> \{sB-grease ?I62? +2WJcNNB2E0iTCiai/72lHjXQ1zTLJqN0OLfPzC+VvZlT2B+Ynw +--- 9KgJwGsIy8AdEWY7QK93lqtlEhCIRhFC3yNWZvh7kiE +愿Ά$#Z +viCL,lE3` Ŧ_Wm+U[UÞ9@oɭj#FL44a+K?&O?5gk~09H #,b.1Q1h \ No newline at end of file diff --git a/secrets/rekeyed/cepheus/afc649762ad30548778f5bb8d31fe871-kanidm-oauth2-miniflux.age b/secrets/rekeyed/cepheus/afc649762ad30548778f5bb8d31fe871-kanidm-oauth2-miniflux.age new file mode 100644 index 0000000..3fcc840 Binary files /dev/null and b/secrets/rekeyed/cepheus/afc649762ad30548778f5bb8d31fe871-kanidm-oauth2-miniflux.age differ diff --git a/secrets/rekeyed/cepheus/dae43b381145ff44a1403588a3da2af9-kanidm-idm-admin-password.age b/secrets/rekeyed/cepheus/dae43b381145ff44a1403588a3da2af9-kanidm-idm-admin-password.age new file mode 100644 index 0000000..9efaa5e Binary files /dev/null and b/secrets/rekeyed/cepheus/dae43b381145ff44a1403588a3da2af9-kanidm-idm-admin-password.age differ diff --git a/secrets/rekeyed/naos/c9c821d1219b1ef10339bd03ff725e90-naos_userasdf_password.age b/secrets/rekeyed/naos/c9c821d1219b1ef10339bd03ff725e90-naos_userasdf_password.age new file mode 100644 index 0000000..aed47e3 --- /dev/null +++ b/secrets/rekeyed/naos/c9c821d1219b1ef10339bd03ff725e90-naos_userasdf_password.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 9h5L6g TqKdGe6bXqhJc6CmfLZtqp0bKccWbF9Jpx8rrswTSUE +YlEhotVwBqDuJlhXv4uSx273qkXXPbY//+eK7qFJ/4o +-> cb_u:-grease +ToQCR3R8jUwD9WSM8wLlJ65miiT7HmtjPZcL8GvFOTOeKxdZn2SplRbLrv3NUNEK +61PJziYG6ceN6OmJBL+XPRkAyPA +--- jXJogQbiMJptwctSwPddmtlieq/hFdVNe/Ih57o94wU +EUƌߝ#ȿšwڝrlM̋=h?M,Ջfv %`a>oq֮H;G=v{h q S!} ip q \ No newline at end of file diff --git a/secrets/rekeyed/phoenix/15d8c1b8df07abbffbe14f4a7efe5831-phoenix_user_password.age b/secrets/rekeyed/phoenix/15d8c1b8df07abbffbe14f4a7efe5831-phoenix_user_password.age new file mode 100644 index 0000000..f1589d9 --- /dev/null +++ b/secrets/rekeyed/phoenix/15d8c1b8df07abbffbe14f4a7efe5831-phoenix_user_password.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 steVWA PC/WCamSNknrrDvq86eJopOTuzxXD2zg4VMj75h1jVo +5E4Jm3y49sPR0a0hmoeFzlxbAiEEGk/+VMX3zlmGDdk +-> vf&~@-grease @SqeGm`# +SqnHo1aZT6/y +--- GXeTvUG9l8VPIIItM2eArNEnGkxhCCWEkgrHdEItCSQ +|ޠ ͧC}÷6/9njwsc͢ Ƿb(E^Ō[-fi&CDmo]ZSu:9d3I= pkPǒ}8)D@NH \ No newline at end of file