├── .gitignore ├── docs └── install.md ├── flake.lock ├── flake.nix ├── home ├── commit-msg.sh ├── default.nix ├── desktop │ ├── chromium.nix │ ├── default.nix │ ├── discord.nix │ ├── spotify.nix │ ├── teams.nix │ └── vscode.nix ├── git.nix ├── k9s.nix ├── shell │ ├── alacritty.nix │ ├── bash.nix │ ├── default.nix │ └── starship.nix └── sway │ ├── default.nix │ ├── kanshi.nix │ ├── mako.nix │ ├── rofi.nix │ ├── sway.nix │ ├── swayidle.nix │ ├── swaylock.nix │ ├── waybar-style.css │ └── waybar.nix ├── hosts ├── common │ ├── default.nix │ ├── env.nix │ ├── locale.nix │ ├── nix.nix │ └── nixpkgs.nix ├── np14s │ └── configuration.nix ├── pi │ └── configuration.nix └── vm-builder │ └── configuration.nix ├── infra └── aws-builder │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ └── variables.tf ├── lib └── default.nix ├── modules ├── btrfs-luks.nix ├── common.nix ├── default.nix ├── disko │ └── btrfs-luks.nix ├── graphical.nix ├── impermanence │ ├── default.nix │ ├── fs-diff.sh │ ├── mod.nix │ └── persist.sh ├── main.nix ├── my.nix ├── remote-builders.nix └── rpi-3-leds.nix ├── overlays └── default.nix ├── packages ├── by-name │ ├── lan951x-led-ctl │ │ └── package.nix │ ├── matrixc.nix │ ├── matrixc.sh │ ├── mkpasswordfile.nix │ ├── nm-setup-rub-eduroam.nix │ ├── nodeshell.nix │ ├── nodeshell.sh │ └── swaylock-cmd.nix └── default.nix ├── symbols ├── de-custom └── us-custom ├── treefmt.nix └── wallpaper ├── pastel.png └── white.png /.gitignore: -------------------------------------------------------------------------------- 1 | result 2 | result-* 3 | .terraform 4 | *.tfstate 5 | *.tfstate.backup 6 | *.lock.hcl 7 | *.tfvars 8 | -------------------------------------------------------------------------------- /docs/install.md: -------------------------------------------------------------------------------- 1 | # Installation with disko 2 | 3 | ### Preparation 4 | 5 | ```sh 6 | sudo -i 7 | # add 'nix.settings.experimental-features = [ "nix-command" "flakes" ];' 8 | nano /etc/nixos/configuration.nix 9 | nixos-rebuild test 10 | nix shell nixpkgs#git 11 | git clone https://github.com/katexochen/nixos 12 | cd nixos 13 | ``` 14 | 15 | ### Partitioning 16 | 17 | ```sh 18 | nix run github:nix-community/disko -- -m disko modules/disko/btrfs-luks.nix --arg disk '"/dev/nvme0n1"' 19 | mount | grep /mnt 20 | ``` 21 | 22 | ### Install 23 | 24 | ```sh 25 | nixos-install --flake .# 26 | ``` 27 | 28 | ### Post-install 29 | 30 | ```sh 31 | nixos-enter 32 | mkdir /persist/secrets 33 | mkpasswordfile /persist/secrets/root 34 | mkpasswordfile /persist/secrets/katexochen 35 | ``` 36 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "disko": { 4 | "inputs": { 5 | "nixpkgs": [ 6 | "nixpkgs" 7 | ] 8 | }, 9 | "locked": { 10 | "lastModified": 1747742835, 11 | "narHash": "sha256-kYL4GCwwznsypvsnA20oyvW8zB/Dvn6K5G/tgMjVMT4=", 12 | "owner": "nix-community", 13 | "repo": "disko", 14 | "rev": "df522e787fdffc4f32ed3e1fca9ed0968a384d62", 15 | "type": "github" 16 | }, 17 | "original": { 18 | "owner": "nix-community", 19 | "repo": "disko", 20 | "type": "github" 21 | } 22 | }, 23 | "home-manager": { 24 | "inputs": { 25 | "nixpkgs": [ 26 | "nixpkgs" 27 | ] 28 | }, 29 | "locked": { 30 | "lastModified": 1747978958, 31 | "narHash": "sha256-pQQnbxWpY3IiZqgelXHIe/OAE/Yv4NSQq7fch7M6nXQ=", 32 | "owner": "nix-community", 33 | "repo": "home-manager", 34 | "rev": "7419250703fd5eb50e99bdfb07a86671939103ea", 35 | "type": "github" 36 | }, 37 | "original": { 38 | "owner": "nix-community", 39 | "repo": "home-manager", 40 | "type": "github" 41 | } 42 | }, 43 | "impermanence": { 44 | "locked": { 45 | "lastModified": 1737831083, 46 | "narHash": "sha256-LJggUHbpyeDvNagTUrdhe/pRVp4pnS6wVKALS782gRI=", 47 | "owner": "nix-community", 48 | "repo": "impermanence", 49 | "rev": "4b3e914cdf97a5b536a889e939fb2fd2b043a170", 50 | "type": "github" 51 | }, 52 | "original": { 53 | "owner": "nix-community", 54 | "repo": "impermanence", 55 | "type": "github" 56 | } 57 | }, 58 | "nixos-hardware": { 59 | "locked": { 60 | "lastModified": 1749195551, 61 | "narHash": "sha256-W5GKQHgunda/OP9sbKENBZhMBDNu2QahoIPwnsF6CeM=", 62 | "owner": "nixos", 63 | "repo": "nixos-hardware", 64 | "rev": "4602f7e1d3f197b3cb540d5accf5669121629628", 65 | "type": "github" 66 | }, 67 | "original": { 68 | "owner": "nixos", 69 | "repo": "nixos-hardware", 70 | "type": "github" 71 | } 72 | }, 73 | "nixpkgs": { 74 | "locked": { 75 | "lastModified": 1747744144, 76 | "narHash": "sha256-W7lqHp0qZiENCDwUZ5EX/lNhxjMdNapFnbErcbnP11Q=", 77 | "owner": "NixOS", 78 | "repo": "nixpkgs", 79 | "rev": "2795c506fe8fb7b03c36ccb51f75b6df0ab2553f", 80 | "type": "github" 81 | }, 82 | "original": { 83 | "id": "nixpkgs", 84 | "ref": "nixos-unstable", 85 | "type": "indirect" 86 | } 87 | }, 88 | "root": { 89 | "inputs": { 90 | "disko": "disko", 91 | "home-manager": "home-manager", 92 | "impermanence": "impermanence", 93 | "nixos-hardware": "nixos-hardware", 94 | "nixpkgs": "nixpkgs", 95 | "srvos": "srvos", 96 | "treefmt-nix": "treefmt-nix" 97 | } 98 | }, 99 | "srvos": { 100 | "inputs": { 101 | "nixpkgs": [ 102 | "nixpkgs" 103 | ] 104 | }, 105 | "locked": { 106 | "lastModified": 1747876980, 107 | "narHash": "sha256-ZRoCqZmuHqPaPDIzSIrijalnRUlyb47mpI81gw+pDAU=", 108 | "owner": "numtide", 109 | "repo": "srvos", 110 | "rev": "20a4a794afc9a25fdaf0d4301de4c47c47a25747", 111 | "type": "github" 112 | }, 113 | "original": { 114 | "owner": "numtide", 115 | "repo": "srvos", 116 | "type": "github" 117 | } 118 | }, 119 | "treefmt-nix": { 120 | "inputs": { 121 | "nixpkgs": [ 122 | "nixpkgs" 123 | ] 124 | }, 125 | "locked": { 126 | "lastModified": 1747912973, 127 | "narHash": "sha256-XgxghfND8TDypxsMTPU2GQdtBEsHTEc3qWE6RVEk8O0=", 128 | "owner": "numtide", 129 | "repo": "treefmt-nix", 130 | "rev": "020cb423808365fa3f10ff4cb8c0a25df35065a3", 131 | "type": "github" 132 | }, 133 | "original": { 134 | "owner": "numtide", 135 | "repo": "treefmt-nix", 136 | "type": "github" 137 | } 138 | } 139 | }, 140 | "root": "root", 141 | "version": 7 142 | } 143 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "nixpkgs/nixos-unstable"; 4 | nixos-hardware.url = "github:nixos/nixos-hardware"; 5 | impermanence.url = "github:nix-community/impermanence"; 6 | 7 | home-manager = { 8 | url = "github:nix-community/home-manager"; 9 | inputs.nixpkgs.follows = "nixpkgs"; 10 | }; 11 | disko = { 12 | url = "github:nix-community/disko"; 13 | inputs.nixpkgs.follows = "nixpkgs"; 14 | }; 15 | srvos = { 16 | url = "github:numtide/srvos"; 17 | inputs.nixpkgs.follows = "nixpkgs"; 18 | }; 19 | treefmt-nix = { 20 | url = "github:numtide/treefmt-nix"; 21 | inputs.nixpkgs.follows = "nixpkgs"; 22 | }; 23 | }; 24 | 25 | outputs = 26 | { 27 | self, 28 | nixpkgs, 29 | nixos-hardware, 30 | disko, 31 | srvos, 32 | treefmt-nix, 33 | ... 34 | }@inputs: 35 | let 36 | lib = import ./lib inputs; 37 | 38 | inherit (self) outputs; 39 | 40 | system = "x86_64-linux"; 41 | 42 | authorizedKeys = [ 43 | "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDcTVEfgXMnzE6iRJM8KWsrPHCXIgxqQNMfU+RmPM25g katexochen@remoteBuilder" 44 | "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEAqa+JmCiwHtCNJAJ8IuHIOIMPBrjLl4vmGh86WkYs+ katexochen@np14s" 45 | ]; 46 | 47 | treefmtEval = lib.eachSystem (pkgs: treefmt-nix.lib.evalModule pkgs ./treefmt.nix); 48 | in 49 | { 50 | nixosModules.common = import ./modules/common.nix; 51 | overlays = import ./overlays { inherit inputs; }; 52 | 53 | nixosConfigurations = { 54 | np14s = nixpkgs.lib.nixosSystem { 55 | inherit system; 56 | modules = [ 57 | disko.nixosModules.disko 58 | ./hosts/np14s/configuration.nix 59 | self.outputs.nixosModules.common 60 | ]; 61 | specialArgs = { inherit inputs outputs; }; 62 | }; 63 | 64 | vm-builder = nixpkgs.lib.nixosSystem { 65 | inherit system; 66 | modules = [ 67 | disko.nixosModules.disko 68 | srvos.nixosModules.server 69 | srvos.nixosModules.roles-nix-remote-builder 70 | ./hosts/vm-builder/configuration.nix 71 | { 72 | users.users.root.openssh.authorizedKeys.keys = authorizedKeys; 73 | users.users.katexochen.openssh.authorizedKeys.keys = authorizedKeys; 74 | roles.nix-remote-builder.schedulerPublicKeys = authorizedKeys; 75 | } 76 | self.outputs.nixosModules.common 77 | ]; 78 | specialArgs = { inherit inputs outputs; }; 79 | }; 80 | 81 | installer = nixpkgs.lib.nixosSystem { 82 | inherit system; 83 | modules = [ 84 | (nixpkgs + "/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix") 85 | (nixpkgs + "/nixos/modules/installer/cd-dvd/channel.nix") 86 | (_: { 87 | services.openssh.enable = true; 88 | users.users.root.openssh.authorizedKeys.keys = authorizedKeys; 89 | isoImage.squashfsCompression = "gzip -Xcompression-level 1"; 90 | }) 91 | ]; 92 | }; 93 | 94 | pi = nixpkgs.lib.nixosSystem { 95 | system = "aarch64-linux"; 96 | modules = [ 97 | nixos-hardware.nixosModules.raspberry-pi-3 98 | ./hosts/pi/configuration.nix 99 | { 100 | services.openssh.enable = true; 101 | users.users.root.openssh.authorizedKeys.keys = authorizedKeys; 102 | users.users.katexochen.openssh.authorizedKeys.keys = authorizedKeys; 103 | } 104 | self.outputs.nixosModules.common 105 | ]; 106 | specialArgs = { inherit inputs outputs; }; 107 | }; 108 | }; 109 | 110 | checks = lib.eachSystem (pkgs: { 111 | formatting = treefmtEval.${pkgs.system}.config.build.check self; 112 | }); 113 | 114 | formatter = lib.eachSystem (pkgs: treefmtEval.${pkgs.system}.config.build.wrapper); 115 | 116 | packages = lib.eachSystem (pkgs: import ./packages { inherit pkgs; }); 117 | 118 | legacyPackages = lib.eachSystem (pkgs: import ./packages { inherit pkgs; }); 119 | }; 120 | 121 | nixConfig = { 122 | extra-substituters = [ 123 | "https://katexochen.cachix.org" 124 | ]; 125 | extra-trusted-public-keys = [ 126 | "katexochen.cachix.org-1:ScfG6cUxfuZxn3n43fYVqK3ha2TMPLG7kJ52s6PKHqo=" 127 | ]; 128 | }; 129 | } 130 | -------------------------------------------------------------------------------- /home/commit-msg.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # An example hook script to check the commit log message. 4 | # Called by "git commit" with one argument, the name of the file 5 | # that has the commit message. The hook should exit with non-zero 6 | # status after issuing an appropriate message if it wants to stop the 7 | # commit. The hook is allowed to edit the commit message file. 8 | # 9 | # To enable this hook, rename this file to "commit-msg". 10 | 11 | # Uncomment the below to add a Signed-off-by line to the message. 12 | # Doing this in a hook is a bad idea in general, but the prepare-commit-msg 13 | # hook is more suited to it. 14 | # 15 | 16 | SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') 17 | grep -qs "^$SOB" "$1" || echo -e "\n$SOB" >>"$1" 18 | 19 | # This example catches duplicate Signed-off-by lines. 20 | 21 | test "" = "$(grep '^Signed-off-by: ' "$1" | 22 | sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { 23 | echo >&2 Duplicate Signed-off-by lines. 24 | exit 1 25 | } 26 | -------------------------------------------------------------------------------- /home/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | { 3 | imports = [ 4 | ./shell 5 | ./sway 6 | ./desktop 7 | 8 | ./git.nix 9 | ./k9s.nix 10 | ]; 11 | 12 | home.packages = with pkgs; [ 13 | mpv 14 | pavucontrol 15 | tailscale 16 | signal-desktop 17 | 18 | # Nix 19 | cachix 20 | deadnix 21 | nix-index 22 | nix-init 23 | nix-output-monitor 24 | nix-tree 25 | nix-update 26 | nixpkgs-fmt 27 | nixpkgs-hammering 28 | nixpkgs-review 29 | nurl 30 | nvd 31 | statix 32 | 33 | # Development 34 | actionlint 35 | cargo 36 | crane 37 | diffoscope 38 | dive 39 | docker 40 | gcc 41 | gh 42 | git-absorb 43 | gnumake 44 | go 45 | gopls 46 | gotools 47 | open-policy-agent 48 | rust-analyzer 49 | rustc 50 | shellcheck 51 | vbindiff 52 | xxd 53 | 54 | # Cloud 55 | awscli2 56 | azure-cli 57 | azure-storage-azcopy 58 | (google-cloud-sdk.withExtraComponents [ google-cloud-sdk.components.gke-gcloud-auth-plugin ]) 59 | kubectl 60 | terraform 61 | 62 | # CLI 63 | bat 64 | btop 65 | curl 66 | dust 67 | eza 68 | fd 69 | file 70 | gdu 71 | jless 72 | jq 73 | magic-wormhole-rs 74 | ncdu 75 | ripgrep 76 | seashells 77 | tmux 78 | unzip 79 | wget 80 | yq-go 81 | zathura 82 | 83 | # Fonts 84 | font-awesome 85 | google-fonts 86 | dejavu_fonts 87 | noto-fonts-color-emoji 88 | nerd-fonts.fira-code 89 | nerd-fonts.droid-sans-mono 90 | source-code-pro 91 | helvetica-neue-lt-std 92 | ubuntu_font_family 93 | ]; 94 | 95 | programs = { 96 | direnv = { 97 | enable = true; 98 | nix-direnv.enable = true; 99 | }; 100 | }; 101 | } 102 | -------------------------------------------------------------------------------- /home/desktop/chromium.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | 3 | { 4 | programs.chromium = { 5 | enable = true; 6 | package = pkgs.chromium.override { 7 | # Proprietary blob for DRM to enable Netflix/Spotify and co. 8 | enableWideVine = true; 9 | }; 10 | commandLineArgs = [ 11 | # Flags for Wayland & PipeWire support 12 | "--enable-features=UseOzonePlatform" 13 | "--ozone-platform=wayland" 14 | "--enable-features=WebRTCPipeWireCapturer" 15 | ]; 16 | extensions = [ 17 | { id = "nngceckbapebfimnlniiiahkandclblb"; } # bitwarden 18 | { id = "ddkjiahejlhfcafbddmgiahcphecmpfh"; } # ublock origin lite 19 | { id = "logpjaacgmcbpdkdchjiaagddngobkck"; } # shortkeys 20 | ]; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /home/desktop/default.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | { 3 | imports = [ 4 | ./chromium.nix 5 | ./discord.nix 6 | ./spotify.nix 7 | ./teams.nix 8 | ./vscode.nix 9 | ]; 10 | } 11 | -------------------------------------------------------------------------------- /home/desktop/discord.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | ... 4 | }: 5 | let 6 | discordScript = pkgs.writeShellApplication { 7 | name = "discord"; 8 | runtimeInputs = [ pkgs.chromium ]; 9 | text = '' 10 | swaymsg exec 'chromium --app=https://discord.com/login' 11 | ''; 12 | }; 13 | discordDeskopItem = pkgs.makeDesktopItem { 14 | name = "discord"; 15 | exec = "${discordScript}/bin/discord"; 16 | desktopName = "Discord"; 17 | genericName = "Chat"; 18 | comment = "Discord as Chromium web app."; 19 | startupWMClass = "discord"; 20 | terminal = true; 21 | }; 22 | in 23 | { 24 | home.packages = [ 25 | discordDeskopItem 26 | discordScript 27 | ]; 28 | } 29 | -------------------------------------------------------------------------------- /home/desktop/spotify.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | ... 4 | }: 5 | let 6 | spotifyScript = pkgs.writeShellApplication { 7 | name = "spotify"; 8 | runtimeInputs = [ pkgs.chromium ]; 9 | text = '' 10 | swaymsg exec 'chromium --app=https://open.spotify.com/' 11 | ''; 12 | }; 13 | spotifyDeskopItem = pkgs.makeDesktopItem { 14 | name = "spotify"; 15 | exec = "${spotifyScript}/bin/spotify"; 16 | desktopName = "Spotify"; 17 | genericName = "Music streaming"; 18 | comment = "Spotify as Chromium web app."; 19 | startupWMClass = "spotify"; 20 | terminal = true; 21 | }; 22 | in 23 | { 24 | home.packages = [ 25 | spotifyDeskopItem 26 | spotifyScript 27 | ]; 28 | } 29 | -------------------------------------------------------------------------------- /home/desktop/teams.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | ... 4 | }: 5 | let 6 | teamsScript = pkgs.writeShellApplication { 7 | name = "teams"; 8 | runtimeInputs = [ pkgs.chromium ]; 9 | text = '' 10 | swaymsg exec 'chromium --app=https://teams.microsoft.com/' 11 | ''; 12 | }; 13 | teamsDeskopItem = pkgs.makeDesktopItem { 14 | name = "teams"; 15 | exec = "${teamsScript}/bin/teams"; 16 | desktopName = "Microsoft Teams"; 17 | genericName = "Buissness Communication"; 18 | comment = "Microsoft Teams as Chromium web app."; 19 | startupWMClass = "teams"; 20 | terminal = true; 21 | }; 22 | in 23 | { 24 | home.packages = [ 25 | teamsDeskopItem 26 | teamsScript 27 | ]; 28 | } 29 | -------------------------------------------------------------------------------- /home/desktop/vscode.nix: -------------------------------------------------------------------------------- 1 | { lib, pkgs, ... }: 2 | { 3 | home.sessionVariables.NIXOS_OZONE_WL = "1"; 4 | 5 | programs.vscode = { 6 | enable = true; 7 | mutableExtensionsDir = false; 8 | profiles.default = { 9 | enableUpdateCheck = false; 10 | enableExtensionUpdateCheck = true; 11 | extensions = with pkgs.vscode-extensions; [ 12 | albymor.increment-selection 13 | bazelbuild.vscode-bazel 14 | eamodio.gitlens 15 | github.copilot 16 | github.copilot-chat 17 | github.vscode-github-actions 18 | golang.go 19 | hashicorp.terraform 20 | iliazeus.vscode-ansi 21 | jamesyang999.vscode-emacs-minimum 22 | jnoortheen.nix-ide 23 | mkhl.direnv 24 | ms-python.python 25 | ms-python.vscode-pylance 26 | ms-vscode-remote.remote-ssh 27 | ms-vscode.cpptools 28 | ms-vsliveshare.vsliveshare 29 | nefrob.vscode-just-syntax 30 | quicktype.quicktype 31 | redhat.vscode-yaml 32 | rust-lang.rust-analyzer 33 | streetsidesoftware.code-spell-checker 34 | tim-koehler.helm-intellisense 35 | timonwong.shellcheck 36 | tsandall.opa 37 | twpayne.vscode-testscript 38 | uloco.theme-bluloco-light 39 | yzhang.markdown-all-in-one 40 | zxh404.vscode-proto3 41 | ]; 42 | userSettings = { 43 | "C_Cpp.clang_format_fallbackStyle" = "{ BasedOnStyle: Google, IndentWidth: 4, TabWidth: 4 }"; 44 | "C_Cpp.clang_format_style" = "{ BasedOnStyle: Google, IndentWidth: 4, TabWidth: 4 }"; 45 | "cSpell.allowCompoundWords" = true; 46 | "diffEditor.ignoreTrimWhitespace" = false; 47 | "editor.acceptSuggestionOnEnter" = "off"; 48 | "editor.bracketPairColorization.enabled" = false; 49 | "editor.fontFamily" = 50 | "'Droid Sans Mono', 'monospace', monospace, 'Font Awesome 6 Free', 'Font Awesome 6 Brands', 'FiraCode Nerd Font'"; 51 | "editor.formatOnPaste" = true; 52 | "editor.formatOnSave" = true; 53 | "editor.inlineSuggest.enabled" = true; 54 | "editor.multiCursorModifier" = "ctrlCmd"; 55 | "editor.suggest.preview" = true; 56 | "editor.suggest.shareSuggestSelections" = true; 57 | "editor.suggestSelection" = "recentlyUsedByPrefix"; 58 | "telemetry.telemetryLevel" = "error"; 59 | "explorer.confirmDragAndDrop" = false; 60 | "extensions.ignoreRecommendations" = false; 61 | "files.insertFinalNewline" = true; 62 | "files.trimFinalNewlines" = true; 63 | "files.trimTrailingWhitespace" = true; 64 | "git.autofetch" = true; 65 | "git.enableSmartCommit" = true; 66 | "git.mergeEditor" = true; 67 | "gitlens.codeLens.enabled" = false; 68 | "gitlens.statusBar.enabled" = false; 69 | "go.buildTags" = "integration"; 70 | "go.coverageOptions" = "showUncoveredCodeOnly"; 71 | "go.coverOnSingleTest" = true; 72 | "go.coverOnSingleTestFile" = true; 73 | "go.lintFlags" = [ "--fast" ]; 74 | "go.lintTool" = "golangci-lint"; 75 | "go.testFlags" = [ 76 | "-count=1" 77 | "-race" 78 | "-v" 79 | ]; 80 | "go.testTimeout" = "2m"; 81 | "gopls" = { 82 | "formatting.gofumpt" = true; 83 | }; 84 | "java.saveActions.organizeImports" = true; 85 | "javascript.updateImportsOnFileMove.enabled" = "always"; 86 | "latex-workshop.bibtex-fields.sort.enabled" = true; 87 | "latex-workshop.bibtex-format.sort.enabled" = true; 88 | "latex-workshop.bibtex-format.trailingComma" = true; 89 | "latex-workshop.latex.recipe.default" = "lastUsed"; 90 | "latex-workshop.linting.chktex.enabled" = true; 91 | "latex-workshop.linting.lacheck.enabled" = true; 92 | "latex-workshop.message.update.show" = false; 93 | "latex-workshop.view.pdf.viewer" = "tab"; 94 | "liveServer.settings.donotShowInfoMsg" = true; 95 | "liveshare.audio.joinCallBehavior" = "accept"; 96 | "nix.enableLanguageServer" = true; 97 | "nix.serverPath" = "${pkgs.nixd}/bin/nixd"; 98 | "nix.serverSettings" = { 99 | "nixd" = { 100 | "formatting" = { 101 | "command" = [ "${lib.getExe pkgs.nixfmt-rfc-style}" ]; 102 | }; 103 | }; 104 | }; 105 | "outline.showFields" = false; 106 | "python.languageServer" = "Pylance"; 107 | "redhat.telemetry.enabled" = false; 108 | "terminal.integrated.allowChords" = false; 109 | "terminal.integrated.scrollback" = 10000; 110 | "vsintellicode.modify.editor.suggestSelection" = "automaticallyOverrodeDefaultValue"; 111 | "window.menuBarVisibility" = "toggle"; 112 | "window.titleBarStyle" = "native"; 113 | "window.customTitleBarVisibility" = "never"; 114 | "workbench.colorTheme" = "Bluloco Light"; 115 | "yaml.completion" = true; 116 | "yaml.hover" = true; 117 | 118 | "[latex]" = { 119 | "editor.wordWrap" = "on"; 120 | }; 121 | 122 | "[markdown]" = { 123 | "editor.quickSuggestions" = { 124 | "other" = true; 125 | "comments" = true; 126 | "strings" = true; 127 | }; 128 | }; 129 | "github.copilot.enable" = { 130 | "*" = true; 131 | "plaintext" = false; 132 | "markdown" = true; 133 | }; 134 | }; 135 | keybindings = [ 136 | { 137 | key = "ctrl+0"; 138 | command = "workbench.action.terminal.toggleTerminal"; 139 | when = "terminal.active"; 140 | } 141 | { 142 | key = "ctrl+0"; 143 | command = "workbench.action.focusActiveEditorGroup"; 144 | when = "terminalFocus"; 145 | } 146 | { 147 | key = "alt+left"; 148 | command = "workbench.action.navigateBack"; 149 | } 150 | { 151 | key = "alt+right"; 152 | command = "workbench.action.navigateForward"; 153 | } 154 | { 155 | key = "ctrl+q"; 156 | command = "workbench.action.closeWindow"; 157 | } 158 | { 159 | key = "ctrl+shift+q"; 160 | command = "workbench.action.quit"; 161 | } 162 | ]; 163 | }; 164 | }; 165 | } 166 | -------------------------------------------------------------------------------- /home/git.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | let 3 | userName = "Paul Meyer"; 4 | userEmail = "katexochen0@gmail.com"; 5 | # siginigKeyPath = "/home/katexochen/.ssh/gitsign.pub"; 6 | 7 | commit-msg-hook = pkgs.writeShellApplication { 8 | name = "commit-msg-hook"; 9 | runtimeInputs = with pkgs; [ 10 | git 11 | gnugrep 12 | ]; 13 | text = builtins.readFile ./commit-msg.sh; 14 | }; 15 | in 16 | { 17 | # home.file.".ssh/allowed_signers".text = "* ${builtins.readFile siginigKeyPath}"; 18 | 19 | programs.git = { 20 | enable = true; 21 | 22 | userName = "${userName}"; 23 | userEmail = "${userEmail}"; 24 | 25 | # signing = { 26 | # signByDefault = true; 27 | # key = ""; 28 | # }; 29 | 30 | extraConfig = { 31 | # commit.gpgsign = true; 32 | # tag.gpgsign = true; 33 | # gpg.format = "ssh"; 34 | # gpg.ssh.allowedSignersFile = "~/.ssh/allowed_signers"; 35 | # user.signingkey = "${siginigKeyPath}"; 36 | 37 | init.defaultBranch = "main"; 38 | push.autoSetupRemote = true; 39 | pull.ff = "only"; 40 | merge.conflictStyle = "zdiff3"; 41 | rebase.autoStash = true; 42 | # rerere.enabled = true; 43 | sendemail = { 44 | smtpServer = "smtp.gmail.com"; 45 | smtpServerPort = 587; 46 | smtpUser = userEmail; 47 | smtpEncryption = "tls"; 48 | }; 49 | credentials.helper = "store"; 50 | }; 51 | 52 | aliases = { 53 | # Print a table like short log. 54 | sl = "log --pretty=format:'%Cred%h %Creset%<(50,trunc)%s %Cgreen%<(12,trunc)%cr %Cblue%an%Creset%C(yellow)%d%Creset' --abbrev-commit"; 55 | # Print the name of the current branch. 56 | b = "rev-parse --abbrev-ref HEAD"; 57 | # List branches without a remote. 58 | bs-no-remote = "!git branch --format '%(refname:short) %(upstream)' | awk '{if (!$2) print $1;}'"; 59 | # List my branches, sorted by last commit date. 60 | bs-mine = "!git branch --sort=-committerdate --format='%(authorname) %09 %(refname:short)' | grep '${userName}' | cut -f2"; 61 | # List my branches that contain wip commits. 62 | bs-wip = "log --all --grep='wip' --first-parent --date-order --author='${userName}' --max-count=15 --pretty='format: %d %cr %C(bold)%s'"; 63 | # Add the fork of someone else as a remote. 64 | add-fork = "!git remote add \${1%/*} https://github.com/\${1} && git fetch \${1%/*}; #"; # $1 is appended to the end, ignoring it with # 65 | # Add changes to the last commit. 66 | oops = "commit --amend --no-edit"; 67 | # Apply a patch from remote URL. 68 | rapply = "!curl -fsSL \${1} | git apply -v --index; #"; 69 | # Deactivate global hooks in the current repository. 70 | hooks-off = "config core.hooksPath /dev/null"; 71 | # Interactive rebase with autosquash. 72 | asq = "!git rebase -i --autosquash HEAD~\${1}; #"; 73 | # Force push with lease. 74 | force = "push --force-with-lease"; 75 | # Show history between two commits, including links to commits on GitHub. 76 | ghhist = "!git log --no-merges --pretty=format:\"$(git config --get remote.upstream.url | git config --get remote.origin.url)/commit/%h %s\" $1^..$2 ; #"; 77 | }; 78 | 79 | hooks = { 80 | commit-msg = "${commit-msg-hook}/bin/commit-msg-hook"; 81 | }; 82 | 83 | difftastic.enable = true; 84 | }; 85 | 86 | programs.mergiraf.enable = true; 87 | } 88 | -------------------------------------------------------------------------------- /home/k9s.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | let 3 | yamlToJson = 4 | drv: 5 | pkgs.stdenv.mkDerivation { 6 | name = "${drv.name}-json"; 7 | src = drv; 8 | nativeBuildInputs = [ pkgs.yq-go ]; 9 | buildCommand = ''cat $src | yq -o json > $out''; 10 | }; 11 | 12 | fromYAML = str: builtins.fromJSON (builtins.readFile (yamlToJson str)); 13 | in 14 | 15 | { 16 | programs.k9s = { 17 | enable = true; 18 | settings.k9s = { 19 | ui = { 20 | skin = "transparent"; 21 | logoless = true; 22 | }; 23 | skipLatestRevCheck = true; 24 | logger.textWrap = true; 25 | }; 26 | skins.transparent = fromYAML ( 27 | pkgs.fetchurl { 28 | url = "https://raw.githubusercontent.com/derailed/k9s/v${pkgs.k9s.version}/skins/transparent.yaml"; 29 | hash = "sha256-4+tCRcI5fsSwqqhnNEZiD6LAc6ZW/AaP7KZ0003/XSE="; 30 | } 31 | ); 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /home/shell/alacritty.nix: -------------------------------------------------------------------------------- 1 | _: { 2 | programs.alacritty = { 3 | enable = true; 4 | settings = { 5 | selection.save_to_clipboard = true; 6 | window = { 7 | padding = { 8 | x = 20; 9 | y = 20; 10 | }; 11 | opacity = 0.8; 12 | }; 13 | font = { 14 | size = 12; 15 | }; 16 | }; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /home/shell/bash.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, ... }: 2 | { 3 | programs.bash = { 4 | enable = true; 5 | historyControl = [ 6 | "ignoredups" 7 | "ignorespace" 8 | "erasedups" 9 | ]; 10 | historyIgnore = [ 11 | "cd" 12 | "exit" 13 | "ls" 14 | "shutdown" 15 | "reboot" 16 | "poweroff" 17 | ]; 18 | sessionVariables = { 19 | EDITOR = "nano"; 20 | MANPAGER = "sh -c 'col -bx | bat -l man -p'"; 21 | MANROFFOPT = "-c"; 22 | }; 23 | initExtra = '' 24 | export PATH=$PATH:$(go env GOPATH)/bin 25 | export PATH=$PATH:/home/katexochen/bin 26 | ''; 27 | shellAliases = { 28 | cat = "${pkgs.bat}/bin/bat -pp"; 29 | k = "${pkgs.kubectl}/bin/kubectl"; 30 | ls = "${pkgs.eza}/bin/eza --git -L 3"; 31 | temp = "cd $(mktemp -d); bash; cd - > /dev/null"; 32 | # https://docs.cachix.org/pushing#pushing-flake-inputs 33 | # nix build .#foo --json | build2cachix | cachix push bar 34 | build2cachix = "${lib.getExe pkgs.jq} -r '.[].outputs | to_entries[].value'"; 35 | sha256result = "find result/ -type f -exec sha256sum {} + | awk '{print $1}' | sort | sha256sum"; 36 | }; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /home/shell/default.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | { 3 | imports = [ 4 | ./bash.nix 5 | ./starship.nix 6 | ./alacritty.nix 7 | ]; 8 | } 9 | -------------------------------------------------------------------------------- /home/shell/starship.nix: -------------------------------------------------------------------------------- 1 | _: { 2 | programs.starship = { 3 | enable = true; 4 | enableBashIntegration = true; 5 | settings = { 6 | golang = { 7 | symbol = "[ ](regular)"; 8 | }; 9 | aws.disabled = true; 10 | azure.disabled = true; 11 | gcloud.disabled = true; 12 | opa.disabled = true; 13 | }; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /home/sway/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | { 3 | imports = [ 4 | ./sway.nix 5 | 6 | ./mako.nix 7 | ./rofi.nix 8 | ./swayidle.nix 9 | ./swaylock.nix 10 | ./waybar.nix 11 | ./kanshi.nix 12 | ]; 13 | 14 | home.packages = with pkgs; [ 15 | grim 16 | libnotify 17 | pamixer 18 | slurp 19 | swayimg 20 | wdisplays 21 | wl-clipboard 22 | wl-mirror 23 | xdg-utils 24 | xwayland 25 | ]; 26 | } 27 | -------------------------------------------------------------------------------- /home/sway/kanshi.nix: -------------------------------------------------------------------------------- 1 | let 2 | dellp27L = "Dell Inc. DELL P2720D CBHJK53"; 3 | dellp27R = "Dell Inc. DELL P2720D GN2ZS03"; 4 | dellu27 = "Dell Inc. DELL U2717D J0XYN8AOA5ML"; 5 | dellaw25 = "Dell Inc. AW2521HFA 7CWTL03"; 6 | p14s = "Lenovo Group Limited 0x403A Unknown"; 7 | l14 = "Lenovo Group Limited L15 U133MM45"; 8 | in 9 | { 10 | services.kanshi = { 11 | enable = true; 12 | settings = [ 13 | { 14 | profile.name = "office"; 15 | profile.outputs = [ 16 | { 17 | criteria = p14s; 18 | status = "enable"; 19 | position = "0,240"; 20 | } 21 | { 22 | criteria = dellp27L; 23 | status = "enable"; 24 | position = "1920,0"; 25 | } 26 | { 27 | criteria = dellp27R; 28 | status = "enable"; 29 | position = "4480,0"; 30 | } 31 | ]; 32 | } 33 | { 34 | profile.name = "home"; 35 | profile.outputs = [ 36 | { 37 | criteria = dellu27; 38 | status = "enable"; 39 | position = "0,0"; 40 | } 41 | { 42 | criteria = p14s; 43 | status = "enable"; 44 | position = "2560,240"; 45 | } 46 | ]; 47 | } 48 | { 49 | profile.name = "undoced"; 50 | profile.outputs = [ 51 | { 52 | criteria = p14s; 53 | status = "enable"; 54 | position = "0,0"; 55 | } 56 | ]; 57 | } 58 | { 59 | profile.name = "mobile-external"; 60 | profile.outputs = [ 61 | { 62 | criteria = l14; 63 | status = "enable"; 64 | position = "0,0"; 65 | } 66 | { 67 | criteria = p14s; 68 | status = "enable"; 69 | position = "1920,0"; 70 | } 71 | ]; 72 | } 73 | { 74 | profile.name = "gf"; 75 | profile.outputs = [ 76 | { 77 | criteria = dellaw25; 78 | status = "enable"; 79 | position = "0,0"; 80 | } 81 | { 82 | criteria = p14s; 83 | status = "enable"; 84 | position = "0,1080"; 85 | } 86 | ]; 87 | } 88 | ]; 89 | }; 90 | } 91 | -------------------------------------------------------------------------------- /home/sway/mako.nix: -------------------------------------------------------------------------------- 1 | _: { 2 | services.mako = { 3 | # test with notify-send. 4 | enable = true; 5 | settings = { 6 | default-timeout = 4500; 7 | background-color = "#2e3440"; 8 | ignore-timeout = true; 9 | "mode=do-not-disturb".invisible = true; 10 | }; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /home/sway/rofi.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | { 3 | programs.rofi = { 4 | enable = true; 5 | package = pkgs.rofi-wayland; 6 | plugins = with pkgs; [ 7 | rofi-calc 8 | ]; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /home/sway/sway.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | config, 4 | pkgs, 5 | ... 6 | }: 7 | let 8 | finalPkg = name: "${config.programs.${name}.finalPackage}"; 9 | finalPkgBin = name: "${finalPkg name}/bin/${name}"; 10 | 11 | cursor = { 12 | theme = "Adwaita"; 13 | size = 18; 14 | }; 15 | in 16 | { 17 | wayland.windowManager.sway = { 18 | enable = true; 19 | checkConfig = false; 20 | wrapperFeatures.gtk = true; 21 | systemd.enable = true; 22 | config = { 23 | terminal = "${pkgs.alacritty}/bin/alacritty"; 24 | menu = "${finalPkgBin "rofi"} -show drun -show-icons -pid"; 25 | bars = [ { command = "${pkgs.waybar}/bin/waybar"; } ]; 26 | 27 | modifier = "Mod4"; 28 | down = "m"; 29 | up = "u"; 30 | left = "j"; 31 | right = "k"; 32 | 33 | input = { 34 | "type:keyboard" = { 35 | xkb_layout = "us-custom,de-custom"; 36 | xkb_options = "ctrl:nocaps,grp:win_space_toggle"; 37 | }; 38 | }; 39 | 40 | output = { 41 | "*".bg = "${../../wallpaper/pastel.png} fill"; 42 | }; 43 | 44 | keybindings = 45 | let 46 | mod = config.wayland.windowManager.sway.config.modifier; 47 | inherit (config.wayland.windowManager.sway.config) 48 | left 49 | down 50 | up 51 | right 52 | menu 53 | terminal 54 | ; 55 | in 56 | { 57 | "${mod}+Return" = "exec ${terminal}"; 58 | "${mod}+Shift+q" = "kill"; 59 | "${mod}+d" = "exec ${menu}"; 60 | 61 | "${mod}+Shift+c" = "reload"; 62 | "${mod}+Shift+r" = "restart"; 63 | 64 | "${mod}+${left}" = "focus left"; 65 | "${mod}+${down}" = "focus down"; 66 | "${mod}+${up}" = "focus up"; 67 | "${mod}+${right}" = "focus right"; 68 | 69 | "${mod}+Left" = "focus left"; 70 | "${mod}+Down" = "focus down"; 71 | "${mod}+Up" = "focus up"; 72 | "${mod}+Right" = "focus right"; 73 | 74 | "${mod}+Shift+${left}" = "move left"; 75 | "${mod}+Shift+${down}" = "move down"; 76 | "${mod}+Shift+${up}" = "move up"; 77 | "${mod}+Shift+${right}" = "move right"; 78 | 79 | "${mod}+Shift+Left" = "move left"; 80 | "${mod}+Shift+Down" = "move down"; 81 | "${mod}+Shift+Up" = "move up"; 82 | "${mod}+Shift+Right" = "move right"; 83 | 84 | "${mod}+1" = "workspace number 1"; 85 | "${mod}+2" = "workspace number 2"; 86 | "${mod}+3" = "workspace number 3"; 87 | "${mod}+4" = "workspace number 4"; 88 | "${mod}+5" = "workspace number 5"; 89 | "${mod}+6" = "workspace number 6"; 90 | "${mod}+7" = "workspace number 7"; 91 | "${mod}+8" = "workspace number 8"; 92 | "${mod}+9" = "workspace number 9"; 93 | "${mod}+0" = "workspace number 10"; 94 | 95 | "${mod}+Shift+1" = "move container to workspace number 1"; 96 | "${mod}+Shift+2" = "move container to workspace number 2"; 97 | "${mod}+Shift+3" = "move container to workspace number 3"; 98 | "${mod}+Shift+4" = "move container to workspace number 4"; 99 | "${mod}+Shift+5" = "move container to workspace number 5"; 100 | "${mod}+Shift+6" = "move container to workspace number 6"; 101 | "${mod}+Shift+7" = "move container to workspace number 7"; 102 | "${mod}+Shift+8" = "move container to workspace number 8"; 103 | "${mod}+Shift+9" = "move container to workspace number 9"; 104 | "${mod}+Shift+0" = "move container to workspace number 10"; 105 | 106 | "${mod}+h" = "split h"; 107 | "${mod}+v" = "split v"; 108 | "${mod}+f" = "fullscreen toggle"; 109 | "${mod}+s" = "layout stacking"; 110 | "${mod}+t" = "layout tabbed"; 111 | "${mod}+e" = "layout toggle split"; 112 | "${mod}+a" = "focus parent"; 113 | "${mod}+Shift+a" = "focus child"; 114 | 115 | "${mod}+equal" = "floating toggle"; 116 | "${mod}+Shift+equal" = "focus mode_toggle"; 117 | 118 | "${mod}+Shift+minus" = "move scratchpad"; 119 | "${mod}+minus" = "scratchpad show"; 120 | 121 | # Modes 122 | "${mod}+r" = "mode resize"; 123 | "${mod}+Shift+v" = ''mode "system: [r]eboot [p]oweroff [e]xit"''; 124 | 125 | # Shortcuts for applications 126 | "${mod}+c" = 127 | "exec ${finalPkgBin "rofi"} -show calc -modi calc -no-show-mathc -no-sort -calc-command 'echo -n {result} | ${pkgs.wl-clipboard}/bin/wl-copy'"; 128 | "${mod}+p" = 129 | "exec ${pkgs.slurp}/bin/slurp | ${pkgs.grim}/bin/grim -g- screenshot-$(date +%Y%m%d-%H%M%S).png"; 130 | "${mod}+Shift+p" = 131 | "exec ${pkgs.slurp}/bin/slurp | ${pkgs.grim}/bin/grim -g- - | ${pkgs.wl-clipboard}/bin/wl-copy -t image/png"; 132 | "${mod}+i" = "exec ${pkgs.mako}/bin/makoctl dismiss"; 133 | "${mod}+Shift+i" = "exec ${pkgs.mako}/bin/makoctl dismiss -a"; 134 | "${mod}+l" = "exec ${lib.getExe pkgs.swaylock-cmd}"; 135 | 136 | # XF86 keys 137 | "XF86AudioMute" = "exec ${pkgs.pamixer}/bin/pamixer -t"; 138 | "XF86AudioMicMute" = "exec ${pkgs.pamixer}/bin/pamixer --default-source -t"; 139 | "XF86AudioRaiseVolume" = "exec ${pkgs.pamixer}/bin/pamixer -i 5"; 140 | "XF86AudioLowerVolume" = "exec ${pkgs.pamixer}/bin/pamixer -d 5"; 141 | "XF86MonBrightnessUp" = "exec ${pkgs.brightnessctl}/bin/brightnessctl s +10%"; 142 | "XF86MonBrightnessDown" = "exec ${pkgs.brightnessctl}/bin/brightnessctl s 10%-"; 143 | "XF86Calculator" = "exec ${finalPkgBin "rofi"} -show calc -modi calc -no-show-mathc -no-sort"; 144 | "XF86Messenger" = 145 | let 146 | toggleNotifications = pkgs.writeShellApplication { 147 | name = "mako-toggle-notifications"; 148 | runtimeInputs = [ pkgs.mako ]; 149 | text = '' 150 | if makoctl mode | grep -q do-not-disturb; then 151 | makoctl mode -r do-not-disturb 152 | else 153 | makoctl mode -a do-not-disturb 154 | fi 155 | ''; 156 | }; 157 | in 158 | "exec ${lib.getExe toggleNotifications}"; 159 | }; 160 | 161 | modes = { 162 | "system: [r]eboot [p]oweroff [e]xit" = { 163 | r = "exec systemctl reboot"; 164 | p = "exec systemctl poweroff"; 165 | e = "exit"; 166 | Return = "mode default"; 167 | Escape = "mode default"; 168 | }; 169 | resize = { 170 | Left = "resize shrink width"; 171 | Right = "resize grow width"; 172 | Down = "resize shrink height"; 173 | Up = "resize grow height"; 174 | Return = "mode default"; 175 | Escape = "mode default"; 176 | }; 177 | }; 178 | 179 | window.commands = [ 180 | { 181 | criteria.app_id = ".*-floating"; 182 | command = "floating enable"; 183 | } 184 | { 185 | criteria.class = ".*"; 186 | command = "inhibit_idle fullscreen"; 187 | } 188 | { 189 | criteria.shell = "xwayland"; 190 | command = "title_format \"%title :: %shell\""; 191 | } 192 | { 193 | criteria.app_id = "pavucontrol"; 194 | command = "floating enable"; 195 | } 196 | { 197 | criteria.app_id = "pavucontrol"; 198 | command = "resize set 800 600"; 199 | } 200 | { 201 | # Chromium inhibits sway shortcuts for some reason when using application 202 | # mode (--app=), this fixes that. 203 | # See: https://www.reddit.com/r/swaywm/comments/vkgfza 204 | criteria.app_id = "^chrome-.*-.*$"; 205 | command = "shortcuts_inhibitor disable"; 206 | } 207 | ]; 208 | }; 209 | extraSessionCommands = '' 210 | export SDL_VIDEODRIVER=wayland 211 | export QT_QPA_PLATFORM=wayland 212 | export QT_WAYLAND_DISABLE_WINDOWDECORATION="1" 213 | export _JAVA_AWT_WM_NONREPARENTING=1 214 | export MOZ_ENABLE_WAYLAND=1 215 | export NIXOS_OZONE_WL=1 216 | export XCURSOR_THEME=${cursor.theme} 217 | export XCURSOR_SIZE=${toString cursor.size} 218 | ''; 219 | }; 220 | 221 | home.pointerCursor = { 222 | name = cursor.theme; 223 | package = pkgs.adwaita-icon-theme; 224 | inherit (cursor) size; 225 | }; 226 | 227 | gtk.cursorTheme = { 228 | name = cursor.theme; 229 | inherit (cursor) size; 230 | }; 231 | } 232 | -------------------------------------------------------------------------------- /home/sway/swayidle.nix: -------------------------------------------------------------------------------- 1 | { lib, pkgs, ... }: 2 | 3 | { 4 | services.swayidle = { 5 | enable = true; 6 | timeouts = [ 7 | { 8 | timeout = 295; 9 | command = "${pkgs.libnotify}/bin/notify-send 'Locking in 5 seconds' -t 5000"; 10 | } 11 | { 12 | timeout = 300; 13 | command = "${lib.getExe pkgs.swaylock-cmd}"; 14 | } 15 | { 16 | timeout = 360; 17 | command = "${pkgs.sway}/bin/swaymsg 'output * dpms off'"; 18 | resumeCommand = "${pkgs.sway}/bin/swaymsg 'output * dpms on'"; 19 | } 20 | ]; 21 | events = [ 22 | { 23 | event = "before-sleep"; 24 | command = "${lib.getExe pkgs.swaylock-cmd}"; 25 | } 26 | ]; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /home/sway/swaylock.nix: -------------------------------------------------------------------------------- 1 | _: { 2 | programs.swaylock = { 3 | settings = { 4 | image = "${../../wallpaper/pastel.png}"; 5 | daemonize = true; 6 | ignore-empty-password = true; 7 | }; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /home/sway/waybar-style.css: -------------------------------------------------------------------------------- 1 | * { 2 | border: none; 3 | border-radius: 0px; 4 | font-size: 14px; 5 | font-family: "DejaVu Sans", "Font Awesome 6 Free", "Font Awesome 6 Brands"; 6 | color: #0e0c16; 7 | min-height: 10px; 8 | } 9 | 10 | window#waybar { 11 | background: transparent; 12 | } 13 | 14 | window#waybar.hidden { 15 | opacity: 0.2; 16 | } 17 | 18 | #window { 19 | background: transparent; 20 | } 21 | 22 | /* fix for font color issue, see https: //github.com/Alexays/Waybar/issues/1741#issuecomment-1288336263 */ 23 | label:disabled, 24 | button:disabled { 25 | color: inherit; 26 | background-image: none; 27 | } 28 | 29 | #mode, 30 | #window, 31 | #workspaces button { 32 | color: rgba(245, 245, 245, 0.4); 33 | } 34 | 35 | #workspaces button * { 36 | color: inherit; 37 | } 38 | 39 | #clock, 40 | #battery, 41 | #bluetooth, 42 | #cpu, 43 | #memory, 44 | #disk, 45 | #temperature, 46 | #backlight, 47 | #network, 48 | #pulseaudio, 49 | #language, 50 | #idle_inhibitor, 51 | #mpd { 52 | margin-bottom: 6px; 53 | margin-left: 8px; 54 | padding: 0px 10px; 55 | border-radius: 0px 0px 10px 10px; 56 | background-color: rgba(245, 245, 245, 0.4); 57 | } 58 | 59 | #network { 60 | min-width: 180px; 61 | } 62 | 63 | #bluetooth { 64 | /* Use Nerd Font for bluetooth icons */ 65 | font-family: "DejaVu Sans", "FiraCode Nerd Font", "Font Awesome 6 Free", "Font Awesome 6 Brands"; 66 | } 67 | 68 | /* If workspaces is the leftmost module, omit left margin */ 69 | .modules-left>widget:first-child>#workspaces { 70 | margin-left: 0px; 71 | } 72 | 73 | /* If workspaces is the rightmost module, omit right margin */ 74 | .modules-right>widget:last-child>#workspaces { 75 | margin-right: 0px; 76 | } 77 | 78 | #battery.charging { 79 | background-color: rgba(108, 252, 106, 0.53); 80 | } 81 | 82 | #battery.critical:not(.charging), 83 | #temperature.critical, 84 | #cpu.critical, 85 | #memory.critical { 86 | animation-name: critical; 87 | animation-duration: 0.5s; 88 | animation-timing-function: linear; 89 | animation-iteration-count: infinite; 90 | animation-direction: alternate; 91 | } 92 | 93 | @keyframes critical { 94 | to { 95 | background-color: rgba(255, 73, 73, 0.53); 96 | } 97 | } 98 | 99 | #battery.warning:not(.charging), 100 | #temperature.warning, 101 | #cpu.warning, 102 | #memory.warning { 103 | animation-name: warning; 104 | animation-duration: 0.5s; 105 | animation-timing-function: linear; 106 | animation-iteration-count: infinite; 107 | animation-direction: alternate; 108 | } 109 | 110 | @keyframes warning { 111 | to { 112 | background-color: rgba(255, 206, 73, 0.53); 113 | } 114 | } 115 | 116 | #tray>.needs-attention { 117 | -gtk-icon-effect: highlight; 118 | } 119 | 120 | #tray>.passive { 121 | -gtk-icon-effect: dim; 122 | } 123 | 124 | 125 | #language { 126 | min-width: 16px; 127 | } 128 | 129 | tooltip { 130 | background-color: rgba(21, 23, 27, 0.85); 131 | border-radius: 10px; 132 | } 133 | 134 | tooltip label { 135 | color: rgb(235, 235, 235); 136 | } 137 | -------------------------------------------------------------------------------- /home/sway/waybar.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, ... }: 2 | { 3 | programs.waybar = { 4 | enable = true; 5 | systemd.target = "sway-session.target"; 6 | style = ./waybar-style.css; 7 | settings = { 8 | mainBar = { 9 | layer = "top"; 10 | position = "top"; 11 | height = 30; 12 | 13 | modules-left = [ 14 | "sway/workspaces" 15 | "sway/window" 16 | ]; 17 | modules-center = [ 18 | "sway/mode" 19 | ]; 20 | modules-right = [ 21 | "tray" 22 | "pulseaudio" 23 | "bluetooth" 24 | "network#wifi" 25 | "network#speed" 26 | "battery" 27 | "cpu" 28 | "memory" 29 | "sway/language" 30 | "clock" 31 | ]; 32 | 33 | "clock" = { 34 | tooltip-format = "{:%B %Y}\n{calendar}"; 35 | format-alt = "{:%d.%m.%y}"; 36 | }; 37 | 38 | "cpu" = { 39 | interval = 2; 40 | format = "{usage}% "; 41 | tooltip = false; 42 | states = { 43 | warning = 70; 44 | critical = 90; 45 | }; 46 | }; 47 | 48 | "memory" = { 49 | interval = 2; 50 | format = "{}% "; 51 | tooltip-format = "{used:0.1f}G / {total:0.1f}G"; 52 | states = { 53 | warning = 70; 54 | critical = 90; 55 | }; 56 | }; 57 | 58 | "network#speed" = { 59 | interval = 2; 60 | tooltip-format = "{ifname} via {gwaddr} "; 61 | format = " {bandwidthDownBytes}  {bandwidthUpBytes}"; 62 | on-click = "swaymsg exec \"${lib.getExe pkgs.alacritty} --class Alacritty-floating -e nmtui-connect\""; 63 | }; 64 | 65 | "network#wifi" = { 66 | interval = 10; 67 | format-wifi = "{essid} ({signalStrength}%) "; 68 | format = ""; 69 | tooltip = false; 70 | on-click = "swaymsg exec \"${lib.getExe pkgs.alacritty} --class Alacritty-floating -e nmtui-connect\""; 71 | }; 72 | 73 | "bluetooth" = { 74 | format = ""; 75 | format-off = ""; 76 | format-disabled = ""; 77 | format-connected = " {num_connections}"; 78 | tooltip-format = "{controller_alias}\t{controller_address}"; 79 | tooltip-format-connected = "{controller_alias}\t{controller_address}\n\n{device_enumerate}"; 80 | tooltip-format-enumerate-connected = "{device_alias}\t{device_address}"; 81 | on-click-right = "bash -c \"if rfkill list bluetooth|grep -q 'yes$';then rfkill unblock bluetooth;else rfkill block bluetooth;fi\""; 82 | on-click = "swaymsg exec \"${lib.getExe pkgs.alacritty} --class Alacritty-floating -e ${lib.getExe pkgs.bluetuith}\""; 83 | }; 84 | 85 | "pulseaudio" = { 86 | scroll-step = 5; 87 | format = "{volume}% {icon} {format_source}"; 88 | format-bluetooth = "{volume}% {icon} {format_source}"; 89 | format-bluetooth-muted = " {icon} {format_source}"; 90 | format-muted = " {format_source}"; 91 | format-source = "{volume}% "; 92 | format-source-muted = ""; 93 | format-icons = { 94 | headphone = ""; 95 | hands-free = ""; 96 | headset = ""; 97 | phone = ""; 98 | portable = ""; 99 | default = [ 100 | "" 101 | "" 102 | "" 103 | ]; 104 | }; 105 | "on-click" = "${lib.getExe pkgs.pavucontrol}"; 106 | }; 107 | 108 | "battery" = { 109 | interval = 60; 110 | states = { 111 | warning = 30; 112 | critical = 15; 113 | }; 114 | format = "{capacity}% {icon}"; 115 | format-icons = [ 116 | "" 117 | "" 118 | "" 119 | "" 120 | "" 121 | ]; 122 | }; 123 | 124 | "sway/window" = { 125 | format = "{}"; 126 | max-length = 60; 127 | tooltip = false; 128 | }; 129 | 130 | "sway/mode" = { 131 | format = "{}"; 132 | tooltip = false; 133 | }; 134 | 135 | "sway/language" = { 136 | on-click = "swaymsg input type:keyboard xkb_switch_layout next"; 137 | tooltip = false; 138 | }; 139 | }; 140 | }; 141 | }; 142 | } 143 | -------------------------------------------------------------------------------- /hosts/common/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | imports = [ 3 | ./env.nix 4 | ./locale.nix 5 | ./nix.nix 6 | ./nixpkgs.nix 7 | ]; 8 | } 9 | -------------------------------------------------------------------------------- /hosts/common/env.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | 3 | { 4 | environment.systemPackages = with pkgs; [ 5 | btop 6 | dig 7 | gdu 8 | git 9 | go 10 | jq 11 | killall 12 | ripgrep 13 | traceroute 14 | unzip 15 | wget 16 | ]; 17 | 18 | programs = { 19 | starship.enable = true; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /hosts/common/locale.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: 2 | 3 | { 4 | i18n = { 5 | extraLocaleSettings = { 6 | LC_COLLATE = "C.UTF-8"; 7 | LC_MEASUREMENT = "de_DE.UTF-8"; 8 | LC_MONETARY = "de_DE.UTF-8"; 9 | LC_NUMERIC = "de_DE.UTF-8"; 10 | LC_TELEPHONE = "de_DE.UTF-8"; 11 | LC_TIME = "de_DE.UTF-8"; 12 | }; 13 | }; 14 | location.provider = "geoclue2"; 15 | time.timeZone = lib.mkDefault (if (config.my.role == "client") then "Europe/Berlin" else "UTC"); 16 | } 17 | -------------------------------------------------------------------------------- /hosts/common/nix.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs, 3 | lib, 4 | ... 5 | }: 6 | 7 | { 8 | nix = { 9 | settings = { 10 | trusted-users = [ 11 | "root" 12 | "@wheel" 13 | ]; 14 | experimental-features = [ 15 | "nix-command" 16 | "flakes" 17 | "auto-allocate-uids" 18 | ]; 19 | builders-use-substitutes = lib.mkDefault true; 20 | auto-optimise-store = lib.mkDefault true; 21 | auto-allocate-uids = lib.mkDefault true; 22 | warn-dirty = true; 23 | system-features = [ 24 | "kvm" 25 | "big-parallel" 26 | ]; 27 | }; 28 | 29 | gc = { 30 | automatic = true; 31 | dates = lib.mkDefault "weekly"; 32 | options = lib.mkDefault "--delete-older-than +3"; 33 | }; 34 | 35 | registry = lib.mapAttrs (_: value: { flake = value; }) inputs; 36 | nixPath = [ "nixpkgs=${inputs.nixpkgs.outPath}" ]; 37 | # nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /hosts/common/nixpkgs.nix: -------------------------------------------------------------------------------- 1 | { outputs, ... }: 2 | 3 | { 4 | nixpkgs = { 5 | overlays = builtins.attrValues outputs.overlays; 6 | config.allowUnfree = true; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /hosts/np14s/configuration.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs, 3 | lib, 4 | ... 5 | }: 6 | 7 | { 8 | imports = [ 9 | ../common 10 | inputs.home-manager.nixosModules.home-manager 11 | inputs.impermanence.nixosModule 12 | ../../modules 13 | ]; 14 | 15 | my = { 16 | host = "np14s"; 17 | role = "client"; 18 | modules = { 19 | btrfs-luks.enable = true; 20 | impermanence.enable = true; 21 | use-remote-builders.enable = true; 22 | }; 23 | }; 24 | 25 | boot = { 26 | initrd.availableKernelModules = [ 27 | "nvme" 28 | "xhci_pci" 29 | "thunderbolt" 30 | "usbhid" 31 | "usb_storage" 32 | "sd_mod" 33 | ]; 34 | initrd.kernelModules = [ 35 | "dm-snapshot" 36 | "amdgpu" 37 | ]; 38 | kernelModules = [ "kvm-amd" ]; 39 | extraModulePackages = [ ]; 40 | binfmt.emulatedSystems = [ "aarch64-linux" ]; 41 | }; 42 | 43 | networking.useDHCP = lib.mkDefault true; 44 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 45 | 46 | hardware = { 47 | enableRedistributableFirmware = true; 48 | cpu.amd.updateMicrocode = true; 49 | }; 50 | 51 | services.libinput.enable = true; 52 | 53 | system.stateVersion = "22.05"; 54 | } 55 | -------------------------------------------------------------------------------- /hosts/pi/configuration.nix: -------------------------------------------------------------------------------- 1 | { config, ... }: 2 | 3 | { 4 | 5 | imports = [ ../common ]; 6 | 7 | my = { 8 | host = "pi"; 9 | role = "server"; 10 | }; 11 | 12 | users.users.katexochen = { 13 | isNormalUser = true; 14 | extraGroups = [ 15 | "wheel" 16 | "docker" 17 | ]; 18 | }; 19 | 20 | zramSwap.enable = true; 21 | 22 | programs = { 23 | tmux = { 24 | enable = true; 25 | clock24 = true; 26 | terminal = "screen-256color"; 27 | historyLimit = 10000; 28 | }; 29 | }; 30 | 31 | services.adguardhome = { 32 | enable = true; 33 | openFirewall = true; 34 | host = "0.0.0.0"; 35 | port = 3000; 36 | settings = { 37 | schema_version = 29; 38 | clients.runtime_sources = { 39 | whois = true; 40 | arp = true; 41 | rdns = true; 42 | dhcp = true; 43 | hosts = false; 44 | }; 45 | dns = { 46 | port = 53; 47 | bind_hosts = [ "0.0.0.0" ]; 48 | bootstrap_dns = [ "1.1.1.1" ]; 49 | local_ptr_upstreams = [ "192.168.178.1" ]; 50 | upstream_dns = [ 51 | "9.9.9.9" 52 | "149.112.112.112" 53 | "2620:fe::11" 54 | "2620:fe::fe:11" 55 | "https://dns10.quad9.net/dns-query" 56 | "8.8.8.8" 57 | "8.8.4.4" 58 | "2001:4860:4860::8888" 59 | "2001:4860:4860::8844" 60 | "https://dns.google/dns-query" 61 | "1.1.1.1" 62 | "1.0.0.1" 63 | "2606:4700:4700::64" 64 | "2606:4700:4700::6400" 65 | "https://dns.cloudflare.com/dns-query" 66 | ]; 67 | upstream_mode = "fastest_addr"; 68 | filtering = { 69 | protection_enabled = true; 70 | filtering_enabled = true; 71 | parental_enabled = false; 72 | safesearch_enabled = false; 73 | safebrowsing_enabled = false; 74 | }; 75 | }; 76 | filters = 77 | map 78 | (url: { 79 | enabled = true; 80 | url = url; 81 | }) 82 | [ 83 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt" # AdGuard DNS filter 84 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_24.txt" # 1Hosts (Lite) 85 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_27.txt" # OISD Blocklist Big 86 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_33.txt" # Steven Black's List 87 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_3.txt" # Peter Lowe's Blocklist 88 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_48.txt" # HaGeZi's Pro Blocklist 89 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_4.txt" # Dan Pollock's List 90 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_53.txt" # AWAvenue Ads Rule 91 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_59.txt" # AdGuard DNS Popup Hosts filter 92 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_39.txt" # Dandelion Sprout's Anti Push Notifications 93 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_47.txt" # HaGeZi's Gambling Blocklist 94 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_60.txt" # HaGeZi's Xiaomi Tracker Blocklist 95 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_61.txt" # HaGeZi's Samsung Tracker Blocklist 96 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_63.txt" # HaGeZi's Windows/Office Tracker Blocklist 97 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_6.txt" # Dandelion Sprout's Game Console Adblock List 98 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_7.txt" # Perflyst and Dandelion Sprout's Smart-TV Blocklist 99 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_10.txt" # Scam Blocklist by DurableNapkin 100 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_11.txt" # Malicious URL Blocklist (URLHaus) 101 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_12.txt" # Dandelion Sprout's Anti-Malware List 102 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_18.txt" # Phishing Army 103 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_30.txt" # Phishing URL Blocklist (PhishTank and OpenPhish) 104 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_42.txt" # ShadowWhisperer's Malware List 105 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_44.txt" # HaGeZi's Threat Intelligence Feeds 106 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_50.txt" # uBlock₀ filters – Badware risks 107 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_54.txt" # HaGeZi's DynDNS Blocklist 108 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_55.txt" # HaGeZi's Badware Hoster Blocklist 109 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_8.txt" # NoCoin Filter List 110 | "https://adguardteam.github.io/HostlistsRegistry/assets/filter_9.txt" # The Big List of Hacked Malware Web Sites 111 | ]; 112 | }; 113 | }; 114 | 115 | boot = { 116 | loader = { 117 | grub.enable = false; 118 | generic-extlinux-compatible.enable = true; 119 | timeout = 7; 120 | }; 121 | initrd.availableKernelModules = [ 122 | "xhci_pci" 123 | "usbhid" 124 | "usb_storage" 125 | ]; 126 | }; 127 | 128 | networking = { 129 | useDHCP = true; 130 | firewall = { 131 | enable = true; 132 | allowedUDPPorts = [ config.services.adguardhome.settings.dns.port ]; 133 | allowedTCPPorts = [ config.services.adguardhome.settings.dns.port ]; 134 | }; 135 | }; 136 | 137 | services.getty.autologinUser = "root"; 138 | 139 | fileSystems."/" = { 140 | device = "/dev/disk/by-label/NIXOS_SD"; 141 | fsType = "ext4"; 142 | options = [ "noatime" ]; 143 | }; 144 | swapDevices = [ ]; 145 | 146 | security.sudo.wheelNeedsPassword = false; 147 | 148 | hardware.enableRedistributableFirmware = true; 149 | hardware.raspberry-pi."3".leds = { 150 | act.disable = true; 151 | pwr.disable = true; 152 | eth.disable = true; 153 | }; 154 | system.stateVersion = "25.11"; 155 | } 156 | -------------------------------------------------------------------------------- /hosts/vm-builder/configuration.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkgs, 4 | lib, 5 | inputs, 6 | ... 7 | }: 8 | { 9 | imports = [ ../common ]; 10 | 11 | my = { 12 | host = "vm-builder"; 13 | role = "server"; 14 | }; 15 | 16 | users.users.katexochen = { 17 | isNormalUser = true; 18 | extraGroups = [ 19 | "wheel" 20 | "docker" 21 | ]; 22 | }; 23 | 24 | zramSwap.enable = true; 25 | 26 | environment.systemPackages = with pkgs; [ 27 | btop 28 | gdu 29 | git 30 | go 31 | gotools 32 | nixpkgs-review 33 | starship 34 | ]; 35 | 36 | programs.tmux = { 37 | enable = true; 38 | clock24 = true; 39 | terminal = "screen-256color"; 40 | historyLimit = 10000; 41 | }; 42 | 43 | virtualisation.docker.enable = true; 44 | 45 | nix = { 46 | registry = lib.mapAttrs (_: value: { flake = value; }) inputs; 47 | nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry; 48 | settings = { 49 | experimental-features = [ 50 | "nix-command" 51 | "flakes" 52 | ]; 53 | auto-optimise-store = true; 54 | # max-jobs = 6; 55 | # cores = 8; 56 | }; 57 | }; 58 | 59 | boot = { 60 | loader = { 61 | systemd-boot.enable = true; 62 | timeout = 7; 63 | }; 64 | initrd.kernelModules = [ 65 | "nvme" 66 | "virtio_net" 67 | "virtio_pci" 68 | "virtio_mmio" 69 | "virtio_blk" 70 | "virtio_scsi" 71 | "9p" 72 | "9pnet_virtio" 73 | ]; 74 | kernelModules = [ 75 | "virtio_pci" 76 | "virtio_net" 77 | "virtio_balloon" 78 | "virtio_console" 79 | "virtio_rng" 80 | "virtio_gpu" 81 | ]; 82 | }; 83 | 84 | systemd.network.enable = true; 85 | networking.useDHCP = true; 86 | 87 | # debugging 88 | boot.kernelParams = [ 89 | "systemd.setenv=SYSTEMD_SULOGIN_FORCE=1" 90 | "console=/dev/tty0" 91 | "console=ttyS0" 92 | "console=tty1" 93 | ]; 94 | 95 | services.getty.autologinUser = "root"; 96 | services.udev.packages = [ pkgs.google-guest-configs ]; 97 | services.udev.path = [ pkgs.google-guest-configs ]; 98 | 99 | disko.devices.disk.sda = { 100 | device = "/dev/sda"; 101 | type = "disk"; 102 | content = { 103 | type = "gpt"; 104 | partitions = { 105 | ESP = { 106 | type = "EF00"; 107 | size = "500M"; 108 | content = { 109 | type = "filesystem"; 110 | format = "vfat"; 111 | mountpoint = "/boot"; 112 | }; 113 | }; 114 | root = { 115 | size = "100%"; 116 | content = { 117 | type = "btrfs"; 118 | extraArgs = [ "-f" ]; 119 | subvolumes = { 120 | "@" = { 121 | mountpoint = "/"; 122 | }; 123 | "@home" = { 124 | mountpoint = "/home"; 125 | mountOptions = [ 126 | "compress=zstd" 127 | "noatime" 128 | ]; 129 | }; 130 | "@nix" = { 131 | mountpoint = "/nix"; 132 | mountOptions = [ 133 | "compress=zstd" 134 | "noatime" 135 | ]; 136 | }; 137 | }; 138 | }; 139 | }; 140 | }; 141 | }; 142 | }; 143 | 144 | system.stateVersion = "24.10"; 145 | } 146 | -------------------------------------------------------------------------------- /infra/aws-builder/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "instance" { 2 | name_prefix = "nix-builder-${local.uid}-" 3 | description = "Nix builder instance security group" 4 | revoke_rules_on_delete = true 5 | } 6 | 7 | resource "aws_security_group_rule" "ssh_in" { 8 | type = "ingress" 9 | from_port = 22 10 | to_port = 22 11 | protocol = "tcp" 12 | cidr_blocks = ["0.0.0.0/0"] 13 | security_group_id = aws_security_group.instance.id 14 | description = "Nix builder ssh access" 15 | } 16 | 17 | resource "aws_security_group_rule" "egress" { 18 | type = "egress" 19 | from_port = 0 20 | to_port = 65535 21 | protocol = -1 22 | security_group_id = aws_security_group.instance.id 23 | cidr_blocks = ["0.0.0.0/0"] 24 | description = "Nix builder egress" 25 | } 26 | 27 | resource "aws_key_pair" "ec2_key" { 28 | key_name = "deployer-key-${local.uid}" 29 | public_key = file(var.install_ssh_pub_path) 30 | } 31 | 32 | module "ec2_instance" { 33 | source = "terraform-aws-modules/ec2-instance/aws" 34 | 35 | name = "nix-builder-${local.uid}" 36 | 37 | instance_type = "c5.9xlarge" 38 | key_name = aws_key_pair.ec2_key.key_name 39 | monitoring = true 40 | ami = "ami-04564c67876ffec56" 41 | vpc_security_group_ids = [aws_security_group.instance.id] 42 | root_block_device = [ 43 | { 44 | volume_type = "gp3" 45 | volume_size = 2048 46 | delete_on_termination = true 47 | } 48 | ] 49 | 50 | tags = { 51 | Terraform = "true" 52 | Environment = "dev" 53 | } 54 | } 55 | 56 | module "system-build" { 57 | source = "git::https://github.com/nix-community/nixos-anywhere.git//terraform/nix-build?ref=bd3f79f11d030d9fa2cf18d3ad096dfdc98abcc8" 58 | attribute = var.nixos_system_attr 59 | file = var.file 60 | } 61 | 62 | module "partitioner-build" { 63 | source = "git::https://github.com/nix-community/nixos-anywhere.git//terraform/nix-build?ref=bd3f79f11d030d9fa2cf18d3ad096dfdc98abcc8" 64 | attribute = var.nixos_partitioner_attr 65 | file = var.file 66 | } 67 | 68 | module "install" { 69 | source = "git::https://github.com/nix-community/nixos-anywhere.git//terraform/install?ref=bd3f79f11d030d9fa2cf18d3ad096dfdc98abcc8" 70 | kexec_tarball_url = var.kexec_tarball_url 71 | target_user = local.install_user 72 | target_host = module.ec2_instance.public_ip 73 | target_port = var.target_port 74 | nixos_partitioner = module.partitioner-build.result.out 75 | nixos_system = module.system-build.result.out 76 | ssh_private_key = file(var.install_ssh_key_path) 77 | debug_logging = var.debug_logging 78 | stop_after_disko = var.stop_after_disko 79 | extra_files_script = var.extra_files_script 80 | disk_encryption_key_scripts = var.disk_encryption_key_scripts 81 | extra_environment = var.extra_environment 82 | instance_id = var.instance_id 83 | # no_reboot = var.no_reboot 84 | } 85 | 86 | module "nixos-rebuild" { 87 | depends_on = [ 88 | module.install 89 | ] 90 | 91 | # Do not execute this step if var.stop_after_disko == true 92 | count = var.stop_after_disko ? 0 : 1 93 | 94 | source = "git::https://github.com/nix-community/nixos-anywhere.git//terraform/nixos-rebuild?ref=bd3f79f11d030d9fa2cf18d3ad096dfdc98abcc8" 95 | nixos_system = module.system-build.result.out 96 | ssh_private_key = file(var.deployment_ssh_key_path) 97 | target_host = module.ec2_instance.public_ip 98 | target_user = var.target_user 99 | } 100 | 101 | resource "random_id" "uid" { 102 | byte_length = 8 103 | } 104 | 105 | locals { 106 | uid = random_id.uid.hex 107 | install_user = var.install_user == null ? var.target_user : var.install_user 108 | } 109 | -------------------------------------------------------------------------------- /infra/aws-builder/outputs.tf: -------------------------------------------------------------------------------- 1 | output "hostname" { 2 | value = module.ec2_instance.public_ip 3 | } 4 | -------------------------------------------------------------------------------- /infra/aws-builder/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | random = { 4 | source = "hashicorp/random" 5 | version = "3.5.1" 6 | } 7 | aws = { 8 | source = "hashicorp/aws" 9 | version = "5.17.0" 10 | } 11 | } 12 | } 13 | 14 | provider "aws" { 15 | region = var.region 16 | } 17 | -------------------------------------------------------------------------------- /infra/aws-builder/variables.tf: -------------------------------------------------------------------------------- 1 | variable "kexec_tarball_url" { 2 | type = string 3 | description = "NixOS kexec installer tarball url" 4 | default = null 5 | } 6 | 7 | # To make this re-usable we maybe should accept a store path here? 8 | variable "nixos_partitioner_attr" { 9 | type = string 10 | default = "..#nixosConfigurations.aws-builder.config.system.build.diskoScript" 11 | description = "Nixos partitioner and mount script i.e. your-flake#nixosConfigurations.your-evaluated-nixos.config.system.build.diskoNoDeps or just your-evaluated.config.system.build.diskNoDeps. `config.system.build.diskNoDeps` is provided by the disko nixos module" 12 | } 13 | 14 | # To make this re-usable we maybe should accept a store path here? 15 | variable "nixos_system_attr" { 16 | type = string 17 | default = "..#nixosConfigurations.aws-builder.config.system.build.toplevel" 18 | description = "The nixos system to deploy i.e. your-flake#nixosConfigurations.your-evaluated-nixos.config.system.build.toplevel or just your-evaluated-nixos.config.system.build.toplevel if you are not using flakes" 19 | } 20 | 21 | variable "file" { 22 | type = string 23 | description = "Nix file containing the nixos_system_attr and nixos_partitioner_attr. Use this if you are not using flake" 24 | default = null 25 | } 26 | 27 | variable "install_user" { 28 | type = string 29 | description = "SSH user used to connect to the target_host, before installing NixOS. If null than the value of `target_host` is used" 30 | default = "ec2-user" 31 | } 32 | 33 | variable "target_user" { 34 | type = string 35 | description = "SSH user used to connect to the target_host after installing NixOS. If install_user is not set than this user is also used before installing." 36 | default = "root" 37 | } 38 | 39 | variable "target_port" { 40 | type = number 41 | description = "SSH port used to connect to the target_host, before installing NixOS" 42 | default = 22 43 | } 44 | 45 | variable "instance_id" { 46 | type = string 47 | description = "The instance id of the target_host, used to track when to reinstall the machine" 48 | default = null 49 | } 50 | 51 | variable "install_ssh_key_path" { 52 | type = string 53 | description = "Content of private key used to connect to the target_host during initial installation" 54 | # sensitive = true 55 | default = "~/.ssh/remote_builder" 56 | } 57 | 58 | variable "deployment_ssh_key_path" { 59 | type = string 60 | description = "Content of private key used to deploy to the target_host after initial installation. To ensure maximum security, it is advisable to connect to your host using ssh-agent instead of relying on this variable" 61 | # sensitive = true 62 | default = "~/.ssh/remote_builder" 63 | } 64 | 65 | variable "install_ssh_pub_path" { 66 | type = string 67 | description = "Content of public key used to connect to the target_host during initial installation" 68 | default = "~/.ssh/remote_builder.pub" 69 | } 70 | 71 | variable "deployment_ssh_pub_path" { 72 | type = string 73 | description = "Content of public key used to deploy to the target_host after initial installation" 74 | default = "~/.ssh/remote_builder.pub" 75 | } 76 | 77 | variable "debug_logging" { 78 | type = bool 79 | description = "Enable debug logging" 80 | default = false 81 | } 82 | 83 | variable "stop_after_disko" { 84 | type = bool 85 | description = "Exit after disko formatting" 86 | default = false 87 | } 88 | 89 | variable "extra_files_script" { 90 | type = string 91 | description = "A script file that prepares extra files to be copied to the target host during installation. The script expected to write all its files to the current directory. This directory is rsynced to the target host during installation to the / directory." 92 | default = null 93 | } 94 | 95 | variable "disk_encryption_key_scripts" { 96 | type = list(object({ 97 | path = string 98 | script = string 99 | })) 100 | description = "Each of these script files will be executed locally and the output of each of them will be made present at the given path to disko during installation. The keys will be not copied to the final system" 101 | default = [] 102 | } 103 | 104 | variable "extra_environment" { 105 | type = map(string) 106 | description = "Extra environment variables to be set during installation. This can be usefull to set extra variables for the extra_files_script or disk_encryption_key_scripts" 107 | default = {} 108 | } 109 | 110 | variable "no_reboot" { 111 | type = bool 112 | description = "Do not reboot after installation" 113 | default = false 114 | } 115 | 116 | variable "region" { 117 | type = string 118 | description = "AWS region" 119 | default = "eu-central-1" 120 | } 121 | -------------------------------------------------------------------------------- /lib/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | nixpkgs, 3 | ... 4 | }: 5 | 6 | { 7 | eachSystem = 8 | f: 9 | nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed (system: f nixpkgs.legacyPackages.${system}); 10 | } 11 | -------------------------------------------------------------------------------- /modules/btrfs-luks.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | let 8 | cfg = config.my.modules.btrfs-luks; 9 | in 10 | { 11 | options.my.modules.btrfs-luks = { 12 | enable = lib.mkEnableOption (lib.mkDoc "btrfs-luks"); 13 | disk = lib.mkOption { 14 | type = lib.types.str; 15 | default = "/dev/nvme0n1"; 16 | description = "Disk to install to"; 17 | }; 18 | }; 19 | 20 | config = lib.mkIf cfg.enable { 21 | disko.devices = 22 | (pkgs.callPackage ./disko/btrfs-luks.nix { 23 | inherit lib; 24 | inherit (cfg) disk; 25 | }).disko.devices; 26 | 27 | fileSystems."/persist".neededForBoot = true; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /modules/common.nix: -------------------------------------------------------------------------------- 1 | { 2 | imports = [ 3 | ./my.nix 4 | ./remote-builders.nix 5 | ./rpi-3-leds.nix 6 | ]; 7 | } 8 | -------------------------------------------------------------------------------- /modules/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | 3 | { 4 | imports = [ 5 | ./impermanence 6 | ./main.nix 7 | ./btrfs-luks.nix 8 | ./graphical.nix 9 | ]; 10 | networking.networkmanager.enable = true; # Easiest to use and most distros use this by default. 11 | 12 | users = { 13 | mutableUsers = false; 14 | users.root.hashedPasswordFile = "/persist/secrets/root"; 15 | users.katexochen = { 16 | hashedPasswordFile = "/persist/secrets/katexochen"; 17 | isNormalUser = true; 18 | extraGroups = [ 19 | "wheel" # Enable 'sudo' for user. 20 | "video" # Access to webcam and other video devices. 21 | "audio" # Access to soundcard and micro. 22 | "networkmanager" 23 | "lp" # Enable use of printers. 24 | "scanner" # Enable use of scanners. 25 | "docker" # Access to the docker socket. 26 | "adbusers" 27 | ]; 28 | }; 29 | }; 30 | 31 | environment.systemPackages = with pkgs; [ 32 | mkpasswordfile 33 | nm-setup-rub-eduroam 34 | nodeshell 35 | swaylock-cmd 36 | matrixc 37 | ]; 38 | 39 | home-manager = { 40 | # As suggested by https://nix-community.github.io/home-manager/index.html#sec-install-nixos-module 41 | useUserPackages = true; 42 | useGlobalPkgs = true; 43 | }; 44 | 45 | home-manager.users.katexochen = 46 | { ... }: 47 | { 48 | imports = [ ../home ]; 49 | 50 | home.stateVersion = "22.05"; 51 | home.enableNixpkgsReleaseCheck = true; 52 | 53 | home.sessionVariables = { 54 | MOZ_ENABLE_WAYLAND = 1; 55 | XDG_CURRENT_DESKTOP = "sway"; 56 | GOPRIVATE = "github.com/edgelesssys"; 57 | }; 58 | 59 | fonts.fontconfig.enable = true; 60 | 61 | xdg.configFile."nixpkgs/config.nix".text = '' 62 | { 63 | allowUnfree = true; 64 | } 65 | ''; 66 | }; 67 | 68 | hardware.bluetooth.enable = true; 69 | 70 | # Needed to store VS Code auth tokens. 71 | services.gnome.gnome-keyring.enable = true; 72 | } 73 | -------------------------------------------------------------------------------- /modules/disko/btrfs-luks.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | disk, 4 | ... 5 | }: 6 | let 7 | btrfMountOpts = [ 8 | "compress=zstd" 9 | "noatime" 10 | ]; 11 | in 12 | { 13 | disko.devices = { 14 | disk = lib.genAttrs [ disk ] (device: { 15 | name = lib.replaceStrings [ "/" ] [ "-" ] device; 16 | inherit device; 17 | type = "disk"; 18 | content = { 19 | type = "gpt"; 20 | partitions = { 21 | ESP = { 22 | size = "512M"; 23 | type = "EF00"; 24 | content = { 25 | type = "filesystem"; 26 | format = "vfat"; 27 | mountpoint = "/boot"; 28 | mountOptions = [ "defaults" ]; 29 | }; 30 | }; 31 | luks = { 32 | size = "100%"; 33 | content = { 34 | type = "luks"; 35 | name = "crypted"; 36 | extraOpenArgs = [ "--allow-discards" ]; 37 | askPassword = true; 38 | content = { 39 | type = "btrfs"; 40 | extraArgs = [ "-f" ]; 41 | subvolumes = { 42 | "@" = { 43 | mountpoint = "/"; 44 | mountOptions = btrfMountOpts; 45 | }; 46 | "@nix" = { 47 | mountpoint = "/nix"; 48 | mountOptions = btrfMountOpts; 49 | }; 50 | "@home" = { 51 | mountpoint = "/home"; 52 | mountOptions = btrfMountOpts; 53 | }; 54 | "@persist" = { 55 | mountpoint = "/persist"; 56 | mountOptions = btrfMountOpts; 57 | }; 58 | "@varlog" = { 59 | mountpoint = "/var/log"; 60 | mountOptions = btrfMountOpts; 61 | }; 62 | }; 63 | }; 64 | }; 65 | }; 66 | }; 67 | }; 68 | }); 69 | }; 70 | } 71 | -------------------------------------------------------------------------------- /modules/graphical.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | { 3 | hardware.graphics.enable = true; 4 | 5 | boot = { 6 | supportedFilesystems = [ "ntfs" ]; 7 | # puts systemd init logs on tty1 8 | # so that tuigreet and systemd logs don't clobber each other 9 | kernelParams = [ "console=tty1" ]; 10 | }; 11 | 12 | xdg.portal = { 13 | enable = true; 14 | wlr.enable = true; 15 | extraPortals = with pkgs; [ xdg-desktop-portal-gtk ]; 16 | config.common.default = "*"; 17 | }; 18 | 19 | # Allow swaylock to unlock the computer for us 20 | security.pam.services = { 21 | swaylock = { 22 | text = "auth include login"; 23 | }; 24 | swaylock-plugin = { 25 | text = "auth include login"; 26 | }; 27 | }; 28 | 29 | services = { 30 | printing.enable = true; 31 | avahi = { 32 | enable = true; 33 | nssmdns4 = true; 34 | openFirewall = true; 35 | }; 36 | pipewire = { 37 | enable = true; 38 | alsa.enable = true; 39 | pulse.enable = true; 40 | }; 41 | greetd = { 42 | enable = true; 43 | vt = 2; 44 | settings = { 45 | default_session = { 46 | command = '' 47 | ${pkgs.greetd.tuigreet}/bin/tuigreet \ 48 | --remember \ 49 | --time \ 50 | --asterisks \ 51 | --cmd ${pkgs.sway}/bin/sway 52 | ''; 53 | }; 54 | }; 55 | }; 56 | }; 57 | 58 | fonts.enableDefaultPackages = true; 59 | fonts.fontconfig = { 60 | enable = true; 61 | antialias = true; 62 | hinting = { 63 | enable = true; 64 | autohint = true; # no difference 65 | }; 66 | subpixel = { 67 | rgba = "rgb"; 68 | lcdfilter = "default"; # no difference 69 | }; 70 | }; 71 | } 72 | -------------------------------------------------------------------------------- /modules/impermanence/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | let 3 | fs-diff = pkgs.writeShellApplication { 4 | name = "fs-diff"; 5 | text = builtins.readFile ./fs-diff.sh; 6 | }; 7 | 8 | persist = pkgs.writeShellApplication { 9 | name = "persist"; 10 | text = builtins.readFile ./persist.sh; 11 | }; 12 | in 13 | { 14 | imports = [ ./mod.nix ]; 15 | 16 | environment.systemPackages = [ 17 | fs-diff 18 | persist 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /modules/impermanence/fs-diff.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # fs-diff.sh 3 | 4 | set -euo pipefail 5 | 6 | cleanup=() 7 | 8 | if [[ ! -e "/mnt" ]]; then 9 | sudo mkdir -p /mnt 10 | cleanup+=("sudo rm -d /mnt") 11 | fi 12 | 13 | if [[ ! $(findmnt /mnt) ]]; then 14 | sudo mount -o subvol=/ /dev/mapper/crypted /mnt 15 | cleanup+=("sudo umount /mnt") 16 | fi 17 | 18 | oldTransID=$(sudo btrfs subvolume find-new /mnt/root-blank 9999999) 19 | oldTransID=${oldTransID#transid marker was } 20 | 21 | sudo btrfs subvolume find-new "/mnt/root" "${oldTransID}" | 22 | sed '$d' | 23 | cut -f17- -d' ' | 24 | sort | 25 | uniq | 26 | while read -r path; do 27 | path="/${path}" 28 | if [ -L "${path}" ]; then 29 | : # The path is a symbolic link, so is probably handled by NixOS already 30 | elif [ -d "${path}" ]; then 31 | : # The path is a directory, ignore 32 | else 33 | echo "${path}" 34 | fi 35 | done 36 | 37 | exitcode=0 38 | 39 | # Cleanup in reverse order 40 | readarray -t <<<"$(printf '%s\n' "${cleanup[@]}" | tac)" 41 | for cmd in "${MAPFILE[@]}"; do 42 | eval "${cmd}" || exitcode=$? 43 | done 44 | 45 | exit "${exitcode}" 46 | -------------------------------------------------------------------------------- /modules/impermanence/mod.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.my.modules.impermanence; 10 | in 11 | { 12 | options.my.modules = { 13 | impermanence = { 14 | enable = lib.mkEnableOption (lib.mdDoc "impermanence"); 15 | }; 16 | }; 17 | 18 | config = lib.mkIf cfg.enable { 19 | environment.persistence."/persist" = { 20 | hideMounts = true; 21 | directories = [ 22 | "/etc/NetworkManager/system-connections" 23 | "/root/.local/share/nix/" 24 | "/root/.ssh" 25 | "/var/cache/tuigreet" 26 | "/var/lib/bluetooth" 27 | "/var/lib/NetworkManager" 28 | "/var/lib/nixos" 29 | "/var/lib/systemd/backlight" 30 | "/var/lib/tailscale" 31 | ]; 32 | files = [ 33 | "/etc/adjtime" 34 | "/etc/docker/key.json" 35 | "/etc/machine-id" 36 | ]; 37 | }; 38 | 39 | boot.initrd.postResumeCommands = pkgs.lib.mkAfter '' 40 | echo "impermanence: Starting backup and cleanup procedure" >&2 41 | mkdir /btrfs_tmp 42 | mount /dev/mapper/crypted /btrfs_tmp 43 | 44 | delete_subvolume_recursively() { 45 | IFS=$'\n' 46 | for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do 47 | delete_subvolume_recursively "/btrfs_tmp/$i" 48 | done 49 | btrfs subvolume delete "$1" 50 | echo "impermanence: Deleted subvolume $1" >&2 51 | } 52 | 53 | if [[ -e /btrfs_tmp/@ ]]; then 54 | delete_subvolume_recursively /btrfs_tmp/@ 55 | fi 56 | 57 | btrfs subvolume create /btrfs_tmp/@ 58 | echo "impermanence: Created new root subvolume at /btrfs_tmp/@" >&2 59 | 60 | umount /btrfs_tmp 61 | echo "impermanence: Done" >&2 62 | ''; 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /modules/impermanence/persist.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # wl-paste | xargs ./persist.sh 4 | 5 | set -euo pipefail 6 | 7 | persistDir="/persist" 8 | 9 | if [[ -z ${1-} ]]; then 10 | echo "Persist a path to the persisten subvolume" 11 | echo 12 | echo "Usage:" 13 | echo " ${0} /path/a [/path/b /path/c ...]" 14 | exit 0 15 | fi 16 | 17 | persist() { 18 | src=$1 19 | dst="${persistDir}${src}" 20 | srcDir=$(dirname "$src") 21 | dstDir="${persistDir}${srcDir}" 22 | 23 | if [[ -f $src ]]; then 24 | : 25 | elif [[ -d $src ]]; then 26 | : 27 | else 28 | echo "Source '$1' is neither file nor dir" 29 | return 1 30 | fi 31 | 32 | sudo mkdir -p "$dstDir" 33 | sudo mv -n "$src" "$dst" 34 | } 35 | 36 | exitcode=0 37 | 38 | for arg in "$@"; do 39 | if persist "$arg"; then 40 | echo "$arg" 41 | else 42 | exitcode=$? 43 | fi 44 | done 45 | 46 | exit $exitcode 47 | -------------------------------------------------------------------------------- /modules/main.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | pkgs, 4 | ... 5 | }: 6 | 7 | { 8 | config = { 9 | boot = { 10 | kernelPackages = pkgs.linuxPackages_latest; 11 | loader.systemd-boot = { 12 | enable = true; 13 | configurationLimit = 30; 14 | }; 15 | loader.efi.canTouchEfiVariables = true; 16 | tmp.cleanOnBoot = true; 17 | }; 18 | 19 | console.useXkbConfig = true; 20 | zramSwap.enable = true; 21 | 22 | services = { 23 | earlyoom.enable = true; 24 | fwupd.enable = true; 25 | dbus.enable = true; 26 | tailscale.enable = true; 27 | xserver.xkb = { 28 | layout = "us-custom,de-custom"; 29 | options = "ctrl:nocaps,grp:win_space_toggle"; 30 | extraLayouts = { 31 | # Custom keyboard layout 32 | # https://nixos.org/manual/nixos/stable/#custom-xkb-layouts 33 | # https://discourse.nixos.org/t/5269 34 | # On change, run the following and logout: 35 | # gsettings reset org.gnome.desktop.input-sources xkb-options 36 | # gsettings reset org.gnome.desktop.input-sources sources 37 | us-custom = { 38 | description = "US custom layout"; 39 | languages = [ "eng" ]; 40 | symbolsFile = pkgs.copyPathToStore ../symbols/us-custom; 41 | }; 42 | de-custom = { 43 | description = "DE custom layout"; 44 | languages = [ "ger" ]; 45 | symbolsFile = pkgs.copyPathToStore ../symbols/de-custom; 46 | }; 47 | }; 48 | }; 49 | }; 50 | 51 | virtualisation.docker.enable = true; 52 | 53 | security.sudo.extraConfig = '' 54 | Defaults lecture = never 55 | ''; 56 | 57 | system.activationScripts.diff = '' 58 | PATH=$PATH:${ 59 | lib.makeBinPath [ 60 | pkgs.nvd 61 | pkgs.nix 62 | ] 63 | } 64 | nvd diff $(ls -dv /nix/var/nix/profiles/system-*-link | tail -2) 65 | ''; 66 | # system.activationScripts.diff = '' 67 | # if [[ -e /run/current-system ]]; then 68 | # ${pkgs.nix}/bin/nix store diff-closures /run/current-system "$systemConfig" 69 | # fi 70 | # ''; 71 | }; 72 | } 73 | -------------------------------------------------------------------------------- /modules/my.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | ... 5 | }: 6 | 7 | let 8 | cfg = config.my; 9 | in 10 | 11 | { 12 | options.my = { 13 | host = lib.mkOption { 14 | type = lib.types.str; 15 | }; 16 | role = lib.mkOption { 17 | type = lib.types.oneOf [ 18 | (lib.types.enum [ 19 | "server" 20 | "client" 21 | ]) 22 | ]; 23 | }; 24 | }; 25 | 26 | config = lib.mkIf (cfg != null) { 27 | networking.hostName = cfg.host; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /modules/remote-builders.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | 3 | let 4 | cfg = config.my.modules.use-remote-builders; 5 | in 6 | 7 | { 8 | options.my.modules.use-remote-builders = { 9 | enable = lib.mkOption { 10 | default = false; 11 | description = lib.mkDoc "remote builder"; 12 | type = lib.types.bool; 13 | }; 14 | }; 15 | 16 | config = lib.mkIf cfg.enable { 17 | nix = { 18 | distributedBuilds = true; 19 | buildMachines = [ 20 | { 21 | hostName = "builder"; 22 | system = "x86_64-linux"; 23 | protocol = "ssh-ng"; 24 | supportedFeatures = [ 25 | "nixos-test" 26 | "big-parallel" 27 | "kvm" 28 | "benchmark" 29 | ]; 30 | maxJobs = 6; 31 | speedFactor = 12; 32 | } 33 | { 34 | hostName = "dell-3340-kirby"; 35 | system = "x86_64-linux"; 36 | protocol = "ssh-ng"; 37 | supportedFeatures = [ 38 | "nixos-test" 39 | "big-parallel" 40 | "kvm" 41 | "benchmark" 42 | ]; 43 | maxJobs = 3; 44 | speedFactor = 4; 45 | } 46 | { 47 | hostName = "dell-3340-samus"; 48 | system = "x86_64-linux"; 49 | protocol = "ssh-ng"; 50 | supportedFeatures = [ 51 | "nixos-test" 52 | "big-parallel" 53 | "kvm" 54 | "benchmark" 55 | ]; 56 | maxJobs = 3; 57 | speedFactor = 4; 58 | } 59 | ]; 60 | }; 61 | 62 | programs.ssh.extraConfig = '' 63 | Host builder 64 | HostName builder.aro.bz 65 | ConnectTimeout 2 66 | IdentitiesOnly yes 67 | IdentityFile /root/.ssh/remote_builder 68 | User katexochen 69 | Host dell-3340-kirby 70 | HostName dell-3340-kirby 71 | ConnectTimeout 2 72 | IdentitiesOnly yes 73 | IdentityFile /root/.ssh/remote_builder 74 | User katexochen 75 | Host dell-3340-samus 76 | HostName dell-3340-samus 77 | ConnectTimeout 2 78 | IdentitiesOnly yes 79 | IdentityFile /root/.ssh/remote_builder 80 | User katexochen 81 | Host aarch64-build-box 82 | HostName aarch64-build-box.nix-community.org 83 | ConnectTimeout 2 84 | IdentitiesOnly yes 85 | IdentityFile /root/.ssh/remote_builder 86 | User katexochen 87 | Host build-box 88 | HostName build-box.nix-community.org 89 | ConnectTimeout 2 90 | IdentitiesOnly yes 91 | IdentityFile /root/.ssh/remote_builder 92 | User katexochen 93 | Host darwin-build-box 94 | HostName darwin-build-box.nix-community.org 95 | ConnectTimeout 2 96 | IdentitiesOnly yes 97 | IdentityFile /root/.ssh/remote_builder 98 | User katexochen 99 | ''; 100 | }; 101 | } 102 | -------------------------------------------------------------------------------- /modules/rpi-3-leds.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.hardware.raspberry-pi."3".leds; 10 | mkDisableOption = 11 | name: 12 | lib.mkOption { 13 | default = false; 14 | example = true; 15 | description = "Whether to disable ${name}."; 16 | type = lib.types.bool; 17 | }; 18 | in 19 | { 20 | options.hardware.raspberry-pi."3".leds = { 21 | act.disable = mkDisableOption ''activity LED''; 22 | pwr.disable = mkDisableOption ''power LED''; 23 | eth.disable = mkDisableOption ''ethernet LEDs''; 24 | }; 25 | 26 | config = lib.mkMerge [ 27 | (lib.mkIf (cfg.act.disable || cfg.pwr.disable) { 28 | hardware.deviceTree.enable = true; 29 | hardware.deviceTree.filter = "*-rpi-3-*.dtb"; 30 | }) 31 | (lib.mkIf cfg.act.disable { 32 | hardware.deviceTree = { 33 | overlays = [ 34 | # Debugging: 35 | # $ hexdump /proc/device-tree/leds/led-act/gpios 36 | # $ cat /proc/device-tree/leds/led-act/linux,default-trigger 37 | { 38 | name = "disable-act-led"; 39 | dtsText = '' 40 | /dts-v1/; 41 | /plugin/; 42 | / { 43 | compatible = "raspberrypi,3-model-b"; 44 | fragment@0 { 45 | target-path = "/leds/led-act"; 46 | __overlay__ { 47 | default-state = "off"; 48 | linux,default-trigger = "none"; 49 | }; 50 | }; 51 | }; 52 | ''; 53 | } 54 | ]; 55 | }; 56 | }) 57 | (lib.mkIf cfg.pwr.disable { 58 | hardware.deviceTree = { 59 | overlays = [ 60 | # Checking the active device tree: 61 | # $ dtc -I fs /proc/device-tree -O dts 2>/dev/null | grep led-pwr -A7 62 | # Checking the path: 63 | # $ cat /proc/device-tree/__symbols__/led_pwr 64 | # Checking the state: 65 | # $ cat /proc/device-tree/leds/led-pwr/default-state 66 | # $ cat /proc/device-tree/leds/led-pwr/linux,default-trigger 67 | # Checking if the overlay is applied: 68 | # nixos-rebuild build 69 | # nix log $(realpath result/dtbs) 70 | { 71 | name = "disable-pwr-led"; 72 | dtsText = '' 73 | /dts-v1/; 74 | /plugin/; 75 | / { 76 | compatible = "raspberrypi,3-model-b"; 77 | fragment@0 { 78 | target-path = "/leds/led-pwr"; 79 | __overlay__ { 80 | default-state = "off"; 81 | linux,default-trigger = "none"; 82 | }; 83 | }; 84 | }; 85 | ''; 86 | } 87 | ]; 88 | }; 89 | }) 90 | (lib.mkIf cfg.eth.disable { 91 | # Note: RPi 3B has ethernet over USB (LAN9514), so the ethernet device isn't 92 | # exposed via device tree and therefore eth leds cannot be disabled via such. 93 | # Instead, we can use the lan951x-led-ctl utility to control the LEDs. 94 | # The later RPi models (3B+ and 4) have the ethernet controller integrated 95 | # into the SoC and can disable the LEDs via device tree. 96 | systemd.services.disable-rpi-eth-leds = { 97 | description = "Disable Raspberry Pi 3B Ethernet LEDs using lan951x-led-ctl"; 98 | after = [ "network.target" ]; 99 | wantedBy = [ "multi-user.target" ]; 100 | serviceConfig = { 101 | Type = "oneshot"; 102 | RemainAfterExit = true; 103 | ExecStart = "${pkgs.lan951x-led-ctl}/bin/lan951x-led-ctl --fdx=0 --lnk=0 --spd=0"; 104 | }; 105 | }; 106 | }) 107 | ]; 108 | } 109 | -------------------------------------------------------------------------------- /overlays/default.nix: -------------------------------------------------------------------------------- 1 | _: 2 | 3 | { 4 | modifications = _final: _prev: { 5 | # example = prev.example.overrideAttrs (oldAttrs: rec { 6 | # ... 7 | # }); 8 | }; 9 | 10 | additions = final: _prev: (import ../packages { inherit (final) pkgs; }); 11 | } 12 | -------------------------------------------------------------------------------- /packages/by-name/lan951x-led-ctl/package.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | fetchgit, 5 | cmake, 6 | pkg-config, 7 | gitMinimal, 8 | libusb1, 9 | }: 10 | 11 | stdenv.mkDerivation (finalAttrs: { 12 | pname = "lan951x-led-ctl"; 13 | version = "1.1-unstable-2024-01-22"; 14 | 15 | src = fetchgit { 16 | url = "https://git.familie-radermacher.ch/linux/lan951x-led-ctl.git/"; 17 | rev = "96bfb76dc4cf262baa13be03202fd2813494b41b"; 18 | hash = "sha256-Z6CKox7G7WT8SLpZUhTb0urHPnFoxiyzX6VvjINHpsc="; 19 | }; 20 | 21 | postPatch = '' 22 | substituteInPlace CMakeLists.txt \ 23 | --replace-fail 'set(CMAKE_INSTALL_PREFIX /usr)' \ 24 | 'set(CMAKE_INSTALL_PREFIX ${builtins.placeholder "out"})' 25 | substituteInPlace cmake/gitversion.cmake \ 26 | --replace-fail '#define VERSION \"''${GIT_TAG}.r''${GIT_COMMITS}.g''${GIT_COMMIT_SHORT}''${GIT_DIFF}\"' \ 27 | '#define VERSION \"v${finalAttrs.version}\"' 28 | ''; 29 | 30 | nativeBuildInputs = [ 31 | cmake 32 | pkg-config 33 | gitMinimal 34 | ]; 35 | 36 | buildInputs = [ 37 | libusb1 38 | ]; 39 | 40 | meta = { 41 | homepage = "https://git.familie-radermacher.ch/linux/lan951x-led-ctl.git/"; 42 | license = lib.licenses.gpl3; 43 | mainProgram = "lan951x-led-ctl"; 44 | platforms = lib.platforms.all; 45 | }; 46 | }) 47 | -------------------------------------------------------------------------------- /packages/by-name/matrixc.nix: -------------------------------------------------------------------------------- 1 | { writeShellApplication, curl }: 2 | 3 | writeShellApplication { 4 | name = "matrixc"; 5 | runtimeInputs = [ curl ]; 6 | text = builtins.readFile ./matrixc.sh; 7 | } 8 | -------------------------------------------------------------------------------- /packages/by-name/matrixc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | function configDir() { 6 | local configDir=~/.config/matrixc 7 | mkdir -p "$configDir" 8 | echo "$configDir" 9 | } 10 | 11 | function requestToken() { 12 | echo "username: " 13 | read -r username 14 | echo "password: " 15 | read -rs password 16 | 17 | resp=$(curl -fsSL -XPOST \ 18 | -d "{\"type\":\"m.login.password\",\"user\":\"${username}\",\"password\":\"${password}\"}" \ 19 | "https://matrix.org/_matrix/client/r0/login") 20 | token=$(echo "$resp" | jq -r .access_token) 21 | 22 | echo "$token" >"$(configDir)/token" 23 | } 24 | 25 | function readToken() { 26 | cat "$(configDir)/token" 27 | } 28 | 29 | function addRoom() { 30 | echo "Room ID: " 31 | read -r roomId 32 | echo "Room alias: " 33 | read -r roomAlias 34 | 35 | echo "$roomAlias $roomId" >>"$(configDir)/rooms" 36 | } 37 | 38 | function readRoom() { 39 | roomAlias=$1 40 | grep "$roomAlias" "$(configDir)/rooms" | cut -d' ' -f2 41 | } 42 | 43 | function send() { 44 | roomAlias=$1 45 | message=$2 46 | 47 | roomId=$(readRoom "$roomAlias") 48 | token=$(readToken) 49 | 50 | curl -fsSL -XPOST \ 51 | -d "{\"msgtype\":\"m.text\",\"body\":\"${message}\"}" \ 52 | "https://matrix.org/_matrix/client/r0/rooms/${roomId}/send/m.room.message?access_token=${token}" >/dev/null 53 | } 54 | 55 | function main() { 56 | case "${1:-}" in 57 | "login") 58 | requestToken 59 | ;; 60 | "add-room") 61 | addRoom 62 | ;; 63 | "send") 64 | shift 65 | send "$@" 66 | ;; 67 | *) 68 | echo "Usage: matrixc >" 69 | exit 1 70 | ;; 71 | esac 72 | } 73 | 74 | main "$@" 75 | -------------------------------------------------------------------------------- /packages/by-name/mkpasswordfile.nix: -------------------------------------------------------------------------------- 1 | { writeShellApplication }: 2 | writeShellApplication { 3 | name = "mkpasswordfile"; 4 | text = ''mkpasswd -m sha-512 | sudo tee "$1" > /dev/null''; 5 | } 6 | -------------------------------------------------------------------------------- /packages/by-name/nm-setup-rub-eduroam.nix: -------------------------------------------------------------------------------- 1 | { 2 | writeShellApplication, 3 | writeTextFile, 4 | networkmanager, 5 | }: 6 | let 7 | rub-eduroam-cert = writeTextFile { 8 | name = "rub-eduroam-cert"; 9 | text = '' 10 | -----BEGIN CERTIFICATE----- 11 | MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx 12 | KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd 13 | BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl 14 | YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 15 | OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy 16 | aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 17 | ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G 18 | CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd 19 | AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC 20 | FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi 21 | 1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq 22 | jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ 23 | wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj 24 | QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ 25 | WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy 26 | NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC 27 | uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw 28 | IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 29 | g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN 30 | 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP 31 | BSeOE6Fuwg== 32 | -----END CERTIFICATE----- 33 | ''; 34 | }; 35 | in 36 | writeShellApplication { 37 | name = "nm-setup-rub-eduroam"; 38 | runtimeInputs = [ networkmanager ]; 39 | text = '' 40 | set -euo pipefail 41 | 42 | user="''${1:-}" 43 | password="''${2:-}" 44 | 45 | if [[ -z "$user" || -z $password ]]; then 46 | echo "Setup RUB eduroam with networkmanage" 47 | echo "Usage: $0 " 48 | exit 1 49 | fi 50 | 51 | nmcli con delete eduroam || true 52 | nmcli con add \ 53 | type wifi \ 54 | con-name "eduroam" \ 55 | ssid "eduroam" -- \ 56 | 802-1x.eap "ttls" \ 57 | 802-1x.identity "$user" \ 58 | 802-1x.password "$password" \ 59 | 802-1x.anonymous-identity "eduroam@ruhr-uni-bochum.de" \ 60 | 802-1x.ca-cert "${rub-eduroam-cert}" \ 61 | 802-1x.altsubject-matches "DNS:radius.ruhr-uni-bochum.de" \ 62 | 802-1x.phase2-auth "pap" \ 63 | 802-1x.system-ca-certs "no" \ 64 | 802-11-wireless-security.key-mgmt "wpa-eap" \ 65 | 802-11-wireless-security.proto "rsn" \ 66 | 802-11-wireless-security.pairwise "ccmp" \ 67 | 802-11-wireless-security.group "ccmp,tkip" 68 | ''; 69 | } 70 | -------------------------------------------------------------------------------- /packages/by-name/nodeshell.nix: -------------------------------------------------------------------------------- 1 | { 2 | writeShellApplication, 3 | kubectl, 4 | }: 5 | 6 | writeShellApplication { 7 | name = "nodeshell"; 8 | runtimeInputs = [ 9 | kubectl 10 | ]; 11 | text = builtins.readFile ./nodeshell.sh; 12 | } 13 | -------------------------------------------------------------------------------- /packages/by-name/nodeshell.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | if [[ -z $1 ]]; then 6 | echo "Usage: nodeshell " 7 | exit 1 8 | fi 9 | 10 | node=${1} 11 | nodeName=$( 12 | kubectl get node "${node}" \ 13 | -o template \ 14 | --template='{{index .metadata.labels "kubernetes.io/hostname"}}' 15 | ) 16 | nodeSelector='"nodeSelector": { "kubernetes.io/hostname": "'${nodeName:?}'" },' 17 | uuid=$(cat /proc/sys/kernel/random/uuid) 18 | podName=nsenter-${node}-${uuid%%-*} 19 | 20 | kubectl run "${podName:?}" --restart=Never -it --rm --image overriden --overrides ' 21 | { 22 | "spec": { 23 | "hostPID": true, 24 | "hostNetwork": true, 25 | '"${nodeSelector?}"' 26 | "tolerations": [{ 27 | "operator": "Exists" 28 | }], 29 | "containers": [ 30 | { 31 | "name": "'"${podName}"'", 32 | "image": "alexeiled/nsenter:2.34", 33 | "command": [ 34 | "/nsenter", "--all", "--target=1", "--", "bash", "-i" 35 | ], 36 | "stdin": true, 37 | "tty": true, 38 | "securityContext": { 39 | "privileged": true 40 | } 41 | } 42 | ] 43 | } 44 | }' --attach "$@" 45 | -------------------------------------------------------------------------------- /packages/by-name/swaylock-cmd.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | writeShellApplication, 4 | fetchurl, 5 | swaylock-plugin, 6 | mpvpaper, 7 | }: 8 | 9 | let 10 | nixcon-idle-loop-vid = fetchurl { 11 | url = "https://github.com/nixcon/2024-intro-generators/raw/refs/heads/main/blender/idle-loop.webm"; 12 | hash = "sha256-xPp7rSRCIumG/FpZ2axTRL4g/6dfWVXXUEJvysBVurw="; 13 | }; 14 | in 15 | 16 | writeShellApplication { 17 | name = "swaylock-cmd"; 18 | text = '' 19 | ${lib.getExe swaylock-plugin} -f --command "${mpvpaper}/bin/mpvpaper -o 'loop' '*' '${nixcon-idle-loop-vid}'" 20 | ''; 21 | } 22 | -------------------------------------------------------------------------------- /packages/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs }: 2 | 3 | # pkgs.lib.packagesFromDirectoryRecursive { 4 | # inherit (pkgs) callPackage; 5 | # directory = ./by-name; 6 | # } 7 | 8 | { 9 | matrixc = pkgs.callPackage ./by-name/matrixc.nix { }; 10 | swaylock-cmd = pkgs.callPackage ./by-name/swaylock-cmd.nix { }; 11 | mkpasswordfile = pkgs.callPackage ./by-name/mkpasswordfile.nix { }; 12 | nodeshell = pkgs.callPackage ./by-name/nodeshell.nix { }; 13 | nm-setup-rub-eduroam = pkgs.callPackage ./by-name/nm-setup-rub-eduroam.nix { }; 14 | lan951x-led-ctl = pkgs.callPackage ./by-name/lan951x-led-ctl/package.nix { }; 15 | } 16 | -------------------------------------------------------------------------------- /symbols/de-custom: -------------------------------------------------------------------------------- 1 | default partial alphanumeric_keys xkb_symbols "de-custom" 2 | { 3 | name[Group1]="DE custom"; 4 | 5 | include "de(basic)" 6 | include "level3(ralt_switch)" 7 | 8 | // include "us-custom(backspace_delete)" 9 | }; 10 | -------------------------------------------------------------------------------- /symbols/us-custom: -------------------------------------------------------------------------------- 1 | default partial alphanumeric_keys modifier_keys xkb_symbols "us-custom" 2 | { 3 | name[Group1]="US custom"; 4 | 5 | include "us(basic)" 6 | 7 | include "us-custom(zy)" 8 | // RedirectKeys function isn't implemented for xkbcommon/sway 9 | // https://github.com/xkbcommon/libxkbcommon/issues/18 10 | // include "us-custom(backspace_delete)" 11 | 12 | include "level3(ralt_switch)" 13 | }; 14 | 15 | 16 | // shift+backspace as delete 17 | // https://askubuntu.com/q/1307192 18 | partial alphanumeric_keys modifier_keys xkb_symbols "backspace_delete" 19 | { 20 | key.type[Group1] = "TWO_LEVEL"; 21 | key { 22 | symbols[Group1] = [ BackSpace, NoSymbol ], 23 | actions[Group1] = [ NoAction(), Redirect(key=, clearmods=Shift) ] 24 | }; 25 | }; 26 | 27 | 28 | // change z and y 29 | partial alphanumeric_keys xkb_symbols "zy" 30 | { 31 | key { [ z, Z, NoSymbol, NoSymbol ] }; 32 | key { [ y, Y, NoSymbol, NoSymbol ] }; 33 | }; 34 | -------------------------------------------------------------------------------- /treefmt.nix: -------------------------------------------------------------------------------- 1 | _: { 2 | projectRootFile = "flake.nix"; 3 | programs = { 4 | nixfmt.enable = true; 5 | deadnix.enable = true; 6 | shellcheck.enable = true; 7 | shfmt.enable = true; 8 | statix.enable = true; 9 | yamlfmt.enable = true; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /wallpaper/pastel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katexochen/nixos/79c70edbfa8036b6fdda1ae02a9565caeb3cda53/wallpaper/pastel.png -------------------------------------------------------------------------------- /wallpaper/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/katexochen/nixos/79c70edbfa8036b6fdda1ae02a9565caeb3cda53/wallpaper/white.png --------------------------------------------------------------------------------