diff --git a/morph/grid/local/README.rst b/morph/grid/local/README.rst index 345547244635734278aa76cb5cd59946f2afd37f..f899c4975bab131e969acc79e8b39dee139b1554 100644 --- a/morph/grid/local/README.rst +++ b/morph/grid/local/README.rst @@ -33,13 +33,6 @@ Use the local development environment install -d ~/.ssh ; vagrant ssh-config >> ~/.ssh/config -5. Edit the generated configuration: Add the ``publicIP`` addresses from ``grid.nix`` to ssh config **Host** match blocks (**not** HostName) so the ``Host`` lines all read like:: - - Host payments 192.168.67.21 - HostName 127.0.0.1 - User vagrant - [...] - Latest Morph honors the ``SSH_CONFIG_FILE`` environment variable (`since 3f90aa88 (March 2020, v 1.5.0) <https://github.com/DBCDK/morph/commit/3f90aa885fac1c29fce9242452fa7c0c505744ef#diff-d155ad793bd62e6ea4c44ba985049ecb13a4f4f32f799791b2bce695a16c0101>`_), so in the future this should get a bit more convenient. 6. Add your SSH key to ``users.nix`` so you'll be able to log in after deploying the new configuration:: @@ -56,4 +49,3 @@ Use the local development environment morph upload-secrets grid.nix You should now be able to log in with the users and keys you set in your ``users.nix`` file. - diff --git a/morph/grid/local/Vagrantfile b/morph/grid/local/Vagrantfile index 7ad95ca872a72e5da6c11b3269e2a824cf8a55f9..fd374a2cc26da63262a16fdf462e235fc5523fd1 100644 --- a/morph/grid/local/Vagrantfile +++ b/morph/grid/local/Vagrantfile @@ -8,7 +8,7 @@ Vagrant.configure("2") do |config| # For a complete reference, please see the online documentation at # https://docs.vagrantup.com. - config.vm.define "payments" do |config| + config.vm.define "payments.localdev" do |config| config.vm.hostname = "payments" config.vm.box = "esselius/nixos" config.vm.box_version = "20.09" @@ -20,7 +20,7 @@ Vagrant.configure("2") do |config| config.vm.provision "shell", inline: "sudo mv /tmp/payments-localdev-ssl/* /var/lib/letsencrypt/live/payments.localdev/" end - config.vm.define "storage1" do |config| + config.vm.define "storage1.localdev" do |config| config.vm.hostname = "storage1" config.vm.box = "esselius/nixos" config.vm.box_version = "20.09" @@ -28,7 +28,7 @@ Vagrant.configure("2") do |config| config.vm.network "private_network", ip: "192.168.67.22" end - config.vm.define "storage2" do |config| + config.vm.define "storage2.localdev" do |config| config.vm.hostname = "storage2" config.vm.box = "esselius/nixos" config.vm.box_version = "20.09" @@ -36,7 +36,7 @@ Vagrant.configure("2") do |config| config.vm.network "private_network", ip: "192.168.67.23" end - config.vm.define "monitoring" do |config| + config.vm.define "monitoring.localdev" do |config| config.vm.hostname = "monitoring" config.vm.box = "esselius/nixos" config.vm.box_version = "20.09" @@ -54,4 +54,3 @@ Vagrant.configure("2") do |config| end end - diff --git a/morph/grid/local/config.json b/morph/grid/local/config.json index 38f00367bf2fa36ad7663c89f7849146783b8515..3d377cc0e1ebbdec0dff421c806c901e2e5ce06d 100644 --- a/morph/grid/local/config.json +++ b/morph/grid/local/config.json @@ -1,4 +1,5 @@ -{ "publicStoragePort": 8898 +{ "domain": "localdev" +, "publicStoragePort": 8898 , "ristrettoSigningKeyPath": "./secrets/ristretto.signing-key" , "stripeSecretKeyPath": "./secrets/stripe.secret" , "monitoringvpnKeyDir": "./secrets/monitoringvpn" diff --git a/morph/grid/local/grid.nix b/morph/grid/local/grid.nix index fdc0cde55be4f1b644c212ce20f6c3e44af8e3df..5345a16198e79dd8c91c8566fb62480ce5cea51a 100644 --- a/morph/grid/local/grid.nix +++ b/morph/grid/local/grid.nix @@ -1,64 +1,73 @@ -# Load the helper function and call it with arguments tailored for the local -# grid. It will make the morph configuration for us. We share this function -# with the production grid and have one fewer possible point of divergence. -import ../../lib/make-grid.nix { - name = "LocalDev"; - config = ./config.json; - nodes = cfg: - let +let + pkgs = import <nixpkgs> { }; + + gridlib = import ../../lib; + rawConfig = pkgs.lib.trivial.importJSON ./config.json; + config = rawConfig // { sshUsers = import ./secrets/users.nix; # Get absolute vpn key directory path, as a string: - monitoringvpnKeyDir = toString ./. + "/${cfg.monitoringvpnKeyDir}"; + monitoringvpnKeyDir = toString ./. + "/${rawConfig.monitoringvpnKeyDir}"; + }; + + payments = { + imports = [ + gridlib.issuer + (gridlib.hardware-virtual ({ publicIPv4 = "192.168.67.21"; })) + (gridlib.customize-issuer (config // { + monitoringvpnIPv4 = "172.23.23.11"; + })) + ]; + }; - # TBD: derive these automatically: - hostsMap = { - "172.23.23.1" = [ "monitoring" "monitoring.monitoringvpn" ]; - "172.23.23.11" = [ "payments" "payments.monitoringvpn" ]; - "172.23.23.12" = [ "storage1" "storage1.monitoringvpn" ]; - "172.23.23.13" = [ "storage2" "storage2.monitoringvpn" ]; - }; - vpnClientIPs = [ "172.23.23.11" "172.23.23.12" "172.23.23.13" ]; - nodeExporterTargets = [ "monitoring" "payments" "storage1" "storage2" ]; + storage1 = { + imports = [ + gridlib.storage + (gridlib.hardware-virtual ({ publicIPv4 = "192.168.67.22"; })) + (gridlib.customize-storage (config // { + monitoringvpnIPv4 = "172.23.23.12"; + stateVersion = "19.09"; + })) + ]; + }; - in { - "payments" = import ../../lib/make-issuer.nix (cfg // rec { - publicIPv4 = "192.168.67.21"; - monitoringvpnIPv4 = "172.23.23.11"; - hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; }); - stateVersion = "19.03"; - inherit monitoringvpnKeyDir; - inherit sshUsers; - }); + storage2 = { + imports = [ + gridlib.storage + (gridlib.hardware-virtual ({ publicIPv4 = "192.168.67.23"; })) + (gridlib.customize-storage (config // { + monitoringvpnIPv4 = "172.23.23.13"; + stateVersion = "19.09"; + })) + ]; + }; - "storage1" = import ../../lib/make-testing.nix (cfg // rec { - publicIPv4 = "192.168.67.22"; - monitoringvpnIPv4 = "172.23.23.12"; - hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; }); - stateVersion = "19.09"; - inherit monitoringvpnKeyDir; - inherit sshUsers; - }); + monitoring = { + imports = [ + gridlib.monitoring + (gridlib.hardware-virtual ({ publicIPv4 = "192.168.67.24"; })) + (gridlib.customize-monitoring { + inherit hostsMap vpnClientIPs nodeExporterTargets; + inherit (config) domain monitoringvpnKeyDir; + monitoringvpnIPv4 = "172.23.23.1"; + stateVersion = "19.09"; + }) + ]; + }; - "storage2" = import ../../lib/make-testing.nix (cfg // rec { - publicIPv4 = "192.168.67.23"; - monitoringvpnIPv4 = "172.23.23.13"; - hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; }); - stateVersion = "19.09"; - inherit monitoringvpnKeyDir; - inherit sshUsers; - }); + # TBD: derive these automatically: + hostsMap = { + "172.23.23.1" = [ "monitoring" "monitoring.monitoringvpn" ]; + "172.23.23.11" = [ "payments" "payments.monitoringvpn" ]; + "172.23.23.12" = [ "storage1" "storage1.monitoringvpn" ]; + "172.23.23.13" = [ "storage2" "storage2.monitoringvpn" ]; + }; + vpnClientIPs = [ "172.23.23.11" "172.23.23.12" "172.23.23.13" ]; + nodeExporterTargets = [ "monitoring" "payments" "storage1" "storage2" ]; - "monitoring" = import ../../lib/make-monitoring.nix (cfg // rec { - publicIPv4 = "192.168.67.24"; - monitoringvpnIPv4 = "172.23.23.1"; - inherit vpnClientIPs; - inherit hostsMap; - inherit nodeExporterTargets; - hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; }); - stateVersion = "19.09"; - inherit monitoringvpnKeyDir; - inherit sshUsers; - }); +in { + network = { + description = "PrivateStorage.io LocalDev Grid"; }; + inherit payments monitoring storage1 storage2; } diff --git a/morph/grid/production/config.json b/morph/grid/production/config.json index ef7dc53649febcd7beb7901bb3608204df197059..21e080d587ae2713a73f756b2b7e078d843b2a95 100644 --- a/morph/grid/production/config.json +++ b/morph/grid/production/config.json @@ -1,4 +1,5 @@ -{ "publicStoragePort": 8898 +{ "domain": "private.storage" +, "publicStoragePort": 8898 , "ristrettoSigningKeyPath": "./secrets/ristretto.signing-key" , "stripeSecretKeyPath": "./secrets/stripe.secret" , "monitoringvpnKeyDir": "./secrets/monitoringvpn" diff --git a/morph/grid/production/grid.nix b/morph/grid/production/grid.nix index fee0c9be6faed47d4a702b5b53c2419cbb677ba6..ae51174b4f15a72ca0c1d1798b067ecb1db64bb3 100644 --- a/morph/grid/production/grid.nix +++ b/morph/grid/production/grid.nix @@ -1,117 +1,111 @@ -# Load the helper function and call it with arguments tailored for the testing -# grid. It will make the morph configuration for us. We share this function -# with the testing grid and have one fewer possible point of divergence. -import ../../lib/make-grid.nix { - name = "Production"; - config = ./config.json; - nodes = cfg: - let - sshUsers = import ./secrets/users.nix; +# See morph/grid/local/grid.nix for additional commentary. +let + pkgs = import <nixpkgs> { }; - # Get absolute vpn key directory path, as a string: - monitoringvpnKeyDir = toString ./. + "/${cfg.monitoringvpnKeyDir}"; + gridlib = import ../../lib; + rawConfig = pkgs.lib.trivial.importJSON ./config.json; + config = rawConfig // { + sshUsers = import ./secrets/users.nix; - # TBD: derive these automatically: - hostsMap = { - "172.23.23.1" = [ "monitoring" "monitoring.monitoringvpn" ]; - "172.23.23.11" = [ "payments" "payments.monitoringvpn" ]; - "172.23.23.21" = [ "storage001" "storage001.monitoringvpn" ]; - "172.23.23.22" = [ "storage002" "storage002.monitoringvpn" ]; - "172.23.23.23" = [ "storage003" "storage003.monitoringvpn" ]; - "172.23.23.24" = [ "storage004" "storage004.monitoringvpn" ]; - "172.23.23.25" = [ "storage005" "storage005.monitoringvpn" ]; - }; - vpnClientIPs = [ - "172.23.23.11" - "172.23.23.21" - "172.23.23.22" - "172.23.23.23" - "172.23.23.24" - "172.23.23.25" - ]; - nodeExporterTargets = [ - "monitoring" - "payments" - "storage001" - "storage002" - "storage003" - "storage004" - "storage005" - ]; + # Get absolute vpn key directory path, as a string: + monitoringvpnKeyDir = toString ./. + "/${rawConfig.monitoringvpnKeyDir}"; + }; - in { - # Here are the hosts that are in this morph network. This is sort of like - # a server manifest. We try to keep as many of the specific details as - # possible out of *this* file so that this file only grows as server count - # grows. If it grows too much, we can load servers by listing contents of - # a directory or reading from another JSON file or some such. For now, - # I'm just manually maintaining these entries. - # - # The name on the left of the `=` is mostly irrelevant but it does provide - # a default hostname for the server if the configuration on the right side - # doesn't specify one. - # - # The names must be unique! - "payments.privatestorage.io" = import ../../lib/make-issuer.nix (cfg // { - publicIPv4 = "18.184.142.208"; - monitoringvpnIPv4 = "172.23.23.11"; - inherit monitoringvpnKeyDir; - inherit sshUsers; - hardware = ../../lib/issuer-aws.nix; - stateVersion = "19.03"; - }); + payments = { + imports = [ + gridlib.issuer + gridlib.hardware-aws + (gridlib.customize-issuer (config // { + monitoringvpnIPv4 = "172.23.23.11"; + })) + ]; + }; - "storage001" = import ../../lib/make-storage.nix (cfg // { - cfg = import ./storage001-config.nix; - inherit sshUsers; - hardware = ./storage001-hardware.nix; - stateVersion = "19.09"; - monitoringvpnIPv4 = "172.23.23.21"; - inherit monitoringvpnKeyDir; - }); - "storage002" = import ../../lib/make-storage.nix (cfg // { - cfg = import ./storage002-config.nix; - inherit sshUsers; - hardware = ./storage002-hardware.nix; - stateVersion = "19.09"; - monitoringvpnIPv4 = "172.23.23.22"; - inherit monitoringvpnKeyDir; - }); - "storage003" = import ../../lib/make-storage.nix (cfg // { - cfg = import ./storage003-config.nix; - inherit sshUsers; - hardware = ./storage003-hardware.nix; + monitoring = { + imports = [ + gridlib.monitoring + gridlib.hardware-aws + (gridlib.customize-monitoring { + inherit hostsMap vpnClientIPs nodeExporterTargets; + inherit (config) domain monitoringvpnKeyDir; + monitoringvpnIPv4 = "172.23.23.1"; stateVersion = "19.09"; - monitoringvpnIPv4 = "172.23.23.23"; - inherit monitoringvpnKeyDir; - }); - "storage004" = import ../../lib/make-storage.nix (cfg // { - cfg = import ./storage004-config.nix; - inherit sshUsers; - hardware = ./storage004-hardware.nix; - stateVersion = "19.09"; - monitoringvpnIPv4 = "172.23.23.24"; - inherit monitoringvpnKeyDir; - }); - "storage005" = import ../../lib/make-storage.nix (cfg // { - cfg = import ./storage005-config.nix; - inherit sshUsers; - hardware = ./storage005-hardware.nix; - stateVersion = "19.03"; - monitoringvpnIPv4 = "172.23.23.25"; - inherit monitoringvpnKeyDir; - }); + }) + ]; + }; + + defineStorageNode = name: { vpnIP, stateVersion }: + let + nodecfg = import "${./.}/${name}-config.nix"; + hardware ="${./.}/${name}-hardware.nix"; + in { + imports = [ + # Get some of the very lowest-level system configuration for this + # node. This isn't all *completely* hardware related. Maybe some + # more factoring is in order, someday. + hardware + + # Slightly awkwardly, enable some of our hardware / network / bootloader options. + ../../../nixos/modules/100tb.nix + + # Get all of the configuration that is common across all storage nodes. + gridlib.storage + + # Then customize the storage system a little bit based on this node's particulars. + (gridlib.customize-storage (config // nodecfg // { + monitoringvpnIPv4 = vpnIP; + inherit stateVersion; + })) + ]; + + # And supply configuration for those hardware / network / bootloader + # options. See the 100tb module for handling of this value. The module + # name is quoted because `1` makes `100tb` look an awful lot like a + # number. + "100tb".config = nodecfg; + }; + + # Define all of the storage nodes for this grid. + storageNodes = builtins.mapAttrs defineStorageNode { + storage001 = { vpnIP = "172.23.23.21"; stateVersion = "19.09"; }; + storage002 = { vpnIP = "172.23.23.22"; stateVersion = "19.09"; }; + storage003 = { vpnIP = "172.23.23.23"; stateVersion = "19.09"; }; + storage004 = { vpnIP = "172.23.23.24"; stateVersion = "19.09"; }; + storage005 = { vpnIP = "172.23.23.25"; stateVersion = "19.03"; }; + }; + + # TBD: derive these automatically: + hostsMap = { + "172.23.23.1" = [ "monitoring" "monitoring.monitoringvpn" ]; + "172.23.23.11" = [ "payments" "payments.monitoringvpn" ]; + "172.23.23.21" = [ "storage001" "storage001.monitoringvpn" ]; + "172.23.23.22" = [ "storage002" "storage002.monitoringvpn" ]; + "172.23.23.23" = [ "storage003" "storage003.monitoringvpn" ]; + "172.23.23.24" = [ "storage004" "storage004.monitoringvpn" ]; + "172.23.23.25" = [ "storage005" "storage005.monitoringvpn" ]; + }; + vpnClientIPs = [ + "172.23.23.11" + "172.23.23.21" + "172.23.23.22" + "172.23.23.23" + "172.23.23.24" + "172.23.23.25" + ]; + nodeExporterTargets = [ + "monitoring" + "payments" + "storage001" + "storage002" + "storage003" + "storage004" + "storage005" + ]; - "monitoring" = import ../../lib/make-monitoring.nix (cfg // { - publicIPv4 = "monitoring.private.storage"; - monitoringvpnIPv4 = "172.23.23.1"; - inherit monitoringvpnKeyDir; - inherit vpnClientIPs; - inherit hostsMap; - inherit nodeExporterTargets; - hardware = ../../lib/issuer-aws.nix; - stateVersion = "19.09"; - inherit sshUsers; - }); +in { + network = { + description = "PrivateStorage.io Production Grid"; }; -} + inherit payments; + inherit monitoring; +} // storageNodes diff --git a/morph/grid/production/storage001-hardware.nix b/morph/grid/production/storage001-hardware.nix index 4cd9f59b76dd77b6e6e85709b3fbee771677b641..b2ca97c1db1b9721b93f2662d6e8d34189d5a0ab 100644 --- a/morph/grid/production/storage001-hardware.nix +++ b/morph/grid/production/storage001-hardware.nix @@ -12,6 +12,7 @@ boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; + boot.kernel.sysctl = { "vm.swappiness" = 0; }; fileSystems."/" = { device = "/dev/disk/by-uuid/f72c1f46-6723-45bf-9ef7-92f31cc37589"; @@ -30,9 +31,12 @@ fsType = "zfs"; }; - swapDevices = - [ { device = "/dev/disk/by-uuid/f986a811-4912-4e9a-8bc3-01cb6926c4c6"; } - ]; + swapDevices = [ { + device = "/var/swapfile"; + size = 8192; # megabytes + randomEncryption = true; + } ]; + nix.maxJobs = lib.mkDefault 24; powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; diff --git a/morph/grid/production/storage002-hardware.nix b/morph/grid/production/storage002-hardware.nix index 4fc3a4097e05ec8c38c86db6bfce92e2a1af6f35..2f354ad29930f048f7eb20b54a1504ed87db85a1 100644 --- a/morph/grid/production/storage002-hardware.nix +++ b/morph/grid/production/storage002-hardware.nix @@ -12,6 +12,7 @@ boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; + boot.kernel.sysctl = { "vm.swappiness" = 0; }; fileSystems."/" = { device = "/dev/disk/by-uuid/0e92ada9-effb-42e2-a26a-9cdb529bcdc7"; @@ -30,9 +31,11 @@ fsType = "ext4"; }; - swapDevices = - [ { device = "/dev/disk/by-uuid/f762b5e2-bbdd-4a02-bbd9-0bf6b11e0ab5"; } - ]; + swapDevices = [ { + device = "/var/swapfile"; + size = 8192; # megabytes + randomEncryption = true; + } ]; nix.maxJobs = lib.mkDefault 24; powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; diff --git a/morph/grid/production/storage003-hardware.nix b/morph/grid/production/storage003-hardware.nix index 9882f5372cecd52794e1500bdef30e367008496e..d8ffe5d59fb39ba4a9c6b1b73313f199a2ed980b 100644 --- a/morph/grid/production/storage003-hardware.nix +++ b/morph/grid/production/storage003-hardware.nix @@ -13,6 +13,7 @@ boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; boot.supportedFilesystems = [ "zfs" ]; + boot.kernel.sysctl = { "vm.swappiness" = 0; }; fileSystems."/" = { device = "/dev/disk/by-uuid/240fc1f6-cd55-48a3-ac80-5b3550a32ef5"; @@ -31,7 +32,11 @@ fsType = "zfs"; }; - swapDevices = [ ]; + swapDevices = [ { + device = "/var/swapfile"; + size = 8192; # megabytes + randomEncryption = true; + } ]; nix.maxJobs = lib.mkDefault 24; powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; diff --git a/morph/grid/production/storage004-hardware.nix b/morph/grid/production/storage004-hardware.nix index 07de74e20ef58ab474b02248bcb6eed6189e1079..1fe78a76e813605d8e181d5a858062f77114ba38 100644 --- a/morph/grid/production/storage004-hardware.nix +++ b/morph/grid/production/storage004-hardware.nix @@ -12,6 +12,7 @@ boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; + boot.kernel.sysctl = { "vm.swappiness" = 0; }; fileSystems."/" = { device = "/dev/disk/by-uuid/d628122e-05d9-4212-b6a5-4b9516d85dbe"; @@ -25,7 +26,11 @@ fsType = "zfs"; }; - swapDevices = [ ]; + swapDevices = [ { + device = "/var/swapfile"; + size = 8192; # megabytes + randomEncryption = true; + } ]; nix.maxJobs = lib.mkDefault 32; powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; diff --git a/morph/grid/production/storage005-hardware.nix b/morph/grid/production/storage005-hardware.nix index 9a5ad02725e30b00619978035772d60bec9fcb8a..e8f7b6391b4cb1c8d3e6059c1fd09512a0cc370b 100644 --- a/morph/grid/production/storage005-hardware.nix +++ b/morph/grid/production/storage005-hardware.nix @@ -12,6 +12,7 @@ boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; + boot.kernel.sysctl = { "vm.swappiness" = 0; }; fileSystems."/" = { device = "/dev/disk/by-uuid/2653c6bb-396f-4911-b9ff-b68de8f9715d"; @@ -30,7 +31,11 @@ fsType = "zfs"; }; - swapDevices = [ ]; + swapDevices = [ { + device = "/var/swapfile"; + size = 8192; # megabytes + randomEncryption = true; + } ]; nix.maxJobs = lib.mkDefault 32; powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; diff --git a/morph/grid/testing/config.json b/morph/grid/testing/config.json index a44b465f7f293f9d70c369a076c30b6cf810924f..c069bbed531e63a425e16a1838dedbfd2f17374d 100644 --- a/morph/grid/testing/config.json +++ b/morph/grid/testing/config.json @@ -1,4 +1,5 @@ -{ "publicStoragePort": 8898 +{ "domain": "privatestorage-staging.com" +, "publicStoragePort": 8898 , "ristrettoSigningKeyPath": "./secrets/ristretto.signing-key" , "stripeSecretKeyPath": "./secrets/stripe.secret" , "monitoringvpnKeyDir": "./secrets/monitoringvpn" diff --git a/morph/grid/testing/grid.nix b/morph/grid/testing/grid.nix index e31a28f2eb7817f393f4e8b6b71972b7fd2f79f1..19eefd9d50d49094a0bcf87698f8c8091032e1fa 100644 --- a/morph/grid/testing/grid.nix +++ b/morph/grid/testing/grid.nix @@ -1,54 +1,62 @@ -# Load the helper function and call it with arguments tailored for the testing -# grid. It will make the morph configuration for us. We share this function -# with the production grid and have one fewer possible point of divergence. -import ../../lib/make-grid.nix { - name = "Testing"; - config = ./config.json; - nodes = cfg: - let +# See morph/grid/local/grid.nix for additional commentary. +let + pkgs = import <nixpkgs> { }; + + gridlib = import ../../lib; + rawConfig = pkgs.lib.trivial.importJSON ./config.json; + config = rawConfig // { sshUsers = import ./secrets/users.nix; # Get absolute vpn key directory path, as a string: - monitoringvpnKeyDir = toString ./. + "/${cfg.monitoringvpnKeyDir}"; + monitoringvpnKeyDir = toString ./. + "/${rawConfig.monitoringvpnKeyDir}"; + }; - # TBD: derive these automatically: - hostsMap = { - "172.23.23.1" = [ "monitoring" "monitoring.monitoringvpn" ]; - "172.23.23.11" = [ "payments" "payments.monitoringvpn" ]; - "172.23.23.12" = [ "storage001" "storage001.monitoringvpn" ]; - }; - vpnClientIPs = [ "172.23.23.11" "172.23.23.12" ]; - nodeExporterTargets = [ "monitoring" "payments" "storage001" ]; + payments = { + imports = [ + gridlib.issuer + gridlib.hardware-aws + (gridlib.customize-issuer (config // { + monitoringvpnIPv4 = "172.23.23.11"; + })) + ]; + }; - in { - "payments" = import ../../lib/make-issuer.nix (cfg // { - publicIPv4 = "18.194.183.13"; - monitoringvpnIPv4 = "172.23.23.11"; - inherit monitoringvpnKeyDir; - inherit sshUsers; - hardware = ../../lib/issuer-aws.nix; - stateVersion = "19.03"; - }); + storage001 = { + imports = [ + gridlib.storage + ./testing001-hardware.nix + (gridlib.customize-storage (config // { + monitoringvpnIPv4 = "172.23.23.12"; + stateVersion = "19.03"; + })) + ]; + }; - "storage001" = import ../../lib/make-testing.nix (cfg // { - publicIPv4 = "3.120.26.190"; - monitoringvpnIPv4 = "172.23.23.12"; - inherit monitoringvpnKeyDir; - inherit sshUsers; - hardware = ./testing001-hardware.nix; - stateVersion = "19.03"; - }); + monitoring = { + imports = [ + gridlib.monitoring + gridlib.hardware-aws + (gridlib.customize-monitoring { + inherit hostsMap vpnClientIPs nodeExporterTargets; + inherit (config) domain monitoringvpnKeyDir; + monitoringvpnIPv4 = "172.23.23.1"; + stateVersion = "19.09"; + }) + ]; + }; + + # TBD: derive these automatically: + hostsMap = { + "172.23.23.1" = [ "monitoring" "monitoring.monitoringvpn" ]; + "172.23.23.11" = [ "payments" "payments.monitoringvpn" ]; + "172.23.23.12" = [ "storage001" "storage001.monitoringvpn" ]; + }; + vpnClientIPs = [ "172.23.23.11" "172.23.23.12" ]; + nodeExporterTargets = [ "monitoring" "payments" "storage001" ]; - "monitoring" = import ../../lib/make-monitoring.nix (cfg // { - publicIPv4 = "18.156.171.217"; - monitoringvpnIPv4 = "172.23.23.1"; - inherit monitoringvpnKeyDir; - inherit vpnClientIPs; - inherit hostsMap; - inherit nodeExporterTargets; - hardware = ../../lib/issuer-aws.nix; - stateVersion = "19.09"; - inherit sshUsers; - }); +in { + network = { + description = "PrivateStorage.io Testing Grid"; }; + inherit payments monitoring storage001; } diff --git a/morph/grid/testing/testing001-hardware.nix b/morph/grid/testing/testing001-hardware.nix index 958a247862a7e4bb2581e7d1bb85cc0f85f3ea24..dd2f9733796875bb9d8a549538cba5743a8727a3 100644 --- a/morph/grid/testing/testing001-hardware.nix +++ b/morph/grid/testing/testing001-hardware.nix @@ -1,6 +1,13 @@ { imports = [ <nixpkgs/nixos/modules/virtualisation/amazon-image.nix> ]; ec2.hvm = true; + boot.kernel.sysctl = { "vm.swappiness" = 0; }; + swapDevices = [ { + device = "/var/swapfile"; + size = 8192; # megabytes + randomEncryption = true; + } ]; + boot.supportedFilesystems = [ "zfs" ]; networking.hostId = "10000000"; diff --git a/morph/lib/customize-issuer.nix b/morph/lib/customize-issuer.nix new file mode 100644 index 0000000000000000000000000000000000000000..28edb72e7e0b74879e9e676113c327f50b040d40 --- /dev/null +++ b/morph/lib/customize-issuer.nix @@ -0,0 +1,88 @@ +# Define a function which returns a value which fills in all the holes left by +# ``issuer.nix``. +{ + # 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. + ristrettoSigningKeyPath + + # 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. +, stripeSecretKeyPath + + # A path on the deployment system to 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 VPN private key for the + # corresponding host. It must also contain ``server.pub`` and + # ``preshared.key`` holding the VPN server's public key and the pre-shared + # key, respectively. All of these things are used as the sources of various + # VPN-related morph secrets. +, monitoringvpnKeyDir + + # A string giving the IP address and port number (":"-separated) of the VPN + # server. +, monitoringvpnEndpoint + + # A string giving the VPN IPv4 address for this system. +, monitoringvpnIPv4 + + # A string giving the domain name associated with this grid. This is meant + # to be combined with the hostname for this system to produce a + # fully-qualified domain name. For example, an issuer might have "payments" + # as its hostname and belong to a grid with the domain + # "example-grid.invalid". This ``domain`` parameter should have the value + # ``"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 + + # A list of strings giving the domain names that point at this issuer + # system. These will all be included in Let's Encrypt certificate. +, issuerDomains + + # A list of strings giving CORS Origins will the issuer will be configured + # to allow. +, allowedChargeOrigins +, ... +}: +{ config, ... }: { + # 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 + # being configured and using variable names complicates a lot of things). + # Instead, just tell morph how to reach the node here - by using its fully + # qualified domain name. + deployment.targetHost = "${config.networking.hostName}.${config.networking.domain}"; + + deployment.secrets = { + "ristretto-signing-key".source = ristrettoSigningKeyPath; + "stripe-secret-key".source = stripeSecretKeyPath; + "monitoringvpn-secret-key".source = "${monitoringvpnKeyDir}/${monitoringvpnIPv4}.key"; + "monitoringvpn-preshared-key".source = "${monitoringvpnKeyDir}/preshared.key"; + }; + + networking.domain = domain; + + services.private-storage.sshUsers = sshUsers; + services.private-storage.monitoring.vpn.client = { + enable = true; + ip = monitoringvpnIPv4; + endpoint = monitoringvpnEndpoint; + endpointPublicKeyFile = "${monitoringvpnKeyDir}/server.pub"; + }; + + services.private-storage-issuer = { + inherit letsEncryptAdminEmail allowedChargeOrigins; + domains = issuerDomains; + }; + + system.stateVersion = "19.03"; +} diff --git a/morph/lib/customize-monitoring.nix b/morph/lib/customize-monitoring.nix new file mode 100644 index 0000000000000000000000000000000000000000..c50eb5062b35480d0b3d296cfaea8abd999f36c5 --- /dev/null +++ b/morph/lib/customize-monitoring.nix @@ -0,0 +1,57 @@ +# Define a function which returns a value which fills in all the holes left by +# ``monitoring.nix``. +{ + # A set mapping VPN IP addresses as strings to lists of hostnames as + # strings. The system's ``/etc/hosts`` will be populated with this + # information. Apart from helping with normal forward resolution, this + # *also* gives us reverse resolution from the VPN IPs to hostnames which + # allows Grafana to show us hostnames instead of VPN IP addresses. + hostsMap + + # See ``customize-issuer.nix``. +, monitoringvpnKeyDir +, monitoringvpnIPv4 +, domain + + # A list of VPN IP addresses as strings indicating which clients will be + # allowed onto the VPN. +, vpnClientIPs + + # A list of VPN clients (IP addresses or hostnames) as strings indicating + # which nodes to scrape "nodeExporter" metrics from. +, nodeExporterTargets + + # A list of VPN clients (IP addresses or hostnames) as strings indicating + # which nodes to scrape "nginxExporter" metrics from. +, nginxExporterTargets ? [] + + # A string giving the NixOS state version for the system. +, stateVersion +, ... +}: +{ config, ... }: { + # See customize-issuer.nix for an explanatoin of targetHost value. + deployment.targetHost = "${config.networking.hostName}.${config.networking.domain}"; + + deployment.secrets = { + "monitoringvpn-private-key".source = "${monitoringvpnKeyDir}/server.key"; + "monitoringvpn-preshared-key".source = "${monitoringvpnKeyDir}/preshared.key"; + }; + + networking.domain = domain; + networking.hosts = hostsMap; + + services.private-storage.monitoring.vpn.server = { + enable = true; + ip = monitoringvpnIPv4; + inherit vpnClientIPs; + pubKeysPath = monitoringvpnKeyDir; + }; + + services.private-storage.monitoring.prometheus = { + inherit nodeExporterTargets; + inherit nginxExporterTargets; + }; + + system.stateVersion = stateVersion; +} diff --git a/morph/lib/customize-storage.nix b/morph/lib/customize-storage.nix new file mode 100644 index 0000000000000000000000000000000000000000..0a08743633126b5898e61a877e62a7b58314b34e --- /dev/null +++ b/morph/lib/customize-storage.nix @@ -0,0 +1,47 @@ +# Define a function which returns a value which fills in all the holes left by +# ``storage.nix``. +{ + # See ``customize-issuer.nix`` + ristrettoSigningKeyPath +, monitoringvpnKeyDir +, monitoringvpnEndpoint +, monitoringvpnIPv4 +, sshUsers +, domain + + # An integer giving the value of a single pass in byte×months. +, passValue + + # An integer giving the port number to include in Tahoe storage service + # advertisements and on which to listen for storage connections. +, publicStoragePort + + # A string giving the NixOS state version for the system. +, stateVersion +, ... +}: +{ config, ... }: { + # See customize-issuer.nix for an explanatoin of targetHost value. + deployment.targetHost = "${config.networking.hostName}.${config.networking.domain}"; + + deployment.secrets = { + "ristretto-signing-key".source = ristrettoSigningKeyPath; + "monitoringvpn-secret-key".source = "${monitoringvpnKeyDir}/${monitoringvpnIPv4}.key"; + "monitoringvpn-preshared-key".source = "${monitoringvpnKeyDir}/preshared.key"; + }; + + networking.domain = domain; + + services.private-storage = { + inherit sshUsers passValue publicStoragePort; + }; + + services.private-storage.monitoring.vpn.client = { + enable = true; + ip = monitoringvpnIPv4; + endpoint = monitoringvpnEndpoint; + endpointPublicKeyFile = "${monitoringvpnKeyDir}/server.pub"; + }; + + system.stateVersion = stateVersion; +} diff --git a/morph/lib/default.nix b/morph/lib/default.nix new file mode 100644 index 0000000000000000000000000000000000000000..bdd92f4bfe52eba2e19df3ac73a087a4af4a53dc --- /dev/null +++ b/morph/lib/default.nix @@ -0,0 +1,16 @@ +# Gather up the grid library functionality and present it in a (somewhat) +# coherent public interface. Application code should prefer these names over +# directly importing the source files in this directory. +{ + hardware-aws = import ./issuer-aws.nix; + hardware-virtual = import ./hardware-virtual.nix; + + issuer = import ./issuer.nix; + customize-issuer = import ./customize-issuer.nix; + + storage = import ./storage.nix; + customize-storage = import ./customize-storage.nix; + + monitoring = import ./monitoring.nix; + customize-monitoring = import ./customize-monitoring.nix; +} diff --git a/morph/grid/local/virtual-hardware.nix b/morph/lib/hardware-virtual.nix similarity index 95% rename from morph/grid/local/virtual-hardware.nix rename to morph/lib/hardware-virtual.nix index d5e9067bd5f3b3ca2ea1bb46746253fa39b25cf6..cf1582792bff77c491210ee5e91f99bfbffbf9f3 100644 --- a/morph/grid/local/virtual-hardware.nix +++ b/morph/lib/hardware-virtual.nix @@ -11,6 +11,7 @@ boot.initrd.availableKernelModules = [ "ata_piix" "sd_mod" "sr_mod" ]; boot.initrd.kernelModules = [ ]; + boot.kernel.sysctl = { "vm.swappiness" = 0; }; boot.kernelModules = [ ]; boot.extraModulePackages = [ ]; @@ -33,4 +34,3 @@ # We want to push packages with morph without having to sign them nix.trustedUsers = [ "@wheel" "root" "vagrant" ]; } - diff --git a/morph/lib/issuer-aws.nix b/morph/lib/issuer-aws.nix index b4d4757ad5597b69363ef12e4297aec80913f00e..3febd796b3eceb5a2da73e4874d52d50767da947 100644 --- a/morph/lib/issuer-aws.nix +++ b/morph/lib/issuer-aws.nix @@ -1,4 +1,15 @@ -{ +{ lib, ... }: { imports = [ <nixpkgs/nixos/modules/virtualisation/amazon-image.nix> ]; + + # amazon-image.nix isn't quite aware of nvme-attached storage so give it a + # little help configuring grub. + boot.loader.grub.device = lib.mkForce "/dev/nvme0n1"; + ec2.hvm = true; + boot.kernel.sysctl = { "vm.swappiness" = 0; }; + swapDevices = [ { + device = "/var/swapfile"; + size = 8192; # megabytes + randomEncryption = true; + } ]; } diff --git a/morph/lib/issuer.nix b/morph/lib/issuer.nix new file mode 100644 index 0000000000000000000000000000000000000000..417ef7965ea0120322995059fcca7a5a9afe2543 --- /dev/null +++ b/morph/lib/issuer.nix @@ -0,0 +1,56 @@ +# 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``. +rec { + deployment = { + secrets = { + "ristretto-signing-key" = { + destination = "/run/keys/ristretto.signing-key"; + owner.user = "root"; + owner.group = "root"; + permissions = "0400"; + action = ["sudo" "systemctl" "restart" "zkapissuer.service"]; + }; + "stripe-secret-key" = { + destination = "/run/keys/stripe.secret-key"; + owner.user = "root"; + owner.group = "root"; + permissions = "0400"; + action = ["sudo" "systemctl" "restart" "zkapissuer.service"]; + }; + + "monitoringvpn-secret-key" = { + destination = "/run/keys/monitoringvpn/client.key"; + owner.user = "root"; + owner.group = "root"; + permissions = "0400"; + action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; + }; + "monitoringvpn-preshared-key" = { + destination = "/run/keys/monitoringvpn/preshared.key"; + owner.user = "root"; + owner.group = "root"; + permissions = "0400"; + action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; + }; + }; + }; + + imports = [ + ../../nixos/modules/issuer.nix + ../../nixos/modules/monitoring/vpn/client.nix + ../../nixos/modules/monitoring/exporters/node.nix + ]; + + services.private-storage-issuer = { + enable = true; + tls = true; + ristrettoSigningKeyPath = deployment.secrets.ristretto-signing-key.destination; + stripeSecretKeyPath = deployment.secrets.stripe-secret-key.destination; + database = "SQLite3"; + databasePath = "/var/db/vouchers.sqlite3"; + }; +} diff --git a/morph/lib/make-grid.nix b/morph/lib/make-grid.nix deleted file mode 100644 index de10df1e9a62ee0ac7fde98070743ee4a9cf484b..0000000000000000000000000000000000000000 --- a/morph/lib/make-grid.nix +++ /dev/null @@ -1,19 +0,0 @@ -# Define a function for making a morph configuration for a storage grid. It -# takes two arguments. A string like "Production" giving the name of the grid -# and a function that takes the grid configuration as an argument and returns -# a set of nodes specifying the addresses and NixOS configurations for each -# server in the morph network. -{ name, config, nodes }: -let - pkgs = import <nixpkgs> { }; - # Load our JSON configuration for later use. - cfg = pkgs.lib.trivial.importJSON config; -in -{ - network = { - # Make all of the hosts in this network use the nixpkgs we pinned above. - inherit pkgs; - # This is just for human consumption as far as I can tell. - description = "PrivateStorage.io ${name} Grid"; - }; -} // (nodes cfg) diff --git a/morph/lib/make-issuer.nix b/morph/lib/make-issuer.nix deleted file mode 100644 index bbdf0cebbf770738e9ccb997daec75e58df021b5..0000000000000000000000000000000000000000 --- a/morph/lib/make-issuer.nix +++ /dev/null @@ -1,91 +0,0 @@ -{ hardware -, ristrettoSigningKeyPath -, stripeSecretKeyPath -, issuerDomains -, letsEncryptAdminEmail -, allowedChargeOrigins -, sshUsers -, stateVersion -, publicIPv4 -, monitoringvpnKeyDir ? null -, monitoringvpnIPv4 ? null -, monitoringvpnEndpoint ? null -, ... -}: let - - enableVpn = monitoringvpnKeyDir != null && - monitoringvpnIPv4 != null && - monitoringvpnEndpoint != null; - - vpnSecrets = if !enableVpn then {} else { - "monitoringvpn-secret-key" = { - source = monitoringvpnKeyDir + "/${monitoringvpnIPv4}.key"; - destination = "/run/keys/monitoringvpn/client.key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; - }; - "monitoringvpn-preshared-key" = { - source = monitoringvpnKeyDir + "/preshared.key"; - destination = "/run/keys/monitoringvpn/preshared.key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; - }; - }; - -in rec { - deployment = { - targetHost = publicIPv4; - - secrets = { - "ristretto-signing-key" = { - source = ristrettoSigningKeyPath; - destination = "/run/keys/ristretto.signing-key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "zkapissuer.service"]; - }; - "stripe-secret-key" = { - source = stripeSecretKeyPath; - destination = "/run/keys/stripe.secret-key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "zkapissuer.service"]; - }; - } // vpnSecrets; - }; - - imports = [ - hardware - ../../nixos/modules/issuer.nix - ../../nixos/modules/monitoring/vpn/client.nix - ../../nixos/modules/monitoring/exporters/node.nix - ]; - - services.private-storage.sshUsers = sshUsers; - services.private-storage-issuer = { - enable = true; - tls = true; - ristrettoSigningKeyPath = deployment.secrets.ristretto-signing-key.destination; - stripeSecretKeyPath = deployment.secrets.stripe-secret-key.destination; - database = "SQLite3"; - databasePath = "/var/db/vouchers.sqlite3"; - inherit letsEncryptAdminEmail; - domains = issuerDomains; - inherit allowedChargeOrigins; - }; - - system.stateVersion = stateVersion; - - services.private-storage.monitoring.vpn.client = if !enableVpn then {} else { - enable = true; - ip = monitoringvpnIPv4; - endpoint = monitoringvpnEndpoint; - endpointPublicKeyFile = monitoringvpnKeyDir + "/server.pub"; - }; -} diff --git a/morph/lib/make-monitoring.nix b/morph/lib/make-monitoring.nix deleted file mode 100644 index 592a859657e624e8fdf5632f8144c5acc6919e8c..0000000000000000000000000000000000000000 --- a/morph/lib/make-monitoring.nix +++ /dev/null @@ -1,77 +0,0 @@ -{ publicIPv4 -, hardware -, publicStoragePort -, ristrettoSigningKeyPath -, passValue -, sshUsers -, stateVersion -, monitoringvpnIPv4 ? null -, monitoringvpnKeyDir ? null -, vpnClientIPs ? null -, nodeExporterTargets ? [] -, nginxExporterTargets ? [] -, hostsMap ? {} -, ... }: let - - enableVpn = monitoringvpnKeyDir != null && - monitoringvpnIPv4 != null && - vpnClientIPs != null; - - vpnSecrets = if !enableVpn then {} else { - "monitoringvpn-private-key" = { - source = monitoringvpnKeyDir + "/server.key"; - destination = "/run/keys/monitoringvpn/server.key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; - }; - "monitoringvpn-preshared-key" = { - source = monitoringvpnKeyDir + "/preshared.key"; - destination = "/run/keys/monitoringvpn/preshared.key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; - }; - }; - -in rec { - - deployment = { - targetHost = publicIPv4; - secrets = vpnSecrets; - }; - - imports = [ - hardware - ../../nixos/modules/monitoring/vpn/server.nix - ../../nixos/modules/monitoring/server/grafana.nix - ../../nixos/modules/monitoring/server/prometheus.nix - ../../nixos/modules/monitoring/exporters/node.nix - # Loki 0.3.0 from Nixpkgs 19.09 is too old and does not work: - # ../../nixos/modules/monitoring/server/loki.nix - ]; - - services.private-storage.monitoring.vpn.server = if !enableVpn then {} else { - enable = true; - ip = monitoringvpnIPv4; - inherit vpnClientIPs; - pubKeysPath = monitoringvpnKeyDir; - }; - - services.private-storage.monitoring.grafana = { - domain = "monitoring.private.storage"; - prometheusUrl = "http://localhost:9090/"; - lokiUrl = "http://localhost:3100/"; - }; - - services.private-storage.monitoring.prometheus = { - inherit nodeExporterTargets; - inherit nginxExporterTargets; - }; - - system.stateVersion = stateVersion; - - networking.hosts = hostsMap; -} diff --git a/morph/lib/make-storage.nix b/morph/lib/make-storage.nix deleted file mode 100644 index 6619336d758f69a677e9178592357480aed3f0c8..0000000000000000000000000000000000000000 --- a/morph/lib/make-storage.nix +++ /dev/null @@ -1,109 +0,0 @@ -# Define the function that defines the node. -{ cfg # Get the configuration that's specific to this node. -, hardware # The path to the hardware configuration for this node. -, publicStoragePort # The storage port number on which to accept connections. -, ristrettoSigningKeyPath # The *local* path to the Ristretto signing key file. -, passValue # Bytes component of size×time value of passes. -, sshUsers # Users for which to configure SSH access to this node. -, stateVersion # The value for system.stateVersion on this node. - # This value determines the NixOS release with - # which your system is to be compatible, in order - # to avoid breaking some software such as - # database servers. You should change this only - # after NixOS release notes say you should. -, monitoringvpnKeyDir ? null # The directory that holds the VPN keys. -, monitoringvpnIPv4 ? null # This node's IP in the monitoring VPN. -, monitoringvpnEndpoint ? null # The VPN server and port. -, ... -}: let - - enableVpn = monitoringvpnKeyDir != null && - monitoringvpnIPv4 != null && - monitoringvpnEndpoint != null; - - vpnSecrets = if !enableVpn then {} else { - "monitoringvpn-secret-key" = { - source = monitoringvpnKeyDir + "/${monitoringvpnIPv4}.key"; - destination = "/run/keys/monitoringvpn/client.key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; - }; - "monitoringvpn-preshared-key" = { - source = monitoringvpnKeyDir + "/preshared.key"; - destination = "/run/keys/monitoringvpn/preshared.key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; - }; - }; - -in rec { - deployment = { - targetHost = cfg.publicIPv4; - - secrets = { - "ristretto-signing-key" = { - source = ristrettoSigningKeyPath; - destination = "/run/keys/ristretto.signing-key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - # Service name here matches the name defined by our tahoe-lafs nixos - # module. It would be nice to not have to hard-code it here. Can we - # extract it from the tahoe-lafs nixos module somehow? - action = ["sudo" "systemctl" "restart" "tahoe.storage.service"]; - }; - } // vpnSecrets; - }; - - # Any extra NixOS modules to load on this server. - imports = [ - # Include the results of the hardware scan. - hardware - # Configure it as a system operated by 100TB. - ../../nixos/modules/100tb.nix - # Bring in our module for configuring the Tahoe-LAFS service and other - # Private Storage-specific things. - ../../nixos/modules/private-storage.nix - # Connect to the monitoringvpn. - ../../nixos/modules/monitoring/vpn/client.nix - # Expose base system metrics over the monitoringvpn. - ../../nixos/modules/monitoring/exporters/node.nix - ]; - - # Pass the configuration specific to this host to the 100TB module to be - # expanded into a complete system configuration. See the 100tb module for - # handling of this value. - # - # The module name is quoted because `1` makes `100tb` look an awful lot like - # it should be a number. - "100tb".config = cfg; - - # Turn on the Private Storage (Tahoe-LAFS) service. - services.private-storage = { - # Yep. Turn it on. - enable = true; - # Get the public IPv4 address from the node configuration. - inherit (cfg) publicIPv4; - # And the port to operate on is specified via parameter. - inherit publicStoragePort; - # Give it the Ristretto signing key, too, to support authorization. - ristrettoSigningKeyPath = deployment.secrets.ristretto-signing-key.destination; - # Assign the configured pass value. - inherit passValue; - # It gets the users, too. - inherit sshUsers; - }; - - system.stateVersion = stateVersion; - - services.private-storage.monitoring.vpn.client = if !enableVpn then {} else { - enable = true; - ip = monitoringvpnIPv4; - endpoint = monitoringvpnEndpoint; - endpointPublicKeyFile = monitoringvpnKeyDir + "/server.pub"; - }; -} diff --git a/morph/lib/make-testing.nix b/morph/lib/make-testing.nix deleted file mode 100644 index 3f6e767db5ee734a8ca2314b216d4fa602c01907..0000000000000000000000000000000000000000 --- a/morph/lib/make-testing.nix +++ /dev/null @@ -1,80 +0,0 @@ -{ publicIPv4 -, hardware -, publicStoragePort -, ristrettoSigningKeyPath -, passValue -, sshUsers -, stateVersion -, monitoringvpnKeyDir ? null -, monitoringvpnIPv4 ? null -, monitoringvpnEndpoint ? null -, ... }: let - - enableVpn = monitoringvpnKeyDir != null && - monitoringvpnIPv4 != null && - monitoringvpnEndpoint != null; - - vpnSecrets = if !enableVpn then {} else { - "monitoringvpn-secret-key" = { - source = monitoringvpnKeyDir + "/${monitoringvpnIPv4}.key"; - destination = "/run/keys/monitoringvpn/client.key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; - }; - "monitoringvpn-preshared-key" = { - source = monitoringvpnKeyDir + "/preshared.key"; - destination = "/run/keys/monitoringvpn/preshared.key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; - }; - }; - -in rec { - - deployment = { - targetHost = publicIPv4; - - secrets = { - "ristretto-signing-key" = { - source = ristrettoSigningKeyPath; - destination = "/run/keys/ristretto.signing-key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - # Service name here matches the name defined by our tahoe-lafs nixos - # module. It would be nice to not have to hard-code it here. Can we - # extract it from the tahoe-lafs nixos module somehow? - action = ["sudo" "systemctl" "restart" "tahoe.storage.service"]; - }; - } // vpnSecrets; - }; - - imports = [ - hardware - ../../nixos/modules/private-storage.nix - ../../nixos/modules/monitoring/vpn/client.nix - ../../nixos/modules/monitoring/exporters/node.nix - ]; - - services.private-storage = - { enable = true; - inherit publicIPv4; - inherit publicStoragePort; - ristrettoSigningKeyPath = deployment.secrets.ristretto-signing-key.destination; - inherit passValue; - inherit sshUsers; - }; - - system.stateVersion = stateVersion; - - services.private-storage.monitoring.vpn.client = if !enableVpn then {} else { - enable = true; - ip = monitoringvpnIPv4; - endpoint = monitoringvpnEndpoint; - endpointPublicKeyFile = monitoringvpnKeyDir + "/server.pub"; - }; -} diff --git a/morph/lib/monitoring.nix b/morph/lib/monitoring.nix new file mode 100644 index 0000000000000000000000000000000000000000..b48820f0941694869fdda06e724ba1ae714b5993 --- /dev/null +++ b/morph/lib/monitoring.nix @@ -0,0 +1,37 @@ +# Similar to ``issuer.nix`` but for a "monitoring"-type system. Holes are +# filled by ``customize-monitoring.nix``. +rec { + deployment = { + secrets = { + "monitoringvpn-private-key" = { + destination = "/run/keys/monitoringvpn/server.key"; + owner.user = "root"; + owner.group = "root"; + permissions = "0400"; + action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; + }; + "monitoringvpn-preshared-key" = { + destination = "/run/keys/monitoringvpn/preshared.key"; + owner.user = "root"; + owner.group = "root"; + permissions = "0400"; + action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; + }; + }; + }; + + imports = [ + ../../nixos/modules/monitoring/vpn/server.nix + ../../nixos/modules/monitoring/server/grafana.nix + ../../nixos/modules/monitoring/server/prometheus.nix + ../../nixos/modules/monitoring/exporters/node.nix + # Loki 0.3.0 from Nixpkgs 19.09 is too old and does not work: + # ../../nixos/modules/monitoring/server/loki.nix + ]; + + services.private-storage.monitoring.grafana = { + domain = "monitoring.private.storage"; + prometheusUrl = "http://localhost:9090/"; + lokiUrl = "http://localhost:3100/"; + }; +} diff --git a/morph/lib/storage.nix b/morph/lib/storage.nix new file mode 100644 index 0000000000000000000000000000000000000000..1cac51b43aa38fb90a535fd34ba53363fc0cdbaa --- /dev/null +++ b/morph/lib/storage.nix @@ -0,0 +1,51 @@ +# Similar to ``issuer.nix`` but for a "storage"-type system. Holes are filled +# by ``customize-storage.nix``. +rec { + deployment = { + secrets = { + "ristretto-signing-key" = { + destination = "/run/keys/ristretto.signing-key"; + owner.user = "root"; + owner.group = "root"; + permissions = "0400"; + # Service name here matches the name defined by our tahoe-lafs nixos + # module. It would be nice to not have to hard-code it here. Can we + # extract it from the tahoe-lafs nixos module somehow? + action = ["sudo" "systemctl" "restart" "tahoe.storage.service"]; + }; + "monitoringvpn-secret-key" = { + destination = "/run/keys/monitoringvpn/client.key"; + owner.user = "root"; + owner.group = "root"; + permissions = "0400"; + action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; + }; + "monitoringvpn-preshared-key" = { + destination = "/run/keys/monitoringvpn/preshared.key"; + owner.user = "root"; + owner.group = "root"; + permissions = "0400"; + action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; + }; + }; + }; + + # Any extra NixOS modules to load on this server. + imports = [ + # Bring in our module for configuring the Tahoe-LAFS service and other + # Private Storage-specific things. + ../../nixos/modules/private-storage.nix + # Connect to the monitoringvpn. + ../../nixos/modules/monitoring/vpn/client.nix + # Expose base system metrics over the monitoringvpn. + ../../nixos/modules/monitoring/exporters/node.nix + ]; + + # Turn on the Private Storage (Tahoe-LAFS) service. + services.private-storage = { + # Yep. Turn it on. + enable = true; + # Give it the Ristretto signing key to support authorization. + ristrettoSigningKeyPath = deployment.secrets.ristretto-signing-key.destination; + }; +} diff --git a/morph/grid/local/vagrant-guest.nix b/morph/lib/vagrant-guest.nix similarity index 100% rename from morph/grid/local/vagrant-guest.nix rename to morph/lib/vagrant-guest.nix diff --git a/nixos/modules/private-storage.nix b/nixos/modules/private-storage.nix index 52720e618973c57b41aade87585c7ab758abff22..38e224709e783b9590de73d728e4d6ca134e5adb 100644 --- a/nixos/modules/private-storage.nix +++ b/nixos/modules/private-storage.nix @@ -18,6 +18,12 @@ let # NOTE: This is promised by the service privacy policy. It *may not* be # raised without following the process for updating the privacy policy. max-incident-age = "29d"; + + fqdn = "${ + assert config.networking.hostName != null; config.networking.hostName + }.${ + assert config.networking.domain != null; config.networking.domain + }"; in { imports = [ @@ -38,12 +44,13 @@ in The package to use for the Tahoe-LAFS daemon. ''; }; - services.private-storage.publicIPv4 = lib.mkOption - { default = "127.0.0.1"; + services.private-storage.publicAddress = lib.mkOption + { default = "${fqdn}"; type = lib.types.str; - example = lib.literalExample "192.0.2.0"; + example = lib.literalExample "storage.example.invalid"; description = '' - An IPv4 address to advertise for this storage service. + A publicly-visible address to use in Tahoe-LAFS advertisements for + this storage service. ''; }; services.private-storage.introducerFURL = lib.mkOption @@ -63,7 +70,7 @@ in ''; }; services.private-storage.issuerRootURL = lib.mkOption - { default = "https://issuer.privatestorage.io/"; + { default = "https://issuer.${config.networking.domain}/"; type = lib.types.str; example = lib.literalExample "https://example.invalid/"; description = '' @@ -122,7 +129,7 @@ in # First, in the syntax which it uses to listen. "tub.port" = "tcp:${toString cfg.publicStoragePort}"; # Second, in the syntax it advertises to in the fURL. - "tub.location" = "tcp:${cfg.publicIPv4}:${toString cfg.publicStoragePort}"; + "tub.location" = "tcp:${cfg.publicAddress}:${toString cfg.publicStoragePort}"; }; storage = { enabled = true; diff --git a/nixos/modules/tests/private-storage.nix b/nixos/modules/tests/private-storage.nix index cbf4c5937ca6780ce9e931d6ceec91c29643fbc3..353abc891fafd1cc988e47a1befa530a012470dc 100644 --- a/nixos/modules/tests/private-storage.nix +++ b/nixos/modules/tests/private-storage.nix @@ -115,7 +115,7 @@ in { ]; services.private-storage = { enable = true; - publicIPv4 = "storage"; + publicAddress = "storage"; introducerFURL = introducerFURL; issuerRootURL = issuerURL; inherit ristrettoSigningKeyPath;