diff --git a/README.md b/README.md index 2f38a3a..41bf140 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,14 @@ lynx primarily uses the flake-parts framework. lynx aims to have similar goals to nixpkgs, providing documentation, testing, and source code. +> [!WARNING] +> This product assumes you're already familiar with the nix ecosystem. Error messages produced by the module system can be unclear and sometimes not informative. Documentation, and other resources in this repository may expect such literacy from its users. + + ## Bibliography +- https://github.com/tweag/rfcs/blob/flakes/rfcs/0049-flakes.md - https://flake.parts +- https://unallocatedspace.dev/blog/emc2i-flake ``` nix { diff --git a/flake-modules/flake-guard/age.md b/flake-modules/flake-guard/age.md new file mode 100644 index 0000000..f9666f6 --- /dev/null +++ b/flake-modules/flake-guard/age.md @@ -0,0 +1,59 @@ +# Agenix +Using flakeguard with agenix has a slightly different configuration. + +`wireguard.networks..sopsLookup` is defective when using agenix, since each secret in the repository has a unique `{key:value}` pair. + +Due to this, the same secret lookup cannot be used across multiple nixosConfigurations. + +> [!TIP] +> `sopsLookup` is still used with age-nix. This will be resolved with +> [#6](https://github.com/the-computer-club/lynx/issues/6) + + +```nix +imports = [ inputs.lynx.flakeModules.flake-guard ]; + +wireguard.enable = true; +wireguard.networks.my-network = { + listenPort = 52180; + + peers.by-name.workstation = { + sopsLookup = "home-privatekey.age"; + publicKey = "g72lA+Jsvp7ZEmXQGpJCrzMVrorSTjr6/kbD9aaLyX0="; + selfEndpoint = "10.0.0.51"; + }; + + peers.by-name.vps = { + sopsLookup = "vps-privatekey.age"; + publicKey = "ic/rfXxqoA4U0eaiL2VvVdkPIjvQL5p0lO/kk2lWZ0M="; + selfEndpoint = "10.0.0.51"; + }; +}; + +nixosModules.my-network = { + networking.wireguard.networks.my-network.autoConfig = { + peers = true; + interface = true; + }; +}; + +nixosConfigurations = { + vps = nixpkgs.lib.nixosSystem { + modules = [ + ./vps/configuration.nix + self.nixosModules.flake-guard-host + self.nixosModules.my-network + { networking.hostName = "vps"; } + ]; + }; + + workstation = nixpkgs.lib.nixosSystem { + modules = [ + ./vps/configuration.nix + self.nixosModules.flake-guard-host + self.nixosModules.my-network + { networking.hostName = "workstation"; } + ]; + }; +} +``` diff --git a/flake-modules/flake-guard/local-key.md b/flake-modules/flake-guard/local-key.md new file mode 100644 index 0000000..108fefd --- /dev/null +++ b/flake-modules/flake-guard/local-key.md @@ -0,0 +1,70 @@ +# Local filesystem key + + +#### Flake +```nix +wireguard.enable = true; + +wireguard.networks.my-network = +{ + listenPort = 52180; + privateKeyFile = "/var/lib/wireguard/privatekey"; + + peers.by-name = { + workstation = { + publicKey = "g72lA+Jsvp7ZEmXQGpJCrzMVrorSTjr6/kbD9aaLyX0="; + selfEndpoint = "10.0.0.51"; + }; + + vps = { + publicKey = "ic/rfXxqoA4U0eaiL2VvVdkPIjvQL5p0lO/kk2lWZ0M="; + selfEndpoint = "10.0.0.52"; + }; + }; +} + +nixosModules.my-network.networking.wireguard.networks.my-network.autoConfig = { + interface = true; + peers = true; +}; + +nixosConfigurations.workstation = nixpkgs.lib.nixosSystem { + modules = [ + self.nixosModules.flake-guard-host + self.nixosModules.my-network + { + networking.hostName = "workstation"; + # interfaces.my-network.generatePrivateKeyFile = true; + } + ./workstation.nix + ] +}; + +nixosConfigurations.vps = nixpkgs.lib.nixosSystem { + modules = [ + self.nixosModules.flake-guard-host + self.nixosModules.my-network + { + networking.hostName = "vps"; + # interfaces.my-network.generatePrivateKeyFile = true; + } + ./vps.nix + ] +}; + +``` + + +#### Nixos Configuration +```nix +imports = [self.nixosModules.flake-guard-host]; + +networking.wireguard = { + networks.my-network.autoConfig = { + peers = true; + interface = true; + }; + + # Useful for sharing with others. +}; +``` diff --git a/flake-modules/flake-guard/readme.md b/flake-modules/flake-guard/readme.md index c1a58df..01a8f0f 100644 --- a/flake-modules/flake-guard/readme.md +++ b/flake-modules/flake-guard/readme.md @@ -1,127 +1,42 @@ # flake-guard +> [!WARNING] +> Unstable. flake guard allows you to define your wireguard network once, and use it across multiple `nixosConfiguration` fields. -### Define your network. -- Step 1: create `wireguard-network.nix` -```nix -# flake-module -{ config, lib, inputs, ... }: -{ - imports = [ inputs.lynx.flakeModules.flake-guard ]; - - wireguard.enable = true; - wireguard.networks.my-network = { - # assumes same sop keys for all hosts. - # this also works with agenix - sopsLookup = "my-network"; - - # assumes the same port for all hosts. - listenPort = 51820; - - peers.by-name = { # - # WARNING: networking.hostName = "host1"; - # must match `host1 = ...` for `autoConfig` to work. (flake-guard-host) - host1 = { - publicKey = "g72lA+Jsvp7ZEmXQGpJCrzMVrorSTjr6/kbD9aaLyX0="; - ipv4 = [ "172.16.0.1/32" ]; - ipv6 = [ "fc90::1/128" ]; - selfEndpoint = "example.com:51820"; - }; - }; - - host2 = { - publicKey = "ic/rfXxqoA4U0eaiL2VvVdkPIjvQL5p0lO/kk2lWZ0M="; - ipv4 = [ "172.16.0.1/32" ]; - ipv6 = [ "fc90::1/128" ]; - selfEndpoint = "example.com:51820"; - }; - }; - }; - }; -} -``` - -- Step 2: - - Add your `wireguard-network.nix` in your `flake.nix` - -```nix -{ - inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11"; - parts.url = "github:hercules-ci/flake-parts"; - lynx.url = "github:the-computer-club/lynx"; - }; - - outputs = inputs: parts.lib.mkFlake { inherit inputs; } - (_: # https://flake.parts/module-arguments - { - imports = [ ./wireguard-network.nix ]; # <- here. - }); -} -``` - -- Step 3: - -Now create secrets for each nixosConfiguration this network is involved with. (or agenix equalivent) -``` -EDITOR=emacs sops secrets/default.json -``` - - -- Step 4: add a field named matching the `sopsLookup` value, and insert the output of `wg genkey`. - -Finally, add the following configuration to the host. - -```nix -{ self, config, lib, pkgs, ... }: -let - net = config.networking.wireguard.networks; -in -{ - imports = [ self.nixosModules.flake-guard-host ]; - - sops.secrets.my-network.mode = "0400"; - networking.firewall.interfaces = { - eno1.allowedUDPPorts = [ - net.my-network.self.listenPort - ]; - my-network.allowedTCPPorts = [ 22 80 443 ]; - }; - - networking.wireguard.networks = { - my-network.autoConfig = { - # Automatically setup - # `networking.wireguard.interfaces..{privateKeyFile,ips}` - interface = true; - # Settings `peers = true` is equalivent - # to a mesh network. - peers = true; - }; - }; -} -``` - -Repeat steps 3 through 4 for every nixosConfiguration in the network. - -Thats it, you're done. - - -### Non-mesh topology. -```nix -{config, lib, pkgs, ...}: -let - net = config.networking.wireguard.networks."my-network"; -in -{ - networking.wireguard.networks = { - my-network.autoConfig.interface = true; - }; - - networking.wireguard.interfaces."my-network".peers = - with net.peers.by-name; [ - host2 - ]; -} -``` +guides: +- [sops](./sops.md) +- [age](./age.md) +- [local-key](./local-key.md) + + + +flake guard uses flake-parts to define options in at the level. `wireguard.networks..peers.by-name.`. + +These options are effectively the same as `wireguard.networking.interfaces.peers.*`. + + +flake guard then provides an nixosModule for interfacing with the flake-level data. This interface is generated on your flake as `self.nixosModule.flake-guard-host`. + + +The peer list is the primary data structure needed to configure the wireguard network, so if you wish to implement your own variation, this is the core premise. + + +`flake-guard-host` provides `networking.wireguard.networks.` +which introduces the following + + +| field | description | +|------------|--------------------------------------------------------------------| +| peers | the network's peer list, same as the flake level. | +| self | this host selected from the peer list | +| autoConfig | will use the data above automatically for the respective interface | +| | | + + +`flake-guard-host` makes an attempt to "discover" which system its ran on. This is accomplished by checking `networking.hostName`, and matching the name from `peers.by-name`. + + +`networking.wireguard.networks.autoConfig` will not work without it. + + diff --git a/flake-modules/flake-guard/sops.md b/flake-modules/flake-guard/sops.md new file mode 100644 index 0000000..40c4f35 --- /dev/null +++ b/flake-modules/flake-guard/sops.md @@ -0,0 +1,129 @@ +# flake-guard + +flake guard allows you to define your wireguard network once, and use it across multiple `nixosConfiguration` fields. + + +### Define your network. +- Step 1: create `wireguard-network.nix` +```nix +# flake-module +{ config, lib, inputs, ... }: +{ + imports = [ inputs.lynx.flakeModules.flake-guard ]; + + wireguard.enable = true; + wireguard.networks.my-network = { + # assumes same sop keys for all hosts. + # this also works with agenix + sopsLookup = "my-network"; + + # assumes the same port for all hosts. + listenPort = 51820; + + peers.by-name = { + # WARNING: networking.hostName = "host1"; + # must match `host1 = ...` for `autoConfig` to work. + # (flake-guard-host) + host1 = { + publicKey = "g72lA+Jsvp7ZEmXQGpJCrzMVrorSTjr6/kbD9aaLyX0="; + ipv4 = [ "172.16.0.1/32" ]; + ipv6 = [ "fc90::1/128" ]; + selfEndpoint = "example.com:51820"; + }; + }; + + host2 = { + publicKey = "ic/rfXxqoA4U0eaiL2VvVdkPIjvQL5p0lO/kk2lWZ0M="; + ipv4 = [ "172.16.0.1/32" ]; + ipv6 = [ "fc90::1/128" ]; + selfEndpoint = "example.com:51820"; + }; + }; + }; + }; +} +``` + +- Step 2: + + Add your `wireguard-network.nix` in your `flake.nix` + +```nix +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11"; + parts.url = "github:hercules-ci/flake-parts"; + lynx.url = "github:the-computer-club/lynx"; + }; + + outputs = inputs: parts.lib.mkFlake { inherit inputs; } + (_: # https://flake.parts/module-arguments + { + imports = [ ./wireguard-network.nix ]; # <- here. + }); +} +``` + +- Step 3: + +Now create secrets for each nixosConfiguration this network is involved with. (or agenix equalivent) +``` +EDITOR=emacs sops secrets/default.json +``` + + +- Step 4: add a field named matching the `sopsLookup` value, and insert the output of `wg genkey`. + +Finally, add the following configuration to the host. + +```nix +{ self, config, lib, pkgs, ... }: +let + net = config.networking.wireguard.networks; +in +{ + imports = [ self.nixosModules.flake-guard-host ]; + + sops.secrets.my-network.mode = "0400"; + networking.firewall.interfaces = { + eno1.allowedUDPPorts = [ + net.my-network.self.listenPort + ]; + my-network.allowedTCPPorts = [ 22 80 443 ]; + }; + + networking.wireguard.networks = { + my-network.autoConfig = { + # Automatically setup + # `networking.wireguard.interfaces..{privateKeyFile,ips}` + interface = true; + # Settings `peers = true` is equalivent + # to a mesh network. + peers = true; + }; + }; +} +``` + +Repeat steps 3 through 4 for every nixosConfiguration in the network. + +Thats it, you're done. + + +### Non-mesh topology. +```nix +{config, lib, pkgs, ...}: +let + net = config.networking.wireguard.networks."my-network"; +in +{ + networking.wireguard.networks = { + my-network.autoConfig.interface = true; + }; + + networking.wireguard.interfaces."my-network".peers = + with net.peers.by-name; [ + host2 + ]; +} +``` diff --git a/flake-modules/flake-guard/usage.md b/flake-modules/flake-guard/usage.md new file mode 100644 index 0000000..938e067 --- /dev/null +++ b/flake-modules/flake-guard/usage.md @@ -0,0 +1,59 @@ +# Flake-guard + +Flake guard provides wireguard networks as a flake option. + + +### Flake-guard networks as inputs +``` +# github:the-computer-club/automous-zones +{ + outputs = _: { + flakeModules.gateway-zone.wireguard.networks.gateway-zone = { + listenPort = 52180; + peers.by-name = { + hostname = { + publicKey = "g72lA+Jsvp7ZEmXQGpJCrzMVrorSTjr6/kbD9aaLyX0="; + selfEndpoint = "10.0.0.51"; + }; + + vps = { + publicKey = "ic/rfXxqoA4U0eaiL2VvVdkPIjvQL5p0lO/kk2lWZ0M="; + selfEndpoint = "10.0.0.52"; + }; + }; + }; + }; +} +``` + +``` +inputs.nixpkgs.url = "github:nixos/nixpkgs"; +inputs.parts.url = "github:the-computer-club/flake-parts"; +inputs.lynx.url = "github:the-computer-club/lynx"; +inputs.aether-net.url = "github:the-computer-club/automous-zones"; + +outputs = inputs: inputs.parts.lib.mkFlake {inherit inputs;} ({ + systems = [ "x86_64-linux" ]; + imports = [ + inputs.lynx.flakeModules.flake-guard + inputs.aether-net.flakeModules.gateway-zone + ]; + + wireguard.enable = true; + + nixosConfigurations.hostname = inputs.nixpkgs.lib.nixosSystem { + modules = [ + self.nixosModules.flake-guard-host + { + networking.wireguard.networks.gateway-zone.autoConfig = { + interface = true; + peers = true; + }; + } + ./home.nix + ./home-hardware.nix + ]; + + }; +}) +```