Compare commits
	
		
			11 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ef247cb3dd | |||
| cad04680c4 | |||
| a2d176a4fc | |||
| 1f813395ee | |||
| 0d5bce2a4f | |||
| 0c2f7cd1b2 | |||
| b80b31d3c3 | |||
| caacb4b7a7 | |||
| 25dba0ee19 | |||
| 4bed47ae43 | |||
| 7c4d2d53f2 | 
| @ -15,5 +15,14 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           fetch-depth: 0 |           fetch-depth: 0 | ||||||
| 
 | 
 | ||||||
|  |       - run: attic -V | ||||||
|  | 
 | ||||||
|  |       - name: Setup Attic Cache | ||||||
|  |         uses: https://git.neet.dev/zuckerberg/attic-action@v0.2.5 | ||||||
|  |         with: | ||||||
|  |           endpoint: ${{ secrets.ATTIC_ENDPOINT }} | ||||||
|  |           cache: ${{ secrets.ATTIC_CACHE }} | ||||||
|  |           token: ${{ secrets.ATTIC_TOKEN }} | ||||||
|  | 
 | ||||||
|       - name: Check Flake |       - name: Check Flake | ||||||
|         run: nix flake check --all-systems --print-build-logs --log-format raw --show-trace |         run: nix flake check --all-systems --print-build-logs --log-format raw --show-trace | ||||||
							
								
								
									
										10
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Makefile
									
									
									
									
									
								
							| @ -25,13 +25,3 @@ clean-old-nixos-profiles: | |||||||
| .PHONY: gc | .PHONY: gc | ||||||
| gc: | gc: | ||||||
| 	nix store gc | 	nix store gc | ||||||
| 
 |  | ||||||
| # Update a flake input by name (ex: 'nixpkgs')
 |  | ||||||
| .PHONY: update-input |  | ||||||
| update-input: |  | ||||||
| 	nix flake update $(filter-out $@,$(MAKECMDGOALS)) |  | ||||||
| 
 |  | ||||||
| # Build Custom Install ISO
 |  | ||||||
| .PHONY: iso |  | ||||||
| iso: |  | ||||||
| 	nix build .#packages.x86_64-linux.iso |  | ||||||
| @ -4,7 +4,7 @@ | |||||||
| - `/common` - common configuration imported into all `/machines` | - `/common` - common configuration imported into all `/machines` | ||||||
|     - `/boot` - config related to bootloaders, cpu microcode, and unlocking LUKS root disks over tor |     - `/boot` - config related to bootloaders, cpu microcode, and unlocking LUKS root disks over tor | ||||||
|     - `/network` - config for tailscale, and NixOS container with automatic vpn tunneling via PIA |     - `/network` - config for tailscale, and NixOS container with automatic vpn tunneling via PIA | ||||||
|     - `/pc` - config that a graphical PC should have. Have the `personal` role set in the machine's `properties.nix` to enable everthing. |     - `/pc` - config that a graphical desktop computer should have. Use `de.enable = true;` to enable everthing. | ||||||
|     - `/server` - config that creates new nixos services or extends existing ones to meet my needs |     - `/server` - config that creates new nixos services or extends existing ones to meet my needs | ||||||
| - `/machines` - all my NixOS machines along with their machine unique configuration for hardware and services | - `/machines` - all my NixOS machines along with their machine unique configuration for hardware and services | ||||||
|     - `/kexec` - a special machine for generating minimal kexec images. Does not import `/common` |     - `/kexec` - a special machine for generating minimal kexec images. Does not import `/common` | ||||||
|  | |||||||
| @ -6,19 +6,12 @@ | |||||||
|       substituters = [ |       substituters = [ | ||||||
|         "https://cache.nixos.org/" |         "https://cache.nixos.org/" | ||||||
|         "https://nix-community.cachix.org" |         "https://nix-community.cachix.org" | ||||||
|         "http://s0.koi-bebop.ts.net:5000" |         "http://s0.koi-bebop.ts.net:28338/nixos" | ||||||
|       ]; |       ]; | ||||||
|       trusted-public-keys = [ |       trusted-public-keys = [ | ||||||
|         "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" |         "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" | ||||||
|         "s0.koi-bebop.ts.net:OjbzD86YjyJZpCp9RWaQKANaflcpKhtzBMNP8I2aPUU=" |         "nixos:IDhKojUaMz+UIiri1/DQk9EpqDokih8dwxmp41uJnls=" | ||||||
|       ]; |       ]; | ||||||
| 
 |  | ||||||
|       # Allow substituters to be offline |  | ||||||
|       # This isn't exactly ideal since it would be best if I could set up a system |  | ||||||
|       # so that it is an error if a derivation isn't available for any substituters |  | ||||||
|       # and use this flag as intended for deciding if it should build missing |  | ||||||
|       # derivations locally. See https://github.com/NixOS/nix/issues/6901 |  | ||||||
|       fallback = true; |  | ||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| { config, pkgs, lib, ... }: | { config, pkgs, ... }: | ||||||
| 
 | 
 | ||||||
| { | { | ||||||
|   imports = [ |   imports = [ | ||||||
| @ -20,12 +20,12 @@ | |||||||
| 
 | 
 | ||||||
|   system.stateVersion = "23.11"; |   system.stateVersion = "23.11"; | ||||||
| 
 | 
 | ||||||
|   networking.useDHCP = lib.mkDefault true; |   networking.useDHCP = false; | ||||||
| 
 | 
 | ||||||
|   networking.firewall.enable = true; |   networking.firewall.enable = true; | ||||||
|   networking.firewall.allowPing = true; |   networking.firewall.allowPing = true; | ||||||
| 
 | 
 | ||||||
|   time.timeZone = "America/Los_Angeles"; |   time.timeZone = "America/Denver"; | ||||||
|   i18n = { |   i18n = { | ||||||
|     defaultLocale = "en_US.UTF-8"; |     defaultLocale = "en_US.UTF-8"; | ||||||
|     extraLocaleSettings = { |     extraLocaleSettings = { | ||||||
| @ -63,6 +63,7 @@ | |||||||
|     lf |     lf | ||||||
|     gnumake |     gnumake | ||||||
|     tree |     tree | ||||||
|  |     attic | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   nixpkgs.config.allowUnfree = true; |   nixpkgs.config.allowUnfree = true; | ||||||
| @ -98,7 +99,4 @@ | |||||||
| 
 | 
 | ||||||
|   security.acme.acceptTerms = true; |   security.acme.acceptTerms = true; | ||||||
|   security.acme.defaults.email = "zuckerberg@neet.dev"; |   security.acme.defaults.email = "zuckerberg@neet.dev"; | ||||||
| 
 |  | ||||||
|   # Enable Desktop Environment if this is a PC (machine role is "personal") |  | ||||||
|   de.enable = lib.mkDefault (config.thisMachine.hasRole."personal"); |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -13,6 +13,12 @@ in | |||||||
|       extraOptions = '' |       extraOptions = '' | ||||||
|         experimental-features = nix-command flakes |         experimental-features = nix-command flakes | ||||||
|       ''; |       ''; | ||||||
|  | 
 | ||||||
|  |       # pin nixpkgs for system commands such as "nix shell" | ||||||
|  |       registry.nixpkgs.flake = config.inputs.nixpkgs; | ||||||
|  | 
 | ||||||
|  |       # pin system nixpkgs to the same version as the flake input | ||||||
|  |       nixPath = [ "nixpkgs=${config.inputs.nixpkgs}" ]; | ||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -5,9 +5,20 @@ | |||||||
| 
 | 
 | ||||||
| let | let | ||||||
|   machines = config.machines.hosts; |   machines = config.machines.hosts; | ||||||
|  | in | ||||||
|  | { | ||||||
|  |   imports = [ | ||||||
|  |     ./ssh.nix | ||||||
|  |     ./roles.nix | ||||||
|  |   ]; | ||||||
| 
 | 
 | ||||||
|   hostOptionsSubmoduleType = lib.types.submodule { |   options.machines = { | ||||||
|  | 
 | ||||||
|  |     hosts = lib.mkOption { | ||||||
|  |       type = lib.types.attrsOf | ||||||
|  |         (lib.types.submodule { | ||||||
|           options = { |           options = { | ||||||
|  | 
 | ||||||
|             hostNames = lib.mkOption { |             hostNames = lib.mkOption { | ||||||
|               type = lib.types.listOf lib.types.str; |               type = lib.types.listOf lib.types.str; | ||||||
|               description = '' |               description = '' | ||||||
| @ -15,18 +26,21 @@ let | |||||||
|                 Used for automatically trusting hosts for ssh connections. |                 Used for automatically trusting hosts for ssh connections. | ||||||
|               ''; |               ''; | ||||||
|             }; |             }; | ||||||
|  | 
 | ||||||
|             arch = lib.mkOption { |             arch = lib.mkOption { | ||||||
|               type = lib.types.enum [ "x86_64-linux" "aarch64-linux" ]; |               type = lib.types.enum [ "x86_64-linux" "aarch64-linux" ]; | ||||||
|               description = '' |               description = '' | ||||||
|                 The architecture of this machine. |                 The architecture of this machine. | ||||||
|               ''; |               ''; | ||||||
|             }; |             }; | ||||||
|  | 
 | ||||||
|             systemRoles = lib.mkOption { |             systemRoles = lib.mkOption { | ||||||
|               type = lib.types.listOf lib.types.str; # TODO: maybe use an enum? |               type = lib.types.listOf lib.types.str; # TODO: maybe use an enum? | ||||||
|               description = '' |               description = '' | ||||||
|                 The set of roles this machine holds. Affects secrets available. (TODO add service config as well using this info) |                 The set of roles this machine holds. Affects secrets available. (TODO add service config as well using this info) | ||||||
|               ''; |               ''; | ||||||
|             }; |             }; | ||||||
|  | 
 | ||||||
|             hostKey = lib.mkOption { |             hostKey = lib.mkOption { | ||||||
|               type = lib.types.str; |               type = lib.types.str; | ||||||
|               description = '' |               description = '' | ||||||
| @ -34,6 +48,7 @@ let | |||||||
|                 and for decrypting secrets with agenix. |                 and for decrypting secrets with agenix. | ||||||
|               ''; |               ''; | ||||||
|             }; |             }; | ||||||
|  | 
 | ||||||
|             remoteUnlock = lib.mkOption { |             remoteUnlock = lib.mkOption { | ||||||
|               default = null; |               default = null; | ||||||
|               type = lib.types.nullOr (lib.types.submodule { |               type = lib.types.nullOr (lib.types.submodule { | ||||||
| @ -65,6 +80,7 @@ let | |||||||
|                 }; |                 }; | ||||||
|               }); |               }); | ||||||
|             }; |             }; | ||||||
|  | 
 | ||||||
|             userKeys = lib.mkOption { |             userKeys = lib.mkOption { | ||||||
|               default = [ ]; |               default = [ ]; | ||||||
|               type = lib.types.listOf lib.types.str; |               type = lib.types.listOf lib.types.str; | ||||||
| @ -74,6 +90,7 @@ let | |||||||
|                 TODO: consider auto populating other programs that use ssh keys such as gitea |                 TODO: consider auto populating other programs that use ssh keys such as gitea | ||||||
|               ''; |               ''; | ||||||
|             }; |             }; | ||||||
|  | 
 | ||||||
|             deployKeys = lib.mkOption { |             deployKeys = lib.mkOption { | ||||||
|               default = [ ]; |               default = [ ]; | ||||||
|               type = lib.types.listOf lib.types.str; |               type = lib.types.listOf lib.types.str; | ||||||
| @ -81,30 +98,17 @@ let | |||||||
|                 The list of deployment keys. Each key here can be used to log into all other systems as `root`. |                 The list of deployment keys. Each key here can be used to log into all other systems as `root`. | ||||||
|               ''; |               ''; | ||||||
|             }; |             }; | ||||||
|  | 
 | ||||||
|             configurationPath = lib.mkOption { |             configurationPath = lib.mkOption { | ||||||
|               type = lib.types.path; |               type = lib.types.path; | ||||||
|               description = '' |               description = '' | ||||||
|                 The path to this machine's configuration directory. |                 The path to this machine's configuration directory. | ||||||
|               ''; |               ''; | ||||||
|             }; |             }; | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| in |  | ||||||
| { |  | ||||||
|   imports = [ |  | ||||||
|     ./ssh.nix |  | ||||||
|     ./roles.nix |  | ||||||
|   ]; |  | ||||||
| 
 | 
 | ||||||
|   options.machines = { |  | ||||||
|     hosts = lib.mkOption { |  | ||||||
|       type = lib.types.attrsOf hostOptionsSubmoduleType; |  | ||||||
|           }; |           }; | ||||||
|  |         }); | ||||||
|     }; |     }; | ||||||
| 
 |  | ||||||
|   options.thisMachine.config = lib.mkOption { |  | ||||||
|     # For ease of use, a direct copy of the host config from machines.hosts.${hostName} |  | ||||||
|     type = hostOptionsSubmoduleType; |  | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   config = { |   config = { | ||||||
| @ -192,16 +196,5 @@ in | |||||||
|           builtins.map (p: { "${dirName p}" = p; }) propFiles; |           builtins.map (p: { "${dirName p}" = p; }) propFiles; | ||||||
|       in |       in | ||||||
|       properties ../../machines; |       properties ../../machines; | ||||||
| 
 |  | ||||||
|     # Don't try to evaluate "thisMachine" when reflecting using moduleless.nix. |  | ||||||
|     # When evaluated by moduleless.nix this will fail due to networking.hostName not |  | ||||||
|     # existing. This is because moduleless.nix is not intended for reflection from the |  | ||||||
|     # perspective of a perticular machine but is instead intended for reflecting on |  | ||||||
|     # the properties of all machines as a whole system. |  | ||||||
|     thisMachine.config = config.machines.hosts.${config.networking.hostName}; |  | ||||||
| 
 |  | ||||||
|     # Add ssh keys from KeepassXC |  | ||||||
|     machines.ssh.userKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILACiZO7QnB4bcmziVaUkUE0ZPMR0M/yJbbHYsHIZz9g" ]; |  | ||||||
|     machines.ssh.deployKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID58MvKGs3GDMMcN8Iyi9S59SciSrVM97wKtOvUAl3li" ]; |  | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,55 +1,19 @@ | |||||||
| { config, lib, ... }: | { config, lib, ... }: | ||||||
| 
 | 
 | ||||||
| # Maps roles to their hosts. | # Maps roles to their hosts | ||||||
| # machines.withRole = { |  | ||||||
| #   personal = [ |  | ||||||
| #     "machine1" "machine3" |  | ||||||
| #   ]; |  | ||||||
| #   cache = [ |  | ||||||
| #     "machine2" |  | ||||||
| #   ]; |  | ||||||
| # }; |  | ||||||
| # |  | ||||||
| # A list of all possible roles |  | ||||||
| # machines.allRoles = [ |  | ||||||
| #   "personal" |  | ||||||
| #   "cache" |  | ||||||
| # ]; |  | ||||||
| # |  | ||||||
| # For each role has true or false if the current machine has that role |  | ||||||
| # thisMachine.hasRole = { |  | ||||||
| #   personal = true; |  | ||||||
| #   cache = false; |  | ||||||
| # }; |  | ||||||
| 
 | 
 | ||||||
| { | { | ||||||
|   options.machines.withRole = lib.mkOption { |   options.machines.roles = lib.mkOption { | ||||||
|     type = lib.types.attrsOf (lib.types.listOf lib.types.str); |     type = lib.types.attrsOf (lib.types.listOf lib.types.str); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   options.machines.allRoles = lib.mkOption { |  | ||||||
|     type = lib.types.listOf lib.types.str; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   options.thisMachine.hasRole = lib.mkOption { |  | ||||||
|     type = lib.types.attrsOf lib.types.bool; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   config = { |   config = { | ||||||
|     machines.withRole = lib.zipAttrs |     machines.roles = lib.zipAttrs | ||||||
|       (lib.mapAttrsToList |       (lib.mapAttrsToList | ||||||
|         (host: cfg: |         (host: cfg: | ||||||
|           lib.foldl (lib.mergeAttrs) { } |           lib.foldl (lib.mergeAttrs) { } | ||||||
|             (builtins.map (role: { ${role} = host; }) |             (builtins.map (role: { ${role} = host; }) | ||||||
|               cfg.systemRoles)) |               cfg.systemRoles)) | ||||||
|         config.machines.hosts); |         config.machines.hosts); | ||||||
| 
 |  | ||||||
|     machines.allRoles = lib.attrNames config.machines.withRole; |  | ||||||
| 
 |  | ||||||
|     thisMachine.hasRole = lib.mapAttrs |  | ||||||
|       (role: cfg: |  | ||||||
|         builtins.elem config.networking.hostName config.machines.withRole.${role} |  | ||||||
|       ) |  | ||||||
|       config.machines.withRole; |  | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -39,6 +39,6 @@ in | |||||||
|         builtins.map |         builtins.map | ||||||
|           (host: machines.hosts.${host}.hostKey) |           (host: machines.hosts.${host}.hostKey) | ||||||
|           hosts) |           hosts) | ||||||
|       machines.withRole; |       machines.roles; | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -151,7 +151,7 @@ in | |||||||
|       partOf = [ containerServiceName ]; |       partOf = [ containerServiceName ]; | ||||||
|       wantedBy = [ "multi-user.target" ]; |       wantedBy = [ "multi-user.target" ]; | ||||||
| 
 | 
 | ||||||
|       path = with pkgs; [ wireguard-tools jq curl iproute2 iputils ]; |       path = with pkgs; [ wireguard-tools jq curl iproute iputils ]; | ||||||
| 
 | 
 | ||||||
|       serviceConfig = { |       serviceConfig = { | ||||||
|         Type = "oneshot"; |         Type = "oneshot"; | ||||||
| @ -224,7 +224,7 @@ in | |||||||
|       after = [ "network.target" "network-online.target" ]; |       after = [ "network.target" "network-online.target" ]; | ||||||
|       wantedBy = [ "multi-user.target" ]; |       wantedBy = [ "multi-user.target" ]; | ||||||
| 
 | 
 | ||||||
|       path = with pkgs; [ wireguard-tools iproute2 curl jq iptables ]; |       path = with pkgs; [ wireguard-tools iproute curl jq iptables ]; | ||||||
| 
 | 
 | ||||||
|       serviceConfig = { |       serviceConfig = { | ||||||
|         Type = "oneshot"; |         Type = "oneshot"; | ||||||
|  | |||||||
| @ -1,14 +1,18 @@ | |||||||
| { config, lib, ... }: | { config, lib, ... }: | ||||||
| 
 | 
 | ||||||
| let | let | ||||||
|  |   builderRole = "nix-builder"; | ||||||
|   builderUserName = "nix-builder"; |   builderUserName = "nix-builder"; | ||||||
| 
 | 
 | ||||||
|   builderRole = "nix-builder"; |   machinesByRole = role: lib.filterAttrs (hostname: cfg: builtins.elem role cfg.systemRoles) config.machines.hosts; | ||||||
|   builders = config.machines.withRole.${builderRole}; |   otherMachinesByRole = role: lib.filterAttrs (hostname: cfg: hostname != config.networking.hostName) (machinesByRole role); | ||||||
|   thisMachineIsABuilder = config.thisMachine.hasRole.${builderRole}; |   thisMachineHasRole = role: builtins.hasAttr config.networking.hostName (machinesByRole role); | ||||||
|  | 
 | ||||||
|  |   builders = machinesByRole builderRole; | ||||||
|  |   thisMachineIsABuilder = thisMachineHasRole builderRole; | ||||||
| 
 | 
 | ||||||
|   # builders don't include themselves as a remote builder |   # builders don't include themselves as a remote builder | ||||||
|   otherBuilders = lib.filter (hostname: hostname != config.networking.hostName) builders; |   otherBuilders = lib.filterAttrs (hostname: cfg: hostname != config.networking.hostName) builders; | ||||||
| in | in | ||||||
| lib.mkMerge [ | lib.mkMerge [ | ||||||
|   # configure builder |   # configure builder | ||||||
| @ -36,9 +40,9 @@ lib.mkMerge [ | |||||||
|     nix.distributedBuilds = true; |     nix.distributedBuilds = true; | ||||||
| 
 | 
 | ||||||
|     nix.buildMachines = builtins.map |     nix.buildMachines = builtins.map | ||||||
|       (builderHostname: { |       (builderCfg: { | ||||||
|         hostName = builderHostname; |         hostName = builtins.elemAt builderCfg.hostNames 0; | ||||||
|         system = config.machines.hosts.${builderHostname}.arch; |         system = builderCfg.arch; | ||||||
|         protocol = "ssh-ng"; |         protocol = "ssh-ng"; | ||||||
|         sshUser = builderUserName; |         sshUser = builderUserName; | ||||||
|         sshKey = "/etc/ssh/ssh_host_ed25519_key"; |         sshKey = "/etc/ssh/ssh_host_ed25519_key"; | ||||||
| @ -46,7 +50,7 @@ lib.mkMerge [ | |||||||
|         speedFactor = 10; |         speedFactor = 10; | ||||||
|         supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ]; |         supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ]; | ||||||
|       }) |       }) | ||||||
|       otherBuilders; |       (builtins.attrValues otherBuilders); | ||||||
| 
 | 
 | ||||||
|     # It is very likely that the builder's internet is faster or just as fast |     # It is very likely that the builder's internet is faster or just as fast | ||||||
|     nix.extraOptions = '' |     nix.extraOptions = '' | ||||||
|  | |||||||
| @ -19,15 +19,6 @@ in | |||||||
|       jack.enable = true; |       jack.enable = true; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     services.pipewire.extraConfig.pipewire."92-fix-wine-audio" = { |  | ||||||
|       context.properties = { |  | ||||||
|         default.clock.rate = 48000; |  | ||||||
|         default.clock.quantum = 256; |  | ||||||
|         default.clock.min-quantum = 256; |  | ||||||
|         default.clock.max-quantum = 2048; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     users.users.googlebot.extraGroups = [ "audio" ]; |     users.users.googlebot.extraGroups = [ "audio" ]; | ||||||
| 
 | 
 | ||||||
|     # bt headset support |     # bt headset support | ||||||
|  | |||||||
| @ -52,12 +52,12 @@ in | |||||||
|         # ungoogled = true; |         # ungoogled = true; | ||||||
|         # --enable-native-gpu-memory-buffers # fails on AMD APU |         # --enable-native-gpu-memory-buffers # fails on AMD APU | ||||||
|         # --enable-webrtc-vp9-support |         # --enable-webrtc-vp9-support | ||||||
|         commandLineArgs = "--use-vulkan"; |         commandLineArgs = "--use-vulkan --use-gl=desktop --enable-zero-copy --enable-hardware-overlays --enable-features=VaapiVideoDecoder,CanvasOopRasterization --ignore-gpu-blocklist --enable-accelerated-mjpeg-decode --enable-accelerated-video  --enable-gpu-rasterization"; | ||||||
|       }; |       }; | ||||||
|     }; |     }; | ||||||
|     # todo vulkan in chrome |     # todo vulkan in chrome | ||||||
|     # todo video encoding in chrome |     # todo video encoding in chrome | ||||||
|     hardware.graphics = { |     hardware.opengl = { | ||||||
|       enable = true; |       enable = true; | ||||||
|       extraPackages = with pkgs; [ |       extraPackages = with pkgs; [ | ||||||
|         intel-media-driver # LIBVA_DRIVER_NAME=iHD |         intel-media-driver # LIBVA_DRIVER_NAME=iHD | ||||||
|  | |||||||
| @ -6,10 +6,12 @@ in | |||||||
| { | { | ||||||
|   imports = [ |   imports = [ | ||||||
|     ./kde.nix |     ./kde.nix | ||||||
|  |     #    ./xfce.nix | ||||||
|     ./yubikey.nix |     ./yubikey.nix | ||||||
|     ./chromium.nix |     ./chromium.nix | ||||||
|     ./firefox.nix |     ./firefox.nix | ||||||
|     ./audio.nix |     ./audio.nix | ||||||
|  |     #    ./torbrowser.nix | ||||||
|     ./pithos.nix |     ./pithos.nix | ||||||
|     ./vscodium.nix |     ./vscodium.nix | ||||||
|     ./discord.nix |     ./discord.nix | ||||||
| @ -25,10 +27,9 @@ in | |||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   config = lib.mkIf cfg.enable { |   config = lib.mkIf cfg.enable { | ||||||
|     environment.systemPackages = with pkgs; [ |     # vulkan | ||||||
|       # https://github.com/NixOS/nixpkgs/pull/328086#issuecomment-2235384618 |     hardware.opengl.driSupport = true; | ||||||
|       gparted |     hardware.opengl.driSupport32Bit = true; | ||||||
|     ]; |  | ||||||
| 
 | 
 | ||||||
|     # Applications |     # Applications | ||||||
|     users.users.googlebot.packages = with pkgs; [ |     users.users.googlebot.packages = with pkgs; [ | ||||||
| @ -41,6 +42,7 @@ in | |||||||
|       mpv |       mpv | ||||||
|       nextcloud-client |       nextcloud-client | ||||||
|       signal-desktop |       signal-desktop | ||||||
|  |       gparted | ||||||
|       libreoffice-fresh |       libreoffice-fresh | ||||||
|       thunderbird |       thunderbird | ||||||
|       spotify |       spotify | ||||||
| @ -54,8 +56,6 @@ in | |||||||
| 
 | 
 | ||||||
|       # For Nix IDE |       # For Nix IDE | ||||||
|       nixpkgs-fmt |       nixpkgs-fmt | ||||||
|       nixd |  | ||||||
|       nil |  | ||||||
|     ]; |     ]; | ||||||
| 
 | 
 | ||||||
|     # Networking |     # Networking | ||||||
| @ -89,10 +89,5 @@ in | |||||||
|     # for luks onlock over tor |     # for luks onlock over tor | ||||||
|     services.tor.enable = true; |     services.tor.enable = true; | ||||||
|     services.tor.client.enable = true; |     services.tor.client.enable = true; | ||||||
| 
 |  | ||||||
|     # Enable wayland support in various chromium based applications |  | ||||||
|     environment.sessionVariables.NIXOS_OZONE_WL = "1"; |  | ||||||
| 
 |  | ||||||
|     fonts.packages = with pkgs; [ nerd-fonts.symbols-only ]; |  | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ in | |||||||
|       # akonadi |       # akonadi | ||||||
|       # kmail |       # kmail | ||||||
|       # plasma5Packages.kmail-account-wizard |       # plasma5Packages.kmail-account-wizard | ||||||
|       kdePackages.kate |       kate | ||||||
|     ]; |     ]; | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										25
									
								
								common/pc/torbrowser.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								common/pc/torbrowser.nix
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | { lib, config, pkgs, ... }: | ||||||
|  | 
 | ||||||
|  | let | ||||||
|  |   cfg = config.de; | ||||||
|  | in | ||||||
|  | { | ||||||
|  |   config = lib.mkIf cfg.enable { | ||||||
|  |     nixpkgs.overlays = [ | ||||||
|  |       (self: super: { | ||||||
|  |         tor-browser-bundle-bin = super.tor-browser-bundle-bin.overrideAttrs (old: rec { | ||||||
|  |           version = "10.0.10"; | ||||||
|  |           lang = "en-US"; | ||||||
|  |           src = pkgs.fetchurl { | ||||||
|  |             url = "https://dist.torproject.org/torbrowser/${version}/tor-browser-linux64-${version}_${lang}.tar.xz"; | ||||||
|  |             sha256 = "vYWZ+NsGN8YH5O61+zrUjlFv3rieaBqjBQ+a18sQcZg="; | ||||||
|  |           }; | ||||||
|  |         }); | ||||||
|  |       }) | ||||||
|  |     ]; | ||||||
|  | 
 | ||||||
|  |     users.users.googlebot.packages = with pkgs; [ | ||||||
|  |       tor-browser-bundle-bin | ||||||
|  |     ]; | ||||||
|  |   }; | ||||||
|  | } | ||||||
| @ -1,9 +1,13 @@ | |||||||
| { lib, config, pkgs, ... }: | { lib, config, pkgs, ... }: | ||||||
| 
 | 
 | ||||||
| let | let | ||||||
|   cfg = config.de; |   cfg = config.de.touchpad; | ||||||
| in | in | ||||||
| { | { | ||||||
|  |   options.de.touchpad = { | ||||||
|  |     enable = lib.mkEnableOption "enable touchpad"; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|   config = lib.mkIf cfg.enable { |   config = lib.mkIf cfg.enable { | ||||||
|     services.libinput.enable = true; |     services.libinput.enable = true; | ||||||
|     services.libinput.touchpad.naturalScrolling = true; |     services.libinput.touchpad.naturalScrolling = true; | ||||||
|  | |||||||
| @ -11,9 +11,6 @@ let | |||||||
|     golang.go |     golang.go | ||||||
|     jnoortheen.nix-ide |     jnoortheen.nix-ide | ||||||
|     ms-vscode.cpptools |     ms-vscode.cpptools | ||||||
|     rust-lang.rust-analyzer |  | ||||||
|     vadimcn.vscode-lldb |  | ||||||
|     tauri-apps.tauri-vscode |  | ||||||
|   ] ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [ |   ] ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [ | ||||||
|     { |     { | ||||||
|       name = "platformio-ide"; |       name = "platformio-ide"; | ||||||
| @ -21,18 +18,6 @@ let | |||||||
|       version = "3.1.1"; |       version = "3.1.1"; | ||||||
|       sha256 = "g9yTG3DjVUS2w9eHGAai5LoIfEGus+FPhqDnCi4e90Q="; |       sha256 = "g9yTG3DjVUS2w9eHGAai5LoIfEGus+FPhqDnCi4e90Q="; | ||||||
|     } |     } | ||||||
|     { |  | ||||||
|       name = "wgsl-analyzer"; |  | ||||||
|       publisher = "wgsl-analyzer"; |  | ||||||
|       version = "0.8.1"; |  | ||||||
|       sha256 = "ckclcxdUxhjWlPnDFVleLCWgWxUEENe0V328cjaZv+Y="; |  | ||||||
|     } |  | ||||||
|     { |  | ||||||
|       name = "volar"; |  | ||||||
|       publisher = "Vue"; |  | ||||||
|       version = "2.2.4"; |  | ||||||
|       sha256 = "FHS/LNjSUVfCb4SVF9naR4W0JqycWzSWiK54jfbRagA="; |  | ||||||
|     } |  | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   vscodium-with-extensions = pkgs.vscode-with-extensions.override { |   vscodium-with-extensions = pkgs.vscode-with-extensions.override { | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								common/pc/xfce.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								common/pc/xfce.nix
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | { lib, config, pkgs, ... }: | ||||||
|  | 
 | ||||||
|  | let | ||||||
|  |   cfg = config.de; | ||||||
|  | in | ||||||
|  | { | ||||||
|  |   config = lib.mkIf cfg.enable { | ||||||
|  |     services.xserver = { | ||||||
|  |       enable = true; | ||||||
|  |       desktopManager = { | ||||||
|  |         xterm.enable = false; | ||||||
|  |         xfce.enable = true; | ||||||
|  |       }; | ||||||
|  |       displayManager.sddm.enable = true; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     # xfce apps | ||||||
|  |     # TODO for some reason whiskermenu needs to be global for it to work | ||||||
|  |     environment.systemPackages = with pkgs; [ | ||||||
|  |       xfce.xfce4-whiskermenu-plugin | ||||||
|  |     ]; | ||||||
|  |   }; | ||||||
|  | } | ||||||
| @ -1,16 +1,87 @@ | |||||||
|  | # Starting point: | ||||||
|  | # https://github.com/aldoborrero/mynixpkgs/commit/c501c1e32dba8f4462dcecb57eee4b9e52038e27 | ||||||
|  | 
 | ||||||
| { config, pkgs, lib, ... }: | { config, pkgs, lib, ... }: | ||||||
| 
 | 
 | ||||||
| let | let | ||||||
|   cfg = config.services.actual; |   cfg = config.services.actual-server; | ||||||
|  |   stateDir = "/var/lib/${cfg.stateDirName}"; | ||||||
| in | in | ||||||
| { | { | ||||||
|   config = lib.mkIf cfg.enable { |   options.services.actual-server = { | ||||||
|     services.actual.settings = { |     enable = lib.mkEnableOption "Actual Server"; | ||||||
|       port = 25448; | 
 | ||||||
|  |     hostname = lib.mkOption { | ||||||
|  |       type = lib.types.str; | ||||||
|  |       default = "localhost"; | ||||||
|  |       description = "Hostname for the Actual Server."; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     backup.group."actual-budget".paths = [ |     port = lib.mkOption { | ||||||
|       "/var/lib/actual" |       type = lib.types.int; | ||||||
|     ]; |       default = 25448; | ||||||
|  |       description = "Port on which the Actual Server should listen."; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     stateDirName = lib.mkOption { | ||||||
|  |       type = lib.types.str; | ||||||
|  |       default = "actual-server"; | ||||||
|  |       description = "Name of the directory under /var/lib holding the server's data."; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     upload = { | ||||||
|  |       fileSizeSyncLimitMB = lib.mkOption { | ||||||
|  |         type = lib.types.nullOr lib.types.int; | ||||||
|  |         default = null; | ||||||
|  |         description = "File size limit in MB for synchronized files."; | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       syncEncryptedFileSizeLimitMB = lib.mkOption { | ||||||
|  |         type = lib.types.nullOr lib.types.int; | ||||||
|  |         default = null; | ||||||
|  |         description = "File size limit in MB for synchronized encrypted files."; | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       fileSizeLimitMB = lib.mkOption { | ||||||
|  |         type = lib.types.nullOr lib.types.int; | ||||||
|  |         default = null; | ||||||
|  |         description = "File size limit in MB for file uploads."; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   config = lib.mkIf cfg.enable { | ||||||
|  |     systemd.services.actual-server = { | ||||||
|  |       description = "Actual Server"; | ||||||
|  |       after = [ "network.target" ]; | ||||||
|  |       wantedBy = [ "multi-user.target" ]; | ||||||
|  |       serviceConfig = { | ||||||
|  |         ExecStart = "${pkgs.actual-server}/bin/actual-server"; | ||||||
|  |         Restart = "always"; | ||||||
|  |         StateDirectory = cfg.stateDirName; | ||||||
|  |         WorkingDirectory = stateDir; | ||||||
|  |         DynamicUser = true; | ||||||
|  |         UMask = "0007"; | ||||||
|  |       }; | ||||||
|  |       environment = { | ||||||
|  |         NODE_ENV = "production"; | ||||||
|  |         ACTUAL_PORT = toString cfg.port; | ||||||
|  | 
 | ||||||
|  |         # Actual is actually very bad at configuring it's own paths despite that information being readily available | ||||||
|  |         ACTUAL_USER_FILES = "${stateDir}/user-files"; | ||||||
|  |         ACTUAL_SERVER_FILES = "${stateDir}/server-files"; | ||||||
|  |         ACTUAL_DATA_DIR = stateDir; | ||||||
|  | 
 | ||||||
|  |         ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB = toString (cfg.upload.fileSizeSyncLimitMB or ""); | ||||||
|  |         ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SIZE_LIMIT_MB = toString (cfg.upload.syncEncryptedFileSizeLimitMB or ""); | ||||||
|  |         ACTUAL_UPLOAD_FILE_SIZE_LIMIT_MB = toString (cfg.upload.fileSizeLimitMB or ""); | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     services.nginx.virtualHosts.${cfg.hostname} = { | ||||||
|  |       enableACME = true; | ||||||
|  |       forceSSL = true; | ||||||
|  |       locations."/".proxyPass = "http://localhost:${toString cfg.port}"; | ||||||
|  |     }; | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										40
									
								
								common/server/atticd.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								common/server/atticd.nix
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | |||||||
|  | { config, lib, ... }: | ||||||
|  | 
 | ||||||
|  | let | ||||||
|  |   cfg = config.services.atticd; | ||||||
|  | in | ||||||
|  | { | ||||||
|  |   config = lib.mkIf cfg.enable { | ||||||
|  |     services.atticd = { | ||||||
|  |       credentialsFile = "/run/agenix/atticd-credentials"; | ||||||
|  | 
 | ||||||
|  |       settings = { | ||||||
|  |         listen = "[::]:28338"; | ||||||
|  | 
 | ||||||
|  |         # Speed things up | ||||||
|  |         require-proof-of-possession = false; | ||||||
|  | 
 | ||||||
|  |         chunking = { | ||||||
|  |           # Disable chunking for performance (I have plenty of space) | ||||||
|  |           nar-size-threshold = 0; | ||||||
|  | 
 | ||||||
|  |           # Chunking is disabled due to poor performance so these values don't matter but are required anyway. | ||||||
|  |           # One day, when I move away from ZFS maybe this will perform well enough. | ||||||
|  |           # nar-size-threshold = 64 * 1024; # 64 KiB | ||||||
|  |           min-size = 16 * 1024; # 16 KiB | ||||||
|  |           avg-size = 64 * 1024; # 64 KiB | ||||||
|  |           max-size = 256 * 1024; # 256 KiB | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         # Disable compression for performance (I have plenty of space) | ||||||
|  |         compression.type = "none"; | ||||||
|  | 
 | ||||||
|  |         garbage-collection = { | ||||||
|  |           default-retention-period = "6 months"; | ||||||
|  |         }; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     age.secrets.atticd-credentials.file = ../../secrets/atticd-credentials.age; | ||||||
|  |   }; | ||||||
|  | } | ||||||
							
								
								
									
										53
									
								
								common/server/dashy.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								common/server/dashy.nix
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | { config, lib, pkgs, ... }: | ||||||
|  | 
 | ||||||
|  | with lib; | ||||||
|  | 
 | ||||||
|  | let | ||||||
|  |   cfg = config.services.dashy; | ||||||
|  | in | ||||||
|  | { | ||||||
|  |   options.services.dashy = { | ||||||
|  |     enable = mkEnableOption "dashy"; | ||||||
|  |     imageTag = mkOption { | ||||||
|  |       type = types.str; | ||||||
|  |       default = "latest"; | ||||||
|  |     }; | ||||||
|  |     port = mkOption { | ||||||
|  |       type = types.int; | ||||||
|  |       default = 56815; | ||||||
|  |     }; | ||||||
|  |     configFile = lib.mkOption { | ||||||
|  |       type = lib.types.path; | ||||||
|  |       description = "Path to the YAML configuration file"; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   config = mkIf cfg.enable { | ||||||
|  |     virtualisation.oci-containers.containers = { | ||||||
|  |       dashy = { | ||||||
|  |         image = "lissy93/dashy:${cfg.imageTag}"; | ||||||
|  |         environment = { | ||||||
|  |           TZ = "${config.time.timeZone}"; | ||||||
|  |         }; | ||||||
|  |         ports = [ | ||||||
|  |           "127.0.0.1:${toString cfg.port}:80" | ||||||
|  |         ]; | ||||||
|  |         volumes = [ | ||||||
|  |           "${cfg.configFile}:/app/public/conf.yml" | ||||||
|  |         ]; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     services.nginx.enable = true; | ||||||
|  |     services.nginx.virtualHosts."s0.koi-bebop.ts.net" = { | ||||||
|  |       default = true; | ||||||
|  |       addSSL = true; | ||||||
|  |       serverAliases = [ "s0" ]; | ||||||
|  |       sslCertificate = "/secret/ssl/s0.koi-bebop.ts.net.crt"; | ||||||
|  |       sslCertificateKey = "/secret/ssl/s0.koi-bebop.ts.net.key"; | ||||||
|  |       locations."/" = { | ||||||
|  |         proxyPass = "http://localhost:${toString cfg.port}"; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | } | ||||||
| @ -10,6 +10,8 @@ | |||||||
|     ./matrix.nix |     ./matrix.nix | ||||||
|     ./zerobin.nix |     ./zerobin.nix | ||||||
|     ./gitea.nix |     ./gitea.nix | ||||||
|  |     ./privatebin/privatebin.nix | ||||||
|  |     ./radio.nix | ||||||
|     ./samba.nix |     ./samba.nix | ||||||
|     ./owncast.nix |     ./owncast.nix | ||||||
|     ./mailserver.nix |     ./mailserver.nix | ||||||
| @ -17,8 +19,9 @@ | |||||||
|     ./iodine.nix |     ./iodine.nix | ||||||
|     ./searx.nix |     ./searx.nix | ||||||
|     ./gitea-actions-runner.nix |     ./gitea-actions-runner.nix | ||||||
|  |     ./dashy.nix | ||||||
|     ./librechat.nix |     ./librechat.nix | ||||||
|     ./actualbudget.nix |     ./actualbudget.nix | ||||||
|     ./unifi.nix |     ./atticd.nix | ||||||
|   ]; |   ]; | ||||||
| } | } | ||||||
|  | |||||||
| @ -9,7 +9,10 @@ | |||||||
| # TODO: skipping running inside of nixos container for now because of issues getting docker/podman running | # TODO: skipping running inside of nixos container for now because of issues getting docker/podman running | ||||||
| 
 | 
 | ||||||
| let | let | ||||||
|   thisMachineIsARunner = config.thisMachine.hasRole."gitea-actions-runner"; |   runnerRole = "gitea-actions-runner"; | ||||||
|  |   runners = config.machines.roles.${runnerRole}; | ||||||
|  |   thisMachineIsARunner = builtins.elem config.networking.hostName runners; | ||||||
|  | 
 | ||||||
|   containerName = "gitea-runner"; |   containerName = "gitea-runner"; | ||||||
| in | in | ||||||
| { | { | ||||||
| @ -113,6 +116,7 @@ in | |||||||
|       git |       git | ||||||
|       # Gitea Actions rely heavily on node. Include it because it would be installed anyway. |       # Gitea Actions rely heavily on node. Include it because it would be installed anyway. | ||||||
|       nodejs |       nodejs | ||||||
|  |       attic | ||||||
|     ]; |     ]; | ||||||
| 
 | 
 | ||||||
|     # To allow building on the host, must override the the service's config so it doesn't use a dynamic user |     # To allow building on the host, must override the the service's config so it doesn't use a dynamic user | ||||||
|  | |||||||
| @ -24,7 +24,7 @@ in | |||||||
|           SHOW_FOOTER_VERSION = false; |           SHOW_FOOTER_VERSION = false; | ||||||
|         }; |         }; | ||||||
|         ui = { |         ui = { | ||||||
|           DEFAULT_THEME = "gitea-dark"; |           DEFAULT_THEME = "arc-green"; | ||||||
|         }; |         }; | ||||||
|         service = { |         service = { | ||||||
|           DISABLE_REGISTRATION = true; |           DISABLE_REGISTRATION = true; | ||||||
|  | |||||||
| @ -21,18 +21,11 @@ in | |||||||
|   config = mkIf cfg.enable { |   config = mkIf cfg.enable { | ||||||
|     virtualisation.oci-containers.containers = { |     virtualisation.oci-containers.containers = { | ||||||
|       librechat = { |       librechat = { | ||||||
|         image = "ghcr.io/danny-avila/librechat:v0.7.7"; |         image = "ghcr.io/danny-avila/librechat:v0.6.6"; | ||||||
|         environment = { |         environment = { | ||||||
|           HOST = "0.0.0.0"; |           HOST = "0.0.0.0"; | ||||||
|           MONGO_URI = "mongodb://host.containers.internal:27017/LibreChat"; |           MONGO_URI = "mongodb://host.containers.internal:27017/LibreChat"; | ||||||
|           ENDPOINTS = "openAI,google,bingAI,gptPlugins"; |           ENDPOINTS = "openAI,google,bingAI,gptPlugins"; | ||||||
|           OPENAI_MODELS = lib.concatStringsSep "," [ |  | ||||||
|             "gpt-4o-mini" |  | ||||||
|             "o3-mini" |  | ||||||
|             "gpt-4o" |  | ||||||
|             "o1" |  | ||||||
|           ]; |  | ||||||
|           REFRESH_TOKEN_EXPIRY = toString (1000 * 60 * 60 * 24 * 30); # 30 days |  | ||||||
|         }; |         }; | ||||||
|         environmentFiles = [ |         environmentFiles = [ | ||||||
|           "/run/agenix/librechat-env-file" |           "/run/agenix/librechat-env-file" | ||||||
|  | |||||||
| @ -28,6 +28,7 @@ in | |||||||
|       indexDir = "/var/lib/mailindex"; |       indexDir = "/var/lib/mailindex"; | ||||||
|       enableManageSieve = true; |       enableManageSieve = true; | ||||||
|       fullTextSearch.enable = true; |       fullTextSearch.enable = true; | ||||||
|  |       fullTextSearch.indexAttachments = true; | ||||||
|       fullTextSearch.memoryLimit = 500; |       fullTextSearch.memoryLimit = 500; | ||||||
|       inherit domains; |       inherit domains; | ||||||
|       loginAccounts = { |       loginAccounts = { | ||||||
| @ -55,7 +56,6 @@ in | |||||||
|         "damon@runyan.org" |         "damon@runyan.org" | ||||||
|         "jonas@runyan.org" |         "jonas@runyan.org" | ||||||
|         "simon@neet.dev" |         "simon@neet.dev" | ||||||
|         "ellen@runyan.org" |  | ||||||
|       ]; |       ]; | ||||||
|       forwards = { |       forwards = { | ||||||
|         "amazon@runyan.org" = [ |         "amazon@runyan.org" = [ | ||||||
|  | |||||||
| @ -3,44 +3,17 @@ | |||||||
| 
 | 
 | ||||||
| let | let | ||||||
|   cfg = config.services.nextcloud; |   cfg = config.services.nextcloud; | ||||||
| 
 |  | ||||||
|   nextcloudHostname = "runyan.org"; |  | ||||||
|   collaboraOnlineHostname = "collabora.runyan.org"; |  | ||||||
|   whiteboardHostname = "whiteboard.runyan.org"; |  | ||||||
|   whiteboardPort = 3002; # Seems impossible to change |  | ||||||
| 
 |  | ||||||
|   # Hardcoded public ip of ponyo... I wish I didn't need this... |  | ||||||
|   public_ip_address = "147.135.114.130"; |  | ||||||
| in | in | ||||||
| { | { | ||||||
|   config = lib.mkIf cfg.enable { |   config = lib.mkIf cfg.enable { | ||||||
|     services.nextcloud = { |     services.nextcloud = { | ||||||
|       https = true; |       https = true; | ||||||
|       package = pkgs.nextcloud31; |       package = pkgs.nextcloud29; | ||||||
|       hostName = nextcloudHostname; |       hostName = "neet.cloud"; | ||||||
|       config.dbtype = "sqlite"; |       config.dbtype = "sqlite"; | ||||||
|       config.adminuser = "jeremy"; |       config.adminuser = "jeremy"; | ||||||
|       config.adminpassFile = "/run/agenix/nextcloud-pw"; |       config.adminpassFile = "/run/agenix/nextcloud-pw"; | ||||||
| 
 |  | ||||||
|       # Apps |  | ||||||
|       autoUpdateApps.enable = true; |       autoUpdateApps.enable = true; | ||||||
|       extraAppsEnable = true; |  | ||||||
|       extraApps = with config.services.nextcloud.package.packages.apps; { |  | ||||||
|         # Want |  | ||||||
|         inherit end_to_end_encryption mail spreed; |  | ||||||
| 
 |  | ||||||
|         # For file and document editing (collabora online and excalidraw) |  | ||||||
|         inherit richdocuments whiteboard; |  | ||||||
| 
 |  | ||||||
|         # Might use |  | ||||||
|         inherit calendar qownnotesapi; |  | ||||||
| 
 |  | ||||||
|         # Try out |  | ||||||
|         # inherit bookmarks cookbook deck memories maps music news notes phonetrack polls forms; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       # Allows installing Apps from the UI (might remove later) |  | ||||||
|       appstoreEnable = true; |  | ||||||
|     }; |     }; | ||||||
|     age.secrets.nextcloud-pw = { |     age.secrets.nextcloud-pw = { | ||||||
|       file = ../../secrets/nextcloud-pw.age; |       file = ../../secrets/nextcloud-pw.age; | ||||||
| @ -56,100 +29,5 @@ in | |||||||
|       enableACME = true; |       enableACME = true; | ||||||
|       forceSSL = true; |       forceSSL = true; | ||||||
|     }; |     }; | ||||||
| 
 |  | ||||||
|     # collabora-online |  | ||||||
|     # https://diogotc.com/blog/collabora-nextcloud-nixos/ |  | ||||||
|     services.collabora-online = { |  | ||||||
|       enable = true; |  | ||||||
|       port = 15972; |  | ||||||
|       settings = { |  | ||||||
|         # Rely on reverse proxy for SSL |  | ||||||
|         ssl = { |  | ||||||
|           enable = false; |  | ||||||
|           termination = true; |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         # Listen on loopback interface only |  | ||||||
|         net = { |  | ||||||
|           listen = "loopback"; |  | ||||||
|           post_allow.host = [ "localhost" ]; |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         # Restrict loading documents from WOPI Host |  | ||||||
|         storage.wopi = { |  | ||||||
|           "@allow" = true; |  | ||||||
|           host = [ config.services.nextcloud.hostName ]; |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         server_name = collaboraOnlineHostname; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     services.nginx.virtualHosts.${config.services.collabora-online.settings.server_name} = { |  | ||||||
|       enableACME = true; |  | ||||||
|       forceSSL = true; |  | ||||||
|       locations."/" = { |  | ||||||
|         proxyPass = "http://localhost:${toString config.services.collabora-online.port}"; |  | ||||||
|         proxyWebsockets = true; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     systemd.services.nextcloud-config-collabora = |  | ||||||
|       let |  | ||||||
|         wopi_url = "http://localhost:${toString config.services.collabora-online.port}"; |  | ||||||
|         public_wopi_url = "https://${collaboraOnlineHostname}"; |  | ||||||
|         wopi_allowlist = lib.concatStringsSep "," [ |  | ||||||
|           "127.0.0.1" |  | ||||||
|           "::1" |  | ||||||
|           public_ip_address |  | ||||||
|         ]; |  | ||||||
|       in |  | ||||||
|       { |  | ||||||
|         wantedBy = [ "multi-user.target" ]; |  | ||||||
|         after = [ "nextcloud-setup.service" "coolwsd.service" ]; |  | ||||||
|         requires = [ "coolwsd.service" ]; |  | ||||||
|         path = [ |  | ||||||
|           config.services.nextcloud.occ |  | ||||||
|         ]; |  | ||||||
|         script = '' |  | ||||||
|           nextcloud-occ -- config:app:set richdocuments wopi_url --value ${lib.escapeShellArg wopi_url} |  | ||||||
|           nextcloud-occ -- config:app:set richdocuments public_wopi_url --value ${lib.escapeShellArg public_wopi_url} |  | ||||||
|           nextcloud-occ -- config:app:set richdocuments wopi_allowlist --value ${lib.escapeShellArg wopi_allowlist} |  | ||||||
|           nextcloud-occ -- richdocuments:setup |  | ||||||
|         ''; |  | ||||||
|         serviceConfig = { |  | ||||||
|           Type = "oneshot"; |  | ||||||
|         }; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|     # Whiteboard |  | ||||||
|     services.nextcloud-whiteboard-server = { |  | ||||||
|       enable = true; |  | ||||||
|       settings.NEXTCLOUD_URL = "https://${nextcloudHostname}"; |  | ||||||
|       secrets = [ "/run/agenix/whiteboard-server-jwt-secret" ]; |  | ||||||
|     }; |  | ||||||
|     systemd.services.nextcloud-config-whiteboard = { |  | ||||||
|       wantedBy = [ "multi-user.target" ]; |  | ||||||
|       after = [ "nextcloud-setup.service" ]; |  | ||||||
|       requires = [ "coolwsd.service" ]; |  | ||||||
|       path = [ |  | ||||||
|         config.services.nextcloud.occ |  | ||||||
|       ]; |  | ||||||
|       script = '' |  | ||||||
|         nextcloud-occ -- config:app:set whiteboard collabBackendUrl --value="https://${whiteboardHostname}" |  | ||||||
|         nextcloud-occ -- config:app:set whiteboard jwt_secret_key --value="$JWT_SECRET_KEY" |  | ||||||
|       ''; |  | ||||||
|       serviceConfig = { |  | ||||||
|         Type = "oneshot"; |  | ||||||
|         EnvironmentFile = [ "/run/agenix/whiteboard-server-jwt-secret" ]; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     age.secrets.whiteboard-server-jwt-secret.file = ../../secrets/whiteboard-server-jwt-secret.age; |  | ||||||
|     services.nginx.virtualHosts.${whiteboardHostname} = { |  | ||||||
|       enableACME = true; |  | ||||||
|       forceSSL = true; |  | ||||||
|       locations."/" = { |  | ||||||
|         proxyPass = "http://localhost:${toString whiteboardPort}"; |  | ||||||
|         proxyWebsockets = true; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,10 +4,6 @@ let | |||||||
|   cfg = config.services.nginx; |   cfg = config.services.nginx; | ||||||
| in | in | ||||||
| { | { | ||||||
|   options.services.nginx = { |  | ||||||
|     openFirewall = lib.mkEnableOption "Open firewall ports 80 and 443"; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   config = lib.mkIf cfg.enable { |   config = lib.mkIf cfg.enable { | ||||||
|     services.nginx = { |     services.nginx = { | ||||||
|       recommendedGzipSettings = true; |       recommendedGzipSettings = true; | ||||||
| @ -16,8 +12,6 @@ in | |||||||
|       recommendedTlsSettings = true; |       recommendedTlsSettings = true; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     services.nginx.openFirewall = lib.mkDefault true; |     networking.firewall.allowedTCPPorts = [ 80 443 ]; | ||||||
| 
 |  | ||||||
|     networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ 80 443 ]; |  | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										42
									
								
								common/server/privatebin/conf.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								common/server/privatebin/conf.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | |||||||
|  | ;<?php http_response_code(403); /* | ||||||
|  | [main] | ||||||
|  | name = "Kode Paste" | ||||||
|  | discussion = false | ||||||
|  | opendiscussion = false | ||||||
|  | password = true | ||||||
|  | fileupload = false | ||||||
|  | burnafterreadingselected = false | ||||||
|  | defaultformatter = "plaintext" | ||||||
|  | sizelimit = 10485760 | ||||||
|  | template = "bootstrap" | ||||||
|  | languageselection = false | ||||||
|  | 
 | ||||||
|  | [expire] | ||||||
|  | default = "1week" | ||||||
|  | 
 | ||||||
|  | [expire_options] | ||||||
|  | 5min = 300 | ||||||
|  | 10min = 600 | ||||||
|  | 1hour = 3600 | ||||||
|  | 1day = 86400 | ||||||
|  | 1week = 604800 | ||||||
|  | 
 | ||||||
|  | [formatter_options] | ||||||
|  | plaintext = "Plain Text" | ||||||
|  | syntaxhighlighting = "Source Code" | ||||||
|  | markdown = "Markdown" | ||||||
|  | 
 | ||||||
|  | [traffic] | ||||||
|  | limit = 10 | ||||||
|  | dir = "/var/lib/privatebin" | ||||||
|  | 
 | ||||||
|  | [purge] | ||||||
|  | limit = 300 | ||||||
|  | batchsize = 10 | ||||||
|  | dir = "/var/lib/privatebin" | ||||||
|  | 
 | ||||||
|  | [model] | ||||||
|  | class = Filesystem | ||||||
|  | 
 | ||||||
|  | [model_options] | ||||||
|  | dir = "/var/lib/privatebin" | ||||||
							
								
								
									
										74
									
								
								common/server/privatebin/privatebin.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								common/server/privatebin/privatebin.nix
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | |||||||
|  | { config, pkgs, lib, ... }: | ||||||
|  | 
 | ||||||
|  | let | ||||||
|  |   cfg = config.services.privatebin; | ||||||
|  |   privateBinSrc = pkgs.stdenv.mkDerivation { | ||||||
|  |     name = "privatebin"; | ||||||
|  |     src = pkgs.fetchFromGitHub { | ||||||
|  |       owner = "privatebin"; | ||||||
|  |       repo = "privatebin"; | ||||||
|  |       rev = "d65bf02d7819a530c3c2a88f6f9947651fe5258d"; | ||||||
|  |       sha256 = "7ttAvEDL1ab0cUZcqZzXFkXwB2rF2t4eNpPxt48ap94="; | ||||||
|  |     }; | ||||||
|  |     installPhase = '' | ||||||
|  |       cp -ar $src $out | ||||||
|  |     ''; | ||||||
|  |   }; | ||||||
|  | in | ||||||
|  | { | ||||||
|  |   options.services.privatebin = { | ||||||
|  |     enable = lib.mkEnableOption "enable privatebin"; | ||||||
|  |     host = lib.mkOption { | ||||||
|  |       type = lib.types.str; | ||||||
|  |       example = "example.com"; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   config = lib.mkIf cfg.enable { | ||||||
|  | 
 | ||||||
|  |     users.users.privatebin = { | ||||||
|  |       description = "privatebin service user"; | ||||||
|  |       group = "privatebin"; | ||||||
|  |       isSystemUser = true; | ||||||
|  |     }; | ||||||
|  |     users.groups.privatebin = { }; | ||||||
|  | 
 | ||||||
|  |     services.nginx.enable = true; | ||||||
|  |     services.nginx.virtualHosts.${cfg.host} = { | ||||||
|  |       enableACME = true; | ||||||
|  |       forceSSL = true; | ||||||
|  |       locations."/" = { | ||||||
|  |         root = privateBinSrc; | ||||||
|  |         index = "index.php"; | ||||||
|  |       }; | ||||||
|  |       locations."~ \.php$" = { | ||||||
|  |         root = privateBinSrc; | ||||||
|  |         extraConfig = '' | ||||||
|  |           fastcgi_pass  unix:${config.services.phpfpm.pools.privatebin.socket}; | ||||||
|  |           fastcgi_index index.php; | ||||||
|  |         ''; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     systemd.tmpfiles.rules = [ | ||||||
|  |       "d '/var/lib/privatebin' 0750 privatebin privatebin - -" | ||||||
|  |     ]; | ||||||
|  | 
 | ||||||
|  |     services.phpfpm.pools.privatebin = { | ||||||
|  |       user = "privatebin"; | ||||||
|  |       group = "privatebin"; | ||||||
|  |       phpEnv = { | ||||||
|  |         CONFIG_PATH = "${./conf.php}"; | ||||||
|  |       }; | ||||||
|  |       settings = { | ||||||
|  |         pm = "dynamic"; | ||||||
|  |         "listen.owner" = config.services.nginx.user; | ||||||
|  |         "pm.max_children" = 5; | ||||||
|  |         "pm.start_servers" = 2; | ||||||
|  |         "pm.min_spare_servers" = 1; | ||||||
|  |         "pm.max_spare_servers" = 3; | ||||||
|  |         "pm.max_requests" = 500; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | } | ||||||
							
								
								
									
										75
									
								
								common/server/radio.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								common/server/radio.nix
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | |||||||
|  | { config, pkgs, lib, ... }: | ||||||
|  | 
 | ||||||
|  | let | ||||||
|  |   cfg = config.services.radio; | ||||||
|  |   radioPackage = config.inputs.radio.packages.${config.currentSystem}.radio; | ||||||
|  | in | ||||||
|  | { | ||||||
|  |   options.services.radio = { | ||||||
|  |     enable = lib.mkEnableOption "enable radio"; | ||||||
|  |     user = lib.mkOption { | ||||||
|  |       type = lib.types.str; | ||||||
|  |       default = "radio"; | ||||||
|  |       description = '' | ||||||
|  |         The user radio should run as | ||||||
|  |       ''; | ||||||
|  |     }; | ||||||
|  |     group = lib.mkOption { | ||||||
|  |       type = lib.types.str; | ||||||
|  |       default = "radio"; | ||||||
|  |       description = '' | ||||||
|  |         The group radio should run as | ||||||
|  |       ''; | ||||||
|  |     }; | ||||||
|  |     dataDir = lib.mkOption { | ||||||
|  |       type = lib.types.str; | ||||||
|  |       default = "/var/lib/radio"; | ||||||
|  |       description = '' | ||||||
|  |         Path to the radio data directory | ||||||
|  |       ''; | ||||||
|  |     }; | ||||||
|  |     host = lib.mkOption { | ||||||
|  |       type = lib.types.str; | ||||||
|  |       description = '' | ||||||
|  |         Domain radio is hosted on | ||||||
|  |       ''; | ||||||
|  |     }; | ||||||
|  |     nginx = lib.mkEnableOption "enable nginx"; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   config = lib.mkIf cfg.enable { | ||||||
|  |     services.icecast = { | ||||||
|  |       enable = true; | ||||||
|  |       hostname = cfg.host; | ||||||
|  |       mount = "stream.mp3"; | ||||||
|  |       fallback = "fallback.mp3"; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     services.nginx.virtualHosts.${cfg.host} = lib.mkIf cfg.nginx { | ||||||
|  |       enableACME = true; | ||||||
|  |       forceSSL = true; | ||||||
|  |       locations."/".root = config.inputs.radio-web; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     users.users.${cfg.user} = { | ||||||
|  |       isSystemUser = true; | ||||||
|  |       group = cfg.group; | ||||||
|  |       home = cfg.dataDir; | ||||||
|  |       createHome = true; | ||||||
|  |     }; | ||||||
|  |     users.groups.${cfg.group} = { }; | ||||||
|  |     systemd.services.radio = { | ||||||
|  |       enable = true; | ||||||
|  |       after = [ "network.target" ]; | ||||||
|  |       wantedBy = [ "multi-user.target" ]; | ||||||
|  |       serviceConfig.ExecStart = "${radioPackage}/bin/radio ${config.services.icecast.listen.address}:${toString config.services.icecast.listen.port} ${config.services.icecast.mount} 5500"; | ||||||
|  |       serviceConfig.User = cfg.user; | ||||||
|  |       serviceConfig.Group = cfg.group; | ||||||
|  |       serviceConfig.WorkingDirectory = cfg.dataDir; | ||||||
|  |       preStart = '' | ||||||
|  |         mkdir -p ${cfg.dataDir} | ||||||
|  |         chown ${cfg.user} ${cfg.dataDir} | ||||||
|  |       ''; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | } | ||||||
| @ -5,28 +5,30 @@ | |||||||
|     services.samba = { |     services.samba = { | ||||||
|       openFirewall = true; |       openFirewall = true; | ||||||
|       package = pkgs.sambaFull; # printer sharing |       package = pkgs.sambaFull; # printer sharing | ||||||
|  |       securityType = "user"; | ||||||
| 
 | 
 | ||||||
|       # should this be on? |       # should this be on? | ||||||
|       nsswins = true; |       nsswins = true; | ||||||
| 
 | 
 | ||||||
|       settings = { |       extraConfig = '' | ||||||
|         global = { |         workgroup = HOME | ||||||
|           security = "user"; |         server string = smbnix | ||||||
|           workgroup = "HOME"; |         netbios name = smbnix | ||||||
|           "server string" = "smbnix"; |         security = user  | ||||||
|           "netbios name" = "smbnix"; |         use sendfile = yes | ||||||
|           "use sendfile" = "yes"; |         min protocol = smb2 | ||||||
|           "min protocol" = "smb2"; |         guest account = nobody | ||||||
|           "guest account" = "nobody"; |         map to guest = bad user | ||||||
|           "map to guest" = "bad user"; |  | ||||||
| 
 | 
 | ||||||
|         # printing |         # printing | ||||||
|           "load printers" = "yes"; |         load printers = yes | ||||||
|           printing = "cups"; |         printing = cups | ||||||
|           "printcap name" = "cups"; |         printcap name = cups | ||||||
| 
 | 
 | ||||||
|           "hide files" = "/.nobackup/.DS_Store/._.DS_Store/"; |         hide files = /.nobackup/.DS_Store/._.DS_Store/ | ||||||
|         }; |       ''; | ||||||
|  | 
 | ||||||
|  |       shares = { | ||||||
|         public = { |         public = { | ||||||
|           path = "/data/samba/Public"; |           path = "/data/samba/Public"; | ||||||
|           browseable = "yes"; |           browseable = "yes"; | ||||||
| @ -75,9 +77,9 @@ | |||||||
| 
 | 
 | ||||||
|     # backups |     # backups | ||||||
|     backup.group."samba".paths = [ |     backup.group."samba".paths = [ | ||||||
|       config.services.samba.settings.googlebot.path |       config.services.samba.shares.googlebot.path | ||||||
|       config.services.samba.settings.cris.path |       config.services.samba.shares.cris.path | ||||||
|       config.services.samba.settings.public.path |       config.services.samba.shares.public.path | ||||||
|     ]; |     ]; | ||||||
| 
 | 
 | ||||||
|     # Windows discovery of samba server |     # Windows discovery of samba server | ||||||
|  | |||||||
| @ -1,26 +0,0 @@ | |||||||
| { config, lib, pkgs, ... }: |  | ||||||
| 
 |  | ||||||
| let |  | ||||||
|   cfg = config.services.unifi; |  | ||||||
| in |  | ||||||
| { |  | ||||||
|   options.services.unifi = { |  | ||||||
|     # Open select Unifi ports instead of using openFirewall to avoid opening access to unifi's control panel |  | ||||||
|     openMinimalFirewall = lib.mkEnableOption "Open bare minimum firewall ports"; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   config = lib.mkIf cfg.enable { |  | ||||||
|     services.unifi.unifiPackage = pkgs.unifi; |  | ||||||
|     services.unifi.mongodbPackage = pkgs.mongodb-7_0; |  | ||||||
| 
 |  | ||||||
|     networking.firewall = lib.mkIf cfg.openMinimalFirewall { |  | ||||||
|       allowedUDPPorts = [ |  | ||||||
|         3478 # STUN |  | ||||||
|         10001 # used for device discovery. |  | ||||||
|       ]; |  | ||||||
|       allowedTCPPorts = [ |  | ||||||
|         8080 # Used for device and application communication. |  | ||||||
|       ]; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| @ -21,6 +21,8 @@ | |||||||
|     shellInit = '' |     shellInit = '' | ||||||
|       # disable annoying fish shell greeting |       # disable annoying fish shell greeting | ||||||
|       set fish_greeting |       set fish_greeting | ||||||
|  | 
 | ||||||
|  |       alias sudo="doas" | ||||||
|     ''; |     ''; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -31,6 +31,8 @@ | |||||||
| 
 | 
 | ||||||
|   # TODO: Old ssh keys I will remove some day... |   # TODO: Old ssh keys I will remove some day... | ||||||
|   machines.ssh.userKeys = [ |   machines.ssh.userKeys = [ | ||||||
|  |     "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMVR/R3ZOsv7TZbICGBCHdjh1NDT8SnswUyINeJOC7QG" | ||||||
|  |     "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0dcqL/FhHmv+a1iz3f9LJ48xubO7MZHy35rW9SZOYM" | ||||||
|     "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHSkKiRUUmnErOKGx81nyge/9KqjkPh8BfDk0D3oP586" # nat |     "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHSkKiRUUmnErOKGx81nyge/9KqjkPh8BfDk0D3oP586" # nat | ||||||
|   ]; |   ]; | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										251
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										251
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							| @ -3,9 +3,7 @@ | |||||||
|     "agenix": { |     "agenix": { | ||||||
|       "inputs": { |       "inputs": { | ||||||
|         "darwin": "darwin", |         "darwin": "darwin", | ||||||
|         "home-manager": [ |         "home-manager": "home-manager", | ||||||
|           "home-manager" |  | ||||||
|         ], |  | ||||||
|         "nixpkgs": [ |         "nixpkgs": [ | ||||||
|           "nixpkgs" |           "nixpkgs" | ||||||
|         ], |         ], | ||||||
| @ -14,11 +12,11 @@ | |||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1750173260, |         "lastModified": 1716561646, | ||||||
|         "narHash": "sha256-9P1FziAwl5+3edkfFcr5HeGtQUtrSdk/MksX39GieoA=", |         "narHash": "sha256-UIGtLO89RxKt7RF2iEgPikSdU53r6v/6WYB0RW3k89I=", | ||||||
|         "owner": "ryantm", |         "owner": "ryantm", | ||||||
|         "repo": "agenix", |         "repo": "agenix", | ||||||
|         "rev": "531beac616433bac6f9e2a19feb8e99a22a66baf", |         "rev": "c2fc0762bbe8feb06a2e59a364fa81b3a57671c9", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
| @ -27,6 +25,36 @@ | |||||||
|         "type": "github" |         "type": "github" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "attic": { | ||||||
|  |       "inputs": { | ||||||
|  |         "crane": "crane", | ||||||
|  |         "flake-compat": [ | ||||||
|  |           "flake-compat" | ||||||
|  |         ], | ||||||
|  |         "flake-utils": [ | ||||||
|  |           "flake-utils" | ||||||
|  |         ], | ||||||
|  |         "nixpkgs": [ | ||||||
|  |           "nixpkgs" | ||||||
|  |         ], | ||||||
|  |         "nixpkgs-stable": [ | ||||||
|  |           "nixpkgs" | ||||||
|  |         ] | ||||||
|  |       }, | ||||||
|  |       "locked": { | ||||||
|  |         "lastModified": 1717279440, | ||||||
|  |         "narHash": "sha256-kH04ReTjxOpQumgWnqy40vvQLSnLGxWP6RF3nq5Esrk=", | ||||||
|  |         "owner": "zhaofengli", | ||||||
|  |         "repo": "attic", | ||||||
|  |         "rev": "717cc95983cdc357bc347d70be20ced21f935843", | ||||||
|  |         "type": "github" | ||||||
|  |       }, | ||||||
|  |       "original": { | ||||||
|  |         "owner": "zhaofengli", | ||||||
|  |         "repo": "attic", | ||||||
|  |         "type": "github" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "blobs": { |     "blobs": { | ||||||
|       "flake": false, |       "flake": false, | ||||||
|       "locked": { |       "locked": { | ||||||
| @ -43,6 +71,27 @@ | |||||||
|         "type": "gitlab" |         "type": "gitlab" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "crane": { | ||||||
|  |       "inputs": { | ||||||
|  |         "nixpkgs": [ | ||||||
|  |           "attic", | ||||||
|  |           "nixpkgs" | ||||||
|  |         ] | ||||||
|  |       }, | ||||||
|  |       "locked": { | ||||||
|  |         "lastModified": 1717025063, | ||||||
|  |         "narHash": "sha256-dIubLa56W9sNNz0e8jGxrX3CAkPXsq7snuFA/Ie6dn8=", | ||||||
|  |         "owner": "ipetkov", | ||||||
|  |         "repo": "crane", | ||||||
|  |         "rev": "480dff0be03dac0e51a8dfc26e882b0d123a450e", | ||||||
|  |         "type": "github" | ||||||
|  |       }, | ||||||
|  |       "original": { | ||||||
|  |         "owner": "ipetkov", | ||||||
|  |         "repo": "crane", | ||||||
|  |         "type": "github" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "dailybuild_modules": { |     "dailybuild_modules": { | ||||||
|       "inputs": { |       "inputs": { | ||||||
|         "flake-utils": [ |         "flake-utils": [ | ||||||
| @ -53,11 +102,11 @@ | |||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1739947126, |         "lastModified": 1651719222, | ||||||
|         "narHash": "sha256-JoiddH5H9up8jC/VKU8M7wDlk/bstKoJ3rHj+TkW4Zo=", |         "narHash": "sha256-p/GY5vOP+HUlxNL4OtEhmBNEVQsedOHXEmjfCGONVmE=", | ||||||
|         "ref": "refs/heads/master", |         "ref": "refs/heads/master", | ||||||
|         "rev": "ea1ad60f1c6662103ef4a3705d8e15aa01219529", |         "rev": "1290ddd9a2ff2bf2d0f702750768312b80efcd34", | ||||||
|         "revCount": 20, |         "revCount": 19, | ||||||
|         "type": "git", |         "type": "git", | ||||||
|         "url": "https://git.neet.dev/zuckerberg/dailybot.git" |         "url": "https://git.neet.dev/zuckerberg/dailybot.git" | ||||||
|       }, |       }, | ||||||
| @ -74,11 +123,11 @@ | |||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1744478979, |         "lastModified": 1700795494, | ||||||
|         "narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=", |         "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=", | ||||||
|         "owner": "lnl7", |         "owner": "lnl7", | ||||||
|         "repo": "nix-darwin", |         "repo": "nix-darwin", | ||||||
|         "rev": "43975d782b418ebf4969e9ccba82466728c2851b", |         "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
| @ -101,11 +150,11 @@ | |||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1749105467, |         "lastModified": 1718194053, | ||||||
|         "narHash": "sha256-hXh76y/wDl15almBcqvjryB50B0BaiXJKk20f314RoE=", |         "narHash": "sha256-FaGrf7qwZ99ehPJCAwgvNY5sLCqQ3GDiE/6uLhxxwSY=", | ||||||
|         "owner": "serokell", |         "owner": "serokell", | ||||||
|         "repo": "deploy-rs", |         "repo": "deploy-rs", | ||||||
|         "rev": "6bc76b872374845ba9d645a2f012b764fecd765f", |         "rev": "3867348fa92bc892eba5d9ddb2d7a97b9e127a8a", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
| @ -117,11 +166,11 @@ | |||||||
|     "flake-compat": { |     "flake-compat": { | ||||||
|       "flake": false, |       "flake": false, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1747046372, |         "lastModified": 1696426674, | ||||||
|         "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", |         "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", | ||||||
|         "owner": "edolstra", |         "owner": "edolstra", | ||||||
|         "repo": "flake-compat", |         "repo": "flake-compat", | ||||||
|         "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", |         "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
| @ -137,11 +186,11 @@ | |||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1731533236, |         "lastModified": 1710146030, | ||||||
|         "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", |         "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", | ||||||
|         "owner": "numtide", |         "owner": "numtide", | ||||||
|         "repo": "flake-utils", |         "repo": "flake-utils", | ||||||
|         "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", |         "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
| @ -150,71 +199,23 @@ | |||||||
|         "type": "github" |         "type": "github" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "git-hooks": { |  | ||||||
|       "inputs": { |  | ||||||
|         "flake-compat": [ |  | ||||||
|           "simple-nixos-mailserver", |  | ||||||
|           "flake-compat" |  | ||||||
|         ], |  | ||||||
|         "gitignore": "gitignore", |  | ||||||
|         "nixpkgs": [ |  | ||||||
|           "simple-nixos-mailserver", |  | ||||||
|           "nixpkgs" |  | ||||||
|         ] |  | ||||||
|       }, |  | ||||||
|       "locked": { |  | ||||||
|         "lastModified": 1750779888, |  | ||||||
|         "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=", |  | ||||||
|         "owner": "cachix", |  | ||||||
|         "repo": "git-hooks.nix", |  | ||||||
|         "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d", |  | ||||||
|         "type": "github" |  | ||||||
|       }, |  | ||||||
|       "original": { |  | ||||||
|         "owner": "cachix", |  | ||||||
|         "repo": "git-hooks.nix", |  | ||||||
|         "type": "github" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "gitignore": { |  | ||||||
|       "inputs": { |  | ||||||
|         "nixpkgs": [ |  | ||||||
|           "simple-nixos-mailserver", |  | ||||||
|           "git-hooks", |  | ||||||
|           "nixpkgs" |  | ||||||
|         ] |  | ||||||
|       }, |  | ||||||
|       "locked": { |  | ||||||
|         "lastModified": 1709087332, |  | ||||||
|         "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", |  | ||||||
|         "owner": "hercules-ci", |  | ||||||
|         "repo": "gitignore.nix", |  | ||||||
|         "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", |  | ||||||
|         "type": "github" |  | ||||||
|       }, |  | ||||||
|       "original": { |  | ||||||
|         "owner": "hercules-ci", |  | ||||||
|         "repo": "gitignore.nix", |  | ||||||
|         "type": "github" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "home-manager": { |     "home-manager": { | ||||||
|       "inputs": { |       "inputs": { | ||||||
|         "nixpkgs": [ |         "nixpkgs": [ | ||||||
|  |           "agenix", | ||||||
|           "nixpkgs" |           "nixpkgs" | ||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1752208517, |         "lastModified": 1703113217, | ||||||
|         "narHash": "sha256-aRY1cYOdVdXdNjcL/Twpa27CknO7pVHxooPsBizDraE=", |         "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", | ||||||
|         "owner": "nix-community", |         "owner": "nix-community", | ||||||
|         "repo": "home-manager", |         "repo": "home-manager", | ||||||
|         "rev": "c6a01e54af81b381695db796a43360bf6db5702f", |         "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|         "owner": "nix-community", |         "owner": "nix-community", | ||||||
|         "ref": "release-25.05", |  | ||||||
|         "repo": "home-manager", |         "repo": "home-manager", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       } |       } | ||||||
| @ -226,11 +227,11 @@ | |||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1752346111, |         "lastModified": 1716772633, | ||||||
|         "narHash": "sha256-SVxCIYnbED0rNYSpm3QQoOhqxYRp1GuE9FkyM5Y2afs=", |         "narHash": "sha256-Idcye44UW+EgjbjCoklf2IDF+XrehV6CVYvxR1omst4=", | ||||||
|         "owner": "Mic92", |         "owner": "Mic92", | ||||||
|         "repo": "nix-index-database", |         "repo": "nix-index-database", | ||||||
|         "rev": "deff7a9a0aa98a08d8c7839fe2658199ce9828f8", |         "rev": "ff80cb4a11bb87f3ce8459be6f16a25ac86eb2ac", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
| @ -241,11 +242,11 @@ | |||||||
|     }, |     }, | ||||||
|     "nixos-hardware": { |     "nixos-hardware": { | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1752048960, |         "lastModified": 1717248095, | ||||||
|         "narHash": "sha256-gATnkOe37eeVwKKYCsL+OnS2gU4MmLuZFzzWCtaKLI8=", |         "narHash": "sha256-e8X2eWjAHJQT82AAN+mCI0B68cIDBJpqJ156+VRrFO0=", | ||||||
|         "owner": "NixOS", |         "owner": "NixOS", | ||||||
|         "repo": "nixos-hardware", |         "repo": "nixos-hardware", | ||||||
|         "rev": "7ced9122cff2163c6a0212b8d1ec8c33a1660806", |         "rev": "7b49d3967613d9aacac5b340ef158d493906ba79", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
| @ -257,57 +258,91 @@ | |||||||
|     }, |     }, | ||||||
|     "nixpkgs": { |     "nixpkgs": { | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1752431364, |         "lastModified": 1717144377, | ||||||
|         "narHash": "sha256-ciGIXIMq2daX5o4Tn6pnZTd1pf5FICHbqUlHu658G9c=", |         "narHash": "sha256-F/TKWETwB5RaR8owkPPi+SPJh83AQsm6KrQAlJ8v/uA=", | ||||||
|         "owner": "NixOS", |         "owner": "NixOS", | ||||||
|         "repo": "nixpkgs", |         "repo": "nixpkgs", | ||||||
|         "rev": "fb0f0dbfd95f0e19fdeab8e0f18bf0b5cf057b68", |         "rev": "805a384895c696f802a9bf5bf4720f37385df547", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|         "owner": "NixOS", |         "owner": "NixOS", | ||||||
|         "ref": "release-25.05", |         "ref": "nixos-24.05", | ||||||
|         "repo": "nixpkgs", |         "repo": "nixpkgs", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "nixpkgs-linkwarden": { |     "nixpkgs-frigate": { | ||||||
|       "flake": false, |  | ||||||
|       "locked": { |       "locked": { | ||||||
|         "narHash": "sha256-wW3F+iRM/ATWkyq8+Romal8oFmsM/p98V96d5G0tasA=", |         "lastModified": 1695825837, | ||||||
|         "type": "file", |         "narHash": "sha256-4Ne11kNRnQsmSJCRSSNkFRSnHC4Y5gPDBIQGjjPfJiU=", | ||||||
|         "url": "https://github.com/NixOS/nixpkgs/pull/347353.diff" |         "owner": "NixOS", | ||||||
|  |         "repo": "nixpkgs", | ||||||
|  |         "rev": "5cfafa12d57374f48bcc36fda3274ada276cf69e", | ||||||
|  |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|         "type": "file", |         "owner": "NixOS", | ||||||
|         "url": "https://github.com/NixOS/nixpkgs/pull/347353.diff" |         "repo": "nixpkgs", | ||||||
|  |         "rev": "5cfafa12d57374f48bcc36fda3274ada276cf69e", | ||||||
|  |         "type": "github" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "nixpkgs-memos": { |     "radio": { | ||||||
|       "flake": false, |       "inputs": { | ||||||
|  |         "flake-utils": [ | ||||||
|  |           "flake-utils" | ||||||
|  |         ], | ||||||
|  |         "nixpkgs": [ | ||||||
|  |           "nixpkgs" | ||||||
|  |         ] | ||||||
|  |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "narHash": "sha256-UidUaQY+9vo90rNCVInX1E+JbJ1xKFVSTMNRYKQEKpQ=", |         "lastModified": 1631585589, | ||||||
|         "type": "file", |         "narHash": "sha256-q4o/4/2pEuJyaKZwNQC5KHnzG1obClzFB7zWk9XSDfY=", | ||||||
|         "url": "https://github.com/NixOS/nixpkgs/pull/426687.diff" |         "ref": "main", | ||||||
|  |         "rev": "5bf607fed977d41a269942a7d1e92f3e6d4f2473", | ||||||
|  |         "revCount": 38, | ||||||
|  |         "type": "git", | ||||||
|  |         "url": "https://git.neet.dev/zuckerberg/radio.git" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|         "type": "file", |         "ref": "main", | ||||||
|         "url": "https://github.com/NixOS/nixpkgs/pull/426687.diff" |         "rev": "5bf607fed977d41a269942a7d1e92f3e6d4f2473", | ||||||
|  |         "type": "git", | ||||||
|  |         "url": "https://git.neet.dev/zuckerberg/radio.git" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "radio-web": { | ||||||
|  |       "flake": false, | ||||||
|  |       "locked": { | ||||||
|  |         "lastModified": 1652121792, | ||||||
|  |         "narHash": "sha256-j1Y9MAjUVNgyFSeGzPoqibAnEysJDjZSXukVfQ7+bsQ=", | ||||||
|  |         "ref": "refs/heads/master", | ||||||
|  |         "rev": "72e7a9e80b780c84ed8d4a6374bfbb242701f900", | ||||||
|  |         "revCount": 5, | ||||||
|  |         "type": "git", | ||||||
|  |         "url": "https://git.neet.dev/zuckerberg/radio-web.git" | ||||||
|  |       }, | ||||||
|  |       "original": { | ||||||
|  |         "type": "git", | ||||||
|  |         "url": "https://git.neet.dev/zuckerberg/radio-web.git" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "root": { |     "root": { | ||||||
|       "inputs": { |       "inputs": { | ||||||
|         "agenix": "agenix", |         "agenix": "agenix", | ||||||
|  |         "attic": "attic", | ||||||
|         "dailybuild_modules": "dailybuild_modules", |         "dailybuild_modules": "dailybuild_modules", | ||||||
|         "deploy-rs": "deploy-rs", |         "deploy-rs": "deploy-rs", | ||||||
|         "flake-compat": "flake-compat", |         "flake-compat": "flake-compat", | ||||||
|         "flake-utils": "flake-utils", |         "flake-utils": "flake-utils", | ||||||
|         "home-manager": "home-manager", |  | ||||||
|         "nix-index-database": "nix-index-database", |         "nix-index-database": "nix-index-database", | ||||||
|         "nixos-hardware": "nixos-hardware", |         "nixos-hardware": "nixos-hardware", | ||||||
|         "nixpkgs": "nixpkgs", |         "nixpkgs": "nixpkgs", | ||||||
|         "nixpkgs-linkwarden": "nixpkgs-linkwarden", |         "nixpkgs-frigate": "nixpkgs-frigate", | ||||||
|         "nixpkgs-memos": "nixpkgs-memos", |         "radio": "radio", | ||||||
|  |         "radio-web": "radio-web", | ||||||
|         "simple-nixos-mailserver": "simple-nixos-mailserver", |         "simple-nixos-mailserver": "simple-nixos-mailserver", | ||||||
|         "systems": "systems" |         "systems": "systems" | ||||||
|       } |       } | ||||||
| @ -318,25 +353,27 @@ | |||||||
|         "flake-compat": [ |         "flake-compat": [ | ||||||
|           "flake-compat" |           "flake-compat" | ||||||
|         ], |         ], | ||||||
|         "git-hooks": "git-hooks", |  | ||||||
|         "nixpkgs": [ |         "nixpkgs": [ | ||||||
|           "nixpkgs" |           "nixpkgs" | ||||||
|         ], |         ], | ||||||
|         "nixpkgs-25_05": [ |         "nixpkgs-24_05": [ | ||||||
|           "nixpkgs" |           "nixpkgs" | ||||||
|  |         ], | ||||||
|  |         "utils": [ | ||||||
|  |           "flake-utils" | ||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1747965231, |         "lastModified": 1718084203, | ||||||
|         "narHash": "sha256-BW3ktviEhfCN/z3+kEyzpDKAI8qFTwO7+S0NVA0C90o=", |         "narHash": "sha256-Cx1xoVfSMv1XDLgKg08CUd1EoTYWB45VmB9XIQzhmzI=", | ||||||
|         "owner": "simple-nixos-mailserver", |         "owner": "simple-nixos-mailserver", | ||||||
|         "repo": "nixos-mailserver", |         "repo": "nixos-mailserver", | ||||||
|         "rev": "53007af63fade28853408370c4c600a63dd97f41", |         "rev": "29916981e7b3b5782dc5085ad18490113f8ff63b", | ||||||
|         "type": "gitlab" |         "type": "gitlab" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|         "owner": "simple-nixos-mailserver", |         "owner": "simple-nixos-mailserver", | ||||||
|         "ref": "nixos-25.05", |         "ref": "master", | ||||||
|         "repo": "nixos-mailserver", |         "repo": "nixos-mailserver", | ||||||
|         "type": "gitlab" |         "type": "gitlab" | ||||||
|       } |       } | ||||||
|  | |||||||
							
								
								
									
										68
									
								
								flake.nix
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								flake.nix
									
									
									
									
									
								
							| @ -1,15 +1,8 @@ | |||||||
| { | { | ||||||
|   inputs = { |   inputs = { | ||||||
|     # nixpkgs |     # nixpkgs | ||||||
|     nixpkgs.url = "github:NixOS/nixpkgs/release-25.05"; |     nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; | ||||||
|     nixpkgs-linkwarden = { |     nixpkgs-frigate.url = "github:NixOS/nixpkgs/5cfafa12d57374f48bcc36fda3274ada276cf69e"; | ||||||
|       url = "https://github.com/NixOS/nixpkgs/pull/347353.diff"; |  | ||||||
|       flake = false; |  | ||||||
|     }; |  | ||||||
|     nixpkgs-memos = { |  | ||||||
|       url = "https://github.com/NixOS/nixpkgs/pull/426687.diff"; |  | ||||||
|       flake = false; |  | ||||||
|     }; |  | ||||||
| 
 | 
 | ||||||
|     # Common Utils Among flake inputs |     # Common Utils Among flake inputs | ||||||
|     systems.url = "github:nix-systems/default"; |     systems.url = "github:nix-systems/default"; | ||||||
| @ -25,19 +18,14 @@ | |||||||
|     # NixOS hardware |     # NixOS hardware | ||||||
|     nixos-hardware.url = "github:NixOS/nixos-hardware/master"; |     nixos-hardware.url = "github:NixOS/nixos-hardware/master"; | ||||||
| 
 | 
 | ||||||
|     # Home Manager |  | ||||||
|     home-manager = { |  | ||||||
|       url = "github:nix-community/home-manager/release-25.05"; |  | ||||||
|       inputs.nixpkgs.follows = "nixpkgs"; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     # Mail Server |     # Mail Server | ||||||
|     simple-nixos-mailserver = { |     simple-nixos-mailserver = { | ||||||
|       url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-25.05"; |       url = "gitlab:simple-nixos-mailserver/nixos-mailserver/master"; | ||||||
|       inputs = { |       inputs = { | ||||||
|         nixpkgs.follows = "nixpkgs"; |         nixpkgs.follows = "nixpkgs"; | ||||||
|         nixpkgs-25_05.follows = "nixpkgs"; |         nixpkgs-24_05.follows = "nixpkgs"; | ||||||
|         flake-compat.follows = "flake-compat"; |         flake-compat.follows = "flake-compat"; | ||||||
|  |         utils.follows = "flake-utils"; | ||||||
|       }; |       }; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| @ -47,10 +35,22 @@ | |||||||
|       inputs = { |       inputs = { | ||||||
|         nixpkgs.follows = "nixpkgs"; |         nixpkgs.follows = "nixpkgs"; | ||||||
|         systems.follows = "systems"; |         systems.follows = "systems"; | ||||||
|         home-manager.follows = "home-manager"; |  | ||||||
|       }; |       }; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     # Radio | ||||||
|  |     radio = { | ||||||
|  |       url = "git+https://git.neet.dev/zuckerberg/radio.git?ref=main&rev=5bf607fed977d41a269942a7d1e92f3e6d4f2473"; | ||||||
|  |       inputs = { | ||||||
|  |         nixpkgs.follows = "nixpkgs"; | ||||||
|  |         flake-utils.follows = "flake-utils"; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |     radio-web = { | ||||||
|  |       url = "git+https://git.neet.dev/zuckerberg/radio-web.git"; | ||||||
|  |       flake = false; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     # Dailybot |     # Dailybot | ||||||
|     dailybuild_modules = { |     dailybuild_modules = { | ||||||
|       url = "git+https://git.neet.dev/zuckerberg/dailybot.git"; |       url = "git+https://git.neet.dev/zuckerberg/dailybot.git"; | ||||||
| @ -75,11 +75,22 @@ | |||||||
|       url = "github:Mic92/nix-index-database"; |       url = "github:Mic92/nix-index-database"; | ||||||
|       inputs.nixpkgs.follows = "nixpkgs"; |       inputs.nixpkgs.follows = "nixpkgs"; | ||||||
|     }; |     }; | ||||||
|  | 
 | ||||||
|  |     # Attic | ||||||
|  |     attic = { | ||||||
|  |       url = "github:zhaofengli/attic"; | ||||||
|  |       inputs = { | ||||||
|  |         nixpkgs.follows = "nixpkgs"; | ||||||
|  |         nixpkgs-stable.follows = "nixpkgs"; | ||||||
|  |         flake-utils.follows = "flake-utils"; | ||||||
|  |         flake-compat.follows = "flake-compat"; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   outputs = { self, nixpkgs, ... }@inputs: |   outputs = { self, nixpkgs, ... }@inputs: | ||||||
|     let |     let | ||||||
|       machineHosts = (import ./common/machine-info/moduleless.nix |       machines = (import ./common/machine-info/moduleless.nix | ||||||
|         { |         { | ||||||
|           inherit nixpkgs; |           inherit nixpkgs; | ||||||
|           assertionsModule = "${nixpkgs}/nixos/modules/misc/assertions.nix"; |           assertionsModule = "${nixpkgs}/nixos/modules/misc/assertions.nix"; | ||||||
| @ -94,7 +105,7 @@ | |||||||
|             agenix.nixosModules.default |             agenix.nixosModules.default | ||||||
|             dailybuild_modules.nixosModule |             dailybuild_modules.nixosModule | ||||||
|             nix-index-database.nixosModules.nix-index |             nix-index-database.nixosModules.nix-index | ||||||
|             home-manager.nixosModules.home-manager |             attic.nixosModules.atticd | ||||||
|             self.nixosModules.kernel-modules |             self.nixosModules.kernel-modules | ||||||
|             ({ lib, ... }: { |             ({ lib, ... }: { | ||||||
|               config = { |               config = { | ||||||
| @ -105,10 +116,6 @@ | |||||||
|                 ]; |                 ]; | ||||||
| 
 | 
 | ||||||
|                 networking.hostName = hostname; |                 networking.hostName = hostname; | ||||||
| 
 |  | ||||||
|                 home-manager.useGlobalPkgs = true; |  | ||||||
|                 home-manager.useUserPackages = true; |  | ||||||
|                 home-manager.users.googlebot = import ./home/googlebot.nix; |  | ||||||
|               }; |               }; | ||||||
| 
 | 
 | ||||||
|               # because nixos specialArgs doesn't work for containers... need to pass in inputs a different way |               # because nixos specialArgs doesn't work for containers... need to pass in inputs a different way | ||||||
| @ -126,14 +133,7 @@ | |||||||
|                 name = "nixpkgs-patched"; |                 name = "nixpkgs-patched"; | ||||||
|                 src = nixpkgs; |                 src = nixpkgs; | ||||||
|                 patches = [ |                 patches = [ | ||||||
|                   # ./patches/gamepadui.patch |                   ./patches/gamepadui.patch | ||||||
|                   ./patches/dont-break-nix-serve.patch |  | ||||||
|                   # music-assistant needs a specific custom version of librespot |  | ||||||
|                   # I tried to use an overlay but my attempts to override the rust package did not work out |  | ||||||
|                   # despite me following guides and examples specific to rust packages. |  | ||||||
|                   ./patches/librespot-pin.patch |  | ||||||
|                   inputs.nixpkgs-linkwarden |  | ||||||
|                   inputs.nixpkgs-memos |  | ||||||
|                 ]; |                 ]; | ||||||
|               }; |               }; | ||||||
|               patchedNixpkgs = nixpkgs.lib.fix (self: (import "${patchedNixpkgsSrc}/flake.nix").outputs { self = nixpkgs; }); |               patchedNixpkgs = nixpkgs.lib.fix (self: (import "${patchedNixpkgsSrc}/flake.nix").outputs { self = nixpkgs; }); | ||||||
| @ -153,7 +153,7 @@ | |||||||
|         nixpkgs.lib.mapAttrs |         nixpkgs.lib.mapAttrs | ||||||
|           (hostname: cfg: |           (hostname: cfg: | ||||||
|             mkSystem cfg.arch nixpkgs cfg.configurationPath hostname) |             mkSystem cfg.arch nixpkgs cfg.configurationPath hostname) | ||||||
|           machineHosts; |           machines; | ||||||
| 
 | 
 | ||||||
|       packages = |       packages = | ||||||
|         let |         let | ||||||
| @ -190,7 +190,7 @@ | |||||||
|         nixpkgs.lib.mapAttrs |         nixpkgs.lib.mapAttrs | ||||||
|           (hostname: cfg: |           (hostname: cfg: | ||||||
|             mkDeploy hostname cfg.arch (builtins.head cfg.hostNames)) |             mkDeploy hostname cfg.arch (builtins.head cfg.hostNames)) | ||||||
|           machineHosts; |           machines; | ||||||
| 
 | 
 | ||||||
|       checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) inputs.deploy-rs.lib; |       checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) inputs.deploy-rs.lib; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,123 +0,0 @@ | |||||||
| { config, lib, pkgs, osConfig, ... }: |  | ||||||
| 
 |  | ||||||
| let |  | ||||||
|   # Check if the current machine has the role "personal" |  | ||||||
|   thisMachineIsPersonal = osConfig.thisMachine.hasRole."personal"; |  | ||||||
| in |  | ||||||
| { |  | ||||||
|   home.username = "googlebot"; |  | ||||||
|   home.homeDirectory = "/home/googlebot"; |  | ||||||
| 
 |  | ||||||
|   home.stateVersion = "24.11"; |  | ||||||
|   programs.home-manager.enable = true; |  | ||||||
| 
 |  | ||||||
|   services.ssh-agent.enable = true; |  | ||||||
| 
 |  | ||||||
|   # System Monitoring |  | ||||||
|   programs.btop.enable = true; |  | ||||||
|   programs.bottom.enable = true; |  | ||||||
| 
 |  | ||||||
|   # Modern "ls" replacement |  | ||||||
|   programs.pls.enable = true; |  | ||||||
|   programs.pls.enableFishIntegration = true; |  | ||||||
|   programs.eza.enable = true; |  | ||||||
| 
 |  | ||||||
|   # Graphical terminal |  | ||||||
|   programs.ghostty.enable = thisMachineIsPersonal; |  | ||||||
|   programs.ghostty.settings = { |  | ||||||
|     theme = "Snazzy"; |  | ||||||
|     font-size = 10; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   # Advanced terminal file explorer |  | ||||||
|   programs.broot.enable = true; |  | ||||||
| 
 |  | ||||||
|   # Shell promt theming |  | ||||||
|   programs.fish.enable = true; |  | ||||||
|   programs.starship.enable = true; |  | ||||||
|   programs.starship.enableFishIntegration = true; |  | ||||||
|   programs.starship.enableInteractive = true; |  | ||||||
|   # programs.oh-my-posh.enable = true; |  | ||||||
|   # programs.oh-my-posh.enableFishIntegration = true; |  | ||||||
| 
 |  | ||||||
|   # Advanced search |  | ||||||
|   programs.ripgrep.enable = true; |  | ||||||
| 
 |  | ||||||
|   # tldr: Simplified, example based and community-driven man pages. |  | ||||||
|   programs.tealdeer.enable = true; |  | ||||||
| 
 |  | ||||||
|   home.shellAliases = { |  | ||||||
|     sudo = "doas"; |  | ||||||
|     ls2 = "eza"; |  | ||||||
|     explorer = "broot"; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   programs.zed-editor = { |  | ||||||
|     enable = thisMachineIsPersonal; |  | ||||||
|     extensions = [ |  | ||||||
|       "nix" |  | ||||||
|       "toml" |  | ||||||
|       "html" |  | ||||||
|       "make" |  | ||||||
|       "git-firefly" |  | ||||||
|       "vue" |  | ||||||
|       "scss" |  | ||||||
|     ]; |  | ||||||
| 
 |  | ||||||
|     userSettings = { |  | ||||||
|       assistant = { |  | ||||||
|         enabled = true; |  | ||||||
|         version = "2"; |  | ||||||
|         default_model = { |  | ||||||
|           provider = "openai"; |  | ||||||
|           model = "gpt-4-turbo"; |  | ||||||
|         }; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       features = { |  | ||||||
|         edit_prediction_provider = "zed"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       node = { |  | ||||||
|         path = lib.getExe pkgs.nodejs; |  | ||||||
|         npm_path = lib.getExe' pkgs.nodejs "npm"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       auto_update = false; |  | ||||||
| 
 |  | ||||||
|       terminal = { |  | ||||||
|         blinking = "off"; |  | ||||||
|         copy_on_select = false; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       lsp = { |  | ||||||
|         rust-analyzer = { |  | ||||||
|           # binary = { |  | ||||||
|           #   path = lib.getExe pkgs.rust-analyzer; |  | ||||||
|           # }; |  | ||||||
|           binary = { |  | ||||||
|             path = "/run/current-system/sw/bin/nix"; |  | ||||||
|             arguments = [ "develop" "--command" "rust-analyzer" ]; |  | ||||||
|           }; |  | ||||||
|           initialization_options = { |  | ||||||
|             cargo = { |  | ||||||
|               features = "all"; |  | ||||||
|             }; |  | ||||||
|           }; |  | ||||||
|         }; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       # tell zed to use direnv and direnv can use a flake.nix enviroment. |  | ||||||
|       load_direnv = "shell_hook"; |  | ||||||
| 
 |  | ||||||
|       base_keymap = "VSCode"; |  | ||||||
|       theme = { |  | ||||||
|         mode = "system"; |  | ||||||
|         light = "One Light"; |  | ||||||
|         dark = "Andrometa"; |  | ||||||
|       }; |  | ||||||
|       ui_font_size = 12; |  | ||||||
|       buffer_font_size = 12; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| @ -29,10 +29,10 @@ | |||||||
|       text = '' |       text = '' | ||||||
|         #!${pkgs.stdenv.shell} |         #!${pkgs.stdenv.shell} | ||||||
|         set -e |         set -e | ||||||
|         ${pkgs.kexec-tools}/bin/kexec -l ${image}/kernel --initrd=${image}/initrd --append="init=${builtins.unsafeDiscardStringContext config.system.build.toplevel}/init ${toString config.boot.kernelParams}" |         ${pkgs.kexectools}/bin/kexec -l ${image}/kernel --initrd=${image}/initrd --append="init=${builtins.unsafeDiscardStringContext config.system.build.toplevel}/init ${toString config.boot.kernelParams}" | ||||||
|         sync |         sync | ||||||
|         echo "executing kernel, filesystems will be improperly umounted" |         echo "executing kernel, filesystems will be improperly umounted" | ||||||
|         ${pkgs.kexec-tools}/bin/kexec -e |         ${pkgs.kexectools}/bin/kexec -e | ||||||
|       ''; |       ''; | ||||||
|     }; |     }; | ||||||
|     kexec_tarball = pkgs.callPackage (modulesPath + "/../lib/make-system-tarball.nix") { |     kexec_tarball = pkgs.callPackage (modulesPath + "/../lib/make-system-tarball.nix") { | ||||||
|  | |||||||
| @ -7,20 +7,12 @@ | |||||||
|     ../../common/ssh.nix |     ../../common/ssh.nix | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   boot.initrd.availableKernelModules = [ |   boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "e1000" "e1000e" "virtio_pci" "r8169" ]; | ||||||
|     "ata_piix" |  | ||||||
|     "uhci_hcd" |  | ||||||
|     "e1000" |  | ||||||
|     "e1000e" |  | ||||||
|     "virtio_pci" |  | ||||||
|     "r8169" |  | ||||||
|     "sdhci" |  | ||||||
|     "sdhci_pci" |  | ||||||
|     "mmc_core" |  | ||||||
|     "mmc_block" |  | ||||||
|   ]; |  | ||||||
|   boot.kernelParams = [ |   boot.kernelParams = [ | ||||||
|  |     "panic=30" | ||||||
|  |     "boot.panic_on_fail" # reboot the machine upon fatal boot issues | ||||||
|     "console=ttyS0,115200" # enable serial console |     "console=ttyS0,115200" # enable serial console | ||||||
|  |     "console=tty1" | ||||||
|   ]; |   ]; | ||||||
|   boot.kernel.sysctl."vm.overcommit_memory" = "1"; |   boot.kernel.sysctl."vm.overcommit_memory" = "1"; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -8,5 +8,6 @@ | |||||||
|   # don't use remote builders |   # don't use remote builders | ||||||
|   nix.distributedBuilds = lib.mkForce false; |   nix.distributedBuilds = lib.mkForce false; | ||||||
| 
 | 
 | ||||||
|   nix.gc.automatic = lib.mkForce false; |   de.enable = true; | ||||||
|  |   de.touchpad.enable = true; | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,8 +6,7 @@ | |||||||
|     nixos-hardware.nixosModules.framework-13-7040-amd |     nixos-hardware.nixosModules.framework-13-7040-amd | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   # boot.kernelPackages = pkgs.linuxPackages_6_14; |   boot.kernelPackages = pkgs.linuxPackages_latest; | ||||||
|   boot.kernelPackages = pkgs.linuxPackages_6_13; |  | ||||||
| 
 | 
 | ||||||
|   hardware.framework.amd-7040.preventWakeOnAC = true; |   hardware.framework.amd-7040.preventWakeOnAC = true; | ||||||
|   services.fwupd.enable = true; |   services.fwupd.enable = true; | ||||||
| @ -31,22 +30,22 @@ | |||||||
|   # disks |   # disks | ||||||
|   remoteLuksUnlock.enable = true; |   remoteLuksUnlock.enable = true; | ||||||
|   boot.initrd.luks.devices."enc-pv" = { |   boot.initrd.luks.devices."enc-pv" = { | ||||||
|     device = "/dev/disk/by-uuid/2e4a6960-a6b1-40ee-9c2c-2766eb718d52"; |     device = "/dev/disk/by-uuid/c801586b-f0a2-465c-8dae-532e61b83fee"; | ||||||
|     allowDiscards = true; |     allowDiscards = true; | ||||||
|   }; |   }; | ||||||
|   fileSystems."/" = |   fileSystems."/" = | ||||||
|     { |     { | ||||||
|       device = "/dev/disk/by-uuid/1f62386c-3243-49f5-b72f-df8fc8f39db8"; |       device = "/dev/disk/by-uuid/95db6950-a7bc-46cf-9765-3ea675ccf014"; | ||||||
|       fsType = "btrfs"; |       fsType = "btrfs"; | ||||||
|     }; |     }; | ||||||
|   fileSystems."/boot" = |   fileSystems."/boot" = | ||||||
|     { |     { | ||||||
|       device = "/dev/disk/by-uuid/F4D9-C5E8"; |       device = "/dev/disk/by-uuid/B087-2C20"; | ||||||
|       fsType = "vfat"; |       fsType = "vfat"; | ||||||
|       options = [ "fmask=0022" "dmask=0022" ]; |       options = [ "fmask=0022" "dmask=0022" ]; | ||||||
|     }; |     }; | ||||||
|   swapDevices = |   swapDevices = | ||||||
|     [{ device = "/dev/disk/by-uuid/5f65cb11-2649-48fe-9c78-3e325b857c53"; }]; |     [{ device = "/dev/disk/by-uuid/49fbdf62-eef4-421b-aac3-c93494afd23c"; }]; | ||||||
| 
 | 
 | ||||||
|   # Enables DHCP on each ethernet and wireless interface. In case of scripted networking |   # Enables DHCP on each ethernet and wireless interface. In case of scripted networking | ||||||
|   # (the default) this is the recommended approach. When using systemd-networkd it's |   # (the default) this is the recommended approach. When using systemd-networkd it's | ||||||
|  | |||||||
| @ -15,6 +15,10 @@ | |||||||
|     "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKPnLt84bKhUgFxjQf10+Htro9Lo1Pabqm8mGalBUniv" |     "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKPnLt84bKhUgFxjQf10+Htro9Lo1Pabqm8mGalBUniv" | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|  |   deployKeys = [ | ||||||
|  |     # TODO | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|   remoteUnlock = { |   remoteUnlock = { | ||||||
|     hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN0N80r0Sl2WlJaUqfxZPkOtYyGumFazkIqq7eq3Gd2o"; |     hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN0N80r0Sl2WlJaUqfxZPkOtYyGumFazkIqq7eq3Gd2o"; | ||||||
|     onionHost = "ll6yjnkh4psmfwmtkmqoutl4gq4elqzbmjxv4s6gpgoavyi3kwhjvnqd.onion"; |     onionHost = "ll6yjnkh4psmfwmtkmqoutl4gq4elqzbmjxv4s6gpgoavyi3kwhjvnqd.onion"; | ||||||
|  | |||||||
| @ -9,4 +9,7 @@ | |||||||
| 
 | 
 | ||||||
|   networking.hostName = "nat"; |   networking.hostName = "nat"; | ||||||
|   networking.interfaces.ens160.useDHCP = true; |   networking.interfaces.ens160.useDHCP = true; | ||||||
|  | 
 | ||||||
|  |   de.enable = true; | ||||||
|  |   de.touchpad.enable = true; | ||||||
| } | } | ||||||
|  | |||||||
| @ -10,8 +10,6 @@ | |||||||
|   # p2p mesh network |   # p2p mesh network | ||||||
|   services.tailscale.exitNode = true; |   services.tailscale.exitNode = true; | ||||||
| 
 | 
 | ||||||
|   services.iperf3.enable = true; |  | ||||||
| 
 |  | ||||||
|   # email server |   # email server | ||||||
|   mailserver.enable = true; |   mailserver.enable = true; | ||||||
| 
 | 
 | ||||||
| @ -56,6 +54,44 @@ | |||||||
|     config.services.drastikbot.dataDir |     config.services.drastikbot.dataDir | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|  |   # music radio | ||||||
|  |   vpn-container.enable = true; | ||||||
|  |   vpn-container.config = { | ||||||
|  |     services.radio = { | ||||||
|  |       enable = true; | ||||||
|  |       host = "radio.runyan.org"; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  |   pia.wireguard.badPortForwardPorts = [ ]; | ||||||
|  |   services.nginx.virtualHosts = { | ||||||
|  |     "radio.runyan.org" = { | ||||||
|  |       enableACME = true; | ||||||
|  |       forceSSL = true; | ||||||
|  |       locations = { | ||||||
|  |         "/stream.mp3" = { | ||||||
|  |           proxyPass = "http://vpn.containers:8001/stream.mp3"; | ||||||
|  |           extraConfig = '' | ||||||
|  |             add_header Access-Control-Allow-Origin *; | ||||||
|  |           ''; | ||||||
|  |         }; | ||||||
|  |         "/".root = config.inputs.radio-web; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |     "radio.neet.space" = { | ||||||
|  |       enableACME = true; | ||||||
|  |       forceSSL = true; | ||||||
|  |       locations = { | ||||||
|  |         "/stream.mp3" = { | ||||||
|  |           proxyPass = "http://vpn.containers:8001/stream.mp3"; | ||||||
|  |           extraConfig = '' | ||||||
|  |             add_header Access-Control-Allow-Origin *; | ||||||
|  |           ''; | ||||||
|  |         }; | ||||||
|  |         "/".root = config.inputs.radio-web; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|   # matrix home server |   # matrix home server | ||||||
|   services.matrix = { |   services.matrix = { | ||||||
|     enable = true; |     enable = true; | ||||||
| @ -66,7 +102,7 @@ | |||||||
|       host = "chat.neet.space"; |       host = "chat.neet.space"; | ||||||
|     }; |     }; | ||||||
|     jitsi-meet = { |     jitsi-meet = { | ||||||
|       enable = false; # disabled until vulnerable libolm dependency is removed/fixed |       enable = true; | ||||||
|       host = "meet.neet.space"; |       host = "meet.neet.space"; | ||||||
|     }; |     }; | ||||||
|     turn = { |     turn = { | ||||||
| @ -78,10 +114,18 @@ | |||||||
|   services.postgresql.package = pkgs.postgresql_15; |   services.postgresql.package = pkgs.postgresql_15; | ||||||
| 
 | 
 | ||||||
|   # iodine DNS-based vpn |   # iodine DNS-based vpn | ||||||
|   # services.iodine.server.enable = true; |   services.iodine.server.enable = true; | ||||||
| 
 | 
 | ||||||
|   # proxied web services |   # proxied web services | ||||||
|   services.nginx.enable = true; |   services.nginx.enable = true; | ||||||
|  |   services.nginx.virtualHosts."jellyfin.neet.cloud" = { | ||||||
|  |     enableACME = true; | ||||||
|  |     forceSSL = true; | ||||||
|  |     locations."/" = { | ||||||
|  |       proxyPass = "http://s0.koi-bebop.ts.net"; | ||||||
|  |       proxyWebsockets = true; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|   services.nginx.virtualHosts."navidrome.neet.cloud" = { |   services.nginx.virtualHosts."navidrome.neet.cloud" = { | ||||||
|     enableACME = true; |     enableACME = true; | ||||||
|     forceSSL = true; |     forceSSL = true; | ||||||
| @ -95,12 +139,12 @@ | |||||||
|     root = "/var/www/tmp"; |     root = "/var/www/tmp"; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   # redirect neet.cloud to nextcloud instance on runyan.org |   # redirect runyan.org to github | ||||||
|   services.nginx.virtualHosts."neet.cloud" = { |   services.nginx.virtualHosts."runyan.org" = { | ||||||
|     enableACME = true; |     enableACME = true; | ||||||
|     forceSSL = true; |     forceSSL = true; | ||||||
|     extraConfig = '' |     extraConfig = '' | ||||||
|       return 302 https://runyan.org$request_uri; |       rewrite ^/(.*)$ https://github.com/GoogleBot42 redirect; | ||||||
|     ''; |     ''; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
| @ -111,4 +155,7 @@ | |||||||
|   # librechat |   # librechat | ||||||
|   services.librechat.enable = true; |   services.librechat.enable = true; | ||||||
|   services.librechat.host = "chat.neet.dev"; |   services.librechat.host = "chat.neet.dev"; | ||||||
|  | 
 | ||||||
|  |   services.actual-server.enable = true; | ||||||
|  |   services.actual-server.hostname = "actual.runyan.org"; | ||||||
| } | } | ||||||
|  | |||||||
| @ -22,7 +22,8 @@ | |||||||
| 
 | 
 | ||||||
|   # networking.useDHCP = lib.mkForce true; |   # networking.useDHCP = lib.mkForce true; | ||||||
| 
 | 
 | ||||||
|   networking.usePredictableInterfaceNames = false; |   # TODO | ||||||
|  |   # networking.usePredictableInterfaceNames = true; | ||||||
| 
 | 
 | ||||||
|   powerManagement.cpuFreqGovernor = "ondemand"; |   powerManagement.cpuFreqGovernor = "ondemand"; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -10,6 +10,8 @@ | |||||||
| 
 | 
 | ||||||
|   # Enable serial output |   # Enable serial output | ||||||
|   boot.kernelParams = [ |   boot.kernelParams = [ | ||||||
|  |     "panic=30" | ||||||
|  |     "boot.panic_on_fail" # reboot the machine upon fatal boot issues | ||||||
|     "console=ttyS0,115200n8" # enable serial console |     "console=ttyS0,115200n8" # enable serial console | ||||||
|   ]; |   ]; | ||||||
|   boot.loader.grub.extraConfig = " |   boot.loader.grub.extraConfig = " | ||||||
| @ -21,8 +23,6 @@ | |||||||
|   # firmware |   # firmware | ||||||
|   firmware.x86_64.enable = true; |   firmware.x86_64.enable = true; | ||||||
|   nixpkgs.config.allowUnfree = true; |   nixpkgs.config.allowUnfree = true; | ||||||
|   hardware.enableRedistributableFirmware = true; |  | ||||||
|   hardware.enableAllFirmware = true; |  | ||||||
| 
 | 
 | ||||||
|   # boot |   # boot | ||||||
|   bios = { |   bios = { | ||||||
| @ -31,18 +31,20 @@ | |||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   # disks |   # disks | ||||||
|  |   remoteLuksUnlock.enable = true; | ||||||
|  |   boot.initrd.luks.devices."enc-pv".device = "/dev/disk/by-uuid/9b090551-f78e-45ca-8570-196ed6a4af0c"; | ||||||
|   fileSystems."/" = |   fileSystems."/" = | ||||||
|     { |     { | ||||||
|       device = "/dev/disk/by-uuid/6aa7f79e-bef8-4b0f-b22c-9d1b3e8ac94b"; |       device = "/dev/disk/by-uuid/421c82b9-d67c-4811-8824-8bb57cb10fce"; | ||||||
|       fsType = "ext4"; |       fsType = "btrfs"; | ||||||
|     }; |     }; | ||||||
|   fileSystems."/boot" = |   fileSystems."/boot" = | ||||||
|     { |     { | ||||||
|       device = "/dev/disk/by-uuid/14dfc562-0333-4ddd-b10c-4eeefe1cd05f"; |       device = "/dev/disk/by-uuid/d97f324f-3a2e-4b84-ae2a-4b3d1209c689"; | ||||||
|       fsType = "ext3"; |       fsType = "ext3"; | ||||||
|     }; |     }; | ||||||
|   swapDevices = |   swapDevices = | ||||||
|     [{ device = "/dev/disk/by-uuid/adf37c64-3b54-480c-a9a7-099d61c6eac7"; }]; |     [{ device = "/dev/disk/by-uuid/45bf58dd-67eb-45e4-9a98-246e23fa7abd"; }]; | ||||||
| 
 | 
 | ||||||
|   nixpkgs.hostPlatform = "x86_64-linux"; |   nixpkgs.hostPlatform = "x86_64-linux"; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,17 +0,0 @@ | |||||||
| { |  | ||||||
|   hostNames = [ |  | ||||||
|     "router" |  | ||||||
|     "192.168.6.159" |  | ||||||
|     "192.168.3.1" |  | ||||||
|   ]; |  | ||||||
| 
 |  | ||||||
|   arch = "x86_64-linux"; |  | ||||||
| 
 |  | ||||||
|   systemRoles = [ |  | ||||||
|     "server" |  | ||||||
|     "wireless" |  | ||||||
|     "router" |  | ||||||
|   ]; |  | ||||||
| 
 |  | ||||||
|   hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKDCMhEvWJxFBNyvpyuljv5Uun8AdXCxBK9HvPBRe5x6"; |  | ||||||
| } |  | ||||||
							
								
								
									
										21
									
								
								machines/router/properties.nix.disabled
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								machines/router/properties.nix.disabled
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | { | ||||||
|  |   hostNames = [ | ||||||
|  |     "router" | ||||||
|  |     "192.168.1.228" | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|  |   arch = "x86_64-linux"; | ||||||
|  | 
 | ||||||
|  |   systemRoles = [ | ||||||
|  |     "server" | ||||||
|  |     "wireless" | ||||||
|  |     "router" | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|  |   hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFr2IHmWFlaLaLp5dGoSmFEYKA/eg2SwGXAogaOmLsHL"; | ||||||
|  | 
 | ||||||
|  |   remoteUnlock = { | ||||||
|  |     hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJOw5dTPmtKqiPBH6VKyz5MYBubn8leAh5Eaw7s/O85c"; | ||||||
|  |     onionHost = "jxx2exuihlls2t6ncs7rvrjh2dssubjmjtclwr2ysvxtr4t7jv55xmqd.onion"; | ||||||
|  |   }; | ||||||
|  | } | ||||||
| @ -31,10 +31,8 @@ in | |||||||
|     networking.bridges = { |     networking.bridges = { | ||||||
|       br0 = { |       br0 = { | ||||||
|         interfaces = [ |         interfaces = [ | ||||||
|           "eth2" |           "enp2s0" | ||||||
|           # "wlp4s0" |           "wlp4s0" | ||||||
|           # "wlan1" |  | ||||||
|           "wlan0" |  | ||||||
|           "wlan1" |           "wlan1" | ||||||
|         ]; |         ]; | ||||||
|       }; |       }; | ||||||
| @ -66,173 +64,142 @@ in | |||||||
| 
 | 
 | ||||||
|     services.dnsmasq = { |     services.dnsmasq = { | ||||||
|       enable = true; |       enable = true; | ||||||
|       settings = { |       extraConfig = '' | ||||||
|         # sensible behaviours |         # sensible behaviours | ||||||
|         domain-needed = true; |         domain-needed | ||||||
|         bogus-priv = true; |         bogus-priv | ||||||
|         no-resolv = true; |         no-resolv | ||||||
| 
 | 
 | ||||||
|         # upstream name servers |         # upstream name servers | ||||||
|         server = [ |         server=1.1.1.1 | ||||||
|           "1.1.1.1" |         server=8.8.8.8 | ||||||
|           "8.8.8.8" |  | ||||||
|         ]; |  | ||||||
| 
 | 
 | ||||||
|         # local domains |         # local domains | ||||||
|         expand-hosts = true; |         expand-hosts | ||||||
|         domain = "home"; |         domain=home | ||||||
|         local = "/home/"; |         local=/home/ | ||||||
| 
 | 
 | ||||||
|         # Interfaces to use DNS on |         # Interfaces to use DNS on | ||||||
|         interface = "br0"; |         interface=br0 | ||||||
| 
 | 
 | ||||||
|         # subnet IP blocks to use DHCP on |         # subnet IP blocks to use DHCP on | ||||||
|         dhcp-range = "${cfg.privateSubnet}.10,${cfg.privateSubnet}.254,24h"; |         dhcp-range=${cfg.privateSubnet}.10,${cfg.privateSubnet}.254,24h | ||||||
|       }; |       ''; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     services.hostapd = { |     services.hostapd = { | ||||||
|       enable = true; |       enable = true; | ||||||
|       radios = { |       radios = { | ||||||
|         # Simple 2.4GHz AP |         # 2.4GHz | ||||||
|         wlan0 = { |         wlp4s0 = { | ||||||
|  |           band = "2g"; | ||||||
|  |           noScan = true; | ||||||
|  |           channel = 6; | ||||||
|           countryCode = "US"; |           countryCode = "US"; | ||||||
|           networks.wlan0 = { |           wifi4 = { | ||||||
|             ssid = "CXNK00BF9176-1"; |             capabilities = [ "LDPC" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "HT40+" ]; | ||||||
|             authentication.saePasswords = [{ passwordFile = "/run/agenix/hostapd-pw-CXNK00BF9176"; }]; |           }; | ||||||
|  |           wifi5 = { | ||||||
|  |             operatingChannelWidth = "20or40"; | ||||||
|  |             capabilities = [ "MAX-A-MPDU-LEN-EXP0" ]; | ||||||
|  |           }; | ||||||
|  |           wifi6 = { | ||||||
|  |             enable = true; | ||||||
|  |             singleUserBeamformer = true; | ||||||
|  |             singleUserBeamformee = true; | ||||||
|  |             multiUserBeamformer = true; | ||||||
|  |             operatingChannelWidth = "20or40"; | ||||||
|  |           }; | ||||||
|  |           networks = { | ||||||
|  |             wlp4s0 = { | ||||||
|  |               ssid = "CXNK00BF9176"; | ||||||
|  |               authentication.saePasswordsFile = "/run/agenix/hostapd-pw-CXNK00BF9176"; | ||||||
|  |             }; | ||||||
|  |             # wlp4s0-1 = { | ||||||
|  |             #   ssid = "- Experimental 5G Tower by AT&T"; | ||||||
|  |             #   authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower"; | ||||||
|  |             # }; | ||||||
|  |             # wlp4s0-2 = { | ||||||
|  |             #   ssid = "FBI Surveillance Van 2"; | ||||||
|  |             #   authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower"; | ||||||
|  |             # }; | ||||||
|  |           }; | ||||||
|  |           settings = { | ||||||
|  |             he_oper_centr_freq_seg0_idx = 8; | ||||||
|  |             vht_oper_centr_freq_seg0_idx = 8; | ||||||
|           }; |           }; | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         # WiFi 5 (5GHz) with two advertised networks |         # 5GHz | ||||||
|         wlan1 = { |         wlan1 = { | ||||||
|           band = "5g"; |           band = "5g"; | ||||||
|           channel = 0; |           noScan = true; | ||||||
|  |           channel = 128; | ||||||
|           countryCode = "US"; |           countryCode = "US"; | ||||||
|           networks.wlan1 = { |           wifi4 = { | ||||||
|             ssid = "CXNK00BF9176-1"; |             capabilities = [ "LDPC" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "HT40-" ]; | ||||||
|             authentication.saePasswords = [{ passwordFile = "/run/agenix/hostapd-pw-CXNK00BF9176"; }]; |           }; | ||||||
|  |           wifi5 = { | ||||||
|  |             operatingChannelWidth = "160"; | ||||||
|  |             capabilities = [ "RXLDPC" "SHORT-GI-80" "SHORT-GI-160" "TX-STBC-2BY1" "SU-BEAMFORMER" "SU-BEAMFORMEE" "MU-BEAMFORMER" "MU-BEAMFORMEE" "RX-ANTENNA-PATTERN" "TX-ANTENNA-PATTERN" "RX-STBC-1" "SOUNDING-DIMENSION-3" "BF-ANTENNA-3" "VHT160" "MAX-MPDU-11454" "MAX-A-MPDU-LEN-EXP7" ]; | ||||||
|  |           }; | ||||||
|  |           wifi6 = { | ||||||
|  |             enable = true; | ||||||
|  |             singleUserBeamformer = true; | ||||||
|  |             singleUserBeamformee = true; | ||||||
|  |             multiUserBeamformer = true; | ||||||
|  |             operatingChannelWidth = "160"; | ||||||
|  |           }; | ||||||
|  |           networks = { | ||||||
|  |             wlan1 = { | ||||||
|  |               ssid = "CXNK00BF9176"; | ||||||
|  |               authentication.saePasswordsFile = "/run/agenix/hostapd-pw-CXNK00BF9176"; | ||||||
|  |             }; | ||||||
|  |             # wlan1-1 = { | ||||||
|  |             #   ssid = "- Experimental 5G Tower by AT&T"; | ||||||
|  |             #   authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower"; | ||||||
|  |             # }; | ||||||
|  |             # wlan1-2 = { | ||||||
|  |             #   ssid = "FBI Surveillance Van 5"; | ||||||
|  |             #   authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower"; | ||||||
|  |             # }; | ||||||
|  |           }; | ||||||
|  |           settings = { | ||||||
|  |             vht_oper_centr_freq_seg0_idx = 114; | ||||||
|  |             he_oper_centr_freq_seg0_idx = 114; | ||||||
|           }; |           }; | ||||||
|         }; |         }; | ||||||
|       }; |       }; | ||||||
|     }; |     }; | ||||||
|  |     age.secrets.hostapd-pw-experimental-tower.file = ../../secrets/hostapd-pw-experimental-tower.age; | ||||||
|     age.secrets.hostapd-pw-CXNK00BF9176.file = ../../secrets/hostapd-pw-CXNK00BF9176.age; |     age.secrets.hostapd-pw-CXNK00BF9176.file = ../../secrets/hostapd-pw-CXNK00BF9176.age; | ||||||
| 
 | 
 | ||||||
|     # wlan0 5Ghz 00:0a:52:08:38:32 |     hardware.firmware = [ | ||||||
|     # wlp4s0 2.4Ghz 00:0a:52:08:38:33 |       pkgs.mt7916-firmware | ||||||
|  |     ]; | ||||||
| 
 | 
 | ||||||
|     # services.hostapd = { |     nixpkgs.overlays = [ | ||||||
|     #   enable = true; |       (self: super: { | ||||||
|     #   radios = { |         mt7916-firmware = pkgs.stdenvNoCC.mkDerivation { | ||||||
|     #     # 2.4GHz |           pname = "mt7916-firmware"; | ||||||
|     #     wlp4s0 = { |           version = "custom-feb-02-23"; | ||||||
|     #       band = "2g"; |           src = ./firmware/mediatek; # from here https://github.com/openwrt/mt76/issues/720#issuecomment-1413537674 | ||||||
|     #       noScan = true; |           dontBuild = true; | ||||||
|     #       channel = 6; |           installPhase = '' | ||||||
|     #       countryCode = "US"; |             for i in \ | ||||||
|     #       wifi4 = { |               mt7916_eeprom.bin \ | ||||||
|     #         capabilities = [ "LDPC" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "HT40+" ]; |               mt7916_rom_patch.bin \ | ||||||
|     #       }; |               mt7916_wa.bin \ | ||||||
|     #       wifi5 = { |               mt7916_wm.bin; | ||||||
|     #         operatingChannelWidth = "20or40"; |             do | ||||||
|     #         capabilities = [ "MAX-A-MPDU-LEN-EXP0" ]; |               install -D -pm644 $i $out/lib/firmware/mediatek/$i | ||||||
|     #       }; |             done | ||||||
|     #       wifi6 = { |           ''; | ||||||
|     #         enable = true; |           meta = with lib; { | ||||||
|     #         singleUserBeamformer = true; |             license = licenses.unfreeRedistributableFirmware; | ||||||
|     #         singleUserBeamformee = true; |           }; | ||||||
|     #         multiUserBeamformer = true; |         }; | ||||||
|     #         operatingChannelWidth = "20or40"; |       }) | ||||||
|     #       }; |     ]; | ||||||
|     #       networks = { |  | ||||||
|     #         wlp4s0 = { |  | ||||||
|     #           ssid = "CXNK00BF9176"; |  | ||||||
|     #           authentication.saePasswordsFile = "/run/agenix/hostapd-pw-CXNK00BF9176"; |  | ||||||
|     #         }; |  | ||||||
|     #         # wlp4s0-1 = { |  | ||||||
|     #         #   ssid = "- Experimental 5G Tower by AT&T"; |  | ||||||
|     #         #   authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower"; |  | ||||||
|     #         # }; |  | ||||||
|     #         # wlp4s0-2 = { |  | ||||||
|     #         #   ssid = "FBI Surveillance Van 2"; |  | ||||||
|     #         #   authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower"; |  | ||||||
|     #         # }; |  | ||||||
|     #       }; |  | ||||||
|     #       settings = { |  | ||||||
|     #         he_oper_centr_freq_seg0_idx = 8; |  | ||||||
|     #         vht_oper_centr_freq_seg0_idx = 8; |  | ||||||
|     #       }; |  | ||||||
|     #     }; |  | ||||||
| 
 |  | ||||||
|     #     # 5GHz |  | ||||||
|     #     wlan1 = { |  | ||||||
|     #       band = "5g"; |  | ||||||
|     #       noScan = true; |  | ||||||
|     #       channel = 128; |  | ||||||
|     #       countryCode = "US"; |  | ||||||
|     #       wifi4 = { |  | ||||||
|     #         capabilities = [ "LDPC" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "HT40-" ]; |  | ||||||
|     #       }; |  | ||||||
|     #       wifi5 = { |  | ||||||
|     #         operatingChannelWidth = "160"; |  | ||||||
|     #         capabilities = [ "RXLDPC" "SHORT-GI-80" "SHORT-GI-160" "TX-STBC-2BY1" "SU-BEAMFORMER" "SU-BEAMFORMEE" "MU-BEAMFORMER" "MU-BEAMFORMEE" "RX-ANTENNA-PATTERN" "TX-ANTENNA-PATTERN" "RX-STBC-1" "SOUNDING-DIMENSION-3" "BF-ANTENNA-3" "VHT160" "MAX-MPDU-11454" "MAX-A-MPDU-LEN-EXP7" ]; |  | ||||||
|     #       }; |  | ||||||
|     #       wifi6 = { |  | ||||||
|     #         enable = true; |  | ||||||
|     #         singleUserBeamformer = true; |  | ||||||
|     #         singleUserBeamformee = true; |  | ||||||
|     #         multiUserBeamformer = true; |  | ||||||
|     #         operatingChannelWidth = "160"; |  | ||||||
|     #       }; |  | ||||||
|     #       networks = { |  | ||||||
|     #         wlan1 = { |  | ||||||
|     #           ssid = "CXNK00BF9176"; |  | ||||||
|     #           authentication.saePasswordsFile = "/run/agenix/hostapd-pw-CXNK00BF9176"; |  | ||||||
|     #         }; |  | ||||||
|     #         # wlan1-1 = { |  | ||||||
|     #         #   ssid = "- Experimental 5G Tower by AT&T"; |  | ||||||
|     #         #   authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower"; |  | ||||||
|     #         # }; |  | ||||||
|     #         # wlan1-2 = { |  | ||||||
|     #         #   ssid = "FBI Surveillance Van 5"; |  | ||||||
|     #         #   authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower"; |  | ||||||
|     #         # }; |  | ||||||
|     #       }; |  | ||||||
|     #       settings = { |  | ||||||
|     #         vht_oper_centr_freq_seg0_idx = 114; |  | ||||||
|     #         he_oper_centr_freq_seg0_idx = 114; |  | ||||||
|     #       }; |  | ||||||
|     #     }; |  | ||||||
|     #   }; |  | ||||||
|     # }; |  | ||||||
|     # age.secrets.hostapd-pw-experimental-tower.file = ../../secrets/hostapd-pw-experimental-tower.age; |  | ||||||
|     # age.secrets.hostapd-pw-CXNK00BF9176.file = ../../secrets/hostapd-pw-CXNK00BF9176.age; |  | ||||||
| 
 |  | ||||||
|     # hardware.firmware = [ |  | ||||||
|     #   pkgs.mt7916-firmware |  | ||||||
|     # ]; |  | ||||||
| 
 |  | ||||||
|     # nixpkgs.overlays = [ |  | ||||||
|     #   (self: super: { |  | ||||||
|     #     mt7916-firmware = pkgs.stdenvNoCC.mkDerivation { |  | ||||||
|     #       pname = "mt7916-firmware"; |  | ||||||
|     #       version = "custom-feb-02-23"; |  | ||||||
|     #       src = ./firmware/mediatek; # from here https://github.com/openwrt/mt76/issues/720#issuecomment-1413537674 |  | ||||||
|     #       dontBuild = true; |  | ||||||
|     #       installPhase = '' |  | ||||||
|     #         for i in \ |  | ||||||
|     #           mt7916_eeprom.bin \ |  | ||||||
|     #           mt7916_rom_patch.bin \ |  | ||||||
|     #           mt7916_wa.bin \ |  | ||||||
|     #           mt7916_wm.bin; |  | ||||||
|     #         do |  | ||||||
|     #           install -D -pm644 $i $out/lib/firmware/mediatek/$i |  | ||||||
|     #         done |  | ||||||
|     #       ''; |  | ||||||
|     #       meta = with lib; { |  | ||||||
|     #         license = licenses.unfreeRedistributableFirmware; |  | ||||||
|     #       }; |  | ||||||
|     #     }; |  | ||||||
|     #   }) |  | ||||||
|     # ]; |  | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,297 +0,0 @@ | |||||||
| { |  | ||||||
|   appConfig = { |  | ||||||
|     theme = "vaporware"; |  | ||||||
|     customColors = { |  | ||||||
|       "material-dark-original" = { |  | ||||||
|         primary = "#f36558"; |  | ||||||
|         background = "#39434C"; |  | ||||||
|         "background-darker" = "#eb615c"; |  | ||||||
|         "material-light" = "#f36558"; |  | ||||||
|         "item-text-color" = "#ff948a"; |  | ||||||
|         "curve-factor" = "5px"; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     enableErrorReporting = false; |  | ||||||
|     layout = "auto"; |  | ||||||
|     iconSize = "large"; |  | ||||||
|     language = "en"; |  | ||||||
|     startingView = "default"; |  | ||||||
|     defaultOpeningMethod = "sametab"; |  | ||||||
|     statusCheck = true; |  | ||||||
|     statusCheckInterval = 20; |  | ||||||
|     faviconApi = "faviconkit"; |  | ||||||
|     routingMode = "history"; |  | ||||||
|     enableMultiTasking = false; |  | ||||||
|     webSearch = { |  | ||||||
|       disableWebSearch = false; |  | ||||||
|       searchEngine = "duckduckgo"; |  | ||||||
|       openingMethod = "sametab"; |  | ||||||
|       searchBangs = { }; |  | ||||||
|     }; |  | ||||||
|     enableFontAwesome = true; |  | ||||||
|     cssThemes = [ ]; |  | ||||||
|     externalStyleSheet = [ ]; |  | ||||||
|     hideComponents = { |  | ||||||
|       hideHeading = false; |  | ||||||
|       hideNav = false; |  | ||||||
|       hideSearch = false; |  | ||||||
|       hideSettings = false; |  | ||||||
|       hideFooter = false; |  | ||||||
|       hideSplashScreen = false; |  | ||||||
|     }; |  | ||||||
|     auth = { |  | ||||||
|       enableGuestAccess = false; |  | ||||||
|       users = [ ]; |  | ||||||
|       enableKeycloak = false; |  | ||||||
|       keycloak = { }; |  | ||||||
|     }; |  | ||||||
|     allowConfigEdit = true; |  | ||||||
|     enableServiceWorker = false; |  | ||||||
|     disableContextMenu = false; |  | ||||||
|     disableUpdateChecks = false; |  | ||||||
|     disableSmartSort = false; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   pageInfo = { |  | ||||||
|     title = "s0"; |  | ||||||
|     description = "s0"; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   sections = [ |  | ||||||
|     ( |  | ||||||
|       let |  | ||||||
|         # Define the media section items once. |  | ||||||
|         mediaItems = { |  | ||||||
|           jellyfin = { |  | ||||||
|             title = "Jellyfin"; |  | ||||||
|             icon = "hl-jellyfin"; |  | ||||||
|             url = "https://jellyfin.s0.neet.dev"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = false; |  | ||||||
|             id = "0_1956_jellyfin"; |  | ||||||
|           }; |  | ||||||
|           sonarr = { |  | ||||||
|             title = "Sonarr"; |  | ||||||
|             description = "Manage TV"; |  | ||||||
|             icon = "hl-sonarr"; |  | ||||||
|             url = "https://sonarr.s0.neet.dev"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = false; |  | ||||||
|             id = "1_1956_sonarr"; |  | ||||||
|           }; |  | ||||||
|           radarr = { |  | ||||||
|             title = "Radarr"; |  | ||||||
|             description = "Manage Movies"; |  | ||||||
|             icon = "hl-radarr"; |  | ||||||
|             url = "https://radarr.s0.neet.dev"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = false; |  | ||||||
|             id = "2_1956_radarr"; |  | ||||||
|           }; |  | ||||||
|           lidarr = { |  | ||||||
|             title = "Lidarr"; |  | ||||||
|             description = "Manage Music"; |  | ||||||
|             icon = "hl-lidarr"; |  | ||||||
|             url = "https://lidarr.s0.neet.dev"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = false; |  | ||||||
|             id = "3_1956_lidarr"; |  | ||||||
|           }; |  | ||||||
|           prowlarr = { |  | ||||||
|             title = "Prowlarr"; |  | ||||||
|             description = "Indexers"; |  | ||||||
|             icon = "hl-prowlarr"; |  | ||||||
|             url = "https://prowlarr.s0.neet.dev"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = false; |  | ||||||
|             id = "4_1956_prowlarr"; |  | ||||||
|           }; |  | ||||||
|           bazarr = { |  | ||||||
|             title = "Bazarr"; |  | ||||||
|             description = "Subtitles"; |  | ||||||
|             icon = "hl-bazarr"; |  | ||||||
|             url = "https://bazarr.s0.neet.dev"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = false; |  | ||||||
|             id = "5_1956_bazarr"; |  | ||||||
|           }; |  | ||||||
|           navidrome = { |  | ||||||
|             title = "Navidrome"; |  | ||||||
|             description = "Play Music"; |  | ||||||
|             icon = "hl-navidrome"; |  | ||||||
|             url = "https://music.s0.neet.dev"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = false; |  | ||||||
|             id = "6_1956_navidrome"; |  | ||||||
|           }; |  | ||||||
|           transmission = { |  | ||||||
|             title = "Transmission"; |  | ||||||
|             description = "Torrenting"; |  | ||||||
|             icon = "hl-transmission"; |  | ||||||
|             url = "https://transmission.s0.neet.dev"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = false; |  | ||||||
|             id = "7_1956_transmission"; |  | ||||||
|           }; |  | ||||||
|         }; |  | ||||||
|         # Build the list once. |  | ||||||
|         mediaList = [ |  | ||||||
|           mediaItems.jellyfin |  | ||||||
|           mediaItems.sonarr |  | ||||||
|           mediaItems.radarr |  | ||||||
|           mediaItems.lidarr |  | ||||||
|           mediaItems.prowlarr |  | ||||||
|           mediaItems.bazarr |  | ||||||
|           mediaItems.navidrome |  | ||||||
|           mediaItems.transmission |  | ||||||
|         ]; |  | ||||||
|       in |  | ||||||
|       { |  | ||||||
|         name = "Media & Entertainment"; |  | ||||||
|         icon = "fas fa-photo-video"; |  | ||||||
|         displayData = { |  | ||||||
|           sortBy = "most-used"; |  | ||||||
|           cols = 1; |  | ||||||
|           rows = 1; |  | ||||||
|           collapsed = false; |  | ||||||
|           hideForGuests = false; |  | ||||||
|         }; |  | ||||||
|         items = mediaList; |  | ||||||
|         filteredItems = mediaList; |  | ||||||
|       } |  | ||||||
|     ) |  | ||||||
|     ( |  | ||||||
|       let |  | ||||||
|         networkItems = { |  | ||||||
|           gateway = { |  | ||||||
|             title = "Gateway"; |  | ||||||
|             description = "openwrt"; |  | ||||||
|             icon = "hl-openwrt"; |  | ||||||
|             url = "http://openwrt.lan/"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = true; |  | ||||||
|             id = "0_746_gateway"; |  | ||||||
|           }; |  | ||||||
|           wireless = { |  | ||||||
|             title = "Wireless"; |  | ||||||
|             description = "openwrt (ish)"; |  | ||||||
|             icon = "hl-openwrt"; |  | ||||||
|             url = "http://PacketProvocateur.lan"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = true; |  | ||||||
|             id = "1_746_wireless"; |  | ||||||
|           }; |  | ||||||
|         }; |  | ||||||
|         networkList = [ |  | ||||||
|           networkItems.gateway |  | ||||||
|           networkItems.wireless |  | ||||||
|         ]; |  | ||||||
|       in |  | ||||||
|       { |  | ||||||
|         name = "Network"; |  | ||||||
|         icon = "fas fa-network-wired"; |  | ||||||
|         items = networkList; |  | ||||||
|         filteredItems = networkList; |  | ||||||
|         displayData = { |  | ||||||
|           sortBy = "default"; |  | ||||||
|           rows = 1; |  | ||||||
|           cols = 1; |  | ||||||
|           collapsed = false; |  | ||||||
|           hideForGuests = false; |  | ||||||
|         }; |  | ||||||
|       } |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     ( |  | ||||||
|       let |  | ||||||
|         servicesItems = { |  | ||||||
|           matrix = { |  | ||||||
|             title = "Matrix"; |  | ||||||
|             description = ""; |  | ||||||
|             icon = "hl-matrix"; |  | ||||||
|             url = "https://chat.neet.space"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = true; |  | ||||||
|             id = "0_836_matrix"; |  | ||||||
|           }; |  | ||||||
|           mumble = { |  | ||||||
|             title = "Mumble"; |  | ||||||
|             description = "voice.neet.space"; |  | ||||||
|             icon = "hl-mumble"; |  | ||||||
|             url = "https://voice.neet.space"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = false; |  | ||||||
|             id = "2_836_mumble"; |  | ||||||
|           }; |  | ||||||
|           irc = { |  | ||||||
|             title = "IRC"; |  | ||||||
|             description = "irc.neet.dev"; |  | ||||||
|             icon = "hl-thelounge"; |  | ||||||
|             url = "https://irc.neet.dev"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = true; |  | ||||||
|             id = "3_836_irc"; |  | ||||||
|           }; |  | ||||||
|           git = { |  | ||||||
|             title = "Git"; |  | ||||||
|             description = "git.neet.dev"; |  | ||||||
|             icon = "hl-gitea"; |  | ||||||
|             url = "https://git.neet.dev"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = true; |  | ||||||
|             id = "4_836_git"; |  | ||||||
|           }; |  | ||||||
|           nextcloud = { |  | ||||||
|             title = "Nextcloud"; |  | ||||||
|             description = "neet.cloud"; |  | ||||||
|             icon = "hl-nextcloud"; |  | ||||||
|             url = "https://neet.cloud"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = true; |  | ||||||
|             id = "5_836_nextcloud"; |  | ||||||
|           }; |  | ||||||
|           roundcube = { |  | ||||||
|             title = "Roundcube"; |  | ||||||
|             description = "mail.neet.dev"; |  | ||||||
|             icon = "hl-roundcube"; |  | ||||||
|             url = "https://mail.neet.dev"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = true; |  | ||||||
|             id = "6_836_roundcube"; |  | ||||||
|           }; |  | ||||||
|           jitsimeet = { |  | ||||||
|             title = "Jitsi Meet"; |  | ||||||
|             description = "meet.neet.space"; |  | ||||||
|             icon = "hl-jitsimeet"; |  | ||||||
|             url = "https://meet.neet.space"; |  | ||||||
|             target = "sametab"; |  | ||||||
|             statusCheck = true; |  | ||||||
|             id = "7_836_jitsimeet"; |  | ||||||
|           }; |  | ||||||
|         }; |  | ||||||
|         servicesList = [ |  | ||||||
|           servicesItems.matrix |  | ||||||
|           servicesItems.mumble |  | ||||||
|           servicesItems.irc |  | ||||||
|           servicesItems.git |  | ||||||
|           servicesItems.nextcloud |  | ||||||
|           servicesItems.roundcube |  | ||||||
|           servicesItems.jitsimeet |  | ||||||
|         ]; |  | ||||||
|       in |  | ||||||
|       { |  | ||||||
|         name = "Services"; |  | ||||||
|         icon = "fas fa-monitor-heart-rate"; |  | ||||||
|         items = servicesList; |  | ||||||
|         filteredItems = servicesList; |  | ||||||
|         displayData = { |  | ||||||
|           sortBy = "default"; |  | ||||||
|           rows = 1; |  | ||||||
|           cols = 1; |  | ||||||
|           collapsed = false; |  | ||||||
|           hideForGuests = false; |  | ||||||
|         }; |  | ||||||
|       } |  | ||||||
|     ) |  | ||||||
|   ]; |  | ||||||
| } |  | ||||||
							
								
								
									
										249
									
								
								machines/storage/s0/dashy.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								machines/storage/s0/dashy.yaml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,249 @@ | |||||||
|  | appConfig: | ||||||
|  |   theme: vaporware | ||||||
|  |   customColors: | ||||||
|  |     material-dark-original: | ||||||
|  |       primary: '#f36558' | ||||||
|  |       background: '#39434C' | ||||||
|  |       background-darker: '#eb615c' | ||||||
|  |       material-light: '#f36558' | ||||||
|  |       item-text-color: '#ff948a' | ||||||
|  |       curve-factor: 5px | ||||||
|  |   enableErrorReporting: false | ||||||
|  |   layout: auto | ||||||
|  |   iconSize: large | ||||||
|  |   language: en | ||||||
|  |   startingView: default | ||||||
|  |   defaultOpeningMethod: sametab | ||||||
|  |   statusCheck: true | ||||||
|  |   statusCheckInterval: 20 | ||||||
|  |   faviconApi: faviconkit | ||||||
|  |   routingMode: history | ||||||
|  |   enableMultiTasking: false | ||||||
|  |   webSearch: | ||||||
|  |     disableWebSearch: false | ||||||
|  |     searchEngine: duckduckgo | ||||||
|  |     openingMethod: sametab | ||||||
|  |     searchBangs: {} | ||||||
|  |   enableFontAwesome: true | ||||||
|  |   cssThemes: [] | ||||||
|  |   externalStyleSheet: [] | ||||||
|  |   hideComponents: | ||||||
|  |     hideHeading: false | ||||||
|  |     hideNav: false | ||||||
|  |     hideSearch: false | ||||||
|  |     hideSettings: false | ||||||
|  |     hideFooter: false | ||||||
|  |     hideSplashScreen: false | ||||||
|  |   auth: | ||||||
|  |     enableGuestAccess: false | ||||||
|  |     users: [] | ||||||
|  |     enableKeycloak: false | ||||||
|  |     keycloak: {} | ||||||
|  |   allowConfigEdit: true | ||||||
|  |   enableServiceWorker: false | ||||||
|  |   disableContextMenu: false | ||||||
|  |   disableUpdateChecks: false | ||||||
|  |   disableSmartSort: false | ||||||
|  | pageInfo: | ||||||
|  |   title: s0 | ||||||
|  |   description: s0 | ||||||
|  | sections: | ||||||
|  |   - name: Media & Entertainment | ||||||
|  |     icon: fas fa-photo-video | ||||||
|  |     displayData: | ||||||
|  |       sortBy: most-used | ||||||
|  |       cols: 1 | ||||||
|  |       rows: 1 | ||||||
|  |       collapsed: false | ||||||
|  |       hideForGuests: false | ||||||
|  |     items: | ||||||
|  |       - &ref_0 | ||||||
|  |         title: Jellyfin | ||||||
|  |         icon: hl-jellyfin | ||||||
|  |         url: http://s0:8097 | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         statusCheckUrl: http://jellyfin.s0 | ||||||
|  |         id: 0_1956_jellyfin | ||||||
|  |       - &ref_1 | ||||||
|  |         title: Sonarr | ||||||
|  |         description: Manage TV | ||||||
|  |         icon: hl-sonarr | ||||||
|  |         url: http://s0:8989 | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         statusCheckUrl: http://sonarr.s0 | ||||||
|  |         id: 1_1956_sonarr | ||||||
|  |       - &ref_2 | ||||||
|  |         title: Radarr | ||||||
|  |         description: Manage Movies | ||||||
|  |         icon: hl-radarr | ||||||
|  |         url: http://s0:7878 | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         statusCheckUrl: http://radarr.s0 | ||||||
|  |         id: 2_1956_radarr | ||||||
|  |       - &ref_3 | ||||||
|  |         title: Lidarr | ||||||
|  |         description: Manage Music | ||||||
|  |         icon: hl-lidarr | ||||||
|  |         url: http://s0:8686 | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         statusCheckUrl: http://lidarr.s0 | ||||||
|  |         id: 3_1956_lidarr | ||||||
|  |       - &ref_4 | ||||||
|  |         title: Prowlarr | ||||||
|  |         description: Indexers | ||||||
|  |         icon: hl-prowlarr | ||||||
|  |         url: http://prowlarr.s0 | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         statusCheckUrl: http://prowlarr.s0 | ||||||
|  |         id: 4_1956_prowlarr | ||||||
|  |       - &ref_5 | ||||||
|  |         title: Bazarr | ||||||
|  |         description: Subtitles | ||||||
|  |         icon: hl-bazarr | ||||||
|  |         url: http://s0:6767 | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         statusCheckUrl: http://bazarr.s0 | ||||||
|  |         id: 5_1956_bazarr | ||||||
|  |       - &ref_6 | ||||||
|  |         title: Navidrome | ||||||
|  |         description: Play Music | ||||||
|  |         icon: hl-navidrome | ||||||
|  |         url: http://s0:4534 | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         statusCheckUrl: http://music.s0 | ||||||
|  |         id: 6_1956_navidrome | ||||||
|  |       - &ref_7 | ||||||
|  |         title: Transmission | ||||||
|  |         description: Torrenting | ||||||
|  |         icon: hl-transmission | ||||||
|  |         url: http://s0:9091 | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         statusCheckUrl: http://transmission.s0 | ||||||
|  |         id: 7_1956_transmission | ||||||
|  |     filteredItems: | ||||||
|  |       - *ref_0 | ||||||
|  |       - *ref_1 | ||||||
|  |       - *ref_2 | ||||||
|  |       - *ref_3 | ||||||
|  |       - *ref_4 | ||||||
|  |       - *ref_5 | ||||||
|  |       - *ref_6 | ||||||
|  |       - *ref_7 | ||||||
|  |   - name: Network | ||||||
|  |     icon: fas fa-network-wired | ||||||
|  |     items: | ||||||
|  |       - &ref_8 | ||||||
|  |         title: Gateway | ||||||
|  |         description: openwrt | ||||||
|  |         icon: hl-openwrt | ||||||
|  |         url: http://openwrt.lan/ | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         id: 0_746_gateway | ||||||
|  |       - &ref_9 | ||||||
|  |         title: Wireless | ||||||
|  |         description: openwrt (ish) | ||||||
|  |         icon: hl-openwrt | ||||||
|  |         url: http://PacketProvocateur.lan | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         id: 1_746_wireless | ||||||
|  |     filteredItems: | ||||||
|  |       - *ref_8 | ||||||
|  |       - *ref_9 | ||||||
|  |     displayData: | ||||||
|  |       sortBy: default | ||||||
|  |       rows: 1 | ||||||
|  |       cols: 1 | ||||||
|  |       collapsed: false | ||||||
|  |       hideForGuests: false | ||||||
|  |   - name: Services | ||||||
|  |     icon: fas fa-monitor-heart-rate | ||||||
|  |     items: | ||||||
|  |       - &ref_10 | ||||||
|  |         title: Matrix | ||||||
|  |         description: '' | ||||||
|  |         icon: hl-matrix | ||||||
|  |         url: https://chat.neet.space | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         id: 0_836_matrix | ||||||
|  |       - &ref_11 | ||||||
|  |         title: Radio | ||||||
|  |         description: Radio service | ||||||
|  |         icon: generative | ||||||
|  |         url: https://radio.runyan.org | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         id: 1_836_radio | ||||||
|  |       - &ref_12 | ||||||
|  |         title: Mumble | ||||||
|  |         description: voice.neet.space | ||||||
|  |         icon: hl-mumble | ||||||
|  |         url: https://voice.neet.space | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: false | ||||||
|  |         id: 2_836_mumble | ||||||
|  |       - &ref_13 | ||||||
|  |         title: IRC | ||||||
|  |         description: irc.neet.dev | ||||||
|  |         icon: hl-thelounge | ||||||
|  |         url: https://irc.neet.dev | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         id: 3_836_irc | ||||||
|  |       - &ref_14 | ||||||
|  |         title: Git | ||||||
|  |         description: git.neet.dev | ||||||
|  |         icon: hl-gitea | ||||||
|  |         url: https://git.neet.dev | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         id: 4_836_git | ||||||
|  |       - &ref_15 | ||||||
|  |         title: Nextcloud | ||||||
|  |         description: neet.cloud | ||||||
|  |         icon: hl-nextcloud | ||||||
|  |         url: https://neet.cloud | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         id: 5_836_nextcloud | ||||||
|  |       - &ref_16 | ||||||
|  |         title: Roundcube | ||||||
|  |         description: mail.neet.dev | ||||||
|  |         icon: hl-roundcube | ||||||
|  |         url: https://mail.neet.dev | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         id: 6_836_roundcube | ||||||
|  |       - &ref_17 | ||||||
|  |         title: Jitsi Meet | ||||||
|  |         description: meet.neet.space | ||||||
|  |         icon: hl-jitsimeet | ||||||
|  |         url: https://meet.neet.space | ||||||
|  |         target: sametab | ||||||
|  |         statusCheck: true | ||||||
|  |         id: 7_836_jitsimeet | ||||||
|  |     filteredItems: | ||||||
|  |       - *ref_10 | ||||||
|  |       - *ref_11 | ||||||
|  |       - *ref_12 | ||||||
|  |       - *ref_13 | ||||||
|  |       - *ref_14 | ||||||
|  |       - *ref_15 | ||||||
|  |       - *ref_16 | ||||||
|  |       - *ref_17 | ||||||
|  |     displayData: | ||||||
|  |       sortBy: default | ||||||
|  |       rows: 1 | ||||||
|  |       cols: 1 | ||||||
|  |       collapsed: false | ||||||
|  |       hideForGuests: false | ||||||
| @ -3,7 +3,6 @@ | |||||||
| { | { | ||||||
|   imports = [ |   imports = [ | ||||||
|     ./hardware-configuration.nix |     ./hardware-configuration.nix | ||||||
|     ./frigate.nix |  | ||||||
|     ./home-automation.nix |     ./home-automation.nix | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
| @ -11,23 +10,6 @@ | |||||||
| 
 | 
 | ||||||
|   # system.autoUpgrade.enable = true; |   # system.autoUpgrade.enable = true; | ||||||
| 
 | 
 | ||||||
|   nix.gc.automatic = lib.mkForce false; # allow the nix store to serve as a build cache |  | ||||||
| 
 |  | ||||||
|   # binary cache |  | ||||||
|   services.nix-serve = { |  | ||||||
|     enable = true; |  | ||||||
|     openFirewall = true; |  | ||||||
|     secretKeyFile = "/run/agenix/binary-cache-private-key"; |  | ||||||
|   }; |  | ||||||
|   age.secrets.binary-cache-private-key.file = ../../../secrets/binary-cache-private-key.age; |  | ||||||
|   # users.users.cache-push = { |  | ||||||
|   #   isNormalUser = true; |  | ||||||
|   #   openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINpUZFFL9BpBVqeeU63sFPhR9ewuhEZerTCDIGW1NPSB" ]; |  | ||||||
|   # }; |  | ||||||
|   # nix.settings = { |  | ||||||
|   #   trusted-users = [ "cache-push" ]; |  | ||||||
|   # }; |  | ||||||
| 
 |  | ||||||
|   services.iperf3.enable = true; |   services.iperf3.enable = true; | ||||||
|   services.iperf3.openFirewall = true; |   services.iperf3.openFirewall = true; | ||||||
| 
 | 
 | ||||||
| @ -75,32 +57,6 @@ | |||||||
|     services.lidarr.enable = true; |     services.lidarr.enable = true; | ||||||
|     services.lidarr.user = "public_data"; |     services.lidarr.user = "public_data"; | ||||||
|     services.lidarr.group = "public_data"; |     services.lidarr.group = "public_data"; | ||||||
|     services.recyclarr = { |  | ||||||
|       enable = true; |  | ||||||
|       configuration = { |  | ||||||
|         radarr.radarr_main = { |  | ||||||
|           api_key = { |  | ||||||
|             _secret = "/run/credentials/recyclarr.service/radarr-api-key"; |  | ||||||
|           }; |  | ||||||
|           base_url = "http://localhost:7878"; |  | ||||||
| 
 |  | ||||||
|           quality_definition.type = "movie"; |  | ||||||
|         }; |  | ||||||
|         sonarr.sonarr_main = { |  | ||||||
|           api_key = { |  | ||||||
|             _secret = "/run/credentials/recyclarr.service/sonarr-api-key"; |  | ||||||
|           }; |  | ||||||
|           base_url = "http://localhost:8989"; |  | ||||||
| 
 |  | ||||||
|           quality_definition.type = "series"; |  | ||||||
|         }; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     systemd.services.recyclarr.serviceConfig.LoadCredential = [ |  | ||||||
|       "radarr-api-key:/run/agenix/radarr-api-key" |  | ||||||
|       "sonarr-api-key:/run/agenix/sonarr-api-key" |  | ||||||
|     ]; |  | ||||||
| 
 | 
 | ||||||
|     services.transmission = { |     services.transmission = { | ||||||
|       enable = true; |       enable = true; | ||||||
| @ -171,8 +127,6 @@ | |||||||
|     8686 # lidarr |     8686 # lidarr | ||||||
|     9091 # transmission web |     9091 # transmission web | ||||||
|   ]; |   ]; | ||||||
|   age.secrets.radarr-api-key.file = ../../../secrets/radarr-api-key.age; |  | ||||||
|   age.secrets.sonarr-api-key.file = ../../../secrets/sonarr-api-key.age; |  | ||||||
| 
 | 
 | ||||||
|   # jellyfin |   # jellyfin | ||||||
|   # jellyfin cannot run in the vpn container and use hardware encoding |   # jellyfin cannot run in the vpn container and use hardware encoding | ||||||
| @ -182,7 +136,7 @@ | |||||||
|   nixpkgs.config.packageOverrides = pkgs: { |   nixpkgs.config.packageOverrides = pkgs: { | ||||||
|     vaapiIntel = pkgs.vaapiIntel.override { enableHybridCodec = true; }; |     vaapiIntel = pkgs.vaapiIntel.override { enableHybridCodec = true; }; | ||||||
|   }; |   }; | ||||||
|   hardware.graphics = { |   hardware.opengl = { | ||||||
|     enable = true; |     enable = true; | ||||||
|     extraPackages = with pkgs; [ |     extraPackages = with pkgs; [ | ||||||
|       intel-media-driver |       intel-media-driver | ||||||
| @ -194,192 +148,76 @@ | |||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   # nginx |   # nginx | ||||||
|   services.nginx = { |   services.nginx.enable = true; | ||||||
|     enable = true; |   services.nginx.virtualHosts."bazarr.s0" = { | ||||||
|     openFirewall = false; # All nginx services are internal |     listen = [{ addr = "0.0.0.0"; port = 6767; } { addr = "0.0.0.0"; port = 80; }]; | ||||||
|     virtualHosts = |     locations."/".proxyPass = "http://vpn.containers:6767"; | ||||||
|       let |  | ||||||
|         mkHost = external: config: |  | ||||||
|           { |  | ||||||
|             ${external} = { |  | ||||||
|               useACMEHost = "s0.neet.dev"; # Use wildcard cert |  | ||||||
|               forceSSL = true; |  | ||||||
|               locations."/" = config; |  | ||||||
|   }; |   }; | ||||||
|  |   services.nginx.virtualHosts."radarr.s0" = { | ||||||
|  |     listen = [{ addr = "0.0.0.0"; port = 7878; } { addr = "0.0.0.0"; port = 80; }]; | ||||||
|  |     locations."/".proxyPass = "http://vpn.containers:7878"; | ||||||
|   }; |   }; | ||||||
|         mkVirtualHost = external: internal: |   services.nginx.virtualHosts."lidarr.s0" = { | ||||||
|           mkHost external { |     listen = [{ addr = "0.0.0.0"; port = 8686; } { addr = "0.0.0.0"; port = 80; }]; | ||||||
|             proxyPass = internal; |     locations."/".proxyPass = "http://vpn.containers:8686"; | ||||||
|  |   }; | ||||||
|  |   services.nginx.virtualHosts."sonarr.s0" = { | ||||||
|  |     listen = [{ addr = "0.0.0.0"; port = 8989; } { addr = "0.0.0.0"; port = 80; }]; | ||||||
|  |     locations."/".proxyPass = "http://vpn.containers:8989"; | ||||||
|  |   }; | ||||||
|  |   services.nginx.virtualHosts."prowlarr.s0" = { | ||||||
|  |     listen = [{ addr = "0.0.0.0"; port = 9696; } { addr = "0.0.0.0"; port = 80; }]; | ||||||
|  |     locations."/".proxyPass = "http://vpn.containers:9696"; | ||||||
|  |   }; | ||||||
|  |   services.nginx.virtualHosts."music.s0" = { | ||||||
|  |     listen = [{ addr = "0.0.0.0"; port = 4534; } { addr = "0.0.0.0"; port = 80; }]; | ||||||
|  |     locations."/".proxyPass = "http://localhost:4533"; | ||||||
|  |   }; | ||||||
|  |   services.nginx.virtualHosts."jellyfin.s0" = { | ||||||
|  |     listen = [{ addr = "0.0.0.0"; port = 8097; } { addr = "0.0.0.0"; port = 80; }]; | ||||||
|  |     locations."/" = { | ||||||
|  |       proxyPass = "http://localhost:8096"; | ||||||
|       proxyWebsockets = true; |       proxyWebsockets = true; | ||||||
|     }; |     }; | ||||||
|         mkStaticHost = external: static: |  | ||||||
|           mkHost external { |  | ||||||
|             root = static; |  | ||||||
|             tryFiles = "$uri /index.html "; |  | ||||||
|   }; |   }; | ||||||
|       in |   services.nginx.virtualHosts."jellyfin.neet.cloud".locations."/" = { | ||||||
|       lib.mkMerge [ |     proxyPass = "http://localhost:8096"; | ||||||
|         (mkVirtualHost "bazarr.s0.neet.dev" "http://vpn.containers:6767") |     proxyWebsockets = true; | ||||||
|         (mkVirtualHost "radarr.s0.neet.dev" "http://vpn.containers:7878") |  | ||||||
|         (mkVirtualHost "lidarr.s0.neet.dev" "http://vpn.containers:8686") |  | ||||||
|         (mkVirtualHost "sonarr.s0.neet.dev" "http://vpn.containers:8989") |  | ||||||
|         (mkVirtualHost "prowlarr.s0.neet.dev" "http://vpn.containers:9696") |  | ||||||
|         (mkVirtualHost "transmission.s0.neet.dev" "http://vpn.containers:9091") |  | ||||||
|         (mkVirtualHost "unifi.s0.neet.dev" "https://localhost:8443") |  | ||||||
|         (mkVirtualHost "music.s0.neet.dev" "http://localhost:4533") |  | ||||||
|         (mkVirtualHost "jellyfin.s0.neet.dev" "http://localhost:8096") |  | ||||||
|         (mkStaticHost "s0.neet.dev" config.services.dashy.finalDrv) |  | ||||||
|         { |  | ||||||
|           # Landing page LAN redirect |  | ||||||
|           "s0" = { |  | ||||||
|             default = true; |  | ||||||
|             redirectCode = 302; |  | ||||||
|             globalRedirect = "s0.neet.dev"; |  | ||||||
|   }; |   }; | ||||||
|         } |   services.nginx.virtualHosts."transmission.s0" = { | ||||||
|         (mkVirtualHost "ha.s0.neet.dev" "http://localhost:${toString config.services.home-assistant.config.http.server_port}") |     listen = [{ addr = "0.0.0.0"; port = 9091; } { addr = "0.0.0.0"; port = 80; }]; | ||||||
|         (mkVirtualHost "esphome.s0.neet.dev" "http://localhost:6052") |     locations."/" = { | ||||||
|         (mkVirtualHost "zigbee.s0.neet.dev" "http://localhost:55834") |       proxyPass = "http://vpn.containers:9091"; | ||||||
|         { |       proxyWebsockets = true; | ||||||
|           "frigate.s0.neet.dev" = { |  | ||||||
|             # Just configure SSL, frigate module configures the rest of nginx |  | ||||||
|             useACMEHost = "s0.neet.dev"; |  | ||||||
|             forceSSL = true; |  | ||||||
|           }; |  | ||||||
|         } |  | ||||||
|         (mkVirtualHost "vacuum.s0.neet.dev" "http://192.168.1.125") # valetudo |  | ||||||
|         (mkVirtualHost "sandman.s0.neet.dev" "http://192.168.9.14:3000") # es |  | ||||||
|         (mkVirtualHost "todo.s0.neet.dev" "http://localhost:${toString config.services.vikunja.port}") |  | ||||||
|         (mkVirtualHost "budget.s0.neet.dev" "http://localhost:${toString config.services.actual.settings.port}") # actual budget |  | ||||||
|         (mkVirtualHost "linkwarden.s0.neet.dev" "http://localhost:${toString config.services.linkwarden.port}") |  | ||||||
|         (mkVirtualHost "memos.s0.neet.dev" "http://localhost:${toString config.services.memos.port}") |  | ||||||
|         (mkVirtualHost "outline.s0.neet.dev" "http://localhost:${toString config.services.outline.port}") |  | ||||||
|         (mkVirtualHost "languagetool.s0.neet.dev" "http://localhost:${toString config.services.languagetool.port}") |  | ||||||
|       ]; |  | ||||||
| 
 |  | ||||||
|     tailscaleAuth = { |  | ||||||
|       enable = true; |  | ||||||
|       virtualHosts = [ |  | ||||||
|         "bazarr.s0.neet.dev" |  | ||||||
|         "radarr.s0.neet.dev" |  | ||||||
|         "lidarr.s0.neet.dev" |  | ||||||
|         "sonarr.s0.neet.dev" |  | ||||||
|         "prowlarr.s0.neet.dev" |  | ||||||
|         "transmission.s0.neet.dev" |  | ||||||
|         "unifi.s0.neet.dev" |  | ||||||
|         # "music.s0.neet.dev" # messes up navidrome |  | ||||||
|         "jellyfin.s0.neet.dev" |  | ||||||
|         "s0.neet.dev" |  | ||||||
|         # "ha.s0.neet.dev" # messes up home assistant |  | ||||||
|         "esphome.s0.neet.dev" |  | ||||||
|         "zigbee.s0.neet.dev" |  | ||||||
|         "vacuum.s0.neet.dev" |  | ||||||
|         "todo.s0.neet.dev" |  | ||||||
|         "budget.s0.neet.dev" |  | ||||||
|         "linkwarden.s0.neet.dev" |  | ||||||
|         # "memos.s0.neet.dev" # messes up memos /auth route |  | ||||||
|         # "outline.s0.neet.dev" # messes up outline /auth route |  | ||||||
|         "languagetool.s0.neet.dev" |  | ||||||
|       ]; |  | ||||||
|       expectedTailnet = "koi-bebop.ts.net"; |  | ||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   # Get wildcard cert |   networking.firewall.allowedTCPPorts = [ | ||||||
|   security.acme.certs."s0.neet.dev" = { |     6767 | ||||||
|     dnsProvider = "digitalocean"; |     7878 | ||||||
|     credentialsFile = "/run/agenix/digitalocean-dns-credentials"; |     8686 | ||||||
|     extraDomainNames = [ "*.s0.neet.dev" ]; |     8989 | ||||||
|     group = "nginx"; |     9696 | ||||||
|     dnsResolver = "1.1.1.1:53"; |     4534 | ||||||
|     dnsPropagationCheck = false; # sadly this erroneously fails |     8097 | ||||||
|   }; |     9091 | ||||||
|   age.secrets.digitalocean-dns-credentials.file = ../../../secrets/digitalocean-dns-credentials.age; |     8443 # unifi | ||||||
|  |   ]; | ||||||
| 
 | 
 | ||||||
|   virtualisation.oci-containers.backend = "podman"; |   virtualisation.oci-containers.backend = "podman"; | ||||||
|   virtualisation.podman.dockerSocket.enable = true; # TODO needed? |   virtualisation.podman.dockerSocket.enable = true; # TODO needed? | ||||||
|   services.dashy = { |   services.dashy = { | ||||||
|     enable = true; |     enable = true; | ||||||
|     settings = import ./dashy.nix; |     configFile = ./dashy.yaml; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   services.unifi = { |   services.unifi = { | ||||||
|     enable = true; |     enable = true; | ||||||
|     openMinimalFirewall = true; |     openFirewall = true; | ||||||
|   }; |     unifiPackage = pkgs.unifi8; | ||||||
| 
 |  | ||||||
|   services.vikunja = { |  | ||||||
|     enable = true; |  | ||||||
|     port = 61473; |  | ||||||
|     frontendScheme = "https"; |  | ||||||
|     frontendHostname = "todo.s0.neet.dev"; |  | ||||||
|     settings = { |  | ||||||
|       service.enableregistration = false; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
|   backup.group."vikunja".paths = [ |  | ||||||
|     "/var/lib/vikunja" |  | ||||||
|   ]; |  | ||||||
| 
 |  | ||||||
|   services.actual.enable = true; |  | ||||||
| 
 |  | ||||||
|   services.linkwarden = { |  | ||||||
|     enable = true; |  | ||||||
|     enableRegistration = true; |  | ||||||
|     port = 41709; |  | ||||||
|     environment.NEXTAUTH_URL = "https://linkwarden.s0.neet.dev/api/v1/auth"; |  | ||||||
|     environment.FLARESOLVERR_URL = "http://localhost:${toString config.services.flaresolverr.port}/v1"; |  | ||||||
|     environmentFile = "/run/agenix/linkwarden-environment"; |  | ||||||
|     package = pkgs.linkwarden.overrideAttrs (oldAttrs: { |  | ||||||
|       # Add patch that adds support for flaresolverr |  | ||||||
|       patches = oldAttrs.patches or [ ] ++ [ |  | ||||||
|         # https://github.com/linkwarden/linkwarden/pull/1251 |  | ||||||
|         ../../../patches/linkwarden-flaresolverr.patch |  | ||||||
|       ]; |  | ||||||
|     }); |  | ||||||
|   }; |  | ||||||
|   age.secrets.linkwarden-environment.file = ../../../secrets/linkwarden-environment.age; |  | ||||||
|   services.meilisearch = { |  | ||||||
|     enable = true; |  | ||||||
|     package = pkgs.meilisearch; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   services.flaresolverr = { |  | ||||||
|     enable = true; |  | ||||||
|     port = 48072; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   services.memos = { |  | ||||||
|     enable = true; |  | ||||||
|     address = "127.0.0.1"; |  | ||||||
|     port = 57643; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   services.outline = { |  | ||||||
|     enable = true; |  | ||||||
|     forceHttps = false; # https through nginx |  | ||||||
|     port = 43933; |  | ||||||
|     publicUrl = "https://outline.s0.neet.dev"; |  | ||||||
|     storage.storageType = "local"; |  | ||||||
|     smtp = { |  | ||||||
|       secure = true; |  | ||||||
|       fromEmail = "robot@runyan.org"; |  | ||||||
|       username = "robot@runyan.org"; |  | ||||||
|       replyEmail = "robot@runyan.org"; |  | ||||||
|       host = "mail.neet.dev"; |  | ||||||
|       port = 465; |  | ||||||
|       passwordFile = "/run/agenix/robots-email-pw"; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
|   age.secrets.robots-email-pw = { |  | ||||||
|     file = ../../../secrets/robots-email-pw.age; |  | ||||||
|     owner = config.services.outline.user; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   services.languagetool = { |  | ||||||
|     enable = true; |  | ||||||
|     port = 60613; |  | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   boot.binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ]; |   boot.binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ]; | ||||||
|  | 
 | ||||||
|  |   services.atticd.enable = true; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,154 +0,0 @@ | |||||||
| { config, pkgs, lib, ... }: |  | ||||||
| 
 |  | ||||||
| let |  | ||||||
|   frigateHostname = "frigate.s0.neet.dev"; |  | ||||||
| 
 |  | ||||||
|   mkGo2RtcStream = name: url: withAudio: { |  | ||||||
|     ${name} = [ |  | ||||||
|       url |  | ||||||
|       "ffmpeg:${name}#video=copy${if withAudio then "#audio=copy" else ""}" |  | ||||||
|     ]; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   # Assumes camera is set to output: |  | ||||||
|   # - rtsp |  | ||||||
|   # - H.264 + AAC |  | ||||||
|   # - a downscaled substream for detection |  | ||||||
|   mkCamera = name: primaryUrl: detectUrl: { |  | ||||||
|     # Reference https://docs.frigate.video/configuration/reference/ |  | ||||||
|     services.frigate.settings = { |  | ||||||
|       cameras.${name} = { |  | ||||||
|         ffmpeg = { |  | ||||||
|           # Camera feeds are relayed through go2rtc |  | ||||||
|           inputs = [ |  | ||||||
|             { |  | ||||||
|               path = "rtsp://127.0.0.1:8554/${name}"; |  | ||||||
|               # input_args = "preset-rtsp-restream"; |  | ||||||
|               input_args = "preset-rtsp-restream-low-latency"; |  | ||||||
|               roles = [ "record" ]; |  | ||||||
|             } |  | ||||||
|             { |  | ||||||
|               path = detectUrl; |  | ||||||
|               roles = [ "detect" ]; |  | ||||||
|             } |  | ||||||
|           ]; |  | ||||||
|           output_args = { |  | ||||||
|             record = "preset-record-generic-audio-copy"; |  | ||||||
|           }; |  | ||||||
|         }; |  | ||||||
|         detect = { |  | ||||||
|           width = 1280; |  | ||||||
|           height = 720; |  | ||||||
|           fps = 5; |  | ||||||
|         }; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     services.go2rtc.settings.streams = lib.mkMerge [ |  | ||||||
|       (mkGo2RtcStream name primaryUrl false) |  | ||||||
| 
 |  | ||||||
|       # Sadly having the detection stream go through go2rpc too makes the stream unreadable by frigate for some reason. |  | ||||||
|       # It might need to be re-encoded to work.  But I am not interested in wasting the processing power if only frigate |  | ||||||
|       # need the detection stream anyway. So just let frigate grab the stream directly since it works. |  | ||||||
|       # (mkGo2RtcStream detectName detectUrl false) |  | ||||||
|     ]; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   mkDahuaCamera = name: address: |  | ||||||
|     let |  | ||||||
|       # go2rtc and frigate have a slightly different syntax for inserting env vars. So the URLs are not interchangable :( |  | ||||||
|       # - go2rtc: ${VAR} |  | ||||||
|       # - frigate: {VAR} |  | ||||||
|       primaryUrl = "rtsp://admin:\${FRIGATE_RTSP_PASSWORD}@${address}/cam/realmonitor?channel=1&subtype=0"; |  | ||||||
|       detectUrl = "rtsp://admin:{FRIGATE_RTSP_PASSWORD}@${address}/cam/realmonitor?channel=1&subtype=3"; |  | ||||||
|     in |  | ||||||
|     mkCamera name primaryUrl detectUrl; |  | ||||||
| 
 |  | ||||||
|   mkEsp32Camera = name: address: { |  | ||||||
|     services.frigate.settings.cameras.${name} = { |  | ||||||
|       ffmpeg = { |  | ||||||
|         input_args = ""; |  | ||||||
|         inputs = [{ |  | ||||||
|           path = "http://${address}:8080"; |  | ||||||
|           roles = [ "detect" "record" ]; |  | ||||||
|         }]; |  | ||||||
| 
 |  | ||||||
|         output_args.record = "-f segment -pix_fmt yuv420p -segment_time 10 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c:v libx264 -preset ultrafast -an "; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| in |  | ||||||
| lib.mkMerge [ |  | ||||||
|   (mkDahuaCamera "dog-cam" "192.168.10.31") |  | ||||||
|   # (mkEsp32Camera "dahlia-cam" "dahlia-cam.lan") |  | ||||||
|   { |  | ||||||
|     services.frigate = { |  | ||||||
|       enable = true; |  | ||||||
|       hostname = frigateHostname; |  | ||||||
|       settings = { |  | ||||||
|         mqtt = { |  | ||||||
|           enabled = true; |  | ||||||
|           host = "localhost"; |  | ||||||
|           port = 1883; |  | ||||||
|           user = "root"; |  | ||||||
|           password = "{FRIGATE_MQTT_PASSWORD}"; |  | ||||||
|         }; |  | ||||||
|         snapshots = { |  | ||||||
|           enabled = true; |  | ||||||
|           bounding_box = true; |  | ||||||
|         }; |  | ||||||
|         record = { |  | ||||||
|           enabled = true; |  | ||||||
|           # sync_recordings = true; # detect if recordings were deleted outside of frigate (expensive) |  | ||||||
|           retain = { |  | ||||||
|             days = 7; # Keep video for 7 days |  | ||||||
|             mode = "all"; |  | ||||||
|             # mode = "motion"; |  | ||||||
|           }; |  | ||||||
|           events = { |  | ||||||
|             retain = { |  | ||||||
|               default = 10; # Keep video with detections for 10 days |  | ||||||
|               mode = "motion"; |  | ||||||
|               # mode = "active_objects"; |  | ||||||
|             }; |  | ||||||
|           }; |  | ||||||
|         }; |  | ||||||
|         # Make frigate aware of the go2rtc streams |  | ||||||
|         go2rtc.streams = config.services.go2rtc.settings.streams; |  | ||||||
|         detect.enabled = false; # :( |  | ||||||
|         objects = { |  | ||||||
|           track = [ "person" "dog" ]; |  | ||||||
|         }; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     services.go2rtc = { |  | ||||||
|       enable = true; |  | ||||||
|       settings = { |  | ||||||
|         rtsp.listen = ":8554"; |  | ||||||
|         webrtc.listen = ":8555"; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     # Pass in env file with secrets to frigate/go2rtc |  | ||||||
|     systemd.services.frigate.serviceConfig.EnvironmentFile = "/run/agenix/frigate-credentials"; |  | ||||||
|     systemd.services.go2rtc.serviceConfig.EnvironmentFile = "/run/agenix/frigate-credentials"; |  | ||||||
|     age.secrets.frigate-credentials.file = ../../../secrets/frigate-credentials.age; |  | ||||||
|   } |  | ||||||
|   { |  | ||||||
|     # hardware encode/decode with amdgpu vaapi |  | ||||||
|     services.frigate.vaapiDriver = "radeonsi"; |  | ||||||
|     services.frigate.settings.ffmpeg.hwaccel_args = "preset-vaapi"; |  | ||||||
|   } |  | ||||||
|   { |  | ||||||
|     # Coral TPU for frigate |  | ||||||
|     services.frigate.settings.detectors.coral = { |  | ||||||
|       type = "edgetpu"; |  | ||||||
|       device = "pci"; |  | ||||||
|     }; |  | ||||||
|   } |  | ||||||
|   { |  | ||||||
|     # Don't require authentication for frigate |  | ||||||
|     # This is ok because the reverse proxy already requires tailscale access anyway |  | ||||||
|     services.frigate.settings.auth.enabled = false; |  | ||||||
|   } |  | ||||||
| ] |  | ||||||
| @ -8,7 +8,6 @@ | |||||||
| 
 | 
 | ||||||
|   # boot |   # boot | ||||||
|   boot.loader.systemd-boot.enable = true; |   boot.loader.systemd-boot.enable = true; | ||||||
|   boot.loader.systemd-boot.memtest86.enable = true; |  | ||||||
|   boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "uas" "sd_mod" "rtsx_pci_sdmmc" ]; |   boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "uas" "sd_mod" "rtsx_pci_sdmmc" ]; | ||||||
|   boot.initrd.kernelModules = [ ]; |   boot.initrd.kernelModules = [ ]; | ||||||
|   boot.kernelModules = [ "kvm-intel" ]; |   boot.kernelModules = [ "kvm-intel" ]; | ||||||
| @ -22,6 +21,7 @@ | |||||||
|   # zfs |   # zfs | ||||||
|   networking.hostId = "5e6791f0"; |   networking.hostId = "5e6791f0"; | ||||||
|   boot.supportedFilesystems = [ "zfs" ]; |   boot.supportedFilesystems = [ "zfs" ]; | ||||||
|  |   boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages; | ||||||
| 
 | 
 | ||||||
|   # luks |   # luks | ||||||
|   remoteLuksUnlock.enable = true; |   remoteLuksUnlock.enable = true; | ||||||
| @ -58,35 +58,8 @@ | |||||||
|     }; |     }; | ||||||
|   swapDevices = [ ]; |   swapDevices = [ ]; | ||||||
| 
 | 
 | ||||||
|   ### networking ### |   networking.interfaces.eth0.useDHCP = true; | ||||||
| 
 |   networking.interfaces.eth1.useDHCP = true; | ||||||
|   # systemd.network.enable = true; |  | ||||||
|   networking = { |  | ||||||
|     # useNetworkd = true; |  | ||||||
|     dhcpcd.enable = false; |  | ||||||
| 
 |  | ||||||
|     vlans = { |  | ||||||
|       iot = { |  | ||||||
|         id = 2; |  | ||||||
|         interface = "eth1"; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     interfaces.eth1.ipv4.addresses = [{ |  | ||||||
|       address = "192.168.1.2"; |  | ||||||
|       prefixLength = 21; |  | ||||||
|     }]; |  | ||||||
|     interfaces.iot.ipv4.addresses = [{ |  | ||||||
|       address = "192.168.9.8"; |  | ||||||
|       prefixLength = 22; |  | ||||||
|     }]; |  | ||||||
| 
 |  | ||||||
|     defaultGateway = { |  | ||||||
|       interface = "eth1"; |  | ||||||
|       address = "192.168.1.1"; |  | ||||||
|     }; |  | ||||||
|     nameservers = [ "1.1.1.1" "8.8.8.8" ]; |  | ||||||
|   }; |  | ||||||
| 
 | 
 | ||||||
|   powerManagement.cpuFreqGovernor = "powersave"; |   powerManagement.cpuFreqGovernor = "powersave"; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,30 +1,112 @@ | |||||||
| { config, lib, pkgs, ... }: | { config, lib, pkgs, ... }: | ||||||
| 
 | 
 | ||||||
| { | let | ||||||
|   services.esphome.enable = true; |   frigateHostname = "frigate.s0"; | ||||||
|  |   frigatePort = 61617; | ||||||
| 
 | 
 | ||||||
|  |   mkEsp32Cam = address: { | ||||||
|  |     ffmpeg = { | ||||||
|  |       input_args = ""; | ||||||
|  |       inputs = [{ | ||||||
|  |         path = address; | ||||||
|  |         roles = [ "detect" "record" ]; | ||||||
|  |       }]; | ||||||
|  | 
 | ||||||
|  |       output_args.record = "-f segment -pix_fmt yuv420p -segment_time 10 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c:v libx264 -preset ultrafast -an "; | ||||||
|  |     }; | ||||||
|  |     rtmp.enabled = false; | ||||||
|  |     snapshots = { | ||||||
|  |       enabled = true; | ||||||
|  |       bounding_box = true; | ||||||
|  |     }; | ||||||
|  |     record = { | ||||||
|  |       enabled = true; | ||||||
|  |       retain.days = 10; # Keep video for 10 days | ||||||
|  |       events.retain = { | ||||||
|  |         default = 30; # Keep video with detections for 30 days | ||||||
|  |         mode = "active_objects"; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |     detect = { | ||||||
|  |       enabled = true; | ||||||
|  |       width = 800; | ||||||
|  |       height = 600; | ||||||
|  |       fps = 10; | ||||||
|  |     }; | ||||||
|  |     objects = { | ||||||
|  |       track = [ "person" ]; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | in | ||||||
|  | { | ||||||
|  |   networking.firewall.allowedTCPPorts = [ | ||||||
|  |     # 1883 # mqtt | ||||||
|  |     55834 # mqtt zigbee frontend | ||||||
|  |     frigatePort | ||||||
|  |     4180 # oauth proxy | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|  |   services.frigate = { | ||||||
|  |     enable = true; | ||||||
|  |     hostname = frigateHostname; | ||||||
|  |     settings = { | ||||||
|  |       mqtt = { | ||||||
|  |         enabled = true; | ||||||
|  |         host = "localhost:1883"; | ||||||
|  |       }; | ||||||
|  |       cameras = { | ||||||
|  |         dahlia-cam = mkEsp32Cam "http://dahlia-cam.lan:8080"; | ||||||
|  |       }; | ||||||
|  |       # ffmpeg = { | ||||||
|  |       #   hwaccel_args = "preset-vaapi"; | ||||||
|  |       # }; | ||||||
|  |       detectors.coral = { | ||||||
|  |         type = "edgetpu"; | ||||||
|  |         device = "pci"; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   # AMD GPU for vaapi | ||||||
|  |   systemd.services.frigate.environment.LIBVA_DRIVER_NAME = "radeonsi"; | ||||||
|  | 
 | ||||||
|  |   # Coral TPU for frigate | ||||||
|  |   services.udev.packages = [ pkgs.libedgetpu ]; | ||||||
|  |   users.groups.apex = { }; | ||||||
|  |   systemd.services.frigate.environment.LD_LIBRARY_PATH = "${pkgs.libedgetpu}/lib"; | ||||||
|  |   systemd.services.frigate.serviceConfig = { | ||||||
|  |     SupplementaryGroups = "apex"; | ||||||
|  |   }; | ||||||
|  |   # Coral PCIe driver | ||||||
|  |   kernel.enableGasketKernelModule = true; | ||||||
|  | 
 | ||||||
|  |   # Allow accessing frigate UI on a specific port in addition to by hostname | ||||||
|  |   services.nginx.virtualHosts.${frigateHostname} = { | ||||||
|  |     listen = [{ addr = "0.0.0.0"; port = frigatePort; } { addr = "0.0.0.0"; port = 80; }]; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   services.esphome = { | ||||||
|  |     enable = true; | ||||||
|  |     address = "0.0.0.0"; | ||||||
|  |     openFirewall = true; | ||||||
|  |   }; | ||||||
|  |   # TODO remove after upgrading nixos version | ||||||
|  |   systemd.services.esphome.serviceConfig.ProcSubset = lib.mkForce "all"; | ||||||
|  |   systemd.services.esphome.serviceConfig.ProtectHostname = lib.mkForce false; | ||||||
|  |   systemd.services.esphome.serviceConfig.ProtectKernelLogs = lib.mkForce false; | ||||||
|  |   systemd.services.esphome.serviceConfig.ProtectKernelTunables = lib.mkForce false; | ||||||
|  | 
 | ||||||
|  |   # TODO lock down | ||||||
|   services.mosquitto = { |   services.mosquitto = { | ||||||
|     enable = true; |     enable = true; | ||||||
|     listeners = [ |     listeners = [ | ||||||
|       { |       { | ||||||
|         users.root = { |         acl = [ "pattern readwrite #" ]; | ||||||
|           acl = [ "readwrite #" ]; |         omitPasswordAuth = true; | ||||||
|           hashedPassword = "$7$101$8+QnkTzCdGizaKqq$lpU4o84n6D/1uwfA9pZDVExr1NDm1D/8tNla2tE9J9HdUqkvu192yYfiySY1MFqVNgUKgWEFu5P1bUKqRnzbUw=="; |         settings.allow_anonymous = true; | ||||||
|         }; |  | ||||||
|       } |       } | ||||||
|     ]; |     ]; | ||||||
|   }; |   }; | ||||||
|   networking.firewall.allowedTCPPorts = [ |  | ||||||
|     # mqtt |  | ||||||
|     1883 |  | ||||||
| 
 |  | ||||||
|     # Must be exposed so some local devices (such as HA voice preview) can pair with home assistant |  | ||||||
|     config.services.home-assistant.config.http.server_port |  | ||||||
| 
 |  | ||||||
|     # Music assistant (must be exposed so local devices can fetch the audio stream from it) |  | ||||||
|     8095 |  | ||||||
|     8097 |  | ||||||
|   ]; |  | ||||||
| 
 | 
 | ||||||
|   services.zigbee2mqtt = { |   services.zigbee2mqtt = { | ||||||
|     enable = true; |     enable = true; | ||||||
| @ -32,125 +114,75 @@ | |||||||
|       homeassistant = true; |       homeassistant = true; | ||||||
|       permit_join = false; |       permit_join = false; | ||||||
|       serial = { |       serial = { | ||||||
|         adapter = "ember"; |  | ||||||
|         port = "/dev/ttyACM0"; |         port = "/dev/ttyACM0"; | ||||||
|       }; |       }; | ||||||
|       mqtt = { |       mqtt = { | ||||||
|         server = "mqtt://localhost:1883"; |         server = "mqtt://localhost:1883"; | ||||||
|         user = "root"; |         # base_topic = "zigbee2mqtt"; | ||||||
|         password = "!/run/agenix/zigbee2mqtt.yaml mqtt_password"; |  | ||||||
|       }; |       }; | ||||||
|       frontend = { |       frontend = { | ||||||
|         host = "localhost"; |         host = "0.0.0.0"; | ||||||
|         port = 55834; |         port = 55834; | ||||||
|       }; |       }; | ||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
|   age.secrets."zigbee2mqtt.yaml" = { |  | ||||||
|     file = ../../../secrets/zigbee2mqtt.yaml.age; |  | ||||||
|     owner = "zigbee2mqtt"; |  | ||||||
|   }; |  | ||||||
| 
 | 
 | ||||||
|   services.home-assistant = { |   services.home-assistant = { | ||||||
|     enable = true; |     enable = true; | ||||||
|  |     openFirewall = true; | ||||||
|  |     configWritable = true; | ||||||
|     extraComponents = [ |     extraComponents = [ | ||||||
|       "default_config" |  | ||||||
|       "rest_command" |  | ||||||
|       "esphome" |       "esphome" | ||||||
|       "met" |       "met" | ||||||
|       "radio_browser" |       "radio_browser" | ||||||
|       "wled" |       "wled" | ||||||
|       "mqtt" |       "mqtt" | ||||||
|       "apple_tv" # why is this even needed? I get `ModuleNotFoundError: No module named 'pyatv'` errors otherwise for some reason. |  | ||||||
|       "unifi" |  | ||||||
|       "digital_ocean" |  | ||||||
|       "downloader" |  | ||||||
|       "mailgun" |  | ||||||
|       "minecraft_server" |  | ||||||
|       "mullvad" |  | ||||||
|       "nextcloud" |  | ||||||
|       "ollama" |  | ||||||
|       "openweathermap" |  | ||||||
|       "jellyfin" |  | ||||||
|       "transmission" |  | ||||||
|       "radarr" |  | ||||||
|       "sonarr" |  | ||||||
|       "syncthing" |  | ||||||
|       "tailscale" |  | ||||||
|       "weather" |  | ||||||
|       "whois" |  | ||||||
|       "youtube" |  | ||||||
|       "homekit_controller" |  | ||||||
|       "zha" |  | ||||||
|       "bluetooth" |  | ||||||
|       "whisper" |  | ||||||
|       "piper" |  | ||||||
|       "wyoming" |  | ||||||
|       "tts" |  | ||||||
|       "music_assistant" |  | ||||||
|       "openai_conversation" |  | ||||||
|     ]; |     ]; | ||||||
|  |     # config = null; | ||||||
|     config = { |     config = { | ||||||
|       # Includes dependencies for a basic setup |       # Includes dependencies for a basic setup | ||||||
|       # https://www.home-assistant.io/integrations/default_config/ |       # https://www.home-assistant.io/integrations/default_config/ | ||||||
|       default_config = { }; |       default_config = { }; | ||||||
| 
 |  | ||||||
|       homeassistant = { |  | ||||||
|         external_url = "https://ha.s0.neet.dev"; |  | ||||||
|         internal_url = "http://192.168.1.2:${toString config.services.home-assistant.config.http.server_port}"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       # Enable reverse proxy support |  | ||||||
|       http = { |  | ||||||
|         use_x_forwarded_for = true; |  | ||||||
|         trusted_proxies = [ |  | ||||||
|           "127.0.0.1" |  | ||||||
|           "::1" |  | ||||||
|         ]; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       "automation manual" = [ |  | ||||||
|       ]; |  | ||||||
|       # Allow using automations generated from the UI |  | ||||||
|       "automation ui" = "!include automations.yaml"; |  | ||||||
| 
 |  | ||||||
|       "rest_command" = { |  | ||||||
|         json_post_request = { |  | ||||||
|           url = "{{ url }}"; |  | ||||||
|           method = "POST"; |  | ||||||
|           content_type = "application/json"; |  | ||||||
|           payload = "{{ payload | default('{}') }}"; |  | ||||||
|         }; |  | ||||||
|       }; |  | ||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   services.wyoming.faster-whisper.servers."hass" = { |   # TODO need services.oauth2-proxy.cookie.domain ? | ||||||
|  |   services.oauth2-proxy = | ||||||
|  |     let | ||||||
|  |       nextcloudServer = "https://neet.cloud/"; | ||||||
|  |     in | ||||||
|  |     { | ||||||
|       enable = true; |       enable = true; | ||||||
|     uri = "tcp://0.0.0.0:45785"; | 
 | ||||||
|     model = "distil-small.en"; |       httpAddress = "http://0.0.0.0:4180"; | ||||||
|     language = "en"; | 
 | ||||||
|  |       nginx.domain = frigateHostname; | ||||||
|  |       # nginx.virtualHosts = [ | ||||||
|  |       #   frigateHostname | ||||||
|  |       # ]; | ||||||
|  | 
 | ||||||
|  |       email.domains = [ "*" ]; | ||||||
|  | 
 | ||||||
|  |       cookie.secure = false; | ||||||
|  | 
 | ||||||
|  |       provider = "nextcloud"; | ||||||
|  | 
 | ||||||
|  |       # redirectURL = "http://s0:4180/oauth2/callback"; # todo forward with nginx? | ||||||
|  |       clientID = "4FfhEB2DNzUh6wWhXTjqQQKu3Ibm6TeYpS8TqcHe55PJC1DorE7vBZBELMKDjJ0X"; | ||||||
|  |       keyFile = "/run/agenix/oauth2-proxy-env"; | ||||||
|  | 
 | ||||||
|  |       loginURL = "${nextcloudServer}/index.php/apps/oauth2/authorize"; | ||||||
|  |       redeemURL = "${nextcloudServer}/index.php/apps/oauth2/api/v1/token"; | ||||||
|  |       validateURL = "${nextcloudServer}/ocs/v2.php/cloud/user?format=json"; | ||||||
|  | 
 | ||||||
|  |       # todo --cookie-refresh | ||||||
|  | 
 | ||||||
|  |       extraConfig = { | ||||||
|  |         # cookie-csrf-per-request = true; | ||||||
|  |         # cookie-csrf-expire = "5m"; | ||||||
|  |         # user-id-claim = "preferred_username"; | ||||||
|  |       }; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|   services.wyoming.piper.servers."hass" = { |   age.secrets.oauth2-proxy-env.file = ../../../secrets/oauth2-proxy-env.age; | ||||||
|     enable = true; |  | ||||||
|     uri = "tcp://0.0.0.0:45786"; |  | ||||||
|     voice = "en_US-joe-medium"; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   services.music-assistant = { |  | ||||||
|     enable = true; |  | ||||||
|     providers = [ |  | ||||||
|       "hass" |  | ||||||
|       "hass_players" |  | ||||||
|       "jellyfin" |  | ||||||
|       "radiobrowser" |  | ||||||
|       "spotify" |  | ||||||
|     ]; |  | ||||||
|   }; |  | ||||||
|   networking.hosts = { |  | ||||||
|     # Workaround for broken spotify api integration |  | ||||||
|     # https://github.com/librespot-org/librespot/issues/1527#issuecomment-3167094158 |  | ||||||
|     "0.0.0.0" = [ "apresolve.spotify.com" ]; |  | ||||||
|   }; |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,7 +1,6 @@ | |||||||
| { | { | ||||||
|   hostNames = [ |   hostNames = [ | ||||||
|     "s0" |     "s0" | ||||||
|     "s0.neet.dev" |  | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   arch = "x86_64-linux"; |   arch = "x86_64-linux"; | ||||||
| @ -12,19 +11,12 @@ | |||||||
|     "pia" |     "pia" | ||||||
|     "binary-cache" |     "binary-cache" | ||||||
|     "gitea-actions-runner" |     "gitea-actions-runner" | ||||||
|     "frigate" |  | ||||||
|     "zigbee" |  | ||||||
|     "media-server" |  | ||||||
|     "linkwarden" |  | ||||||
|     "outline" |  | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwiXcUFtAvZCayhu4+AIcF+Ktrdgv9ee/mXSIhJbp4q"; |   hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwiXcUFtAvZCayhu4+AIcF+Ktrdgv9ee/mXSIhJbp4q"; | ||||||
| 
 | 
 | ||||||
|   remoteUnlock = { |   remoteUnlock = { | ||||||
|     hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFNiceeFMos5ZXcYem4yFxh8PiZNNnuvhlyLbQLrgIZH"; |     hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFNiceeFMos5ZXcYem4yFxh8PiZNNnuvhlyLbQLrgIZH"; | ||||||
| 
 |  | ||||||
|     clearnetHost = "192.168.1.2"; |  | ||||||
|     onionHost = "r3zvf7f2ppaeithzswigma46pajt3hqytmkg3rshgknbl3jbni455fqd.onion"; |     onionHost = "r3zvf7f2ppaeithzswigma46pajt3hqytmkg3rshgknbl3jbni455fqd.onion"; | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -5,6 +5,8 @@ | |||||||
|     ./hardware-configuration.nix |     ./hardware-configuration.nix | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|  |   de.enable = true; | ||||||
|  | 
 | ||||||
|   # Login DE Option: Steam |   # Login DE Option: Steam | ||||||
|   programs.steam.gamescopeSession.enable = true; |   programs.steam.gamescopeSession.enable = true; | ||||||
|   # programs.gamescope.capSysNice = true; |   # programs.gamescope.capSysNice = true; | ||||||
| @ -31,9 +33,9 @@ | |||||||
|   hardware.enableAllFirmware = true; |   hardware.enableAllFirmware = true; | ||||||
| 
 | 
 | ||||||
|   # ROCm |   # ROCm | ||||||
|   hardware.graphics.extraPackages = with pkgs; [ |   hardware.opengl.extraPackages = with pkgs; [ | ||||||
|     rocmPackages.clr.icd |     rocm-opencl-icd | ||||||
|     rocmPackages.clr |     rocm-opencl-runtime | ||||||
|   ]; |   ]; | ||||||
|   systemd.tmpfiles.rules = [ |   systemd.tmpfiles.rules = [ | ||||||
|     "L+    /opt/rocm/hip   -    -    -     -    ${pkgs.rocmPackages.clr}" |     "L+    /opt/rocm/hip   -    -    -     -    ${pkgs.rocmPackages.clr}" | ||||||
|  | |||||||
| @ -17,17 +17,16 @@ | |||||||
|   boot.extraModulePackages = [ ]; |   boot.extraModulePackages = [ ]; | ||||||
|   boot.kernelPackages = pkgs.linuxPackages_latest; |   boot.kernelPackages = pkgs.linuxPackages_latest; | ||||||
| 
 | 
 | ||||||
|   # luks unlock with clevis |  | ||||||
|   boot.initrd.systemd.enable = true; |  | ||||||
|   boot.initrd.clevis = { |  | ||||||
|     enable = true; |  | ||||||
|     devices."enc-pv".secretFile = "/secret/decrypt.jwe"; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   # disks |   # disks | ||||||
|  |   remoteLuksUnlock.enable = true; | ||||||
|   boot.initrd.luks.devices."enc-pv" = { |   boot.initrd.luks.devices."enc-pv" = { | ||||||
|     device = "/dev/disk/by-uuid/04231c41-2f13-49c0-8fce-0357eea67990"; |     device = "/dev/disk/by-uuid/04231c41-2f13-49c0-8fce-0357eea67990"; | ||||||
|     allowDiscards = true; |     allowDiscards = true; | ||||||
|  | 
 | ||||||
|  |     # Fetch key from USB drive | ||||||
|  |     keyFileSize = 4096; | ||||||
|  |     keyFile = "/dev/disk/by-id/usb-Mass_Storage_Device_121220160204-0:0-part2"; | ||||||
|  |     fallbackToPassword = true; | ||||||
|   }; |   }; | ||||||
|   fileSystems."/" = |   fileSystems."/" = | ||||||
|     { |     { | ||||||
|  | |||||||
							
								
								
									
										39
									
								
								overlays/actualbudget/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								overlays/actualbudget/default.nix
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | |||||||
|  | { lib | ||||||
|  | , buildNpmPackage | ||||||
|  | , fetchFromGitHub | ||||||
|  | , python3 | ||||||
|  | , nodejs | ||||||
|  | , runtimeShell | ||||||
|  | }: | ||||||
|  | buildNpmPackage rec { | ||||||
|  |   pname = "actual-server"; | ||||||
|  |   version = "24.3.0"; | ||||||
|  | 
 | ||||||
|  |   src = fetchFromGitHub { | ||||||
|  |     owner = "actualbudget"; | ||||||
|  |     repo = pname; | ||||||
|  |     rev = "refs/tags/v${version}"; | ||||||
|  |     hash = "sha256-y51Dhdn84AWR/gM4LnAzvBIBpvKwUiclnPnwzkRoJ0I="; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   npmDepsHash = "sha256-/UM2Tz8t4hi621HtXSu0LTDIzZ9SWMqKXqKfPwkdpE8="; | ||||||
|  | 
 | ||||||
|  |   patches = [ | ||||||
|  |     ./migrations-should-use-pkg-path.patch | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|  |   postPatch = '' | ||||||
|  |     cp ${./package-lock.json} package-lock.json | ||||||
|  |   ''; | ||||||
|  | 
 | ||||||
|  |   dontNpmBuild = true; | ||||||
|  | 
 | ||||||
|  |   postInstall = '' | ||||||
|  |     mkdir -p $out/bin | ||||||
|  |     cat <<EOF > $out/bin/actual-server | ||||||
|  |     #!${runtimeShell} | ||||||
|  |     exec ${nodejs}/bin/node $out/lib/node_modules/actual-sync/app.js "\$@" | ||||||
|  |     EOF | ||||||
|  |     chmod +x $out/bin/actual-server | ||||||
|  |   ''; | ||||||
|  | } | ||||||
							
								
								
									
										47
									
								
								overlays/actualbudget/migrations-should-use-pkg-path.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								overlays/actualbudget/migrations-should-use-pkg-path.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | diff --git a/src/load-config.js b/src/load-config.js
 | ||||||
|  | index d3cc5dd..cfcad8a 100644
 | ||||||
|  | --- a/src/load-config.js
 | ||||||
|  | +++ b/src/load-config.js
 | ||||||
|  | @@ -3,7 +3,8 @@ import path from 'node:path';
 | ||||||
|  |  import { fileURLToPath } from 'node:url'; | ||||||
|  |  import createDebug from 'debug'; | ||||||
|  |   | ||||||
|  | -const debug = createDebug('actual:config');
 | ||||||
|  | +// const debug = createDebug('actual:config');
 | ||||||
|  | +const debug = console.log;
 | ||||||
|  |  const debugSensitive = createDebug('actual-sensitive:config'); | ||||||
|  |   | ||||||
|  |  const projectRoot = path.dirname(path.dirname(fileURLToPath(import.meta.url))); | ||||||
|  | @@ -90,6 +91,7 @@ const finalConfig = {
 | ||||||
|  |    serverFiles: process.env.ACTUAL_SERVER_FILES || config.serverFiles, | ||||||
|  |    userFiles: process.env.ACTUAL_USER_FILES || config.userFiles, | ||||||
|  |    webRoot: process.env.ACTUAL_WEB_ROOT || config.webRoot, | ||||||
|  | +  dataDir: process.env.ACTUAL_DATA_DIR || config.dataDir,
 | ||||||
|  |    https: | ||||||
|  |      process.env.ACTUAL_HTTPS_KEY && process.env.ACTUAL_HTTPS_CERT | ||||||
|  |        ? { | ||||||
|  | diff --git a/src/migrations.js b/src/migrations.js
 | ||||||
|  | index 964e1f2..3a341d7 100644
 | ||||||
|  | --- a/src/migrations.js
 | ||||||
|  | +++ b/src/migrations.js
 | ||||||
|  | @@ -1,6 +1,12 @@
 | ||||||
|  |  import migrate from 'migrate'; | ||||||
|  |  import path from 'node:path'; | ||||||
|  |  import config from './load-config.js'; | ||||||
|  | +import { fileURLToPath } from 'url';
 | ||||||
|  | +
 | ||||||
|  | +const __filename = fileURLToPath(import.meta.url);
 | ||||||
|  | +const __dirname = path.dirname(__filename);
 | ||||||
|  | +const appRoot = path.dirname(__dirname);
 | ||||||
|  | +const migrationsDirectory = path.join(appRoot, "migrations");
 | ||||||
|  |   | ||||||
|  |  export default function run(direction = 'up') { | ||||||
|  |    console.log( | ||||||
|  | @@ -13,6 +19,7 @@ export default function run(direction = 'up') {
 | ||||||
|  |          stateStore: `${path.join(config.dataDir, '.migrate')}${ | ||||||
|  |            config.mode === 'test' ? '-test' : '' | ||||||
|  |          }`, | ||||||
|  | +        migrationsDirectory,
 | ||||||
|  |        }, | ||||||
|  |        (err, set) => { | ||||||
|  |          if (err) { | ||||||
							
								
								
									
										8807
									
								
								overlays/actualbudget/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										8807
									
								
								overlays/actualbudget/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -3,5 +3,20 @@ final: prev: | |||||||
| 
 | 
 | ||||||
| let | let | ||||||
|   system = prev.system; |   system = prev.system; | ||||||
|  |   frigatePkgs = inputs.nixpkgs-frigate.legacyPackages.${system}; | ||||||
| in | in | ||||||
| { } | { | ||||||
|  |   # It seems that libedgetpu needs to be built with the newer version of tensorflow in nixpkgs | ||||||
|  |   # but I am lazy so I instead just downgrade by using the old nixpkgs | ||||||
|  |   libedgetpu = frigatePkgs.callPackage ./libedgetpu { }; | ||||||
|  |   frigate = frigatePkgs.frigate; | ||||||
|  | 
 | ||||||
|  |   actual-server = prev.callPackage ./actualbudget { }; | ||||||
|  |   unifi8 = prev.unifi.overrideAttrs (oldAttrs: rec { | ||||||
|  |     version = "8.1.113"; | ||||||
|  |     src = prev.fetchurl { | ||||||
|  |       url = "https://dl.ui.com/unifi/8.1.113/unifi_sysvinit_all.deb"; | ||||||
|  |       sha256 = "1knm+l8MSb7XKq2WIbehAnz7loRPjgnc+R98zpWKEAE="; | ||||||
|  |     }; | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | |||||||
| @ -7,5 +7,13 @@ | |||||||
| 
 | 
 | ||||||
| let | let | ||||||
|   cfg = config.kernel; |   cfg = config.kernel; | ||||||
|  | 
 | ||||||
|  |   gasket = config.boot.kernelPackages.callPackage ./gasket.nix { }; | ||||||
| in | in | ||||||
| { } | { | ||||||
|  |   options.kernel.enableGasketKernelModule = lib.mkEnableOption "Enable Gasket Kernel Module"; | ||||||
|  | 
 | ||||||
|  |   config = lib.mkIf cfg.enableGasketKernelModule { | ||||||
|  |     boot.extraModulePackages = [ gasket ]; | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										36
									
								
								overlays/kernel-modules/gasket.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								overlays/kernel-modules/gasket.nix
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | |||||||
|  | { stdenv, lib, fetchFromGitHub, kernel }: | ||||||
|  | 
 | ||||||
|  | stdenv.mkDerivation rec { | ||||||
|  |   pname = "gasket"; | ||||||
|  |   version = "1.0-18-unstable-2023-09-05"; | ||||||
|  | 
 | ||||||
|  |   src = fetchFromGitHub { | ||||||
|  |     owner = "google"; | ||||||
|  |     repo = "gasket-driver"; | ||||||
|  |     rev = "5815ee3908a46a415aac616ac7b9aedcb98a504c"; | ||||||
|  |     sha256 = "sha256-O17+msok1fY5tdX1DvqYVw6plkUDF25i8sqwd6mxYf8="; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   makeFlags = kernel.makeFlags ++ [ | ||||||
|  |     "-C" | ||||||
|  |     "${kernel.dev}/lib/modules/${kernel.modDirVersion}/build" | ||||||
|  |     "M=$(PWD)" | ||||||
|  |   ]; | ||||||
|  |   buildFlags = [ "modules" ]; | ||||||
|  | 
 | ||||||
|  |   installFlags = [ "INSTALL_MOD_PATH=${placeholder "out"}" ]; | ||||||
|  |   installTargets = [ "modules_install" ]; | ||||||
|  | 
 | ||||||
|  |   sourceRoot = "${src.name}/src"; | ||||||
|  |   hardeningDisable = [ "pic" "format" ]; | ||||||
|  |   nativeBuildInputs = kernel.moduleBuildDependencies; | ||||||
|  | 
 | ||||||
|  |   meta = with lib; { | ||||||
|  |     description = "The Coral Gasket Driver allows usage of the Coral EdgeTPU on Linux systems."; | ||||||
|  |     homepage = "https://github.com/google/gasket-driver"; | ||||||
|  |     license = licenses.gpl2; | ||||||
|  |     maintainers = [ lib.maintainers.kylehendricks ]; | ||||||
|  |     platforms = platforms.linux; | ||||||
|  |     broken = versionOlder kernel.version "5.15"; | ||||||
|  |   }; | ||||||
|  | } | ||||||
							
								
								
									
										72
									
								
								overlays/libedgetpu/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								overlays/libedgetpu/default.nix
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | |||||||
|  | { stdenv | ||||||
|  | , lib | ||||||
|  | , fetchFromGitHub | ||||||
|  | , libusb1 | ||||||
|  | , abseil-cpp | ||||||
|  | , flatbuffers | ||||||
|  | , xxd | ||||||
|  | }: | ||||||
|  | 
 | ||||||
|  | let | ||||||
|  |   flatbuffers_1_12 = flatbuffers.overrideAttrs (oldAttrs: rec { | ||||||
|  |     version = "1.12.0"; | ||||||
|  |     NIX_CFLAGS_COMPILE = "-Wno-error=class-memaccess -Wno-error=maybe-uninitialized"; | ||||||
|  |     cmakeFlags = (oldAttrs.cmakeFlags or [ ]) ++ [ "-DFLATBUFFERS_BUILD_SHAREDLIB=ON" ]; | ||||||
|  |     NIX_CXXSTDLIB_COMPILE = "-std=c++17"; | ||||||
|  |     configureFlags = (oldAttrs.configureFlags or [ ]) ++ [ "--enable-shared" ]; | ||||||
|  |     src = fetchFromGitHub { | ||||||
|  |       owner = "google"; | ||||||
|  |       repo = "flatbuffers"; | ||||||
|  |       rev = "v${version}"; | ||||||
|  |       sha256 = "sha256-L1B5Y/c897Jg9fGwT2J3+vaXsZ+lfXnskp8Gto1p/Tg="; | ||||||
|  |     }; | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  | in | ||||||
|  | stdenv.mkDerivation rec { | ||||||
|  |   pname = "libedgetpu"; | ||||||
|  |   version = "grouper"; | ||||||
|  | 
 | ||||||
|  |   src = fetchFromGitHub { | ||||||
|  |     owner = "google-coral"; | ||||||
|  |     repo = pname; | ||||||
|  |     rev = "release-${version}"; | ||||||
|  |     sha256 = "sha256-73hwItimf88Iqnb40lk4ul/PzmCNIfdt6Afi+xjNiBE="; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   patches = [ ./libedgetpu-stddef.diff ]; | ||||||
|  | 
 | ||||||
|  |   makeFlags = [ "-f" "makefile_build/Makefile" "libedgetpu" ]; | ||||||
|  | 
 | ||||||
|  |   buildInputs = [ | ||||||
|  |     libusb1 | ||||||
|  |     abseil-cpp | ||||||
|  |     flatbuffers_1_12 | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|  |   nativeBuildInputs = [ | ||||||
|  |     xxd | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|  |   NIX_CXXSTDLIB_COMPILE = "-std=c++17"; | ||||||
|  | 
 | ||||||
|  |   TFROOT = "${fetchFromGitHub { | ||||||
|  |     owner = "tensorflow"; | ||||||
|  |     repo = "tensorflow"; | ||||||
|  |     rev = "v2.7.4"; | ||||||
|  |     sha256 = "sha256-liDbUAdaVllB0b74aBeqNxkYNu/zPy7k3CevzRF5dk0="; | ||||||
|  |   }}"; | ||||||
|  | 
 | ||||||
|  |   enableParallelBuilding = false; | ||||||
|  | 
 | ||||||
|  |   installPhase = '' | ||||||
|  |     mkdir -p $out/lib | ||||||
|  |     cp out/direct/k8/libedgetpu.so.1.0 $out/lib | ||||||
|  |     ln -s $out/lib/libedgetpu.so.1.0 $out/lib/libedgetpu.so.1 | ||||||
|  |     mkdir -p $out/lib/udev/rules.d | ||||||
|  |     cp debian/edgetpu-accelerator.rules $out/lib/udev/rules.d/99-edgetpu-accelerator.rules | ||||||
|  | 
 | ||||||
|  |     # PCIe rule | ||||||
|  |     echo 'SUBSYSTEM=="apex", MODE="0660", GROUP="apex"' > $out/lib/udev/rules.d/65-apex.rules | ||||||
|  |   ''; | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								overlays/libedgetpu/libedgetpu-stddef.diff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								overlays/libedgetpu/libedgetpu-stddef.diff
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | diff --git a/api/allocated_buffer.h b/api/allocated_buffer.h
 | ||||||
|  | index 97740f0..7bc0547 100644
 | ||||||
|  | --- a/api/allocated_buffer.h
 | ||||||
|  | +++ b/api/allocated_buffer.h
 | ||||||
|  | @@ -16,6 +16,7 @@
 | ||||||
|  |  #define DARWINN_API_ALLOCATED_BUFFER_H_ | ||||||
|  |   | ||||||
|  |  #include <functional> | ||||||
|  | +#include <cstddef>
 | ||||||
|  |   | ||||||
|  |  namespace platforms { | ||||||
|  |  namespace darwinn { | ||||||
| @ -1,15 +0,0 @@ | |||||||
| diff --git a/nixos/modules/services/video/frigate.nix b/nixos/modules/services/video/frigate.nix
 |  | ||||||
| index 49f8ed673816..643b59d68dde 100644
 |  | ||||||
| --- a/nixos/modules/services/video/frigate.nix
 |  | ||||||
| +++ b/nixos/modules/services/video/frigate.nix
 |  | ||||||
| @@ -482,10 +482,6 @@ in
 |  | ||||||
|            }; |  | ||||||
|          }; |  | ||||||
|          extraConfig = '' |  | ||||||
| -          # Frigate wants to connect on 127.0.0.1:5000 for unauthenticated requests
 |  | ||||||
| -          # https://github.com/NixOS/nixpkgs/issues/370349
 |  | ||||||
| -          listen 127.0.0.1:5000;
 |  | ||||||
| -
 |  | ||||||
|            # vod settings |  | ||||||
|            vod_base_url ""; |  | ||||||
|            vod_segments_base_url ""; |  | ||||||
| @ -1,28 +0,0 @@ | |||||||
| diff --git a/pkgs/applications/audio/librespot/default.nix b/pkgs/applications/audio/librespot/default.nix
 |  | ||||||
| index 9694c3d0cf4f..ca9502de7ee1 100644
 |  | ||||||
| --- a/pkgs/applications/audio/librespot/default.nix
 |  | ||||||
| +++ b/pkgs/applications/audio/librespot/default.nix
 |  | ||||||
| @@ -25,14 +25,19 @@ rustPlatform.buildRustPackage rec {
 |  | ||||||
|    version = "0.6.0"; |  | ||||||
|   |  | ||||||
|    src = fetchFromGitHub { |  | ||||||
| -    owner = "librespot-org";
 |  | ||||||
| +    owner = "googlebot42";
 |  | ||||||
|      repo = "librespot"; |  | ||||||
| -    rev = "v${version}";
 |  | ||||||
| -    sha256 = "sha256-dGQDRb7fgIkXelZKa+PdodIs9DxbgEMlVGJjK/hU3Mo=";
 |  | ||||||
| +    rev = "786cc46199e583f304a84c786acb0a9b37bc3fbd";
 |  | ||||||
| +    sha256 = "sha256-xaOrqC8yCjF23Tz31RD3CzqZ3xxrDM6ncW1yoovEaGQ=";
 |  | ||||||
|    }; |  | ||||||
|   |  | ||||||
|    useFetchCargoVendor = true; |  | ||||||
| -  cargoHash = "sha256-SqvJSHkyd1IicT6c4pE96dBJNNodULhpyG14HRGVWCk=";
 |  | ||||||
| +  cargoHash = "sha256-sUAZgOuBD9CGAy1mRqLRzVnVfxB0DqSCNAc2yzItTCA=";
 |  | ||||||
| +
 |  | ||||||
| +  cargoBuildFlags = [
 |  | ||||||
| +    "--features"
 |  | ||||||
| +    "passthrough-decoder"
 |  | ||||||
| +  ];
 |  | ||||||
|   |  | ||||||
|    nativeBuildInputs = [ |  | ||||||
|      pkg-config |  | ||||||
| @ -1,144 +0,0 @@ | |||||||
| commit 3dac9f081f267e4a528decbd9d50e1f45ea7c2ba |  | ||||||
| Author: SteveImmanuel <steve@telepix.net> |  | ||||||
| Date:   Fri Jun 27 13:07:38 2025 +0900 |  | ||||||
| 
 |  | ||||||
|     Add flaresolverr support into linkwarden |  | ||||||
| 
 |  | ||||||
| diff --git a/.env.sample b/.env.sample
 |  | ||||||
| index bd3abcb0..0ca96d92 100644
 |  | ||||||
| --- a/.env.sample
 |  | ||||||
| +++ b/.env.sample
 |  | ||||||
| @@ -43,6 +43,7 @@ TEXT_CONTENT_LIMIT=
 |  | ||||||
|  SEARCH_FILTER_LIMIT= |  | ||||||
|  INDEX_TAKE_COUNT= |  | ||||||
|  MEILI_TIMEOUT= |  | ||||||
| +FLARESOLVERR_URL=
 |  | ||||||
|   |  | ||||||
|  # AI Settings |  | ||||||
|  NEXT_PUBLIC_OLLAMA_ENDPOINT_URL= |  | ||||||
| diff --git a/apps/worker/lib/archiveHandler.ts b/apps/worker/lib/archiveHandler.ts
 |  | ||||||
| index 8ae19e2c..6c8656b2 100644
 |  | ||||||
| --- a/apps/worker/lib/archiveHandler.ts
 |  | ||||||
| +++ b/apps/worker/lib/archiveHandler.ts
 |  | ||||||
| @@ -6,6 +6,7 @@ import {
 |  | ||||||
|    chromium, |  | ||||||
|    devices, |  | ||||||
|  } from "playwright"; |  | ||||||
| +import axios from 'axios';
 |  | ||||||
|  import { prisma } from "@linkwarden/prisma"; |  | ||||||
|  import sendToWayback from "./preservationScheme/sendToWayback"; |  | ||||||
|  import { AiTaggingMethod } from "@linkwarden/prisma/client"; |  | ||||||
| @@ -75,6 +76,22 @@ export default async function archiveHandler(
 |  | ||||||
|    }); |  | ||||||
|   |  | ||||||
|    const { browser, context } = await getBrowser(); |  | ||||||
| +
 |  | ||||||
| +  const captchaSolve = await solveCaptcha(link.url);
 |  | ||||||
| +
 |  | ||||||
| +  if (captchaSolve.status === 'error') {
 |  | ||||||
| +    console.error('Error solving captcha');
 |  | ||||||
| +  } else if (captchaSolve.status === 'fail') {
 |  | ||||||
| +    console.warn('Failed solving captcha');
 |  | ||||||
| +  } else if (captchaSolve.status === 'skip') {
 |  | ||||||
| +    console.info('Skip solving captcha');
 |  | ||||||
| +  } else {
 |  | ||||||
| +    if (captchaSolve.solution) {
 |  | ||||||
| +      console.info('Solving captcha');
 |  | ||||||
| +      await context.addCookies(captchaSolve.solution.cookies);
 |  | ||||||
| +    }
 |  | ||||||
| +  }
 |  | ||||||
| +
 |  | ||||||
|    const page = await context.newPage(); |  | ||||||
|   |  | ||||||
|    createFolder({ filePath: `archives/preview/${link.collectionId}` }); |  | ||||||
| @@ -105,6 +122,7 @@ export default async function archiveHandler(
 |  | ||||||
|            aiTag: user.aiTaggingMethod !== AiTaggingMethod.DISABLED, |  | ||||||
|          }; |  | ||||||
|   |  | ||||||
| +  let newLinkName = '';
 |  | ||||||
|    try { |  | ||||||
|      await Promise.race([ |  | ||||||
|        (async () => { |  | ||||||
| @@ -127,6 +145,7 @@ export default async function archiveHandler(
 |  | ||||||
|            // archive url |  | ||||||
|   |  | ||||||
|            await page.goto(link.url, { waitUntil: "domcontentloaded" }); |  | ||||||
| +          newLinkName = await page.title();
 |  | ||||||
|   |  | ||||||
|            const metaDescription = await page.evaluate(() => { |  | ||||||
|              const description = document.querySelector( |  | ||||||
| @@ -186,10 +205,16 @@ export default async function archiveHandler(
 |  | ||||||
|        where: { id: link.id }, |  | ||||||
|      }); |  | ||||||
|   |  | ||||||
| -    if (finalLink)
 |  | ||||||
| +    if (finalLink) {
 |  | ||||||
| +      // Replace the captcha-blocked link name if it has not been updated by user, else keep the same name
 |  | ||||||
| +      if (newLinkName === '' || finalLink.name === newLinkName || finalLink.name !== 'Just a moment...') {
 |  | ||||||
| +        newLinkName = finalLink.name;
 |  | ||||||
| +      }
 |  | ||||||
| +
 |  | ||||||
|        await prisma.link.update({ |  | ||||||
|          where: { id: link.id }, |  | ||||||
|          data: { |  | ||||||
| +          name: newLinkName,
 |  | ||||||
|            lastPreserved: new Date().toISOString(), |  | ||||||
|            readable: !finalLink.readable ? "unavailable" : undefined, |  | ||||||
|            image: !finalLink.image ? "unavailable" : undefined, |  | ||||||
| @@ -203,6 +228,7 @@ export default async function archiveHandler(
 |  | ||||||
|                : undefined, |  | ||||||
|          }, |  | ||||||
|        }); |  | ||||||
| +    }
 |  | ||||||
|      else { |  | ||||||
|        await removeFiles(link.id, link.collectionId); |  | ||||||
|      } |  | ||||||
| @@ -271,6 +297,48 @@ export function getBrowserOptions(): LaunchOptions {
 |  | ||||||
|    return browserOptions; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +async function solveCaptcha(url: string, maxTimeout: number = 60000): Promise<{
 |  | ||||||
| +  status: string,
 |  | ||||||
| +  solution?: {
 |  | ||||||
| +    cookies: {
 |  | ||||||
| +      name: string,
 |  | ||||||
| +      value: string,
 |  | ||||||
| +      domain: string,
 |  | ||||||
| +      path: string,
 |  | ||||||
| +      secure: boolean,
 |  | ||||||
| +      expires?: number,
 |  | ||||||
| +      httpOnly?: boolean,
 |  | ||||||
| +      sameSite?: "Strict" | "Lax" | "None"
 |  | ||||||
| +    }[],
 |  | ||||||
| +  }
 |  | ||||||
| +}> {
 |  | ||||||
| +  if (process.env.FLARESOLVERR_URL) {
 |  | ||||||
| +    try {
 |  | ||||||
| +      const response = await axios.post(process.env.FLARESOLVERR_URL,
 |  | ||||||
| +        {
 |  | ||||||
| +          cmd: 'request.get',
 |  | ||||||
| +          url,
 |  | ||||||
| +          maxTimeout
 |  | ||||||
| +        },
 |  | ||||||
| +        {
 |  | ||||||
| +          headers: { 'Content-Type': 'application/json' }
 |  | ||||||
| +        }
 |  | ||||||
| +      )
 |  | ||||||
| +
 |  | ||||||
| +      if (response.status !== 200) {
 |  | ||||||
| +        return { status: 'fail' };
 |  | ||||||
| +      }
 |  | ||||||
| +
 |  | ||||||
| +      return { status: response.data.status, solution: response.data.solution };
 |  | ||||||
| +    } catch (error) {
 |  | ||||||
| +      console.error('Error during captcha solving:', error);
 |  | ||||||
| +      return { status: 'error' };
 |  | ||||||
| +    }
 |  | ||||||
| +  }
 |  | ||||||
| +
 |  | ||||||
| +  return { status: 'skip' };
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  async function getBrowser(): Promise<{ |  | ||||||
|    browser: Browser; |  | ||||||
|    context: BrowserContext; |  | ||||||
							
								
								
									
										8
									
								
								secrets/atticd-credentials.age
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								secrets/atticd-credentials.age
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | age-encryption.org/v1 | ||||||
|  | -> ssh-ed25519 hPp1nw tMy5kLAcQD62yAfEVJ4LQZjs0kkEEQOfM4HN9yj3hBY | ||||||
|  | JvlklGTxxfAZbP+alm3nxLxqhmcu2mTKwRU5WaapL9w | ||||||
|  | -> ssh-ed25519 w3nu8g ZGzufldXq7kmIpqFecbkpDxiykWZ207k0+09I2dmxEM | ||||||
|  | SK25e5HBe4b5reGXXfCjIFbFGzfu32RFjY++/yteRVc | ||||||
|  | --- xZOe1syYAcVRDhiNRv+CsfFgoQbiANA6vNCon+5NExc | ||||||
|  | -·ñ1Å,C-.M§Áè?ÐêóµµàY|u+ | ||||||
|  | ‹	³Ø<C2B3>÷ŽæÒ¡ôm†Œûäfß]=érøÜüÎAg¤€æSú:Ð8•S¦LiœùªsêÁâ9JŠð<>¸ÏæñÄÐÃ<ûAz¹[ý§xï<78>:‡'U*<2A>wÀ™D/…±VpM~!õ,* ¿”µ¡øk¥Ö´ßEíîïh› {¢p$¾R`ÿ” | ||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -1,9 +1,10 @@ | |||||||
| age-encryption.org/v1 | age-encryption.org/v1 | ||||||
| -> ssh-ed25519 6AT2/g /5WB1i5RrjWIbnBErUWliedwnv8qTIsl8r8zbWNkOmA | -> ssh-ed25519 6AT2/g WZ9p/pCsEDpKbgGDLcTtisn25kExQX9iv+tL3wyPwiY | ||||||
| wr8fN2FbNnCRUNgV3aZPQibXHy1MNjMP9SMK7urHL+o | vom2z9QRIQSFB0+4/7lSWUEB0eoAG+08nXgiUg/OSX4 | ||||||
| -> ssh-ed25519 w3nu8g exWaIxM68nwycLphws0PRnRvvdOuT7h3xOZqndsAHxo | -> ssh-ed25519 w3nu8g ECLZwCRJVJqyUMf70EOl2/3ExTruKaxCSQlY5fBZqxk | ||||||
| EIUTjS57F5MKGt6bJjaFxHnbTFzUrpmrTVqNZoQ060Y | VemnmGpzx1VprkybW1hPlkfmiDaNcBDoEzX0mDZgmu0 | ||||||
| -> ssh-ed25519 evqvfg SAQyzljqtBd65bpZo6yMsIAS1d5ymjKBoODjOQMUdTs | -> ssh-ed25519 dMQYog QiPsbFE8MtXnRNBwkUEC+6grqXEbDstEtxYR8uJks2w | ||||||
| /roobEvljSoREVHygqLNKTJHWG6rDdhXmlc4BM/7Em8 | O3JWQGppFeZEd6o3W0KVTEIyNVGeLxKfTYTlgsAEVHQ | ||||||
| --- Gp+OLOIN5aqR3G1fSM+Epdw4B6RTXrB99Ty/YUWI0S8 | --- RncZzBFEyMAkpZRWrPORA0DPHuCTNswmWG5CMNnfm4A | ||||||
| ÊžÁ<EFBFBD>¶…Àoÿ;¥3ŽeºÉ<>„Ôu
âT
éÄdŸ«‡ñüÈ<²y{ Jëë¶ñg]nŸþ+QX˜Øéóå´qEÜ™çƒMþË/QàÓÔ#kÉ[8(‚ß5 | 	ñ/¼ÔËõôŒ8nàÅ¥«¸7hîtä?T˜=‘%zˆ°[¤ÝØ!(…uÔdÇuò@ | ||||||
|  | ×¢Ebƒyަù¦D=Ü!‹„XþtÞÔ:#¦þþãÞXÈX@ú_M‘ | ||||||
| @ -1,16 +0,0 @@ | |||||||
| age-encryption.org/v1 |  | ||||||
| -> ssh-ed25519 WBT1Hw ZMrG+yubAhxfDf/hh8gSfxZuvM5hsOBQu/V/KfdcNyk |  | ||||||
| un2XWeWmt9pYLAk4n54A52T96sgvasNgD65AiYL9YO0 |  | ||||||
| -> ssh-ed25519 6AT2/g KxgJ1UJ1amcXzpcFmFFi3C3umo70iwmL5GxDaqfk1j8 |  | ||||||
| VZkDd3vgf1xX9kdzrDhmv2w/Ubq6UUJyw7UAkqmWlOU |  | ||||||
| -> ssh-ed25519 r848+g MXTm1V8lHIb4oHg0glttyooeECLn0uVrHaY5NzAE718 |  | ||||||
| Qv+vEeuFz+sew5GmR17ALXKmpfByjwi2j93dMVAU5WY |  | ||||||
| -> ssh-ed25519 hPp1nw 7dxkddbQHdVi+7dpxBHXYi8pNgMsRjfj8KLqgJFYqQc |  | ||||||
| 984ysvTIvdjJirkUIfNMEUVKkzUTCBDAOgLbKZj5AhU |  | ||||||
| -> ssh-ed25519 w3nu8g fC2KGM9/I2Sl0VHkYZy7YbvmF5CMWRIUahgGaGiZPVM |  | ||||||
| +IGvvjHj14bV9PS2r0L3pFNV+eDCE63ZmNdHfCG0yCw |  | ||||||
| -> ssh-ed25519 evqvfg fAr1POoqc5y1stRkCJfgCHSW8QXIPEiFZT0STSP931s |  | ||||||
| wFWWX6tPV0mV5HC3be7a2xr4Pax35rT16S0h7eiF990 |  | ||||||
| --- N5A6/IK5wKwzUT20Hxu/37ovLEkLGGj7Y30p1hu5fNM |  | ||||||
| r&BãHA%ǺhŒRÕ²~!Ä<>{bÝ[ØU?‹k(‹µD |  | ||||||
| öB7[öùððb/ [¿YçÚÃy[yOCjT-9:†xâ²(;ÝüœXy\¬N‘hÄíòäLPö¼§y¿mG±—ÑÁfŽý4aT<²Š
‡çaŠè†@ |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| age-encryption.org/v1 |  | ||||||
| -> ssh-ed25519 hPp1nw p8uus03Jrn9HtEelmufFx2orYkSlyAq90L7bTm3n/GQ |  | ||||||
| Ki+Pf1RG27H2wmgxXz2u7fqlU2hrxTmBZCn8RMIh8wI |  | ||||||
| -> ssh-ed25519 w3nu8g UQQYC93hQLRIgaA5P3Upax2HzfNddWkjTkAyZF5/hFs |  | ||||||
| 33fVUBBaJFRhDIuZoM8Rn1fd0JwqjmyXsbu4pioxXw4 |  | ||||||
| -> ssh-ed25519 evqvfg /J1fpbZORlnYADjqAcF8kV81e+mlxXC4mhMwozG7YXw |  | ||||||
| KYAtHd1MyNiEKoN/RgBCOsn/uCvXIjusXPFWW4urMFY |  | ||||||
| --- KVdBWZjlOA44GAK3GubvPaXlbg1zdpxL7+rJ4hv4Lmo |  | ||||||
| X/{×[P¼æÎÅ+³$_Z,t\#e¶ÐÃfñø>„,0ié©Ì’;þ°ÖVñB§QÍ8,Øëñú'JªRו=´ÕLœ–êÉäêL³Ý@bìðp?HÅM¦2—uÁò³€àÝp'g:ÄWÀ;YXs©ÍóN ÃO´m»y~£ò |  | ||||||
| @ -1,9 +1,11 @@ | |||||||
| age-encryption.org/v1 | age-encryption.org/v1 | ||||||
| -> ssh-ed25519 hPp1nw 5wFHyqBRdZxUDa180U3RgrL4DWNF3BO60C1ytWdZvXM | -> ssh-ed25519 WBT1Hw PbGwwDeulHF6kdh073rq0RvD1hlx6spnKNgKU+QeDAw | ||||||
| anPvoQk7kvz/wBddKYquSZ7b6dslhIrhV8wnMpC725E | 7dITwSQ2p1LZuaVEzLxcGOhB97MQT2zGoRrnNUMcOFk | ||||||
| -> ssh-ed25519 w3nu8g McO3H/GkcqQavMokZhXAsRijGq0wiXzmN1GH29n12wg | -> ssh-ed25519 hPp1nw Dn+5Fpme+JmRZKkCkqtCuD87p+sDYDA6OZ2aUmBkCRs | ||||||
| ooFxa+vYd49JSwdj9Knc8iDFyxX4elDb3IjOjrC5Cmo | Dgg3orXF4RYT/fHtc2tRuIhOQu48zICMqgPyV47vpf4 | ||||||
| -> ssh-ed25519 evqvfg pW/T4WXURnk7G+HL+O3STBWkQ+5by7EgwOPTcMNakyw | -> ssh-ed25519 w3nu8g dghNLDH1Tm+sm42HXDhrLFtmU4iDF1yCGrO2VSgzZjo | ||||||
| HByJjWNhOg7PSms4Px9NO0FnFcMj1Ig2rOXhCNQri7Y | 71scUVrGr4c4dunAFJYKd+uJ6aYJpSWBAk9swbv+IzM | ||||||
| --- LCgnSaNDEKv8du0OxZoLtyF4W02E/6pC/e1h0+XDDGA | -> ssh-ed25519 dMQYog Wnl1+rh0Q3YD2s1UD0OYVm39wY/Uw1NRK3K7EFhFMls | ||||||
| õViÁ°“ìbð[¾í<C2BE><C3AD>%þÚ{œtäL8àP‚[¦2z{g/KG®üÈAëZýåšœÂïàþ0pÃSg²…󶵿P³ÊYÊù—$•á | wXF6QBonlCalS1vI9cxzWgv1Gi+yAtYn6HrYCfpl5Nw | ||||||
|  | --- rLOoGk0iX+wuNd1CKv7g2PRd2Ic+8JHCQhrVBaF9zbE | ||||||
|  | <EFBFBD>òüüˤ/A¦Ì(ØiHC¸@¢Þð‰h`ˆ3ªá´'	¬ÚöáDì>ð¿¤~¸ÿÁö?ÑÃMêÙ@<40>t°(“Ò@ö׿^xÆMÉ} | ||||||
| @ -1,9 +1,9 @@ | |||||||
| age-encryption.org/v1 | age-encryption.org/v1 | ||||||
| -> ssh-ed25519 6AT2/g kH4DufpuybglKzupJsGvWKfWsZ5xhRwefdPKkx/AuW4 | -> ssh-ed25519 6AT2/g 98/m3t8axoVBE6WzdxBtRhV2uSQKSCXwQjyxfWXPmQk | ||||||
| QrDu/vSbgEIgYSnraG5u37RNp6Mp6ARjqzAduy9iX/Y | AxV0FTvqbWfk/gf65d05PcotbEnYr4PgDQnsaYxP/MU | ||||||
| -> ssh-ed25519 w3nu8g mBt4VQNJAMwcseVhc8k/mB5XThbQT48OnstkWaGQ8zQ | -> ssh-ed25519 w3nu8g jys7B4COD4iINANeSCD3BqGFoghxTmsbuXoOOIiP+wQ | ||||||
| 6w7lMJA8giG9PVux1ncjCPrN7ER0S7uWi8UjhOOeMS8 | b7eSN5fe4szfliINOr7ZQ7AoSsIK5akmIQ6uLDabcIE | ||||||
| -> ssh-ed25519 evqvfg uM4SAf1aMCvtRKdPn5BFr1EWlBGVgbgjp6OkuMV7GnU | -> ssh-ed25519 dMQYog ToNUqTPYmxpz9OUcC94egELcPfHQHCErfHN6l9kSrRY | ||||||
| Zi5X5TL7phRpwsbUVsFgS0qHvqtLdckz01qDfVypn/s | 2KoSVoWp+FH29YfH57ri2KOvhkuqYew1+PXm99e0BaI | ||||||
| --- I92hNxGkHSHR/fQhUI5UAXvzIvMd+YBih9nFP5IZW3w | --- Cjk3E/MjgCF45aLlFeyoGiaUEZk/QuKtsvPb6GpzD8Q | ||||||
| áÎ_§ØN/	nÞúú®H<C2AE>ô¡ÒaŽeõâ¼ÈêÅhÊB¤ê»[Ô´ðªqÂ<71>\ý+M:F‹Üîñ‚gP¦¤¤nh’¨¼N/¸2ÞÇl8µ3q>	rHt’UJG×n | m°å>‹“~czÆê匦†``ÜÏqX«š'ÁÎ%ôwÔž~×ÄL·eä'a±]û‹0ò´LÉÀ‰%ÍY‚TÊÓc9f¡W¶Ã^¤9ÊõÙÝ2®™æ¶ÆBÌa ƒ™  | ||||||
										
											Binary file not shown.
										
									
								
							| @ -1,7 +1,7 @@ | |||||||
| age-encryption.org/v1 | age-encryption.org/v1 | ||||||
| -> ssh-ed25519 w3nu8g 6127BAGsI/0p6vDXwo4W9ehh/Tzr/XblDYFYYtNfziU | -> ssh-ed25519 w3nu8g ER07FH17Wm9op5F4pCftNK76f+nNjtA6zQc/2dLyAHI | ||||||
| k0ZYtv6bTTKTdE81mPqwmuC3KSgimMn+noAm3LrzAkw | nxxq/8tS3ENJhAEIhJCiSi7dV+68AmcEMh9zvZoWpdY | ||||||
| -> ssh-ed25519 evqvfg n2/Ds6CbjTEGK0/faiUj+S1VbZ8cLjqAMBZEVM6PIwQ | -> ssh-ed25519 dMQYog JelCfh+akP7C/i1kimq3fC5PRQa9gHbmBaOnjKu+PDw | ||||||
| sPaFFL2bU2mUzKf8DLIHqXxGXZcER5gnKq9VpGA+GyU | GVTwo7MzkpCereZRh0HVjGYmtdMY1gHowMZtUQl7XQw | ||||||
| --- /KNS4o0n8Ol/i8vRJ1dBJklDR1UhR6kQNcM2rwqGNRw | --- p2l83t3bEdBrrp1ctaqqKhwB4l2McgZqZTtc2SXgd8Q | ||||||
| Îd;©<>_ɕԟ
ŽVë3_"ûÈ)“Ú(e…âßqÍþ$+ÓA¨æ±ÿç”Y#G | ø±ôeÆd\Yå4lXVF§U©<55>þM||)دÔûú•¶Ü8¿>ëž%ðóJ$à´Õè | ||||||
										
											Binary file not shown.
										
									
								
							| @ -1,9 +1,9 @@ | |||||||
| age-encryption.org/v1 | age-encryption.org/v1 | ||||||
| -> ssh-ed25519 6AT2/g +D1KEq8bDAErE5NJABbpoONsmolgc2aNDPucgzJZT2A | -> ssh-ed25519 6AT2/g Knb25oYknkiXyMqVBR3T0sFSO4hDjWUTq3xIml/b4ig | ||||||
| jJpebutfcnNYT71oiwEATP89ZSnmjXx3skHrrk2MLOY | n7xamnrZ+SCWiKqniF3r2JvH4G8q2pJaHzF0riNEDf4 | ||||||
| -> ssh-ed25519 w3nu8g MHVAh0Jp4pTahZoHIw5wUsp8STJ3rlH1C6+jrA+sJFI | -> ssh-ed25519 w3nu8g 7+2R5RpLjBf4jjj3S8ibMquUWgRMrifziGQubwuLrhA | ||||||
| sqMpGLw3HPumgAE7GYddT/iuewYZH3xy7mE5gyrWloA | 3jLCalnbA3Z2jr8Zs+qrpzSoi3Jv6E5OV2binpr3Kk4 | ||||||
| -> ssh-ed25519 evqvfg HoJqNfMckAJbHBCleHcSnI1VbOx3l7lQv1yM030G5mc | -> ssh-ed25519 dMQYog Nh2e7me0tiG7ZwQK8669VS0LCYFSH+b33I9tr8uI5CY | ||||||
| cscFawOoA4rA3EAc/FtCafLYlVZ4vcDEEmzouOrwVVY | 7Gs1N9eZa1CGR9pczzugHbqnghqevX7kQCOeqR4q0eI | ||||||
| --- sjGmx4I61x+AP72rCFeWyNJAEUlQz/az5rQ7jNfjXjU | --- OzW+omJsZA/b4DMF4hdQga7JVgiEYluZok3r8JM258I | ||||||
| ËgîV&\÷MŒ²ÜuÊMm;ãY?‡úRDÆ`‰(2Õ·ÕøÒ‘à–逯²)¸
Àò¦Ý£T | *³²ÝPކAcèÈ1·@Át¸e÷nf&ù#I7‡a‰Ûâc†ÃÀ<C383>êbDâ–~aõ]1w=Á | ||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -1,12 +1,11 @@ | |||||||
| age-encryption.org/v1 | age-encryption.org/v1 | ||||||
| -> ssh-ed25519 6AT2/g rk3jNJlQwab++isNOPpQJZlb4rL7nIAYfoAhlvY9QTc | -> ssh-ed25519 6AT2/g MGKlbzVOk5+czgAOerwl+eIyOifXJm/q4UgQUXVpx1c | ||||||
| J+6/MRepeixmDQzz3bRd/AMJpZls60dUBjrHh+p759Y | 43l6s4+5TSMQyO9tAg7v9Y5OdXOjKYz56lbr9Jm2r+o | ||||||
| -> ssh-ed25519 hPp1nw GnjIH+V6mLcXvfNhiBBwqBvY6NO8W+1sPcgvu6fS0nI | -> ssh-ed25519 hPp1nw aOxni4sFPPgedUkBOuOyEWfFPJrhdTJnivIaWt5RJxM | ||||||
| qP6jDxd+0h/AZhsBs7om0BDutrPmP/1NUEuZ7LBlxmw | KNaxijzSMp7EjYKwWiAP66nPYYZK3/VXL8u+3uJt6bg | ||||||
| -> ssh-ed25519 w3nu8g QwztUaCCtEVeI9AbJn5dKH07Y2fal+Nn9/bsnBkTJgI | -> ssh-ed25519 w3nu8g qTAzEzQbFze35AtbvkYREw3wa7ApDN5u7RSZUXrEpms | ||||||
| /Ce0a9bGv6RmQiK8C3wIvMCh5DM+m/EujYFsXgNjieY | Dy0uGF458A9RJMvDl2XKOkEABbbRgT+eIgvb6ZOEQqg | ||||||
| -> ssh-ed25519 evqvfg VLoQNzz62Q1KawvTHWeyBfCGTlGYNPQcdTaPq7cLxDo | -> ssh-ed25519 dMQYog 5DfYuGeWuN0/CO6WWbFIi7LaKl23FXYVdPROM+TFpCA | ||||||
| eabkTR9iUPYqCj50R7rwYcrMqcs+RHWqRZai2KKzPMQ | PDBdDn+YUMKYNKFkCEfXesmkB/XUxZRK3ddQt0kqQ7g | ||||||
| --- fQkT/xI/iptJd/UmihEcUWx77d2wr6bOj5lecPa/P8o | --- JOeG87EVD+QBx6n+rMoPTOni0PyoG7xx4a2USNiapYI | ||||||
| ,V„ý²lzºOP¿'Ìü2ÑÃ4¦o¸ü|ÅK‘m÷´»²FYL†Ì&ìâÓáéÊÁ>†©Ä\@emVÈnŒm½®6nôu—O@wRèãÁ‘åý^_ | Zsý{ÅiÁ_QÂ\+ô@@Üò߸ù&_š5$¿Gt2¢rF“y×ÄQ§Iaž7ôÙÉzàgf%O(µÙ,VéÂ}ÿn|û'J¸2ø¨óQÑB | ||||||
| ztFŠ©~ |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| age-encryption.org/v1 |  | ||||||
| -> ssh-ed25519 hPp1nw MRItBkM6GC+jht3ly0K04wCptE28UI9FmFAm2+8KHHw |  | ||||||
| Pbz+oZcWtzSz4eyWyRbi/a89Q3PripNJ+PYM/wiLKq0 |  | ||||||
| -> ssh-ed25519 w3nu8g a5G6FrbGmglm2Ba2T6NPsaVP+/4g//jh9ui/BVzR0EU |  | ||||||
| f0xNuCbhC0FqqFH6CD9jPAgWmTEZqga/fRjU6VMdfSk |  | ||||||
| -> ssh-ed25519 evqvfg 1lhGzpY7I0fKimq6sQ/zWUHCFSEaN31rmGCckUepfHY |  | ||||||
| 3OfNrzAajS6azIT90CmVnBzXLXcwMw/BRhOfbcuuz3c |  | ||||||
| --- vagzuZWeWUcZTBISnL4vNVcpMX2CbJGHwfaAFiIZeHM |  | ||||||
| en¼!<z'ß‹û,W
8†}òÙö=åà—lõÖŸê^^56èiÌ”½àÜd<C39C>æß»ü<C2BB>t.yçw>_% |  | ||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -17,13 +17,10 @@ with roles; | |||||||
|   "cris-hashed-email-pw.age".publicKeys = email-server; |   "cris-hashed-email-pw.age".publicKeys = email-server; | ||||||
|   "sasl_relay_passwd.age".publicKeys = email-server; |   "sasl_relay_passwd.age".publicKeys = email-server; | ||||||
|   "hashed-robots-email-pw.age".publicKeys = email-server; |   "hashed-robots-email-pw.age".publicKeys = email-server; | ||||||
|   "robots-email-pw.age".publicKeys = gitea ++ outline; |   "robots-email-pw.age".publicKeys = gitea; | ||||||
| 
 | 
 | ||||||
|   # nix binary cache |   # nix binary cache | ||||||
|   # public key: s0.koi-bebop.ts.net:OjbzD86YjyJZpCp9RWaQKANaflcpKhtzBMNP8I2aPUU= |   "atticd-credentials.age".publicKeys = binary-cache; | ||||||
|   "binary-cache-private-key.age".publicKeys = binary-cache; |  | ||||||
|   # public key: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINpUZFFL9BpBVqeeU63sFPhR9ewuhEZerTCDIGW1NPSB |  | ||||||
|   "binary-cache-push-sshkey.age".publicKeys = nobody; # this value is directly given to gitea |  | ||||||
| 
 | 
 | ||||||
|   # vpn |   # vpn | ||||||
|   "iodine.age".publicKeys = iodine; |   "iodine.age".publicKeys = iodine; | ||||||
| @ -31,14 +28,12 @@ with roles; | |||||||
| 
 | 
 | ||||||
|   # cloud |   # cloud | ||||||
|   "nextcloud-pw.age".publicKeys = nextcloud; |   "nextcloud-pw.age".publicKeys = nextcloud; | ||||||
|   "whiteboard-server-jwt-secret.age".publicKeys = nextcloud; |  | ||||||
|   "smb-secrets.age".publicKeys = personal ++ media-center; |   "smb-secrets.age".publicKeys = personal ++ media-center; | ||||||
|   "oauth2-proxy-env.age".publicKeys = server; |   "oauth2-proxy-env.age".publicKeys = server; | ||||||
| 
 | 
 | ||||||
|   # services |   # services | ||||||
|   "searx.age".publicKeys = nobody; |   "searx.age".publicKeys = nobody; | ||||||
|   "wolframalpha.age".publicKeys = dailybot; |   "wolframalpha.age".publicKeys = dailybot; | ||||||
|   "linkwarden-environment.age".publicKeys = linkwarden; |  | ||||||
| 
 | 
 | ||||||
|   # hostapd |   # hostapd | ||||||
|   "hostapd-pw-experimental-tower.age".publicKeys = nobody; |   "hostapd-pw-experimental-tower.age".publicKeys = nobody; | ||||||
| @ -53,17 +48,4 @@ with roles; | |||||||
| 
 | 
 | ||||||
|   # Librechat |   # Librechat | ||||||
|   "librechat-env-file.age".publicKeys = librechat; |   "librechat-env-file.age".publicKeys = librechat; | ||||||
| 
 |  | ||||||
|   # For ACME DNS Challenge |  | ||||||
|   "digitalocean-dns-credentials.age".publicKeys = server; |  | ||||||
| 
 |  | ||||||
|   # Frigate (DVR) |  | ||||||
|   "frigate-credentials.age".publicKeys = frigate; |  | ||||||
| 
 |  | ||||||
|   # zigbee2mqtt secrets |  | ||||||
|   "zigbee2mqtt.yaml.age".publicKeys = zigbee; |  | ||||||
| 
 |  | ||||||
|   # Sonarr and Radarr secrets |  | ||||||
|   "radarr-api-key.age".publicKeys = media-server; |  | ||||||
|   "sonarr-api-key.age".publicKeys = media-server; |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,17 +1,19 @@ | |||||||
| age-encryption.org/v1 | age-encryption.org/v1 | ||||||
| -> ssh-ed25519 N7drjg lVrCcpRGeAJ+62CF+fTT+iGKmaaiBk2rmtzS3jz4ux4 | -> ssh-ed25519 N7drjg x2s9QZ7Ijvg4t2peGng9/zX1ZmnGggsvWHJFHEktCgw | ||||||
| BbMLKa0uCoopsV0BekIcApzyJggQf4uFICuC26inA/c | o64an6DJ6Be8Jlhzn9ciQTByRAK5f2ckankCRH3y+Uw | ||||||
| -> ssh-ed25519 jQaHAA k7JCJlbAKDuH+bLhaoiQQssN5gfwPw9w30J3OAA4nWg | -> ssh-ed25519 yHDAQw HYHo6anhKDnD74ab04Ql4RB8+WBA6EavYASX7532NCE | ||||||
| fQ6te5iDG54mn5oXdarxMYPeze4ZWbk1yPAsLsTFby4 | aTp2V9g18yzUTq1ezqETj6jM2Yb1Bt5+JNkrIDT2Djs | ||||||
| -> ssh-ed25519 w3nu8g r3wLOavRLT++n+NaBRtcQqKXFTFhRYGl8naqUWNR0kE | -> ssh-ed25519 jQaHAA xGKcIQOkO/i4E2ZWZ+O4sAp7ADqCRqfRQHhKQu6yWh4 | ||||||
| pYkqQIiwzpN/XkDBrfCuFPc3yzyFjRbdCcFmRaY8iIU | RJnqK/t0YQrIej8fRDJGjOtQD7VvgJRfCUWR0/UYcSY | ||||||
| -> ssh-ed25519 evqvfg b+BUWYHdu1z38I0BMqpkSf5qaeaCm2C+vf9Hcqgjlg4 | -> ssh-ed25519 w3nu8g P9DQy19TvDCi3nfOhFj73bNZEtUs1BrLubt5/BtLoU4 | ||||||
| PK0y5MadYrM9ANyTMdHKXRTNi5cwD8/+19mN+vaTNiM | Sx41bk41dQYa3eoBayUMRIHqMWaRiwXm8BqErDBSbDw | ||||||
| -> ssh-ed25519 jQaHAA 86i8je5q4vVBfdi/Ws8/n4R/Z25uLw1e6zXDza8SwiI | -> ssh-ed25519 dMQYog OWU92PMFo9tGtlkK9zlmMFhh81TGkYlcX1PrxZl35yc | ||||||
| 5yuvdl0InHxrjRyi4SJOWEo6pWZt/mX8BsaFer3NwlE | owDk8wWXETS+iybhTMDmQH+eBuzZRDJIlVGCwu4LqTI | ||||||
| -> ssh-ed25519 w3nu8g N2QWi7I8V//jfK2ZGsXwBkEt2Zh7/5zpWCKUNV30bFA | -> ssh-ed25519 jQaHAA MzA8dSYZ/Ysp4ogKEEu84mal8779RgkT4Gy6rBEw+kM | ||||||
| ZmjY/lwFaVeM88FZSGwG+BYHi+32UPffZPZPbVcw+J8 | m75x/b83aP5G1vg7EXlcLizcm16fEAUAD+VNcdTMnnQ | ||||||
| -> ssh-ed25519 evqvfg cZflDyFn9H85TnSbi2HFrdVvlT5uZ+6+l4stOaoyOxE | -> ssh-ed25519 w3nu8g AAA3Me3KJgLvtQvyxLvlQ7pCnv7w73ja6Z2+3A82eGs | ||||||
| 3HpWWCbWoU1ufbi02xpXnU47Ti6YjrpMVh/mS5jgO0M | +yCW7qCdjk0fiQJmH8poMoc7APKyX/PY7zZyAG1O+Yg | ||||||
| --- wF990HQn1zh8JVo2alfC/QhpFimLsLDtj26DREVYr18 | -> ssh-ed25519 dMQYog Dd8e6srT+EIl2PH0RP1bQVsDx+HCQjhFndx5TFyhfx8 | ||||||
| QhE{+帻R(+ ÝNYIľ›Ť<ýęţ’k¦/ČÖŻ„pA<70>ݶ°Đ_ž'ËĹ«ž‰@3ů;»°÷-0‰Çˇa€b9W5ÔĂęźbU3)ASóĹ÷Śe÷ůQ/SMJ“_šĹe<16>Ža*‡:ť<>µ | j7Met77pWZzK9cMTt29gWB+d9YFVH5T9qs+ulHS3kAo | ||||||
|  | --- MgOK/g5hOVkGuUNDBSgVeGc9+ndjxLEA7nKSfLJMr4s | ||||||
|  | ~Ÿ‹¬&”™)<29>ŠG®Ÿ¨‡'UÐÞzc¾uFGì(<ò¯ùçV"ƒÕ3þH0x0$•<>w$YvO3	"Ï×ðV~ÀЏHÁ~XÛ]GœÆqµ®ã÷œ¢y'ãÓ*–Dê±ÏúœÕk#\ðAï<41>5ë{«Fe\~ | ||||||
| @ -1,9 +0,0 @@ | |||||||
| age-encryption.org/v1 |  | ||||||
| -> ssh-ed25519 hPp1nw aoj3IvYutQWfkOYOcDu0g7/FX05Y1t5NE2dP/x50gw8 |  | ||||||
| KV2kpClMmBPavyyhtC2coc3Gw9/QJQwXxfM13aKRrvQ |  | ||||||
| -> ssh-ed25519 w3nu8g ZjQIXYV3oK5ppG9ltfojwZ0Z93wFvXdiVBnFz5ncSSQ |  | ||||||
| CI3je4tMSb9ws+IyAgBVokFdy7z23n2EwtDrvLTziM8 |  | ||||||
| -> ssh-ed25519 evqvfg bWwaEp5s9nvzzQXbPd3rwmy4Ei9PWZg3Gk2I1nYBcCM |  | ||||||
| PwLLVWVI0GY4snYRadT92NZFneuA54yzL+Ie4RWDxDk |  | ||||||
| --- aqM1/sssbDgs4DNsGHqiaVH1LCyhh0vtoHSD3ju67Ew |  | ||||||
| &ネ゙<EFBE88>タニg~ハ*Y<12>訷E┴<45>゙oE,yセワE{濁チ瑩ャ*レ訶_A=キ6=怨M'燕ヘァr0<72> |  | ||||||
										
											Binary file not shown.
										
									
								
							| @ -1,9 +1,10 @@ | |||||||
| age-encryption.org/v1 | age-encryption.org/v1 | ||||||
| -> ssh-ed25519 6AT2/g G3ahigKIYvEJNDgz97yprVfANFzbR2uKcvBPNAxgwWI | -> ssh-ed25519 6AT2/g Kw5/he5m/XAJUNv8XEJQU+e+Ou7hCYluMXXWlHiePXY | ||||||
| iLpm56WMuc1Y10FwZ8HPOyBFNlhm1nWFS05DMXsjDD4 | GkhJOzSlcC9S7bs8FuDNMvMaFU3+fQ5z+o+Pb8wllp8 | ||||||
| -> ssh-ed25519 w3nu8g lx5NuJq4c4wwww887MFA1qwuLPVvddvG83l4xLzUYgk | -> ssh-ed25519 w3nu8g fUORtXN1ygOeV42jveCosGXR/Y6R6OG6DK7LPDBEAk8 | ||||||
| JgYBgcPw1jBa5yLSFBYVjf4jdoJJPoV6Q/d4Hkr3Efs | yFpoasbY/sl6BQp0LVBQnInA4Kxd8A8meEObU1KD108 | ||||||
| -> ssh-ed25519 evqvfg Gw0pMtP3bxgZXeEseJ+2xSb21AFX46JCAeHMroEJg1c | -> ssh-ed25519 dMQYog 75qVEe6/1yOV4DDLAOGaufs3ojx1/Sc1fIQOe+Oirz0 | ||||||
| qj1BjH+J9HOwYxoL2PEMa74nxfk9nlakl+40qoFunJ4 | iDFsr6/30AHKH6hUs/WTpHEM8WQ03QMlGbtQkGrnVCU | ||||||
| --- 5Om+5hhrNjOi0MRmrb8N1t9vVnM3wWosDsJCARknPNk | --- islx8t7a6bShXGxvYeDVuUxkmAMtpUfr0Gp7aYrJUkI | ||||||
| ©5HÉòÉ;)ôŽ\K“Au¯7ìx¢‹jûox…e›*FÈæ€†)èµ&<26>	úÑú}é<> | 2Ûí4¤†7Õ | ||||||
|  | ?Õw€À<E282AC>JÁÆØv	¨º9’,ËxÅŠò¨‰¦Æ¦ñnäH?>I | ||||||
| @ -1,9 +0,0 @@ | |||||||
| age-encryption.org/v1 |  | ||||||
| -> ssh-ed25519 hPp1nw FnUaydWe7+2dVUIYrKqx2/0AzRPN3ZylczJBkTqeeXg |  | ||||||
| boSEnMZmQyre4mJBQkEPuXuRP90woU1obqMdh+uQKhM |  | ||||||
| -> ssh-ed25519 w3nu8g pIDzDUVLZuZUCn6tGKpCLVS7OmhQiMgtMvuCKfWcgiM |  | ||||||
| zZxCUe0LslQ0ZqHV6sSMNQ5fhyscDFxVmJk0h2voEfc |  | ||||||
| -> ssh-ed25519 evqvfg eukXn1jUoHwP/cVmYCJ1O0kYQw+Xsad1PswvbcFUMEk |  | ||||||
| B0AvuWyfqK8ZFgCAW/iuXB0sKoKmB9d62ZNRTdDG43w |  | ||||||
| --- 0aziJ5/DCB9kJUqWhIggCqRnsuqu9s/g4Rt4vbwsBJk |  | ||||||
| FVÜçi`í1¥XFI–ÇI´@ŸoÞmf§Á³¤õ“ˆQ=ñè–彈臼i?²¿ƒb?Á
P6ŒA„-“°ÉY´°[Gö9<C3B6>ó î¥„½ÇÕ |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user