diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..8392d15 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ff33889 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/result* +*.qcow2 +/.direnv +/book +/.sops.yaml diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9b38bdc --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "private"] + path = private + url = https://git.qo.is/fabianhauser/nix-config-private.git + branch = main diff --git a/flake.lock b/flake.lock index 0e9dfd4..d2ee11d 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,137 @@ { "nodes": { + "catppuccin": { + "inputs": { + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1739934729, + "narHash": "sha256-PcrLk10meIJICzUJqtCMOJxoITzbH52fZg2XAB7SSsM=", + "owner": "catppuccin", + "repo": "nix", + "rev": "b1ff2a638afa827f1473498190a2c1cae1cf41cf", + "type": "github" + }, + "original": { + "owner": "catppuccin", + "repo": "nix", + "type": "github" + } + }, + "commonmark-simple": { + "flake": false, + "locked": { + "lastModified": 1707333942, + "narHash": "sha256-o1am93UXviPVdwwPPL5DcD8M4gwFple8SKw/lVmixa8=", + "owner": "srid", + "repo": "commonmark-simple", + "rev": "0308362957d77eea462c2c99d110820fbf30b4b8", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "commonmark-simple", + "type": "github" + } + }, + "commonmark-wikilink": { + "flake": false, + "locked": { + "lastModified": 1738248145, + "narHash": "sha256-UN2Nh+uf+DzM336Ojzr6YZV4RJy8BPx9Q5GZpax3wt0=", + "owner": "srid", + "repo": "commonmark-wikilink", + "rev": "1d7aa327fb33b41f3c4899d5b29aa122780c900f", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "commonmark-wikilink", + "type": "github" + } + }, + "crane": { + "locked": { + "lastModified": 1731098351, + "narHash": "sha256-HQkYvKvaLQqNa10KEFGgWHfMAbWBfFp+4cAgkut+NNE=", + "owner": "ipetkov", + "repo": "crane", + "rev": "ef80ead953c1b28316cc3f8613904edc2eb90c28", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1739841949, + "narHash": "sha256-lSOXdgW/1zi/SSu7xp71v+55D5Egz8ACv0STkj7fhbs=", + "owner": "nix-community", + "repo": "disko", + "rev": "15dbf8cebd8e2655a883b74547108e089f051bf0", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, + "ema": { + "flake": false, + "locked": { + "lastModified": 1738428103, + "narHash": "sha256-vZgaNI0y6IKnWDSLFsl7mwSUZ3ONgduclQkB6WK0VMo=", + "owner": "srid", + "repo": "ema", + "rev": "4478e88d33126ef0b478b2980a71592b8f9afd6b", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "ema", + "type": "github" + } + }, + "emanote": { + "inputs": { + "commonmark-simple": "commonmark-simple", + "commonmark-wikilink": "commonmark-wikilink", + "ema": "ema", + "emanote-template": [], + "flake-parts": "flake-parts", + "flake-root": "flake-root", + "haskell-flake": "haskell-flake", + "heist-extra": "heist-extra", + "nixos-unified": "nixos-unified", + "nixpkgs": [ + "nixpkgs" + ], + "treefmt-nix": "treefmt-nix", + "unionmount": "unionmount" + }, + "locked": { + "lastModified": 1739923609, + "narHash": "sha256-ZKdpDTsVUoxBiqyXqvkM1Klr6oc4ORCqX1nlm5EW05E=", + "owner": "srid", + "repo": "emanote", + "rev": "6a4295cd7fad530beafe8aa45bdaf0693254b3c0", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "emanote", + "type": "github" + } + }, "ez-configs": { "inputs": { "flake-parts": [ @@ -23,7 +155,64 @@ "type": "github" } }, + "fcc-unlock": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1737026299, + "narHash": "sha256-1Tjq0nNWCdncwv5kkC5ZxSAjJRNyREU04QpPCtchQZo=", + "owner": "fabianhauser", + "repo": "fcc-unlock", + "rev": "3b53fefd0f43de3ccbcc4e7f709cd4f46bda7e46", + "type": "github" + }, + "original": { + "owner": "fabianhauser", + "repo": "fcc-unlock", + "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-parts": { + "inputs": { + "nixpkgs-lib": [ + "emanote", + "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": "nixpkgs-lib" }, @@ -41,6 +230,95 @@ "type": "github" } }, + "flake-parts_3": { + "inputs": { + "nixpkgs-lib": [ + "lanzaboote", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1730504689, + "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "506278e768c2a08bec68eb62932193e341f55c90", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-root": { + "locked": { + "lastModified": 1723604017, + "narHash": "sha256-rBtQ8gg+Dn4Sx/s+pvjdq3CB2wQNzx9XGFq/JVGCB6k=", + "owner": "srid", + "repo": "flake-root", + "rev": "b759a56851e10cb13f6b8e5698af7b59c44be26e", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "flake-root", + "type": "github" + } + }, + "gitignore": { + "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" + } + }, + "haskell-flake": { + "locked": { + "lastModified": 1734984991, + "narHash": "sha256-oUYtRBD3Yhw2jvKYo0lfd82fgEQQbFoiJcHO923gmOc=", + "owner": "srid", + "repo": "haskell-flake", + "rev": "daf00052906bdd977e57a07f7048437214232e87", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "haskell-flake", + "type": "github" + } + }, + "heist-extra": { + "flake": false, + "locked": { + "lastModified": 1737313814, + "narHash": "sha256-WCXhs/xhCR4CKBEadQjqqgUb47bLzDY7P7oL5cSgDHc=", + "owner": "srid", + "repo": "heist-extra", + "rev": "6f73e000a34b7c054b516b9504b5a7ed08ce6a2d", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "heist-extra", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -62,13 +340,54 @@ "type": "github" } }, + "lanzaboote": { + "inputs": { + "crane": "crane", + "flake-compat": "flake-compat", + "flake-parts": "flake-parts_3", + "nixpkgs": [ + "nixpkgs" + ], + "pre-commit-hooks-nix": "pre-commit-hooks-nix", + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1737639419, + "narHash": "sha256-AEEDktApTEZ5PZXNDkry2YV2k6t0dTgLPEmAZbnigXU=", + "owner": "nix-community", + "repo": "lanzaboote", + "rev": "a65905a09e2c43ff63be8c0e86a93712361f871e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "v0.4.2", + "repo": "lanzaboote", + "type": "github" + } + }, + "nixos-unified": { + "locked": { + "lastModified": 1729697921, + "narHash": "sha256-gqcmWE+4Vr5/l6AoQc2jIbJHCAXAY+qWPC0ruoAHV1Q=", + "owner": "srid", + "repo": "nixos-unified", + "rev": "e60e64841e74c777799624531dcb2f311f95f639", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "nixos-unified", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1739866667, - "narHash": "sha256-EO1ygNKZlsAC9avfcwHkKGMsmipUk1Uc0TbrEZpkn64=", + "lastModified": 1736012469, + "narHash": "sha256-/qlNWm/IEVVH7GfgAIyP6EsVZI6zjAx1cV5zNyrs+rI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "73cf49b8ad837ade2de76f87eb53fc85ed5d4680", + "rev": "8f3e1f807051e32d8c95cd12b9b421623850a34d", "type": "github" }, "original": { @@ -90,16 +409,138 @@ "url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz" } }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1730741070, + "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1739866667, + "narHash": "sha256-EO1ygNKZlsAC9avfcwHkKGMsmipUk1Uc0TbrEZpkn64=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "73cf49b8ad837ade2de76f87eb53fc85ed5d4680", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks-nix": { + "inputs": { + "flake-compat": [ + "lanzaboote", + "flake-compat" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "lanzaboote", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1731363552, + "narHash": "sha256-vFta1uHnD29VUY4HJOO/D6p6rxyObnf+InnSMT4jlMU=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "private": { + "locked": { + "lastModified": 1740248734, + "narHash": "sha256-BJM/A7lFYi7G+AaNjttLNmZdXGGFi1dI82Mse+JYkes=", + "ref": "refs/heads/main", + "rev": "f2b5747476e21c585d304e38f2ba519e9a99714d", + "revCount": 1, + "type": "git", + "url": "file:./private" + }, + "original": { + "type": "git", + "url": "file:./private" + } + }, "root": { "inputs": { + "catppuccin": "catppuccin", + "disko": "disko", + "emanote": "emanote", "ez-configs": "ez-configs", - "flake-parts": "flake-parts", + "fcc-unlock": "fcc-unlock", + "flake-parts": "flake-parts_2", "home-manager": "home-manager", - "nixpkgs": "nixpkgs", - "treefmt-nix": "treefmt-nix" + "lanzaboote": "lanzaboote", + "nixpkgs": "nixpkgs_2", + "private": "private", + "treefmt-nix": "treefmt-nix_2" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "lanzaboote", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1731897198, + "narHash": "sha256-Ou7vLETSKwmE/HRQz4cImXXJBr/k9gp4J4z/PF8LzTE=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "0be641045af6d8666c11c2c40e45ffc9667839b5", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" } }, "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "emanote", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1734982074, + "narHash": "sha256-N7M37KP7cHWoXicuE536GrVvU8nMDT/gpI1kja2hkdg=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "e41e948cf097cbf96ba4dff47a30ea6891af9f33", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "treefmt-nix_2": { "inputs": { "nixpkgs": [ "nixpkgs" @@ -118,6 +559,22 @@ "repo": "treefmt-nix", "type": "github" } + }, + "unionmount": { + "flake": false, + "locked": { + "lastModified": 1710078535, + "narHash": "sha256-gKBgBtuiRTD3/3EeY8aMgFzuaSEffJacBxsCB3ct1eg=", + "owner": "srid", + "repo": "unionmount", + "rev": "41ae982fa118770bf4d3a3f2d48ac1ffb61c9f09", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "unionmount", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index ae424da..9e8c745 100644 --- a/flake.nix +++ b/flake.nix @@ -1,9 +1,11 @@ { - description = "Description for the project"; + nixConfig = { + extra-substituters = "https://cache.garnix.io"; + extra-trusted-public-keys = "cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="; + }; inputs = { flake-parts.url = "github:hercules-ci/flake-parts"; - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; treefmt-nix = { url = "github:numtide/treefmt-nix"; inputs.nixpkgs.follows = "nixpkgs"; @@ -15,14 +17,39 @@ flake-parts.follows = "flake-parts"; }; }; + + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; home-manager = { url = "github:nix-community/home-manager/master"; inputs.nixpkgs.follows = "nixpkgs"; }; + + lanzaboote = { + url = "github:nix-community/lanzaboote/v0.4.2"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + disko = { + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + fcc-unlock = { + url = "github:fabianhauser/fcc-unlock"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + catppuccin.url = "github:catppuccin/nix"; + emanote = { + url = "github:srid/emanote"; + inputs = { + emanote-template.follows = ""; + nixpkgs.follows = "nixpkgs"; + }; + }; + + private.url = "git+file:./private"; }; outputs = - inputs@{ flake-parts, ... }: + inputs@{ flake-parts, nixpkgs, ... }: flake-parts.lib.mkFlake { inherit inputs; } { imports = map (name: inputs.${name}.flakeModule) [ "treefmt-nix" @@ -32,17 +59,37 @@ "x86_64-linux" ]; perSystem = - { ... }: + { pkgs, lib, ... }: { - treefmt.programs = { - nixfmt.enable = true; - deadnix.enable = true; + treefmt = { + programs = { + nixfmt.enable = true; + deadnix.enable = true; + }; + settings.global.excludes = [ "*.jpg" ]; + }; + + devShells.default = pkgs.mkShell { + name = "nix-config-default-shell"; + packages = lib.attrValues { + inherit (pkgs) + nixos-rebuild + sops + ssh-to-age + nixd + ; + }; }; }; ezConfigs = { root = ./.; globalArgs = { inherit inputs; }; + nixos.hosts = + with nixpkgs.lib; + genAttrs [ "speer" "ochsenchopf" ] (const { + userHomeModules = [ "fhauser" ]; + }); }; }; } diff --git a/home-configurations/fhauser.nix b/home-configurations/fhauser.nix new file mode 100644 index 0000000..35a2b67 --- /dev/null +++ b/home-configurations/fhauser.nix @@ -0,0 +1,15 @@ +{ + osConfig, + ... +}: +{ + home = + let + username = "fhauser"; + in + { + inherit username; + inherit (osConfig.system) stateVersion; + homeDirectory = osConfig.users.users.${username}.home; + }; +} diff --git a/home-modules/applications/catppuccin.nix b/home-modules/applications/catppuccin.nix new file mode 100644 index 0000000..89f5dd3 --- /dev/null +++ b/home-modules/applications/catppuccin.nix @@ -0,0 +1,4 @@ +{ ... }: +{ + catppuccin.flavor = "mocha"; +} diff --git a/home-modules/applications/codium.nix b/home-modules/applications/codium.nix new file mode 100644 index 0000000..c0aa60e --- /dev/null +++ b/home-modules/applications/codium.nix @@ -0,0 +1,12 @@ +{ pkgs, ... }: + +{ + programs.vscode = { + enable = true; + package = pkgs.vscodium; + extensions = with pkgs.vscode-extensions; [ + mkhl.direnv + jnoortheen.nix-ide + ]; + }; +} diff --git a/home-modules/applications/default.nix b/home-modules/applications/default.nix new file mode 100644 index 0000000..2564b71 --- /dev/null +++ b/home-modules/applications/default.nix @@ -0,0 +1,126 @@ +{ + config, + pkgs, + lib, + ... +}: + +{ + + imports = [ + ./catppuccin.nix + ./codium.nix + ./emanote.nix + ./evolution.nix + ./firefox.nix + ./gammastep.nix + ./git.nix + ./gpg.nix + ./kanshi.nix + ./kitty.nix + ./mako.nix + ./psql.nix + ./scripts.nix + ./shell.nix + ./ssh.nix + ./sway.nix + ./swaylock.nix + ./vim.nix + ./waybar.nix + ./webapps.nix + ./zed-editor.nix + ]; + + services = { + network-manager-applet.enable = true; + nextcloud-client = { + enable = true; + startInBackground = true; + }; + pasystray.enable = true; + blueman-applet.enable = true; + }; + + home = { + sessionVariables = { + NIXOS_OZONE_WL = "1"; + }; + packages = + with pkgs; + [ + # Networking + transmission_4 # GUI Tools, maybe extract... + ] + ++ [ + # Desktop Environment Applications + google-chrome + chromium + nextcloud-client + xfce.thunar + xfce.thunar-archive-plugin + xfce.xfce4-appfinder + xfce.mousepad + bitwarden-desktop + pinentry-rofi # Required by gnupg + ] + ++ [ + # office + libreoffice-fresh # TODO: Dictionaries, nixos/nixpkgs#14430 + tectonic + pandoc + texliveSmall + simple-scan + gnome-online-accounts + gnome-control-center + todoist-electron + obsidian + smile + qdigidoc + ] + ++ [ + # Communication + jitsi-meet-electron + teams-for-linux + rdesktop + davinci-resolve + ] + ++ [ + # Development + virt-manager + modemmanager # TODO: makes sense here? + modem-manager-gui + tealdeer + llm + ]; + + #TODO: Write module + activation.statefulConfigSymlinks = config.lib.dag.entryAfter [ "writeBoundary" ] '' + set -eo pipefail + + STATEFUL_ROOT="$HOME/.stateful" + if [ ! -d "$STATEFUL_ROOT" ]; then + $DRY_RUN_CMD mkdir "$STATEFUL_ROOT" + fi + + STATEFUL_CONFS=( + ".config/spotify" + ".mozilla" + ".password-store" + ) + for STATEFUL_CONF in ''${STATEFUL_CONFS[@]}; do + if [ -e "$STATEFUL_CONF" ] && [ ! -h "$STATEFUL_CONF" ]; then + echo "File $STATEFUL_CONF already exists, exiting!" >&2 + exit 1 + fi + + if [ -h "$STATEFUL_CONF" ]; then + $DRY_RUN_CMD rm "$STATEFUL_CONF" + fi + + STATEFUL_CONF_DIR="$STATEFUL_ROOT/$STATEFUL_CONF" + $DRY_RUN_CMD mkdir -p "$STATEFUL_CONF_DIR" + $DRY_RUN_CMD ln -s $VERBOSE_ARG "$STATEFUL_CONF_DIR" "$HOME/$STATEFUL_CONF" + done + ''; + }; +} diff --git a/home-modules/applications/emanote.nix b/home-modules/applications/emanote.nix new file mode 100644 index 0000000..f49c61c --- /dev/null +++ b/home-modules/applications/emanote.nix @@ -0,0 +1,17 @@ +{ + inputs, + ... +}: +{ + imports = [ + inputs.emanote.homeManagerModule + ]; + services.emanote = { + enable = true; + host = "127.0.0.1"; + port = 7000; + notes = [ + "/home/fhauser/cloud/Notes" + ]; + }; +} diff --git a/home-modules/applications/evolution.nix b/home-modules/applications/evolution.nix new file mode 100644 index 0000000..59de573 --- /dev/null +++ b/home-modules/applications/evolution.nix @@ -0,0 +1,4 @@ +{ ... }: +{ + dconf.settings."org/gnome/evolution-data-server/calendar".notify-enable-audio = false; +} diff --git a/home-modules/applications/firefox.nix b/home-modules/applications/firefox.nix new file mode 100644 index 0000000..bada23c --- /dev/null +++ b/home-modules/applications/firefox.nix @@ -0,0 +1,11 @@ +{ pkgs, ... }: +{ + programs.firefox = { + enable = true; + package = pkgs.firefox; + }; + home.sessionVariables = { + MOZ_ENABLE_WAYLAND = "true"; + MOZ_DBUS_REMOTE = "1"; + }; +} diff --git a/home-modules/applications/gammastep.nix b/home-modules/applications/gammastep.nix new file mode 100644 index 0000000..d28ee15 --- /dev/null +++ b/home-modules/applications/gammastep.nix @@ -0,0 +1,14 @@ +{ ... }: +{ + services.gammastep = { + enable = true; + settings.general.brightness-night = "0.9"; + + temperature.day = 6300; + temperature.night = 5500; + + latitude = "47.2"; + longitude = "8.8"; + tray = true; + }; +} diff --git a/home-modules/applications/git.nix b/home-modules/applications/git.nix new file mode 100644 index 0000000..912331c --- /dev/null +++ b/home-modules/applications/git.nix @@ -0,0 +1,104 @@ +{ pkgs, ... }: +{ + + home.packages = with pkgs; [ + git-absorb + git-trim + ]; + programs.git = { + enable = true; + package = pkgs.gitAndTools.gitFull; + aliases = { + s = "status --short --branch"; + a = "add --patch"; + c = "commit --message"; + l = "log --color --graph --pretty=format:'%Cred%h%Creset - %C(bold)%s%Creset%C(yellow)%d%Creset %C(green)%an%Creset %C(cyan)%cr%Creset (S: %G?)' --abbrev-commit"; + d = "diff"; + + fup = "commit --fixup"; + fuprebase = "rebase --interactive --autosquash"; + + ignore = "update-index --skip-worktree"; + unignore = "update-index --no-skip-worktree"; + ignored = ''!git ls-files -v | grep "^S"''; + }; + #delta = { + # enable = true; + # catppuccin.enable = true; + # options = { + # side-by-side = "true"; + + # line-numbers = "true"; + # line-numbers-minus-style = "#444444"; + # line-numbers-zero-style = "#444444"; + # line-numbers-plus-style = "#444444"; + # line-numbers-left-format = "{nm:>4}┊"; + # line-numbers-right-format = "{np:>4}│"; + # line-numbers-left-style = "blue"; + # line-numbers-right-style = "blue"; + # }; + #}; + extraConfig = { + init.defaultBranch = "main"; + core = { + packedGitWindowSize = "16m"; + packedGitLimit = "64m"; + }; + pack = { + windowMemory = "64m"; + packSizeLimit = "64m"; + thread = "1"; + deltaCacheSize = "1m"; + }; + color = { + branch = "auto"; + diff = "auto"; + status = "auto"; + }; + push = { + default = "current"; + autoSetupRemote = true; + }; + pull.rebase = "true"; + branch.autosetuprebase = "always"; + log.follow = true; + rerere.enabled = true; + fetch.recurseSubmodules = "on-demand"; + credential.helper = [ + "libsecret" + "cache --timeout 21600" + ]; + }; + ignores = [ + "*~" + "*.swp" + ".direnv/" + ]; + lfs.enable = true; + includes = + let + mkConfig = ( + dir: { + condition = "gitdir:${dir}"; + contents = { + user = { + signingkey = "0x8A52A140BEBF7D2C"; + email = "fabian@fh2.ch"; + name = "Fabian Hauser"; + }; + }; + } + ); + in + map mkConfig [ + "~/private/" + "~/projects/" + "/etc/nixos/" + "~/.password-store/" + "~/.stateful/" + "~/shares/cloud.qo.is/" + "~/shares/drive.switch.ch/" + ]; + }; + programs.git-credential-oauth.enable = true; +} diff --git a/home-modules/applications/gpg.nix b/home-modules/applications/gpg.nix new file mode 100644 index 0000000..d5f29c4 --- /dev/null +++ b/home-modules/applications/gpg.nix @@ -0,0 +1,86 @@ +{ + pkgs, + lib, + ... +}: +{ + #TODO: ENV variabls for agent + programs.gpg = { + enable = true; + package = pkgs.gnupg; + settings = { + "use-agent" = true; + "trust-model" = "tofu"; + "no-emit-version" = true; + "no-comments" = true; + "sig-notation" = "issuer-fpr@notations.openpgp.fifthhorseman.net=%g"; + "keyserver" = "hkps://keys.openpgp.org"; + "keyserver-options" = "auto-key-retrieve no-honor-keyserver-url"; + "personal-cipher-preferences" = "AES256 AES192 AES CAST5"; + "cert-digest-algo" = "SHA512"; + "personal-digest-preferences" = "SHA512 SHA384 SHA256 SHA224"; + "default-preference-list" = + "SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed"; + "display-charset" = "utf-8"; + "fixed-list-mode" = true; + "with-fingerprint" = true; + "keyid-format" = "0xlong"; + "verify-options" = "show-uid-validity"; + "list-options" = "show-uid-validity"; + }; + scdaemonSettings = { + disable-ccid = true; + }; + # TODO: Complete this list and maybe transfer to managed configuration? + #publicKeys = [ + # { source = "./fabian.hauser@qo.is.pub"; trust = 5; } + #]; + }; + services.gpg-agent = { + enable = true; + enableScDaemon = true; + enableSshSupport = true; + enableExtraSocket = true; + # TODO: pinentryPackage = + extraConfig = + let + pinentryBemenu = pkgs.writeShellApplication { + name = "pinentry-bemenu-with-env"; + text = '' + PATH="$PATH:${pkgs.coreutils}/bin:${pkgs.bemenu}/bin" + "${pkgs.pinentry-bemenu}/bin/pinentry-bemenu" "$@" + ''; + }; + in + '' + pinentry-program ${pinentryBemenu}/bin/pinentry-bemenu-with-env + ''; + sshKeys = [ + "638143D3F6421377E9D4C7F1D2EDC5AA0A860351" # 0x3E957C9C8CB5D6B2 / fabian.hauser@qo.is + ]; + }; + + systemd.user.sockets.yubikey-touch-detector = { + Unit.Description = "Unix socket activation for YubiKey touch detector service"; + Socket = { + ListenStream = "%t/yubikey-touch-detector.socket"; + RemoveOnStop = true; + }; + Install.WantedBy = [ "sockets.target" ]; + }; + + systemd.user.services.yubikey-touch-detector = { + Unit = { + Description = "Detects when your YubiKey is waiting for a touch"; + Requires = "yubikey-touch-detector.socket"; + }; + Service = { + ExecStart = "${lib.getExe pkgs.yubikey-touch-detector} --libnotify"; + EnvironmentFile = "-%E/yubikey-touch-detector/service.conf"; + }; + Install = { + Also = "yubikey-touch-detector.socket"; + WantedBy = [ "default.target" ]; + }; + }; +} diff --git a/home-modules/applications/kanshi.nix b/home-modules/applications/kanshi.nix new file mode 100644 index 0000000..2e525cf --- /dev/null +++ b/home-modules/applications/kanshi.nix @@ -0,0 +1,87 @@ +{ + pkgs, + lib, + ... +}: +{ + # systemd.user.services.kanshi.Install.WantedBy = "home-manager-fhauser.service"; # TODO: Upstream array type of systemdTarget + services.kanshi = { + enable = true; + settings = + let + mkScreen = display: position: { + inherit (display.output) criteria; + inherit position; + status = "enable"; + }; + mkProfile = name: outputs: { + profile = { + inherit name outputs; + exec = backgroundCommand; + }; + }; + # Can be applied by profile.exec + backgroundPicturePath = "~/shares/cloud.qo.is/pictures/backgrounds"; + backgroundCommand = '' + ${pkgs.sway}/bin/swaymsg "output * bg `find ${backgroundPicturePath} -type f | shuf -n 1` fill" + ''; + + screens = { + x1-screen.output = { + criteria = "California Institute of Technology 0x1404 Unknown"; + scale = null; + }; + tallinn-4k.output = { + criteria = "HP Inc. HP Z27 CN482201RP"; + scale = 1.2; + }; + chur-dell.output = { + criteria = "Dell Inc. DELL P2720DC 22JPK53"; + scale = null; + }; + chur-small.output = { + criteria = "Eizo Nanao Corporation EV2450 92395086"; + scale = null; + }; + tallinn-thinkvision.output = { + criteria = "Lenovo Group Limited LEN P24h-20 V307DA61"; + scale = null; + }; + tallinn-tv.output = { + criteria = "Samsung Electric Company SAMSUNG 0x01000E00"; + scale = 2.0; + }; + walrueti-buero.output = { + criteria = "Dell Inc. DELL U2719D 12DGV13"; + scale = null; + }; + }; + in + with lib; + (attrValues screens) + ++ (with screens; [ + (mkProfile "mobile-only" [ + (mkScreen x1-screen "0,0") + ]) + (mkProfile "desktop-oly" [ + (mkScreen tallinn-4k "0,0") + ]) + (mkProfile "home-dock" [ + (mkScreen x1-screen "0,120") + (mkScreen tallinn-4k "1920,0") + ]) + (mkProfile "saba-desk" [ + (mkScreen x1-screen "0,0") + (mkScreen tallinn-thinkvision "1920,0") + ]) + (mkProfile "tv" [ + ((mkScreen x1-screen "0,0") // { status = "disable"; }) + (mkScreen tallinn-tv "0,0") + ]) + (mkProfile "walrueti" [ + (mkScreen x1-screen "0,0") + (mkScreen walrueti-buero "1920,0") + ]) + ]); + }; +} diff --git a/home-modules/applications/kitty.nix b/home-modules/applications/kitty.nix new file mode 100644 index 0000000..917bc48 --- /dev/null +++ b/home-modules/applications/kitty.nix @@ -0,0 +1,8 @@ +{ ... }: +{ + programs.kitty = { + enable = true; + settings.term = "xterm"; + }; + catppuccin.kitty.enable = true; +} diff --git a/home-modules/applications/mako.nix b/home-modules/applications/mako.nix new file mode 100644 index 0000000..7a706bb --- /dev/null +++ b/home-modules/applications/mako.nix @@ -0,0 +1,16 @@ +{ ... }: +{ + services.mako = { + enable = true; + #backgroundColor = "#CCCCCCCC"; # TODO: Make layout colors in a central place + borderSize = 0; + #borderColor = "#4C7899FF"; + defaultTimeout = 1500; + #ignoreTimeout = true; + #textColor = "#FFFFFFFF"; + #width = 300; + #height = 100; + #font = "monospace 10"; + }; # TODO + catppuccin.mako.enable = true; +} diff --git a/home-modules/applications/mountain.jpg b/home-modules/applications/mountain.jpg new file mode 100644 index 0000000..f7fbf5a Binary files /dev/null and b/home-modules/applications/mountain.jpg differ diff --git a/home-modules/applications/psql.nix b/home-modules/applications/psql.nix new file mode 100644 index 0000000..9af5881 --- /dev/null +++ b/home-modules/applications/psql.nix @@ -0,0 +1,21 @@ +{ ... }: +{ + home.file.".psqlrc".text = '' + \set QUIET 1 + + \pset linestyle unicode + \pset border 2 + + \set null [null] + \set COMP_KEYWORD_CASE upper + \set ON_ERROR_ROLLBACK interactive + \set PROMPT1 '%[%033[1m%]%M/%/%R%[%033[0m%]%# ' + \set PROMPT2 '''' + \set VERBOSITY verbose + \timing + \x auto + + \unset QUIET + \conninfo + ''; +} diff --git a/home-modules/applications/scripts.nix b/home-modules/applications/scripts.nix new file mode 100644 index 0000000..6ac9e6d --- /dev/null +++ b/home-modules/applications/scripts.nix @@ -0,0 +1,66 @@ +{ pkgs, ... }: + +let + suspend = pkgs.writeScriptBin "suspend" '' + #!${pkgs.stdenv.shell} + ${pkgs.systemd}/bin/systemctl suspend + ''; + passbemenu = pkgs.writeScriptBin "passbemenu" '' + #!${pkgs.stdenv.shell} + shopt -s nullglob globstar + + typeit=0 + if [[ $1 == "--type" ]]; then + typeit=1 + shift + fi + + export BEMENU_BACKEND=wayland + + prefix=''${PASSWORD_STORE_DIR-~/.password-store} + password_files=( $(find -L "$prefix" -type f -name '*.gpg') ) + password_files=( "''${password_files[@]#"$prefix"/}" ) + password_files=( "''${password_files[@]%.gpg}" ) + + password=$(printf '%s\n' "''${password_files[@]}" | \ + ${pkgs.bemenu}/bin/bemenu --list 20 --ignorecase --prompt 'Pass: ' "$@") + + [[ -n $password ]] || exit + + password_value=$(${pkgs.pass-wayland}/bin/pass show "$password" | tail -1 2>/dev/null) + ${pkgs.wtype}/bin/wtype "''${password_value}" + ''; + bt-connect = pkgs.writeShellApplication { + name = "bt"; + meta.description = "Connect known Bluetooth device"; + runtimeInputs = [ pkgs.bluez ]; + text = '' + COMMAND="connect" + if [[ $1 == "--disconnect" ]]; then + COMMAND="disconnect" + shift + fi + + DEVICE=""; + + case "$1" in + headset) + DEVICE="88:C9:E8:7A:11:C2" + ;; + *) + echo "Unknown Device" >&2 + exit 1 + ;; + esac + + exec bluetoothctl $COMMAND $DEVICE + ''; + }; +in +{ + home.packages = [ + passbemenu + suspend + bt-connect + ]; +} diff --git a/home-modules/applications/shell.nix b/home-modules/applications/shell.nix new file mode 100644 index 0000000..24d11ea --- /dev/null +++ b/home-modules/applications/shell.nix @@ -0,0 +1,72 @@ +{ ... }: +{ + programs = { + bash = { + enable = true; + historyIgnore = [ + "ls" + "cd" + "exit" + "j" + ]; + shellAliases = { + # Sane defaults + l = "ls -lah"; + cp = "cp --reflink=auto"; + pwgen = "pwgen -c -n -s -N 30"; + bc = "bc --mathlib"; + cal = "cal -m"; + curl = "curl -L"; + ack = "rg"; + + # Git helpers + git-fetch-pr = "git config --add remote.origin.fetch '+refs/pull/*/head:refs/remotes/origin/pr/*'"; + git-config-fetchall = ''git config --add remote.origin.fetch "+refs/pull/*/head:refs/remotes/origin/pr/*"''; + + git-enable-signing = "git config commit.gpgsign true && git config tag.gpgsign true"; + # Common Typos + gits = "git s"; + }; + initExtra = '' + function o(){ + xdg-open "$*" >/dev/null 2>&1 & + } + ''; + shellOptions = [ + "autocd" + "checkjobs" + "dotglob" + "globstar" + "histappend" + ]; + sessionVariables = { + #TODO: Some of these should be migrated to the according application. + GPG_TTY = "$(tty)"; + PGDATABASE = "postgres"; + NIXOS_OZONE_WL = "1"; + }; + }; + + autojump = { + enable = true; + enableBashIntegration = true; + }; + powerline-go = { + enable = true; + settings = { + hostname-only-if-ssh = true; + numeric-exit-codes = true; + colorize-hostname = true; + cwd-max-depth = 4; + cwd-max-dir-size = 48; + cwd-mode = "semifancy"; + modules = "ssh,host,root,cwd,perms,dotenv,venv,nix-shell,git,jobs"; + }; + }; + direnv = { + enable = true; + enableBashIntegration = true; + nix-direnv.enable = true; + }; + }; +} diff --git a/home-modules/applications/ssh.nix b/home-modules/applications/ssh.nix new file mode 100644 index 0000000..786b40c --- /dev/null +++ b/home-modules/applications/ssh.nix @@ -0,0 +1,26 @@ +{ pkgs, ... }: +{ + programs.ssh = + let + forceIdentityPrivate = { + identityFile = toString ( + pkgs.writeText "fabian.hauser@qo.is.pub" '' + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIPF8ZV7vhpbVvLxiKq8ANVusNUHMbtii5MuvjxCbVz7vSNVPo9OOLvYyDqhbRAWMTdQeGZVAaALBufKKmprDTRFMpnA7Ut4TFrdz/5DTaR2KEjJ7P75moH+0xooR/GsbzFGsNBSQSXK3u1igndPYEC/PqCHN++32kDo2wLqTB4VLrEovU3iq8BMckn329Bu1fGbXKTgDpEvUEEwFO2brQZLMmzILGF/v4B9ImEGtinAUNgDSfEpgPN23sdWQH9rwEClGv95JmWNf05tuVomhZzOBtCFoAno3XB1nj16avjsqJ3aGFY2CCcfsNrwKzhIotmm82bcI4BJuJIVRIKbZ1 cardno:000610954665 + '' + ); + identitiesOnly = true; + }; + in + { + enable = true; + matchBlocks = { + "github.com" = forceIdentityPrivate // { + user = "git"; + }; + }; + extraConfig = '' + IdentityAgent /run/user/1000/gnupg/S.gpg-agent.ssh + ''; + #TODO: Authorized keys implementation, see https://github.com/nix-community/home-manager/pull/9 + }; +} diff --git a/home-modules/applications/sway.nix b/home-modules/applications/sway.nix new file mode 100644 index 0000000..78189ac --- /dev/null +++ b/home-modules/applications/sway.nix @@ -0,0 +1,171 @@ +{ + pkgs, + lib, + config, + ... +}: +let + adhereTheSwayTarget = { + Install.WantedBy = lib.mkForce [ "sway-session.target" ]; + Unit.PartOf = lib.mkForce [ "sway-session.target" ]; + }; + # TODO: active screen with -m $active_screen + bemenuLauncher = pkgs.writeScriptBin "bemenuLauncher" '' + #!${pkgs.stdenv.shell} + #active_screen=$(swaymsg -r -t get_outputs | \ + # ${pkgs.jq}/bin/jq '. [] | select (.focused == true) | .name | split ("-") | last') + ${pkgs.dmenu}/bin/dmenu_path | \ + ${pkgs.bemenu}/bin/bemenu --list 20 --ignorecase --prompt 'Start: ' | \ + xargs swaymsg exec -- + ''; +in +rec { + home.packages = with pkgs; [ + sway-contrib.grimshot + wl-clipboard + libappindicator + adwaita-icon-theme + gnome-icon-theme + hicolor-icon-theme # TODO: Move these requirements? + fuzzel # Required for rofimoji + ]; + + xsession.preferStatusNotifierItems = true; + + wayland.windowManager.sway = { + enable = true; + systemd.enable = true; + xwayland = true; + wrapperFeatures = { + gtk = true; + }; + extraSessionCommands = '' + #export XDG_CURRENT_DESKTOP=Unity + export XDG_CURRENT_DESKTOP=sway + export XDG_SESSION_TYPE="wayland" + export _JAVA_AWT_WM_NONREPARENTING=1 + export QT_QPA_PLATFORM=wayland + export QT_WAYLAND_DISABLE_WINDOWDECORATION="1" + # TODO: QTpie + export WLR_DRM_NO_MODIFIERS=1 + export WLR_NO_HARDWARE_CURSORS=1 + ''; + config = { + input = { + "type:keyboard" = { + xkb_layout = "ch,de"; + xkb_options = "eurosign:e"; + }; + "*" = { + xkb_numlock = "enable"; + }; + }; + terminal = "${pkgs.kitty}/bin/kitty"; + menu = "${bemenuLauncher}/bin/bemenuLauncher"; + gaps.inner = 8; + modifier = "Mod4"; + window.border = 0; + #colors.focused.border = "#323232"; + + #TODO: Workspace Programm assignment: Not working properly + assigns = { + "10" = [ { app_id = "^firefox$"; } ]; + "11" = [ { app_id = "^(claws-mail|thunderbird|evolution)$"; } ]; + "12" = [ + { + class = "^Chromium-browser$"; + instance = "^web.threema.ch"; + } + ]; + "13" = [ { class = "^Spotify$"; } ]; + }; + + keybindings = + let + mod = wayland.windowManager.sway.config.modifier; + playerctl = "${pkgs.playerctl}/bin/playerctl"; + wpctl = "${pkgs.wireplumber}/bin/wpctl"; + light = "${pkgs.light}/bin/light"; + in + lib.mkOptionDefault { + "${mod}+p" = "exec passbemenu"; + "${mod}+Shift+d" = "exec ${pkgs.rofimoji}/bin/rofimoji --action clipboard --selector fuzzel"; + "${mod}+x" = "move workspace to output right"; + "${mod}+y" = "move workspace to output left"; + + "${mod}+section" = "workspace 0"; + "${mod}+0" = "workspace 10"; + "${mod}+apostrophe" = "workspace 11"; + "${mod}+dead_circumflex" = "workspace 12"; + "${mod}+dead_diaeresis" = "workspace 13"; + "${mod}+dollar" = "workspace 14"; + + "${mod}+Shift+section" = "move container to workspace 0"; + "${mod}+Shift+0" = "move container to workspace 10"; + "${mod}+Shift+apostrophe" = "move container to workspace 11"; + "${mod}+Shift+dead_circumflex" = "move container to workspace 12"; + "${mod}+Shift+dead_diaeresis" = "move container to workspace 13"; + "${mod}+Shift+dollar" = "move container to workspace 14"; + + "Ctrl+mod1+l" = "exec ${pkgs.systemd}/bin/loginctl lock-session"; + "Ctrl+mod1+Shift+L" = "exec ${pkgs.systemd}/bin/systemctl suspend"; + + # pulse audio volume control + XF86AudioLowerVolume = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ 3%-"; + XF86AudioRaiseVolume = "exec ${wpctl} set-volume @DEFAULT_AUDIO_SINK@ 3%+"; + XF86AudioMute = "exec ${wpctl} set-mute @DEFAULT_AUDIO_SINK@ toggle"; + XF86AudioMicMute = "exec ${wpctl} set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; + + # Spotify control + XF86AudioPause = "exec ${playerctl} play-pause"; + XF86AudioPlay = "exec ${playerctl} play-pause"; + XF86AudioNext = "exec ${playerctl} next"; + XF86AudioPrev = "exec ${playerctl} previous"; + + # screen brightness + XF86MonBrightnessUp = "exec ${light} -A 10"; + XF86MonBrightnessDown = "exec ${light} -U 5"; + + # screenshot + Print = "exec ${pkgs.sway-contrib.grimshot}/bin/grimshot copy area"; + }; + }; + extraConfig = '' + # Disable the laptop screen when the lid is closed. + bindswitch --reload lid:on output eDP-1 disable + bindswitch --reload lid:off output eDP-1 enable + + # Workaround for https://bugs.chromium.org/p/chromium/issues/detail?id=1338554 + for_window [app_id="^chrome-.*-.*$"] shortcuts_inhibitor disable + + output "*" bg ${./mountain.jpg} fill + ''; + }; + catppuccin.sway.enable = true; + + systemd.user.services.network-manager-applet = adhereTheSwayTarget; + systemd.user.services.nextcloud-client = adhereTheSwayTarget // { + # For trayicon to work: + Unit.After = lib.mkForce [ "waybar.service" ]; + Service = { + ExecStartPre = "${pkgs.coreutils}/bin/sleep 3"; + Environment = lib.mkForce "PATH=${config.home.profileDirectory}/bin XDG_CURRENT_DESKTOP=Unity"; + }; + }; + systemd.user.services.pasystray = adhereTheSwayTarget; + + gtk = { + iconTheme = { + # package = pkgs.gnome-icon-theme; + # name = "gnome"; + package = pkgs.hicolor_icon_theme; + name = "hicolor"; + }; + gtk3.extraConfig.gtk-menu-images = true; + }; + catppuccin.gtk.enable = true; + + dconf.settings = { + "org/gnome/desktop/interface".menus-have-icons = true; + }; +} diff --git a/home-modules/applications/swaylock.nix b/home-modules/applications/swaylock.nix new file mode 100644 index 0000000..ef8b0f9 --- /dev/null +++ b/home-modules/applications/swaylock.nix @@ -0,0 +1,36 @@ +{ pkgs, ... }: +{ + systemd.user.services.swayidle = + let + lock = "${pkgs.swaylock}/bin/swaylock --hide-keyboard-layout --daemonize --show-failed-attempts --color=000000"; + logTimeCmd = "${pkgs.coreutils}/bin/date --rfc-3339=seconds >> ~/locklog"; + idleCmd = (action: ''${pkgs.sway}/bin/swaymsg "output * dpms ${action}" && ${logTimeCmd}''); + timeout-screens-off = 600; + timeout-lock = 630; + timeout-suspend = 1800; + in + { + Unit = { + Description = "Idle Manager for Wayland"; + Documentation = [ "man:swayidle(1)" ]; + PartOf = [ "graphical-session.target" ]; + }; + Service = { + Environment = "PATH=${pkgs.bash}/bin"; + ExecStart = '' + ${pkgs.swayidle}/bin/swayidle -w -d \ + timeout ${toString timeout-lock} '${lock}' \ + timeout ${toString timeout-screens-off} '${idleCmd "off"}' \ + resume '${idleCmd "on"}' \ + timeout ${toString timeout-suspend} '${pkgs.systemd}/bin/systemctl suspend' \ + lock '${lock}' \ + before-sleep '${lock}'; + ''; # TODO: Make this configurable and add home-manager module. (Requires sway with systemd-target support) + }; + Install = { + WantedBy = [ "sway-session.target" ]; + }; + }; + + catppuccin.swaylock.enable = true; +} diff --git a/home-modules/applications/vim.nix b/home-modules/applications/vim.nix new file mode 100644 index 0000000..d8e7533 --- /dev/null +++ b/home-modules/applications/vim.nix @@ -0,0 +1,58 @@ +{ pkgs, ... }: +{ + programs.neovim = { + enable = true; + defaultEditor = true; + viAlias = true; + vimAlias = true; + vimdiffAlias = true; + extraConfig = '' + " colorscheme elflord + set autoindent + set ruler + set pastetoggle= + set splitbelow + set splitright + set mouse= + set hidden + set expandtab + + set tabstop=2 + set softtabstop=2 + + set listchars="eol:¬,tab:>·,trail:~,extends:>,precedes:<,space:␣" + set grepprg=ack\ -k + + set statusline+=%{SyntasticStatuslineFlag()} + set statusline+=%* + + let g:syntastic_always_populate_loc_list = 1 + let g:syntastic_auto_loc_list = 1 + let g:syntastic_check_on_open = 1 + let g:syntastic_check_on_wq = 0 + let g:syntastic_mode_map = { 'mode': 'passive', 'active_filetypes': [],'passive_filetypes': [] } + "nnoremap E :SyntasticCheck :SyntasticToggleMode + + " Rust + "let g:rustfmt_autosave = 1 + let g:racer_cmd="~/.cargo/bin/racer" + "let g:racer_experimental_completer = 1 + au FileType rust nmap gd (rust-def) + au FileType rust nmap gs (rust-def-split) + au FileType rust nmap gx (rust-def-vertical) + au FileType rust nmap gd (rust-doc) + + " Typescript + au BufRead,BufNewFile *.ts setfiletype typescript + + " Options + filetype plugin indent on + syntax on + ''; + plugins = with pkgs.vimPlugins; [ + vim-sensible + vim-airline + ]; + }; + catppuccin.nvim.enable = true; +} diff --git a/home-modules/applications/waybar.nix b/home-modules/applications/waybar.nix new file mode 100644 index 0000000..f3e9694 --- /dev/null +++ b/home-modules/applications/waybar.nix @@ -0,0 +1,348 @@ +{ + config, + ... +}: +{ + xsession.preferStatusNotifierItems = true; + wayland.windowManager.sway.config.bars = [ ]; + + programs.waybar = { + enable = true; + systemd = { + enable = true; + target = "tray.target"; + }; + settings = [ + { + position = "top"; + #height = + modules-left = [ + "sway/mode" + "sway/workspaces" + ]; + modules-center = [ "sway/window" ]; + modules-right = [ + "idle_inhibitor" + "backlight" + "battery" + "pulseaudio" + "tray" + "clock" + ]; + backlight.format = " {percent}%"; + disk.format = " {percentage_used}%"; + clock.format = "{:%Y-%m-%d %H:%M}"; + "sway/workspaces" = { + disable-scroll-wraparound = true; + enable-bar-scroll = true; + numeric-first = true; + }; + + battery = { + interval = 60; + states = { + warning = 15; + critical = 10; + }; + format = " {capacity}% {time}"; # Icon: bolt + format-discharging = "{icon} {capacity}% {time}"; + format-time = "{H}:{M}"; + format-icons = [ + "" # Icon: battery-full + "" # Icon: battery-three-quarters + "" # Icon: battery-half + "" # Icon: battery-quarter + "" # Icon: battery-empty + ]; + tooltip = "true"; + }; + + cpu = { + interval = "5"; + format = " {usage}% ({load})"; # Icon: microchip + states = { + warning = "70"; + critical = "90"; + }; + }; + + memory = { + interval = "5"; + format = " {}%"; # Icon: microchip + states = { + warning = "70"; + critical = "90"; + }; + }; + + "sway/mode" = { + format = '' {}''; # Icon: expand-arrows-alt + tooltip = "false"; + }; + + "sway/window" = { + format = "{}"; + max-length = "120"; + }; + + "sway/workspaces" = { + all-outputs = false; + disable-scroll = true; + format = "{icon}"; + format-icons = { + "10" = " 10"; + "11" = " 11"; + "12" = " 12"; + "13" = " 13"; + }; + }; + + pulseaudio = { + scroll-step = 3; + format = "{icon} {volume}%"; + format-bluetooth = "{icon} {volume}%"; + format-muted = "🔇"; + format-icons = { + headphones = ""; + handsfree = ""; + headset = ""; + phone = ""; + portable = ""; + car = ""; + default = [ + "" + "" + "" + ]; + }; + on-click = "pavucontrol"; + }; + + idle_inhibitor = { + format = "{icon}"; + format-icons = { + activated = " active"; + deactivated = ""; + }; + }; + + tray = { + icon-size = "21"; + spacing = "10"; + }; + } + ]; + + style = '' + /* ============================================================================= + * + * Waybar configuration + * + * Configuration reference: https://github.com/Alexays/Waybar/wiki/Configuration + * + * =========================================================================== */ + + /* ----------------------------------------------------------------------------- + * Keyframes + * -------------------------------------------------------------------------- */ + + @keyframes blink-warning { + 70% { + color: white; + } + + to { + color: white; + background-color: orange; + } + } + + @keyframes blink-critical { + 70% { + color: white; + } + + to { + color: white; + background-color: red; + } + } + + + /* ----------------------------------------------------------------------------- + * Base styles + * -------------------------------------------------------------------------- */ + + /* Reset all styles */ + * { + border: none; + border-radius: 0; + min-height: 0; + margin: 0; + padding: 0; + } + + /* The whole bar */ + #waybar { + background: #323232; + color: white; + /*font-family: Cantarell, Noto Sans, sans-serif;*/ + font-size: 13px; + } + + /* Each module */ + #battery, + #clock, + #cpu, + #custom-keyboard-layout, + #memory, + #mode, + #network, + #pulseaudio, + #temperature, + #backlight, + #idle_inhibitor, + #tray { + margin-left: 5px; + margin-right: 5px; + padding-left: 5px; + padding-right: 5px; + /*border-right: solid 1px black;*/ + } + + #backlight { + margin-right: 0; + padding-right: 0; + } + + #idle_inhibiter { + margin-left: 0; + padding-left: 0; + } + + + /* ----------------------------------------------------------------------------- + * Module styles + * -------------------------------------------------------------------------- */ + + #battery { + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; + } + + #battery.warning { + color: orange; + } + + #battery.critical { + color: red; + } + + #battery.warning.discharging { + animation-name: blink-warning; + animation-duration: 4s; + } + + #battery.critical.discharging { + animation-name: blink-critical; + animation-duration: 3s; + } + + #clock { + font-weight: bold; + } + + #cpu { + /* No styles */ + } + + #cpu.warning { + color: orange; + } + + #cpu.critical { + color: red; + } + + #memory { + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; + } + + #memory.warning { + color: orange; + } + + #memory.critical { + color: red; + animation-name: blink-critical; + animation-duration: 2s; + } + + #mode { + background: #64727D; + border-top: 2px solid white; + /* To compensate for the top border and still have vertical centering */ + padding-bottom: 2px; + } + + #network { + /* No styles */ + } + + #network.disconnected { + color: orange; + } + + #pulseaudio { + /* No styles */ + } + + #pulseaudio.muted { + /* No styles */ + } + + #custom-spotify { + color: rgb(102, 220, 105); + } + + #temperature { + /* No styles */ + } + + #temperature.critical { + color: red; + } + + #tray { + /* No styles */ + } + + #window { + font-weight: bold; + } + + #workspaces button { + border-top: 2px solid transparent; + /* To compensate for the top border and still have vertical centering */ + padding-bottom: 2px; + padding-left: 10px; + padding-right: 10px; + color: #888888; + } + + #workspaces button.focused { + border-color: #4c7899; + color: white; + background-color: #285577; + } + + #workspaces button.urgent { + border-color: #c9545d; + color: #c9545d; + } + ''; + }; +} diff --git a/home-modules/applications/webapps.nix b/home-modules/applications/webapps.nix new file mode 100644 index 0000000..75bbba7 --- /dev/null +++ b/home-modules/applications/webapps.nix @@ -0,0 +1,18 @@ +{ pkgs, ... }: + +let + web-app = + name: url: + pkgs.writeScriptBin name '' + #!${pkgs.stdenv.shell} + exec ${pkgs.chromium}/bin/chromium --user-data-dir=$HOME/.config/chromium-app-${name} --app="${url}" + ''; + whatsapp = web-app "whatsapp" "https://web.whatsapp.com/"; + threema = web-app "threema" "https://web-beta.threema.ch/"; +in +{ + home.packages = [ + whatsapp + threema + ]; +} diff --git a/home-modules/applications/zed-editor.nix b/home-modules/applications/zed-editor.nix new file mode 100644 index 0000000..db64280 --- /dev/null +++ b/home-modules/applications/zed-editor.nix @@ -0,0 +1,53 @@ +{ pkgs, ... }: +{ + programs.zed-editor = { + enable = true; + extensions = [ + "nix" + "cspell" + "latex" + "sql" + "toml" + "plantuml" + + "helm" + + "html" + "svelte" + + "java" + "kotlin" + + ]; + extraPackages = with pkgs; [ + nixd + nodePackages.cspell + direnv + ]; + userSettings = { + assistant = { + default_model = { + provider = "openai"; + model = "o1-mini"; + }; + version = "2"; + }; + vim_mode = false; + ui_font_size = 16; + buffer_font_size = 16; + theme = { + mode = "system"; + light = "Andromeda"; + dark = "One Dark"; + }; + telemetry = { + diagnostics = false; + metrics = false; + }; + languages = { + Markdown.remove_trailing_whitespace_on_save = false; + Markdown-Inline.remove_trailing_whitespace_on_save = false; + }; + }; + }; +} diff --git a/home-modules/default.nix b/home-modules/default.nix new file mode 100644 index 0000000..70ea541 --- /dev/null +++ b/home-modules/default.nix @@ -0,0 +1,16 @@ +{ + ... +}: +{ + imports = [ + ./applications + ./theme + ./multimedia.nix + ./mimetypes.nix + ]; + + systemd.user.targets.tray.Unit = { + Description = "Home Manager System Tray"; + Requires = [ "graphical-session-pre.target" ]; + }; +} diff --git a/home-modules/mimetypes.nix b/home-modules/mimetypes.nix new file mode 100644 index 0000000..8828ac0 --- /dev/null +++ b/home-modules/mimetypes.nix @@ -0,0 +1,69 @@ +{ + ... +}: +{ + + xdg.mimeApps = rec { + enable = true; + associations.added = defaultApplications; + defaultApplications = + let + browser = [ "firefox.desktop" ]; + email = [ "org.gnome.Evolution.desktop" ]; + doc-editor = [ "writer.desktop" ]; + sheet-editor = [ "calc.desktop" ]; + presentation-editor = [ "impress.desktop" ]; + pdf = [ "org.gnome.Evince.desktop" ]; + image = [ + "org.gnome.Loupe.desktop" + "gimp.desktop" + ]; + image-vector = [ "org.inkscape.Inkscape.desktop" ]; + ebooks = [ "calibre-ebook-viewer.desktop" ]; + code-general = [ "codium.desktop" ]; + video = [ "mpv.desktop" ]; + compression = [ "org.gnome.Nautilus.desktop" ]; + in + { + "text/html" = browser; + "x-scheme-handler/http" = browser; + "x-scheme-handler/https" = browser; + "x-scheme-handler/chrome" = browser; + "application/xhtml+xml" = browser; + "application/x-extension-htm" = browser; + "application/x-extension-html" = browser; + "application/x-extension-shtml" = browser; + "application/x-extension-xhtml" = browser; + "application/x-extension-xht" = browser; + "x-scheme-handler/mailto" = email; + "text/calendar" = email; + + "application/vnd.oasis.opendocument.text" = doc-editor; + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" = doc-editor; + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" = sheet-editor; + "application/vnd.openxmlformats-officedocument.presentationml.presentation" = presentation-editor; + "application/vnd.oasis.opendocument.presentation" = presentation-editor; + "application/pdf" = pdf; + "application/x-extension-pdf" = pdf; + "application/epub+zip" = ebooks; + + "text/plain" = code-general; + "application/json" = code-general; + "text/markdown" = code-general; + + "image/png" = image; + "image/jpg" = image; + "image/jpeg" = image; + "image/x-tga" = image; + "image/tiff" = image; + "image/x-canon-cr2" = image; + "application/x-ptoptimizer-script" = [ "hugin.desktop" ]; + "image/svg+xml" = image-vector; + + "video/mp4" = video; + "video/x-matroska" = video; + + "application/zip" = compression; + }; + }; +} diff --git a/home-modules/multimedia.nix b/home-modules/multimedia.nix new file mode 100644 index 0000000..edf52a3 --- /dev/null +++ b/home-modules/multimedia.nix @@ -0,0 +1,70 @@ +{ + config, + pkgs, + ... +}: + +{ + + programs.mpv = { + enable = true; + config = { + hwdec = "auto-safe"; + vo = "gpu"; + gpu-context = "wayland"; + force-window = true; + profile = "gpu-hq"; + }; + scripts = [ pkgs.mpvScripts.mpris ]; + }; + home.packages = + with pkgs; + [ + v4l-utils + playerctl + yt-dlp + ] + ++ [ + # Audio + gnome-sound-recorder + enblend-enfuse + ffmpeg + #sox mencoder + vorbis-tools + vorbisgain + opusTools + flac + lame + id3lib + id3v2 # icedax + pasystray + pavucontrol + spotify + ] + ++ [ + # Imaging + gimp + hugin + lensfun + darktable + inkscape + ghostscript + ] + ++ [ + # Codecs for Audio and Video + libdv + libdvbpsi # librtmp + xvidcore + x264 + ] + ++ (with gst_all_1; [ + gstreamer + gst-vaapi + gst-rtsp-server + gst-libav + gst-plugins-base + gst-plugins-bad + gst-plugins-good + gst-plugins-ugly + ]); +} diff --git a/home-modules/theme/default.nix b/home-modules/theme/default.nix new file mode 100644 index 0000000..3e86482 --- /dev/null +++ b/home-modules/theme/default.nix @@ -0,0 +1,9 @@ +{ + inputs, + ... +}: +{ + imports = [ + inputs.catppuccin.homeManagerModules.catppuccin + ]; +} diff --git a/nixos-configurations/ochsenchopf/default.nix b/nixos-configurations/ochsenchopf/default.nix new file mode 100644 index 0000000..5f10e7c --- /dev/null +++ b/nixos-configurations/ochsenchopf/default.nix @@ -0,0 +1,38 @@ +{ ... }: +{ + + imports = [ + ./filesystems.nix + ./networking.nix + + # TODO: Hardware + + ]; + + nixpkgs.hostPlatform = "x86_64-linux"; + + virtualisation = { + # TODO: This should probably be somewhere else. + docker = { + enable = true; + enableOnBoot = false; + }; + libvirtd.enable = true; + spiceUSBRedirection.enable = true; + }; + users.extraUsers.fhauser.extraGroups = [ "libvirtd" ]; + + boot.extraModprobeConfig = '' + options kvm_intel nested=1 + options kvm_intel emulate_invalid_guest_state=0 + options kvm ignore_msrs=1 + ''; + + # This value determines the NixOS release from which the default + # settings for stateful data, like fi:le locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "24.05"; # Did you read the comment? +} diff --git a/nixos-configurations/ochsenchopf/filesystems.nix b/nixos-configurations/ochsenchopf/filesystems.nix new file mode 100644 index 0000000..7eff1f8 --- /dev/null +++ b/nixos-configurations/ochsenchopf/filesystems.nix @@ -0,0 +1,43 @@ +{ + lib, + ... +}: +{ + + boot.initrd.luks.devices = { + "luks".device = "/dev/disk/by-label/luks"; + }; + + fileSystems = + let + rootdev = "/dev/disk/by-label/hv_ochsenchopf"; + in + { + "/" = { + device = rootdev; + fsType = "btrfs"; + options = [ "subvol=nixos" ]; + }; + "/home" = { + device = rootdev; + fsType = "btrfs"; + options = [ "subvol=home" ]; + }; + "/boot" = { + device = "/dev/disk/by-label/boot"; + fsType = "vfat"; + }; + }; + + swapDevices = [ { device = "/dev/disk/by-label/swap"; } ]; + + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = lib.mkForce false; + boot.loader.efi.canTouchEfiVariables = true; + + boot.initrd.systemd.enable = true; + boot.lanzaboote = { + enable = true; + pkiBundle = "/etc/secureboot"; + }; +} diff --git a/nixos-configurations/ochsenchopf/networking.nix b/nixos-configurations/ochsenchopf/networking.nix new file mode 100644 index 0000000..07fb8b7 --- /dev/null +++ b/nixos-configurations/ochsenchopf/networking.nix @@ -0,0 +1,26 @@ +{ ... }: + +{ + networking = { + networkmanager = { + enable = true; + # Does currently not work... + #enableFccUnlock = true; + }; + useDHCP = false; + }; + + services.tailscale = { + enable = true; + openFirewall = true; + useRoutingFeatures = "client"; + authKeyFile = "/secrets/wireguard/tailscale-key"; + extraUpFlags = [ + "--operator" + "fhauser" + "--accept-routes" + "--exit-node=100.64.0.6" + "--login-server=https://vpn.qo.is" + ]; + }; +} diff --git a/nixos-configurations/speer/default.nix b/nixos-configurations/speer/default.nix new file mode 100644 index 0000000..5fff9fa --- /dev/null +++ b/nixos-configurations/speer/default.nix @@ -0,0 +1,40 @@ +{ ... }: +{ + + imports = [ + ./filesystems.nix + ./networking.nix + ./disko-config.nix + + # TODO: Hardware + ]; + + nixpkgs.hostPlatform = "x86_64-linux"; + + virtualisation = { + # TODO: This should probably be somewhere else. + docker = { + enable = true; + enableOnBoot = false; + }; + libvirtd.enable = true; + spiceUSBRedirection.enable = true; + }; + + boot.extraModprobeConfig = '' + options kvm_intel nested=1 + options kvm_intel emulate_invalid_guest_state=0 + options kvm ignore_msrs=1 + ''; + + # Set your time zone. + time.timeZone = "Europe/Tallinn"; + + # This value determines the NixOS release from which the default + # settings for stateful data, like fi:le locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "24.11"; # Did you read the comment? +} diff --git a/nixos-configurations/speer/disko-config.nix b/nixos-configurations/speer/disko-config.nix new file mode 100644 index 0000000..e956450 --- /dev/null +++ b/nixos-configurations/speer/disko-config.nix @@ -0,0 +1,98 @@ +{ ... }: +{ + disko.devices = { + disk = rec { + system-1 = { + type = "disk"; + device = "/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NX0W821176E"; + content = { + type = "gpt"; + partitions = { + boot = { + size = "1G"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + }; + raid_system = { + start = "30G"; + size = "100%"; + content = { + type = "mdraid"; + name = "raid_system"; + }; + }; + }; + }; + }; + #system-2 = { + # type = "disk"; + # device = "/dev/disk/by-id/nvme-XXXXX"; + # content = pkgs.lib.recursiveUpdate system-1.content { + # partitions.boot.content.mountpoint = "/boot-secondary"; + # }; + #}; + }; + + mdadm = { + "raid_system" = { + type = "mdadm"; + level = 1; + content = { + type = "luks"; + name = "crypted_system"; + passwordFile = "/run/secrets/system/hdd.key"; + settings = { + allowDiscards = true; + bypassWorkqueues = true; + }; + content = { + type = "lvm_pv"; + vg = "vg_system"; + }; + }; + }; + }; + lvm_vg = { + vg_system = { + type = "lvm_vg"; + lvs = { + swap = { + size = "32G"; + content = { + type = "swap"; + resumeDevice = true; + }; + }; + data = { + size = "1000GB"; + content = { + type = "btrfs"; + mountOptions = [ + "defaults" + "noatime" + ]; + subvolumes."/home".mountpoint = "/home"; + }; + }; + hv_speer = { + size = "200GiB"; + content = { + type = "btrfs"; + mountOptions = [ + "defaults" + "noatime" + ]; + subvolumes = { + "/root".mountpoint = "/"; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/nixos-configurations/speer/filesystems.nix b/nixos-configurations/speer/filesystems.nix new file mode 100644 index 0000000..d6db5af --- /dev/null +++ b/nixos-configurations/speer/filesystems.nix @@ -0,0 +1,22 @@ +{ + config, + pkgs, + lib, + ... +}: +{ + # Configurations are set in disko-config.nix! + + # mdadm.conf generated by `mdadm --detail --scan` + # TODO + boot.swraid.enable = true; + boot.swraid.mdadmConf = '' + MAILADDR root + ''; + + services.fwupd.daemonSettings.EspLocation = pkgs.lib.mkForce config.disko.devices.disk.system-1.content.partitions.boot.content.mountpoint; + + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; +} diff --git a/nixos-configurations/speer/networking.nix b/nixos-configurations/speer/networking.nix new file mode 100644 index 0000000..9ec98da --- /dev/null +++ b/nixos-configurations/speer/networking.nix @@ -0,0 +1,22 @@ +{ ... }: +{ + networking = { + networkmanager.enable = true; + useDHCP = false; + + }; + + services.tailscale = { + enable = true; + openFirewall = true; + useRoutingFeatures = "client"; + authKeyFile = "/secrets/wireguard/tailscale-key"; + extraUpFlags = [ + "--operator" + "fhauser" + "--accept-routes" + "--exit-node=100.64.0.6" + "--login-server=https://vpn.qo.is" + ]; + }; +} diff --git a/nixos-modules/base-system/default.nix b/nixos-modules/base-system/default.nix new file mode 100644 index 0000000..93137bb --- /dev/null +++ b/nixos-modules/base-system/default.nix @@ -0,0 +1,4 @@ +{ inputs, ... }: +{ + imports = [ inputs.lanzaboote.nixosModules.lanzaboote ]; +} diff --git a/nixos-modules/base/applications.nix b/nixos-modules/base/applications.nix new file mode 100644 index 0000000..ca2cff7 --- /dev/null +++ b/nixos-modules/base/applications.nix @@ -0,0 +1,87 @@ +{ + pkgs, + ... +}: + +{ + environment.systemPackages = + with pkgs; + [ + tmux + pciutils + dmidecode + smartmontools + borgbackup + iw + killall + bc + efibootmgr + efitools + efivar + mkpasswd + rename + wipe + gnupg + pass-wayland + pwgen + powertop + lm_sensors + sbctl + ] + ++ [ + nixfmt-rfc-style + nix-index + nix-diff + nixpkgs-review + nixos-option + ] + ++ [ + autojump + powerline-go + ] + ++ [ + # File Utilities + ripgrep + unzip + p7zip + unrar + iotop + cabextract + tree + vim + vimPlugins.pathogen + vimPlugins.airline + git + git-lfs + ] + ++ [ + # Filesystem & Disk Utilities + exfat + samba + cifs-utils + keyutils # required for cifs kerberos auth + sshfs-fuse + hdparm + mtpfs + ntfs3g + smartmontools + parted + usbutils + ] + ++ [ + # Networking Utilities + nmap + bind + curl + wget + tor + whois + wol + rsync + sshuttle + iftop + mailutils + imapsync + bluez-tools + ]; +} diff --git a/nixos-modules/base/default.nix b/nixos-modules/base/default.nix new file mode 100644 index 0000000..c25126f --- /dev/null +++ b/nixos-modules/base/default.nix @@ -0,0 +1,112 @@ +{ + lib, + pkgs, + inputs, + ... +}: + +let + users = { + fhauser = { + uid = 1000; + isNormalUser = true; + description = "Fabian Hauser"; + group = "fhauser"; + extraGroups = [ + "wheel" + "video" + "docker" + "networkmanager" + "libvirtd" + "adbusers" + ]; + openssh.authorizedKeys.keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIPF8ZV7vhpbVvLxiKq8ANVusNUHMbtii5MuvjxCbVz7vSNVPo9OOLvYyDqhbRAWMTdQeGZVAaALBufKKmprDTRFMpnA7Ut4TFrdz/5DTaR2KEjJ7P75moH+0xooR/GsbzFGsNBSQSXK3u1igndPYEC/PqCHN++32kDo2wLqTB4VLrEovU3iq8BMckn329Bu1fGbXKTgDpEvUEEwFO2brQZLMmzILGF/v4B9ImEGtinAUNgDSfEpgPN23sdWQH9rwEClGv95JmWNf05tuVomhZzOBtCFoAno3XB1nj16avjsqJ3aGFY2CCcfsNrwKzhIotmm82bcI4BJuJIVRIKbZ1 cardno:000603507108" + ]; + }; + }; +in +{ + imports = [ + inputs.private.nixosModules.users # Contains hashedPasswords for users. + ./unfree.nix + ./applications.nix + ]; + + boot.loader.timeout = 2; + boot.tmp.useTmpfs = true; + boot.kernelPackages = pkgs.linuxPackages_latest; + boot.bootspec.enable = true; + + catppuccin = { + flavor = "mocha"; + tty.enable = true; + }; + + console.keyMap = "de_CH-latin1"; + i18n.defaultLocale = "en_US.UTF-8"; + + users.mutableUsers = false; + users.groups = { + fhauser.gid = 1000; + }; + users.users = users // { + root.openssh.authorizedKeys.keys = + with lib; + concatLists ( + mapAttrsToList ( + _name: user: if elem "wheel" user.extraGroups then user.openssh.authorizedKeys.keys else [ ] + ) users + ); + }; + + # Package management + nix = { + settings.trusted-users = [ + "root" + "@wheel" + ]; + optimise.automatic = true; + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 60d"; + }; + package = pkgs.nixVersions.stable; + extraOptions = '' + experimental-features = nix-command flakes + ''; + }; + + # System Services + services.btrfs.autoScrub.enable = true; + services.fwupd.enable = true; + + # Network services + networking.networkmanager.enable = true; + networking.firewall = { + allowPing = true; + allowedTCPPorts = [ 22 ]; + }; + systemd.services.NetworkManager-wait-online.enable = false; + + services.openssh = { + enable = true; + settings.PasswordAuthentication = false; + }; + + # Default Settings + environment.etc = { + gitconfig.source = ./etc/gitconfig; + vimrc.source = ./etc/vimrc; + }; + + programs.autojump.enable = true; + programs.vim = { + enable = true; + defaultEditor = true; + }; + environment.systemPackages = [ pkgs.comma ]; + + services.dbus.implementation = "broker"; +} diff --git a/nixos-modules/base/etc/gitconfig b/nixos-modules/base/etc/gitconfig new file mode 100644 index 0000000..1971e05 --- /dev/null +++ b/nixos-modules/base/etc/gitconfig @@ -0,0 +1,31 @@ +[core] + packedGitWindowSize = 16m + packedGitLimit = 64m +[pack] + windowMemory = 64m + packSizeLimit = 64m + thread = 1 + deltaCacheSize = 1m +[color] + branch = auto + diff = auto + status = auto +[push] + default = simple +[pull] + rebase = true +[branch] + autosetuprebase = always +[commit] +# gpgsign = true +[tag] +# gpgsign = true + +[alias] + s = status --short --branch + a = add --patch + c = commit --message + l = log --color --graph --pretty=format:'%Cred%h%Creset - %C(bold)%s%Creset%C(yellow)%d%Creset %C(green)%an%Creset %C(cyan)%cr%Creset' --abbrev-commit + d = diff +[diff] +# noprefix = true diff --git a/nixos-modules/base/etc/vimrc b/nixos-modules/base/etc/vimrc new file mode 100644 index 0000000..fc66567 --- /dev/null +++ b/nixos-modules/base/etc/vimrc @@ -0,0 +1,54 @@ + +" Use Vim settings, rather than Vi settings (much better!). +" This must be first, because it changes other options as a side effect. +" Avoid side effects when it was already reset. +if &compatible + set nocompatible +endif + +" Convenient command to see the difference between the current buffer and the +" file it was loaded from, thus the changes you made. +" Only define it when not defined already. +" Revert with: ":delcommand DiffOrig". +if !exists(":DiffOrig") + command DiffOrig vert new | set bt=nofile | r ++edit # | 0d_ | diffthis + \ | wincmd p | diffthis +endif + +" Don't wake up system with blinking cursor: +" http://www.linuxpowertop.org/known.php +let &guicursor = &guicursor . ",a:blinkon0" + + + + +"""""""""""""""""""""""""" +" Design Settings +"""""""""""""""""""""""""" +set background=dark +colorscheme elflord + +"""""""""""""""""""""""""" +" Other Settings +"""""""""""""""""""""""""" +set ignorecase " Ignore search case +set autoindent " Newline with automatic text indent +set ruler " Show current position +set pastetoggle= +set ignorecase +set hidden + +set splitbelow +set splitright + +set tabstop=2 +set shiftwidth=2 +set softtabstop=2 +set expandtab + +set listchars="eol:¬,tab:>·,trail:~,extends:>,precedes:<,space:␣" +set grepprg=ack\ -k + +filetype plugin indent on +syntax on + diff --git a/nixos-modules/base/unfree.nix b/nixos-modules/base/unfree.nix new file mode 100644 index 0000000..ca8c69f --- /dev/null +++ b/nixos-modules/base/unfree.nix @@ -0,0 +1,56 @@ +{ + config, + lib, + ... +}: + +{ + nixpkgs.config.allowUnfreePredicate = + pkg: + builtins.elem (lib.getName pkg) [ + "unrar" + + "steam" + "steam-run" + "steam-original" + "steam-unwrapped" + + "hplip" + + "google-chrome" + "spotify" + "spotify-unwrapped" + "discord" + "teamviewer" + "todoist-electron" + "todoist-electron-8.10.1" + "obsidian" + + "davinci-resolve" + "davinci-resolve-18.6.3" + + "lightworks" + "lightworks-2023.1" + "nvidia-cg-toolkit-3.1" + "nvidia-cg-toolkit" + + "corefonts" + "camingo-code" + "helvetica-neue-lt-std" + #"kochi-substitute-naga10" + "ttf-envy-code-r" + "vista-fonts" + "vista-fonts-chs" + "xkcd-font-unstable" + "xkcd-font" + "xkcd-font-unstable-2017-08-24" + "ricty" + + "pycharm-professional" + "idea-ultimate" + "android-studio-stable" + "android-studio-beta" + + "vmware-view" + ]; +} diff --git a/nixos-modules/default.nix b/nixos-modules/default.nix new file mode 100644 index 0000000..2ea5b5e --- /dev/null +++ b/nixos-modules/default.nix @@ -0,0 +1,14 @@ +{ ... }: +{ + + imports = [ + ./base + ./base-system + ./desktop + ./filesystems + #./hardware #TODO + ./home-manager + ./printing + ./theme + ]; +} diff --git a/nixos-modules/desktop/default.nix b/nixos-modules/desktop/default.nix new file mode 100644 index 0000000..cd2c88a --- /dev/null +++ b/nixos-modules/desktop/default.nix @@ -0,0 +1,15 @@ +{ + ... +}: +{ + + imports = [ + ./desktop-environment.nix + ./greeter.nix + ./hardware.nix + ./office-suite.nix + ./security.nix + ./video.nix + ./llm.nix + ]; +} diff --git a/nixos-modules/desktop/desktop-environment.nix b/nixos-modules/desktop/desktop-environment.nix new file mode 100644 index 0000000..c83c023 --- /dev/null +++ b/nixos-modules/desktop/desktop-environment.nix @@ -0,0 +1,81 @@ +{ + pkgs, + lib, + ... +}: +let + mkDefault = lib.mkDefault; +in +{ + + environment.systemPackages = with pkgs; [ + freetype + lxappearance + sound-theme-freedesktop + + qt5.qtwayland # Required for qt applications + ]; + environment.sessionVariables.NIXOS_OZONE_WL = "1"; + environment.sessionVariables.DO_NOT_TRACK = "1"; + + programs = { + gnome-terminal.enable = false; + evolution = { + enable = true; + #plugins = [ pkgs.evolution-ews ]; + }; + geary.enable = false; + light.enable = true; + + dconf.enable = true; + + sway.enable = true; + }; + + services.gnome = { + # TODO: Do this manually and not all at once. + core-utilities.enable = true; + core-os-services.enable = false; + + gnome-keyring.enable = true; + evolution-data-server.enable = true; + gnome-online-accounts.enable = true; + gnome-remote-desktop.enable = true; + sushi.enable = false; + }; + + ########## + # gnome.core-os-services excerpt + + security.polkit.enable = true; + services.power-profiles-daemon.enable = false; # TODO: Remove + + # Explicitly enabled since GNOME will be severely broken without these. + xdg.mime.enable = true; + xdg.icons.enable = true; + + # Harmonize Qt5 application style and also make them use the portal for file chooser dialog. + qt = { + enable = mkDefault true; + platformTheme = mkDefault "gnome"; + style = mkDefault "adwaita"; + }; + + # Needed for themes and backgrounds + environment.pathsToLink = [ + "/share" # TODO: https://github.com/NixOS/nixpkgs/issues/47173 + ]; + + # GVFS + services.gvfs.enable = true; + + # Flatpak + services.flatpak.enable = true; + + # Portals + xdg.portal = { + enable = true; + wlr.enable = true; + extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; + }; +} diff --git a/nixos-modules/desktop/greeter.nix b/nixos-modules/desktop/greeter.nix new file mode 100644 index 0000000..bb57bf0 --- /dev/null +++ b/nixos-modules/desktop/greeter.nix @@ -0,0 +1,35 @@ +{ + ... +}: +{ + + services.xserver.windowManager.i3.enable = false; + + services.displayManager = { + defaultSession = "sway"; + }; + + # Enable touchpad support. + services.libinput.enable = true; + + services.xserver = { + enable = true; + desktopManager.xterm.enable = false; + displayManager = { + startx.enable = false; + lightdm.enable = false; + gdm = { + enable = true; + wayland = true; + }; + }; + + # TODO: Extract i18n + xkb = { + layout = "ch,de"; + options = "eurosign:e"; + }; + + updateDbusEnvironment = true; + }; +} diff --git a/nixos-modules/desktop/hardware.nix b/nixos-modules/desktop/hardware.nix new file mode 100644 index 0000000..200e367 --- /dev/null +++ b/nixos-modules/desktop/hardware.nix @@ -0,0 +1,60 @@ +{ + config, + pkgs, + ... +}: + +{ + + services.blueman.enable = true; + + # Enable sound. + nixpkgs.config.pulseaudio = true; + + services.pulseaudio.enable = false; + services.pipewire = { + enable = true; + alsa.enable = true; + pulse.enable = true; + }; + security.rtkit.enable = true; + + hardware = { + graphics = { + enable = true; + enable32Bit = true; + extraPackages = with pkgs; [ + intel-compute-runtime + intel-media-driver + libvdpau-va-gl + vaapiVdpau + ]; + + }; + acpilight.enable = true; + bluetooth = { + enable = true; + package = pkgs.bluez; + }; + logitech.wireless = { + enable = true; + enableGraphical = true; + }; + }; + + services.hardware.bolt.enable = true; + services.udisks2.enable = true; + services.upower.enable = config.powerManagement.enable; + + programs.light.enable = true; + programs.adb.enable = true; + + services.fprintd = { + enable = true; + package = pkgs.fprintd-tod; + tod = { + enable = true; + driver = pkgs.libfprint-2-tod1-vfs0090; + }; + }; +} diff --git a/nixos-modules/desktop/llm.nix b/nixos-modules/desktop/llm.nix new file mode 100644 index 0000000..638cc63 --- /dev/null +++ b/nixos-modules/desktop/llm.nix @@ -0,0 +1,10 @@ +{ ... }: +{ + + services.ollama.enable = true; + + services.nextjs-ollama-llm-ui = { + enable = true; + port = 7001; + }; +} diff --git a/nixos-modules/desktop/office-suite.nix b/nixos-modules/desktop/office-suite.nix new file mode 100644 index 0000000..0fa66c5 --- /dev/null +++ b/nixos-modules/desktop/office-suite.nix @@ -0,0 +1,180 @@ +{ + pkgs, + ... +}: + +{ + + # Hamster + environment.systemPackages = with pkgs; [ + hamster + ]; + programs.hamster.enable = true; + + # Fonts + fonts.packages = with pkgs; [ + # google-fonts # Breaks fwesome + lalezar-fonts + nahid-fonts + nika-fonts + agave + aileron + amiri + andagii + #andika # Breaks Font-Awesome + ankacoder + ankacoder-condensed + aurulent-sans + caladea + cantarell-fonts + carlito + cascadia-code + #charis-sil # Breaks Font-Awesome + cherry + cnstrokeorder + comfortaa + comic-neue + comic-relief + # corefonts # breaks fawesome + culmus + clearlyU + creep + crimson + dejavu_fonts + dina-font + #doulos-sil # Breaks Font-Awesome + cabin + camingo-code + cooper-hewitt + #d2coding + dosis + dosemu_fonts + eb-garamond + eunomia + ferrum + # fixedsys-excelsior # Breaks fawesome + emacs-all-the-icons-fonts + emojione + encode-sans + envypn-font + fantasque-sans-mono + fira + fira-code + fira-code-symbols + fira-mono + #gentium + #gentium-book-basic + #gohufont + #go-font + #gubbi-font + #gyre-fonts + #hack-font + ##helvetica-neue-lt-std + #hanazono + #hermit + #hyperscrypt-font + #ia-writer-duospace + #inconsolata + #inconsolata-lgc + ##input-fonts + #inriafonts + #iosevka + #iosevka-bin + #ipafont + #ipaexfont + #iwona + #jetbrains-mono + #jost + #kanji-stroke-order-font + #latinmodern-math + #lato + #league-of-moveable-type + ##liberation-sans-narrow + #libertine + #libertinus + #libre-baskerville + #libre-bodoni + #libre-caslon + #libre-franklin + #lmmath + #lmodern + #luculent + #marathi-cursive + #manrope + #material-design-icons + #material-icons + #meslo-lg + #migmix + #migu + #medio + #mno16 + #monoid + #mononoki + #montserrat + #mph_2b_damase + #mplus-outline-fonts + #mro-unicode + #myrica + #nafees + #nanum-gothic-coding + #national-park-typeface + #office-code-pro + #oldstandard + #oldsindhi + #open-dyslexic + open-sans + orbitron + overpass + oxygenfonts + #pecita + #paratype-pt-mono # Breaks fawseome + #paratype-pt-sans # Breaks fawseome + #paratype-pt-serif # Breaks fawseome + penna + poly + powerline-fonts + profont + proggyfonts + public-sans + redhat-official-fonts + route159 + #sarasa-gothic + seshat + scheherazade + #signwriting + stix-otf + stix-two + quattrocento + quattrocento-sans + raleway + recursive + rhodium-libre + roboto + roboto-mono + roboto-slab + hasklig + siji + source-code-pro + source-sans-pro + source-serif-pro + tamsyn + theano + tenderness + terminus_font + tipa + twemoji-color-font + twitter-color-emoji + ubuntu_font_family + #ucs-fonts + ultimate-oldschool-pc-font-pack + victor-mono + work-sans + wqy_microhei + wqy_zenhei + xits-math + xkcd-font + yanone-kaffeesatz + norwester-font + font-awesome + ]; # Generated with `cd /home/fhauser/projects/nixos/nixpkgs/pkgs/data/fonts; echo *` +} diff --git a/nixos-modules/desktop/security.nix b/nixos-modules/desktop/security.nix new file mode 100644 index 0000000..0e6c7e1 --- /dev/null +++ b/nixos-modules/desktop/security.nix @@ -0,0 +1,13 @@ +{ + ... +}: + +{ + services.pcscd.enable = true; + + # Make pam accept both password and fingerprint + security.pam.services.swaylock.rules.auth = { + fprintd.order = 11601; + unix.args = [ "nullok" ]; + }; +} diff --git a/nixos-modules/desktop/video.nix b/nixos-modules/desktop/video.nix new file mode 100644 index 0000000..c8b8794 --- /dev/null +++ b/nixos-modules/desktop/video.nix @@ -0,0 +1,10 @@ +{ + ... +}: + +{ + #boot.kernelModules = [ "v4l2loopback" ]; + #boot.extraModulePackages = [ pkgs.linuxPackages_latest.v4l2loopback ]; + + programs.steam.enable = true; +} diff --git a/nixos-modules/filesystems/default.nix b/nixos-modules/filesystems/default.nix new file mode 100644 index 0000000..3dbd19b --- /dev/null +++ b/nixos-modules/filesystems/default.nix @@ -0,0 +1,4 @@ +{ inputs, ... }: +{ + imports = [ inputs.disko.nixosModules.disko ]; +} diff --git a/nixos-modules/hardware/amd-board.nix b/nixos-modules/hardware/amd-board.nix new file mode 100644 index 0000000..2fa3bd0 --- /dev/null +++ b/nixos-modules/hardware/amd-board.nix @@ -0,0 +1,69 @@ +{ + lib, + pkgs, + modulesPath, + ... +}: +let + thunderboltDevices = '' + THUNDERBOLT_DEVICES="$(${pkgs.pciutils}/bin/lspci -D | ${pkgs.gnugrep}/bin/grep -i thunderbolt | cut --delimiter=' ' --fields=1)" + ''; + forceThunderboltOnScript = pkgs.writeScriptBin "force-thunderbolt-power-on" '' + #!${pkgs.stdenv.shell} + + ${thunderboltDevices} + + echo "Force PCI power on all thunderbolt devices" + for DEVICE in $THUNDERBOLT_DEVICES; do + echo 'on' > "/sys/bus/pci/devices/$DEVICE/power/control" + done + ''; + thunderboltDockRestart = pkgs.writeScriptBin "thunderbolt-dock-restart" '' + #!${pkgs.stdenv.shell} + + ${thunderboltDevices} + + echo "Force PCI remove on all thunderbolt devices" + for DEVICE in $THUNDERBOLT_DEVICES; do + echo 1 > /sys/bus/pci/devices/$DEVICE/remove + echo "Dropped device $DEVICE" + done + + + echo 'Please re-plug the dock and confirm [enter]' + read + + echo 'Rescanning PCI devices...' + echo 1 > /sys/bus/pci/rescan + + echo 'Done.' + ''; +in +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + boot.initrd.availableKernelModules = [ + "nvme" + "usbhid" + "usb_storage" + "sd_mod" + "xhci_pci" + "ahci" + "virtio-pci" + "igb" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ + "kvm-amd" + "uhid" + ]; + boot.extraModulePackages = [ ]; + boot.kernelParams = [ "acpi_enforce_resources=lax" ]; + + environment.systemPackages = [ thunderboltDockRestart ]; + + hardware.cpu.amd.updateMicrocode = true; + nix.settings.max-jobs = lib.mkDefault 24; + + powerManagement.powerUpCommands = "${forceThunderboltOnScript}/bin/force-thunderbolt-power-on"; +} diff --git a/nixos-modules/hardware/ecc-memory.nix b/nixos-modules/hardware/ecc-memory.nix new file mode 100644 index 0000000..5ef1eb6 --- /dev/null +++ b/nixos-modules/hardware/ecc-memory.nix @@ -0,0 +1,8 @@ +{ + ... +}: +{ + hardware.rasdaemon = { + enable = true; + }; +} diff --git a/nixos-modules/hardware/thinkpad-x1-gen9.nix b/nixos-modules/hardware/thinkpad-x1-gen9.nix new file mode 100644 index 0000000..d6bc106 --- /dev/null +++ b/nixos-modules/hardware/thinkpad-x1-gen9.nix @@ -0,0 +1,42 @@ +{ + lib, + pkgs, + modulesPath, + hardwareModules, + pkgFccUnlock, + ... +}: +{ + + imports = with hardwareModules; [ + (modulesPath + "/installer/scan/not-detected.nix") + hardwareModules.lenovo-thinkpad-x1-9th-gen + ]; + + boot.initrd.availableKernelModules = [ + "xhci_pci" + "thunderbolt" + "nvme" + "usb_storage" + "sd_mod" + "ahci" + "usbhid" + ]; + boot.kernelModules = [ "kvm-intel" ]; + + boot.initrd.kernelModules = [ "dm-snapshot" ]; # TODO: This should be moved to defaults + + environment.systemPackages = with pkgs; [ + modemmanager + libmbim + ]; + + environment.etc."ModemManager/fcc-unlock.d/1eac:1001" = { + source = "${pkgFccUnlock}/bin/fcc-unlock"; + }; + + # CPU Configuration + hardware.cpu.intel.updateMicrocode = true; + services.throttled.enable = true; + powerManagement.cpuFreqGovernor = lib.mkDefault "performance"; +} diff --git a/nixos-modules/home-manager/default.nix b/nixos-modules/home-manager/default.nix new file mode 100644 index 0000000..8aee9e7 --- /dev/null +++ b/nixos-modules/home-manager/default.nix @@ -0,0 +1,12 @@ +{ inputs, ... }: + +{ + + imports = [ inputs.home-manager.nixosModules.home-manager ]; + + home-manager = { + backupFileExtension = ".hm-bak"; + useGlobalPkgs = true; + useUserPackages = true; + }; +} diff --git a/nixos-modules/printing/default.nix b/nixos-modules/printing/default.nix new file mode 100644 index 0000000..f3d9471 --- /dev/null +++ b/nixos-modules/printing/default.nix @@ -0,0 +1,17 @@ +{ + ... +}: + +{ + #services.printing = { + # enable = true; + # drivers = with pkgs; [ + # gutenprint + # hplip + # splix + # ]; + #}; + + #services.system-config-printer.enable = true; + #programs.system-config-printer.enable = true; +} diff --git a/nixos-modules/theme/default.nix b/nixos-modules/theme/default.nix new file mode 100644 index 0000000..b71b9df --- /dev/null +++ b/nixos-modules/theme/default.nix @@ -0,0 +1,6 @@ +{ inputs, ... }: + +{ + imports = [ inputs.catppuccin.nixosModules.catppuccin ]; + +} diff --git a/private b/private new file mode 160000 index 0000000..f2b5747 --- /dev/null +++ b/private @@ -0,0 +1 @@ +Subproject commit f2b5747476e21c585d304e38f2ba519e9a99714d diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..9df5a17 --- /dev/null +++ b/renovate.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ "config:recommended" ], + "lockFileMaintenance": { + "enabled": true, + "extends": [ "schedule:weekly" ] + }, + "cloneSubmodules": true, + "nix": { + "enabled": true + } +} +