diff --git a/morph/grid/local/grid.nix b/morph/grid/local/grid.nix index 51f41832ded8fe18290c47b5b3ad85fb58c2a511..c8c2747715924d41578c6601b3f2452d14ddb5d6 100644 --- a/morph/grid/local/grid.nix +++ b/morph/grid/local/grid.nix @@ -2,20 +2,27 @@ let pkgs = import <nixpkgs> { }; gridlib = import ../../lib; - rawConfig = pkgs.lib.trivial.importJSON ./config.json; - config = rawConfig // { - sshUsers = import ./public-keys/users.nix; + grid-config = pkgs.lib.trivial.importJSON ./config.json; + # Module with per-grid configuration + grid-module = {config, ...}: { + imports = [ + gridlib.base + # Allow us to remotely trigger updates to this system. + ../../../nixos/modules/deployment.nix + # Give it a good SSH configuration. + ../../../nixos/modules/ssh.nix + ]; + services.private-storage.sshUsers = import ./public-keys/users.nix; # Convert relative paths to absolute so library code can resolve names # correctly. - publicKeyPath = toString ./. + "/${rawConfig.publicKeyPath}"; - privateKeyPath = toString ./. + "/${rawConfig.privateKeyPath}"; - }; - - # Configure deployment management authorization for all systems in the grid. - deployment = { + grid = { + publicKeyPath = toString ./. + "/${grid-config.publicKeyPath}"; + privateKeyPath = toString ./. + "/${grid-config.privateKeyPath}"; + }; + # Configure deployment management authorization for all systems in the grid. services.private-storage.deployment = { - authorizedKey = builtins.readFile "${config.publicKeyPath}/deploy_key.pub"; + authorizedKey = builtins.readFile "${config.grid.publicKeyPath}/deploy_key.pub"; gridName = "local"; }; }; @@ -24,10 +31,10 @@ let imports = [ gridlib.issuer (gridlib.hardware-virtual ({ publicIPv4 = "192.168.67.21"; })) - (gridlib.customize-issuer (config // { + (gridlib.customize-issuer (grid-config // { monitoringvpnIPv4 = "172.23.23.11"; })) - deployment + grid-module ]; }; @@ -35,11 +42,11 @@ let imports = [ gridlib.storage (gridlib.hardware-virtual ({ publicIPv4 = "192.168.67.22"; })) - (gridlib.customize-storage (config // { + (gridlib.customize-storage (grid-config // { monitoringvpnIPv4 = "172.23.23.12"; stateVersion = "19.09"; })) - deployment + grid-module ]; }; @@ -47,11 +54,11 @@ let imports = [ gridlib.storage (gridlib.hardware-virtual ({ publicIPv4 = "192.168.67.23"; })) - (gridlib.customize-storage (config // { + (gridlib.customize-storage (grid-config // { monitoringvpnIPv4 = "172.23.23.13"; stateVersion = "19.09"; })) - deployment + grid-module ]; }; @@ -61,12 +68,12 @@ let (gridlib.hardware-virtual ({ publicIPv4 = "192.168.67.24"; })) (gridlib.customize-monitoring { inherit hostsMap vpnClientIPs nodeExporterTargets paymentExporterTargets; - inherit (config) domain publicKeyPath privateKeyPath sshUsers letsEncryptAdminEmail; - googleOAuthClientID = config.monitoringGoogleOAuthClientID; + inherit (grid-config) domain letsEncryptAdminEmail; + googleOAuthClientID = grid-config.monitoringGoogleOAuthClientID; monitoringvpnIPv4 = "172.23.23.1"; stateVersion = "19.09"; }) - deployment + grid-module ]; }; diff --git a/morph/grid/production/grid.nix b/morph/grid/production/grid.nix index 06eefdd28da57ad65ea99543ba8421bc934ef752..91eec738fe8344728ed35564bacd3a57e94b9e5e 100644 --- a/morph/grid/production/grid.nix +++ b/morph/grid/production/grid.nix @@ -3,20 +3,27 @@ let pkgs = import <nixpkgs> { }; gridlib = import ../../lib; - rawConfig = pkgs.lib.trivial.importJSON ./config.json; - config = rawConfig // { - sshUsers = import ./public-keys/users.nix; + grid-config = pkgs.lib.trivial.importJSON ./config.json; + # Module with per-grid configuration + grid-module = {config, ...}: { + imports = [ + gridlib.base + # Allow us to remotely trigger updates to this system. + ../../../nixos/modules/deployment.nix + # Give it a good SSH configuration. + ../../../nixos/modules/ssh.nix + ]; + services.private-storage.sshUsers = import ./public-keys/users.nix; # Convert relative paths to absolute so library code can resolve names # correctly. - publicKeyPath = toString ./. + "/${rawConfig.publicKeyPath}"; - privateKeyPath = toString ./. + "/${rawConfig.privateKeyPath}"; - }; - - # Configure deployment management authorization for all systems in the grid. - deployment = { + grid = { + publicKeyPath = toString ./. + "/${grid-config.publicKeyPath}"; + privateKeyPath = toString ./. + "/${grid-config.privateKeyPath}"; + }; + # Configure deployment management authorization for all systems in the grid. services.private-storage.deployment = { - authorizedKey = builtins.readFile "${config.publicKeyPath}/deploy_key.pub"; + authorizedKey = builtins.readFile "${config.grid.publicKeyPath}/deploy_key.pub"; gridName = "production"; }; }; @@ -25,10 +32,10 @@ let imports = [ gridlib.issuer gridlib.hardware-aws - (gridlib.customize-issuer (config // { + (gridlib.customize-issuer (grid-config // { monitoringvpnIPv4 = "172.23.23.11"; })) - deployment + grid-module ]; }; @@ -38,12 +45,12 @@ let gridlib.hardware-aws (gridlib.customize-monitoring { inherit hostsMap vpnClientIPs nodeExporterTargets paymentExporterTargets; - inherit (config) domain publicKeyPath privateKeyPath sshUsers letsEncryptAdminEmail; - googleOAuthClientID = config.monitoringGoogleOAuthClientID; + inherit (grid-config) domain letsEncryptAdminEmail; + googleOAuthClientID = grid-config.monitoringGoogleOAuthClientID; monitoringvpnIPv4 = "172.23.23.1"; stateVersion = "19.09"; }) - deployment + grid-module ]; }; @@ -65,13 +72,13 @@ let gridlib.storage # Then customize the storage system a little bit based on this node's particulars. - (gridlib.customize-storage (config // nodecfg // { + (gridlib.customize-storage (grid-config // nodecfg // { monitoringvpnIPv4 = vpnIP; inherit stateVersion; })) # Also configure deployment management authorization - deployment + grid-module ]; # And supply configuration for those hardware / network / bootloader diff --git a/morph/grid/testing/grid.nix b/morph/grid/testing/grid.nix index 7b06c99e1f7a1b65b535f924a0a24aebe6753586..3e15e5137194d2637a9637fecb61fb0a8d132f1c 100644 --- a/morph/grid/testing/grid.nix +++ b/morph/grid/testing/grid.nix @@ -3,20 +3,27 @@ let pkgs = import <nixpkgs> { }; gridlib = import ../../lib; - rawConfig = pkgs.lib.trivial.importJSON ./config.json; - config = rawConfig // { - sshUsers = import ./public-keys/users.nix; + grid-config = pkgs.lib.trivial.importJSON ./config.json; + # Module with per-grid configuration + grid-module = {config, ...}: { + imports = [ + gridlib.base + # Allow us to remotely trigger updates to this system. + ../../../nixos/modules/deployment.nix + # Give it a good SSH configuration. + ../../../nixos/modules/ssh.nix + ]; + services.private-storage.sshUsers = import ./public-keys/users.nix; # Convert relative paths to absolute so library code can resolve names # correctly. - publicKeyPath = toString ./. + "/${rawConfig.publicKeyPath}"; - privateKeyPath = toString ./. + "/${rawConfig.privateKeyPath}"; - }; - - # Configure deployment management authorization for all systems in the grid. - deployment = { + grid = { + publicKeyPath = toString ./. + "/${grid-config.publicKeyPath}"; + privateKeyPath = toString ./. + "/${grid-config.privateKeyPath}"; + }; + # Configure deployment management authorization for all systems in the grid. services.private-storage.deployment = { - authorizedKey = builtins.readFile "${config.publicKeyPath}/deploy_key.pub"; + authorizedKey = builtins.readFile "${config.grid.publicKeyPath}/deploy_key.pub"; gridName = "testing"; }; }; @@ -25,10 +32,10 @@ let imports = [ gridlib.issuer gridlib.hardware-aws - (gridlib.customize-issuer (config // { + (gridlib.customize-issuer (grid-config // { monitoringvpnIPv4 = "172.23.23.11"; })) - deployment + grid-module ]; }; @@ -37,11 +44,11 @@ let gridlib.storage gridlib.hardware-aws ./testing001-hardware.nix - (gridlib.customize-storage (config // { + (gridlib.customize-storage (grid-config // { monitoringvpnIPv4 = "172.23.23.12"; stateVersion = "19.03"; })) - deployment + grid-module ]; }; @@ -51,12 +58,12 @@ let gridlib.hardware-aws (gridlib.customize-monitoring { inherit hostsMap vpnClientIPs nodeExporterTargets paymentExporterTargets; - inherit (config) domain publicKeyPath privateKeyPath sshUsers letsEncryptAdminEmail; - googleOAuthClientID = config.monitoringGoogleOAuthClientID; + inherit (grid-config) domain letsEncryptAdminEmail; + googleOAuthClientID = grid-config.monitoringGoogleOAuthClientID; monitoringvpnIPv4 = "172.23.23.1"; stateVersion = "19.09"; }) - deployment + grid-module ]; }; diff --git a/morph/lib/base.nix b/morph/lib/base.nix new file mode 100644 index 0000000000000000000000000000000000000000..809e3556c534c55890520d81d3e3383cc0b18f85 --- /dev/null +++ b/morph/lib/base.nix @@ -0,0 +1,22 @@ +# This module contains settings and configuration that apply to all nodes in a grid. +{ lib, config, ...}: +{ + options.grid = { + publicKeyPath = lib.mkOption { + type = lib.types.path; + description = '' + A path on the deployment system of a directory containing all of the + public keys for the system. For example, this holds Wireguard public keys + for the VPN configuration and SSH public keys to configure SSH + authentication. + ''; + }; + privateKeyPath = lib.mkOption { + type = lib.types.path; + description = '' + A path on the deployment system of a directory containing all of the + corresponding private keys for the system. + ''; + }; + }; +} diff --git a/morph/lib/customize-issuer.nix b/morph/lib/customize-issuer.nix index 1c0d668fbd4ae59bab115c2116b7fa377395dcfc..4e0872b1315c4ce62d06832063f758522aacb585 100644 --- a/morph/lib/customize-issuer.nix +++ b/morph/lib/customize-issuer.nix @@ -1,19 +1,9 @@ # Define a function which returns a value which fills in all the holes left by # ``issuer.nix``. { - # A path on the deployment system of a directory containing all of the - # public keys for the system. For example, this holds Wireguard public keys - # for the VPN configuration and SSH public keys to configure SSH - # authentication. - publicKeyPath - - # A path on the deployment system of a directory containing all of the - # corresponding private keys for the system. -, privateKeyPath - # A string giving the IP address and port number (":"-separated) of the VPN # server. -, monitoringvpnEndpoint + monitoringvpnEndpoint # A string giving the VPN IPv4 address for this system. , monitoringvpnIPv4 @@ -26,12 +16,6 @@ # ``"example-grid.invalid"`` for the system figure out that # ``payments.example-grid.invalid`` is the name of this system. , domain - - # A set mapping usernames as strings to SSH public keys as strings. For - # each element of the site, the indicated user is configured on the system - # with the indicated SSH key as an authorized key. -, sshUsers - # A string giving an email address to use for Let's Encrypt registration and # certificate issuance. , letsEncryptAdminEmail @@ -45,7 +29,10 @@ , allowedChargeOrigins , ... }: -{ config, ... }: { +{ config, ... }: +let + inherit (config.grid) publicKeyPath privateKeyPath; +in { # The morph default deployment target the name of the node in the network # attrset. We don't always want to give the node its proper public address # there (because it depends on which domain is associated with the grid @@ -55,15 +42,6 @@ deployment.targetHost = "${config.networking.hostName}.${config.networking.domain}"; deployment.secrets = { - # A path on the deployment system to a file containing the Ristretto - # signing key. This is used as the source of the Ristretto signing key - # morph secret. - "ristretto-signing-key".source = "${privateKeyPath}/ristretto.signing-key"; - - # A path on the deployment system to a file containing the Stripe secret - # key. This is used as the source of the Stripe secret key morph secret. - "stripe-secret-key".source = "${privateKeyPath}/stripe.secret"; - # ``.../monitoringvpn`` is a path on the deployment system of a directory # containing a number of VPN-related secrets. This is expected to contain # a number of files named like ``<VPN IPv4 address>.key`` containing the @@ -77,7 +55,6 @@ networking.domain = domain; - services.private-storage.sshUsers = sshUsers; services.private-storage.monitoring.vpn.client = { enable = true; ip = monitoringvpnIPv4; diff --git a/morph/lib/customize-monitoring.nix b/morph/lib/customize-monitoring.nix index 391aa5602575100c8650d8e4fb6892e38fc95ebf..324f99f2453938d46a7f17118a80e8c411d2acdf 100644 --- a/morph/lib/customize-monitoring.nix +++ b/morph/lib/customize-monitoring.nix @@ -9,11 +9,8 @@ hostsMap # See ``customize-issuer.nix``. -, publicKeyPath -, privateKeyPath , monitoringvpnIPv4 , domain -, sshUsers , letsEncryptAdminEmail # A list of VPN IP addresses as strings indicating which clients will be @@ -40,7 +37,10 @@ , stateVersion , ... }: -{ config, ... }: { +{ config, ... }: +let + inherit (config.grid) publicKeyPath privateKeyPath; +in { # See customize-issuer.nix for an explanatoin of targetHost value. deployment.targetHost = "${config.networking.hostName}.${config.networking.domain}"; @@ -85,8 +85,6 @@ networking.domain = domain; networking.hosts = hostsMap; - services.private-storage.sshUsers = sshUsers; - services.private-storage.monitoring.vpn.server = { enable = true; ip = monitoringvpnIPv4; diff --git a/morph/lib/customize-storage.nix b/morph/lib/customize-storage.nix index 68655874efd9ba39b52dacfdddaedb54863ed769..be4c2a9322cf6d692d90778ffabfaefa02fd8706 100644 --- a/morph/lib/customize-storage.nix +++ b/morph/lib/customize-storage.nix @@ -2,11 +2,8 @@ # ``storage.nix``. { # See ``customize-issuer.nix`` - privateKeyPath -, publicKeyPath -, monitoringvpnEndpoint + monitoringvpnEndpoint , monitoringvpnIPv4 -, sshUsers , domain # An integer giving the value of a single pass in byte×months. @@ -20,12 +17,14 @@ , stateVersion , ... }: -{ config, ... }: { +{ config, ... }: +let + inherit (config.grid) publicKeyPath privateKeyPath; +in { # See customize-issuer.nix for an explanatoin of targetHost value. deployment.targetHost = "${config.networking.hostName}.${config.networking.domain}"; deployment.secrets = { - "ristretto-signing-key".source = "${privateKeyPath}/ristretto.signing-key"; "monitoringvpn-secret-key".source = "${privateKeyPath}/monitoringvpn/${monitoringvpnIPv4}.key"; "monitoringvpn-preshared-key".source = "${privateKeyPath}/monitoringvpn/preshared.key"; }; @@ -33,7 +32,7 @@ networking.domain = domain; services.private-storage = { - inherit sshUsers passValue publicStoragePort; + inherit passValue publicStoragePort; }; services.private-storage.monitoring.vpn.client = { diff --git a/morph/lib/default.nix b/morph/lib/default.nix index bdd92f4bfe52eba2e19df3ac73a087a4af4a53dc..bf25e5a58d04d148296bffef48acc4e4e125684b 100644 --- a/morph/lib/default.nix +++ b/morph/lib/default.nix @@ -2,6 +2,8 @@ # coherent public interface. Application code should prefer these names over # directly importing the source files in this directory. { + base = import ./base.nix; + hardware-aws = import ./issuer-aws.nix; hardware-virtual = import ./hardware-virtual.nix; @@ -13,4 +15,6 @@ monitoring = import ./monitoring.nix; customize-monitoring = import ./customize-monitoring.nix; + + modules = builtins.toString ../../nixos/modules; } diff --git a/morph/lib/issuer.nix b/morph/lib/issuer.nix index f617eef171cfaa35f7cf676915e57ba2654a4319..a14d70e0634ad150d3c076abcdfc36fb6a167513 100644 --- a/morph/lib/issuer.nix +++ b/morph/lib/issuer.nix @@ -1,15 +1,18 @@ -# This is all of the static NixOS system configuration necessary to specify an -# "issuer"-type system. The configuration has various holes in it which must -# be filled somehow. These holes correspond to configuration which is not -# statically known. This value is suitable for use as a module to be imported -# into a more complete system configuration. It is expected that the holes -# will be filled by a sibling module created by ``customize-issuer.nix``. +# This, along with `customize-issuer.nix, contains all of the NixOS system +# configuration necessary to specify an "issuer"-type system. Originally, this +# file has all the static configuration, and `customize-issuer.nix` was a function +# that filled in the holes. We are in the process of merging the modules, using settings +# instead of function arguments. +# See https://whetstone.privatestorage.io/privatestorage/PrivateStorageio/-/issues/80 { config, ...}: -{ +let + inherit (config.grid) publicKeyPath privateKeyPath; +in { deployment = { secrets = { "ristretto-signing-key" = { destination = "/run/keys/ristretto.signing-key"; + source = "${privateKeyPath}/ristretto.signing-key"; owner.user = "root"; owner.group = "root"; permissions = "0400"; @@ -17,6 +20,7 @@ }; "stripe-secret-key" = { destination = "/run/keys/stripe.secret-key"; + source = "${privateKeyPath}/stripe.secret"; owner.user = "root"; owner.group = "root"; permissions = "0400"; @@ -41,9 +45,6 @@ }; imports = [ - # Allow us to remotely trigger updates to this system. - ../../nixos/modules/deployment.nix - ../../nixos/modules/issuer.nix ../../nixos/modules/monitoring/vpn/client.nix ../../nixos/modules/monitoring/exporters/node.nix diff --git a/morph/lib/monitoring.nix b/morph/lib/monitoring.nix index 7d59c296d12b06e430ff031b9f0b8b8a0e8616e1..bf92d1041f2bf9b9fb1ff4580a25ff7b596a9bbb 100644 --- a/morph/lib/monitoring.nix +++ b/morph/lib/monitoring.nix @@ -21,11 +21,6 @@ }; imports = [ - # Give it a good SSH configuration. - ../../nixos/modules/ssh.nix - # Allow us to remotely trigger updates to this system. - ../../nixos/modules/deployment.nix - ../../nixos/modules/monitoring/vpn/server.nix ../../nixos/modules/monitoring/server/grafana.nix ../../nixos/modules/monitoring/server/prometheus.nix diff --git a/morph/lib/storage.nix b/morph/lib/storage.nix index 52be81364a3659a625854503b8efa7a8c97e108b..86e142286351237099337d38d03a9b54255b8246 100644 --- a/morph/lib/storage.nix +++ b/morph/lib/storage.nix @@ -1,11 +1,14 @@ # Similar to ``issuer.nix`` but for a "storage"-type system. Holes are filled # by ``customize-storage.nix``. { config, ...} : -{ +let + inherit (config.grid) publicKeyPath privateKeyPath; +in { deployment = { secrets = { "ristretto-signing-key" = { destination = "/run/keys/ristretto.signing-key"; + source = "${privateKeyPath}/ristretto.signing-key"; owner.user = "root"; owner.group = "root"; permissions = "0400"; @@ -33,8 +36,6 @@ # Any extra NixOS modules to load on this server. imports = [ - # Allow us to remotely trigger updates to this system. - ../../nixos/modules/deployment.nix # Bring in our module for configuring the Tahoe-LAFS service and other # Private Storage-specific things. ../../nixos/modules/private-storage.nix diff --git a/nixos/modules/issuer.nix b/nixos/modules/issuer.nix index 451901ac3b13959d433b50ad82060336c2cda104..e712ac0d3bbbcafcafd07552e69488e046e3e7e2 100644 --- a/nixos/modules/issuer.nix +++ b/nixos/modules/issuer.nix @@ -4,11 +4,6 @@ cfg = config.services.private-storage-issuer; zkapissuer = pkgs.callPackage ../pkgs/zkapissuer { }; in { - imports = [ - # Give it a good SSH configuration. - ../../nixos/modules/ssh.nix - ]; - options = { services.private-storage-issuer.enable = lib.mkEnableOption "PrivateStorage ZKAP Issuer Service"; services.private-storage-issuer.package = lib.mkOption { diff --git a/nixos/modules/private-storage.nix b/nixos/modules/private-storage.nix index fa5fea837c544e66ae8811a2e3c468a67a18759e..d3bc9e61bb8a805d4432edf7d37d51a9501ecc1e 100644 --- a/nixos/modules/private-storage.nix +++ b/nixos/modules/private-storage.nix @@ -30,8 +30,6 @@ let in { imports = [ - # Give it a good SSH configuration. - ./ssh.nix # Load our tahoe-lafs module. It is configurable in the way I want it to # be configurable. ./tahoe.nix diff --git a/nixos/modules/tests/private-storage.nix b/nixos/modules/tests/private-storage.nix index 59c572fabc6730d2b8351b4bcd37987adab2f88b..2687718bcba3f07cf9e229dadf071489445e4a54 100644 --- a/nixos/modules/tests/private-storage.nix +++ b/nixos/modules/tests/private-storage.nix @@ -111,6 +111,7 @@ in { { config, pkgs, ... }: { imports = [ ../private-storage.nix + ../ssh.nix ]; services.private-storage = { enable = true; @@ -128,6 +129,7 @@ in { { config, pkgs, ... }: { imports = [ ../issuer.nix + ../ssh.nix ]; services.private-storage.sshUsers = sshUsers;