Kieran's opinionated (and probably slightly dumb) nix config
1{ 2 inputs, 3 lib, 4 config, 5 pkgs, 6 ... 7}: 8{ 9 imports = [ 10 ./disk-config.nix 11 ./home-manager.nix 12 13 (inputs.import-tree ../../modules/nixos) 14 inputs.tangled.nixosModules.knot 15 inputs.tangled.nixosModules.spindle 16 ]; 17 18 nixpkgs = { 19 hostPlatform = "aarch64-linux"; 20 config = { 21 allowUnfree = true; 22 }; 23 }; 24 25 nix = 26 let 27 flakeInputs = lib.filterAttrs (_: lib.isType "flake") inputs; 28 in 29 { 30 settings = { 31 experimental-features = "nix-command flakes"; 32 flake-registry = ""; 33 nix-path = config.nix.nixPath; 34 trusted-users = [ 35 "kierank" 36 ]; 37 }; 38 channel.enable = false; 39 optimise.automatic = true; 40 registry = lib.mapAttrs (_: flake: { inherit flake; }) flakeInputs; 41 nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs; 42 }; 43 44 time.timeZone = "America/New_York"; 45 46 environment.systemPackages = with pkgs; [ 47 # core 48 coreutils 49 screen 50 bc 51 jq 52 psmisc 53 # cli_utils 54 direnv 55 zsh 56 gum 57 vim 58 # networking 59 xh 60 curl 61 wget 62 dogdns 63 inetutils 64 mosh 65 # nix_tools 66 inputs.nixvim.packages.aarch64-linux.default 67 nixd 68 nil 69 nixfmt-rfc-style 70 inputs.agenix.packages.aarch64-linux.default 71 # security 72 openssl 73 gpgme 74 gnupg 75 # dev_langs 76 nodejs_22 77 unstable.bun 78 python3 79 go 80 gopls 81 gotools 82 go-tools 83 gcc 84 # misc 85 neofetch 86 git 87 ]; 88 89 programs.nh = { 90 enable = true; 91 clean.enable = true; 92 clean.extraArgs = "--keep-since 4d --keep 3"; 93 flake = "/home/kierank/dots"; 94 }; 95 96 age.identityPaths = [ 97 "/home/kierank/.ssh/id_rsa" 98 "/etc/ssh/id_rsa" 99 ]; 100 age.secrets = { 101 wakatime = { 102 file = ../../secrets/wakatime.age; 103 path = "/home/kierank/.wakatime.cfg"; 104 owner = "kierank"; 105 }; 106 cachet = { 107 file = ../../secrets/cachet.age; 108 owner = "cachet"; 109 }; 110 hn-alerts = { 111 file = ../../secrets/hn-alerts.age; 112 owner = "hn-alerts"; 113 }; 114 emojibot = { 115 file = ../../secrets/emojibot.age; 116 owner = "emojibot"; 117 }; 118 cloudflare = { 119 file = ../../secrets/cloudflare.age; 120 owner = "caddy"; 121 }; 122 github-knot-sync = { 123 file = ../../secrets/github-knot-sync.age; 124 owner = "git"; 125 }; 126 }; 127 128 environment.sessionVariables = { 129 XDG_CACHE_HOME = "$HOME/.cache"; 130 XDG_CONFIG_HOME = "$HOME/.config"; 131 XDG_DATA_HOME = "$HOME/.local/share"; 132 XDG_STATE_HOME = "$HOME/.local/state"; 133 EDITOR = "nvim"; 134 SYSTEMD_EDITOR = "nvim"; 135 VISUAL = "nvim"; 136 }; 137 138 atelier = { 139 authentication.enable = true; 140 }; 141 142 networking = { 143 hostName = "terebithia"; 144 networkmanager.enable = true; 145 }; 146 147 programs.zsh.enable = true; 148 programs.direnv.enable = true; 149 150 users.users = { 151 kierank = { 152 initialPassword = "changeme"; 153 isNormalUser = true; 154 shell = pkgs.zsh; 155 openssh.authorizedKeys.keys = [ 156 "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCzEEjvbL/ttqmYoDjxYQmDIq36BabROJoXgQKeh9liBxApwp+2PmgxROzTg42UrRc9pyrkq5kVfxG5hvkqCinhL1fMiowCSEs2L2/Cwi40g5ZU+QwdcwI8a4969kkI46PyB19RHkxg54OUORiIiso/WHGmqQsP+5wbV0+4riSnxwn/JXN4pmnE//stnyAyoiEZkPvBtwJjKb3Ni9n3eNLNs6gnaXrCtaygEZdebikr9kS2g9mM696HvIFgM6cdR/wZ7DcLbG3IdTXuHN7PC3xxL+Y4ek5iMreQIPmuvs4qslbthPGYoYbYLUQiRa9XO5s/ksIj5Z14f7anHE6cuTQVpvNWdGDOigyIVS5qU+4ZF7j+rifzOXVL48gmcAvw/uV68m5Wl/p0qsC/d8vI3GYwEsWG/EzpAlc07l8BU2LxWgN+d7uwBFaJV9VtmUDs5dcslsh8IbzmtC9gq3OLGjklxTfIl6qPiL8U33oc/UwqzvZUrI2BlbagvIZYy6rP+q0= kierank@mockingjay" 157 ]; 158 extraGroups = [ 159 "wheel" 160 "networkmanager" 161 "services" 162 ]; 163 }; 164 root.openssh.authorizedKeys.keys = [ 165 "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCzEEjvbL/ttqmYoDjxYQmDIq36BabROJoXgQKeh9liBxApwp+2PmgxROzTg42UrRc9pyrkq5kVfxG5hvkqCinhL1fMiowCSEs2L2/Cwi40g5ZU+QwdcwI8a4969kkI46PyB19RHkxg54OUORiIiso/WHGmqQsP+5wbV0+4riSnxwn/JXN4pmnE//stnyAyoiEZkPvBtwJjKb3Ni9n3eNLNs6gnaXrCtaygEZdebikr9kS2g9mM696HvIFgM6cdR/wZ7DcLbG3IdTXuHN7PC3xxL+Y4ek5iMreQIPmuvs4qslbthPGYoYbYLUQiRa9XO5s/ksIj5Z14f7anHE6cuTQVpvNWdGDOigyIVS5qU+4ZF7j+rifzOXVL48gmcAvw/uV68m5Wl/p0qsC/d8vI3GYwEsWG/EzpAlc07l8BU2LxWgN+d7uwBFaJV9VtmUDs5dcslsh8IbzmtC9gq3OLGjklxTfIl6qPiL8U33oc/UwqzvZUrI2BlbagvIZYy6rP+q0= kierank@mockingjay" 166 ]; 167 }; 168 169 # Allow passwordless sudo for wheel group (needed for deploy-rs) 170 security.sudo.wheelNeedsPassword = false; 171 172 services.openssh = { 173 enable = true; 174 openFirewall = true; 175 settings = { 176 PermitRootLogin = "no"; 177 PasswordAuthentication = false; 178 }; 179 }; 180 181 networking.firewall = { 182 enable = true; 183 allowedTCPPorts = [ 22 80 443 ]; 184 logRefusedConnections = false; 185 rejectPackets = true; 186 }; 187 188 services.tailscale = { 189 enable = true; 190 useRoutingFeatures = "client"; 191 }; 192 193 services.caddy = { 194 enable = true; 195 package = pkgs.caddy.withPlugins { 196 plugins = [ "github.com/caddy-dns/cloudflare@v0.2.2" ]; 197 hash = "sha256-Z8nPh4OI3/R1nn667ZC5VgE+Q9vDenaQ3QPKxmqPNkc="; 198 }; 199 email = "me@dunkirk.sh"; 200 globalConfig = '' 201 acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN} 202 ''; 203 virtualHosts."knot.dunkirk.sh" = { 204 extraConfig = '' 205 tls { 206 dns cloudflare {env.CLOUDFLARE_API_TOKEN} 207 } 208 header { 209 Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" 210 } 211 reverse_proxy localhost:5555 { 212 header_up X-Forwarded-Proto {scheme} 213 header_up X-Forwarded-For {remote} 214 } 215 ''; 216 }; 217 virtualHosts."spindle.dunkirk.sh" = { 218 extraConfig = '' 219 tls { 220 dns cloudflare {env.CLOUDFLARE_API_TOKEN} 221 } 222 header { 223 Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" 224 } 225 reverse_proxy localhost:6555 { 226 header_up X-Forwarded-Proto {scheme} 227 header_up X-Forwarded-For {remote} 228 } 229 ''; 230 }; 231 virtualHosts."emojibot.dunkirk.sh" = { 232 extraConfig = '' 233 tls { 234 dns cloudflare {env.CLOUDFLARE_API_TOKEN} 235 } 236 header { 237 Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" 238 } 239 reverse_proxy localhost:3002 { 240 header_up X-Forwarded-Proto {scheme} 241 header_up X-Forwarded-For {remote} 242 } 243 ''; 244 }; 245 extraConfig = '' 246 # Default response for unhandled domains 247 :80 { 248 respond "404 - Looks like this bridge doesn't have an end" 404 249 } 250 :443 { 251 respond "404 - Looks like this bridge doesn't have an end" 404 252 } 253 ''; 254 }; 255 256 systemd.services.caddy.serviceConfig = { 257 EnvironmentFile = config.age.secrets.cloudflare.path; 258 }; 259 260 atelier.services.cachet = { 261 enable = true; 262 domain = "cachet.dunkirk.sh"; 263 secretsFile = config.age.secrets.cachet.path; 264 }; 265 266 atelier.services.hn-alerts = { 267 enable = true; 268 domain = "hn.dunkirk.sh"; 269 secretsFile = config.age.secrets.hn-alerts.path; 270 }; 271 272 atelier.services.emojibot = { 273 enable = true; 274 domain = "emojibot.dunkirk.sh"; 275 secretsFile = config.age.secrets.emojibot.path; 276 }; 277 278 services.tangled.knot = { 279 enable = true; 280 package = inputs.tangled.packages.aarch64-linux.knot; 281 appviewEndpoint = "https://tangled.org"; 282 server = { 283 owner = "did:plc:krxbvxvis5skq7jj6eot23ul"; 284 hostname = "knot.dunkirk.sh"; 285 listenAddr = "127.0.0.1:5555"; 286 }; 287 }; 288 289 services.tangled.spindle = { 290 enable = true; 291 package = inputs.tangled.packages.aarch64-linux.spindle; 292 server = { 293 owner = "did:plc:krxbvxvis5skq7jj6eot23ul"; 294 hostname = "spindle.dunkirk.sh"; 295 listenAddr = "127.0.0.1:6555"; 296 }; 297 }; 298 299 atelier.services.knot-sync = { 300 enable = true; 301 secretsFile = config.age.secrets.github-knot-sync.path; 302 }; 303 304 boot.loader.systemd-boot.enable = true; 305 boot.loader.efi.canTouchEfiVariables = true; 306 boot.kernelParams = [ "console=ttyS0" ]; 307 308 system.stateVersion = "23.05"; 309}