diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 205bedaf0b86d05a8f87ffcf368d6024d2fd57cb..b91f7d5f175a32a49a5ed0788a87146d9b86c3f3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,6 +23,7 @@ unit-tests: vulnerability-scan: stage: "test" script: + - "sed -i 's/undefined/\"unundefined\"/' morph/grid/local/secrets/users.nix" - "ci-tools/vulnerability-scan security-report.json" - "ci-tools/count-vulnerabilities <security-report.json" artifacts: diff --git a/ci-tools/vulnerability-scan b/ci-tools/vulnerability-scan index 48bf51e071a398f37565717a22b2066d3f905fbe..3162e49511697ed0ea13e0121a67336405ce5225 100755 --- a/ci-tools/vulnerability-scan +++ b/ci-tools/vulnerability-scan @@ -21,7 +21,7 @@ OUTPUT=$1 [ -e scan-target ] && rm -v scan-target nix-shell --run ' set -x -if morph_result=$(morph build morph/grid/testing/grid.nix 2>&1); then +if morph_result=$(morph build morph/grid/local/grid.nix 2>&1); then object=$(echo "$morph_result" | tail -n 1) ln -s "$object" scan-target else diff --git a/docs/source/ops/README.rst b/docs/source/ops/README.rst index 8007d8dfbb8a42d27aed4fb014423b7f91742252..b78e5ef82c0ae4dad88e65e9517f3fc6ec7bdfd2 100644 --- a/docs/source/ops/README.rst +++ b/docs/source/ops/README.rst @@ -9,3 +9,5 @@ This contains documentation regarding running PrivateStorageio. .. include:: monitoring.rst +.. include:: + generating-keys.rst diff --git a/docs/source/ops/generating-keys.rst b/docs/source/ops/generating-keys.rst new file mode 100644 index 0000000000000000000000000000000000000000..afe2ece4009f761aea56acd24fcbf627b985cadb --- /dev/null +++ b/docs/source/ops/generating-keys.rst @@ -0,0 +1,50 @@ +Generating keys +=============== + +``config.json`` has the paths for the Ristretto and the Stripe secret key files. + +Here is a Ristretto key you can use, randomly generated just now:: + + SILOWzbnkBjxC1hGde9d5Q3Ir/4yLosCLEnEQGAxEQE= + +Generate your own like this:: + + [flo@la:~/PrivateStorageio]$ nix-shell + [nix-shell:~/PrivateStorageio]$ nix-shell -p zkapissuer.components.exes.PaymentServer-generate-key + [nix-shell:~/PrivateStorageio]$ PaymentServer-generate-key + SILOWzbnkBjxC1hGde9d5Q3Ir/4yLosCLEnEQGAxEQE= + +Make sure you write it into the key file `without any leading or trailing white space, also without newlines <https://github.com/LeastAuthority/python-challenge-bypass-ristretto/issues/37>`_. +For example:: + + echo -n "SILOWzbnkBjxC1hGde9d5Q3Ir/4yLosCLEnEQGAxEQE=" > ristretto.signing-key + +For the Stripe key any random bytes with a little light formatting "work" - at least to make our software happy - but if you want to be able to interact with Stripe and have payments (even pretend payments) move all the way through the system you should get a Stripe account and generate a key w/ them. +Lauri can get you added to our "dev" Stripe account, too, though I forget how important that is for ad hoc dev/testing. + +I think this will work for generating random Stripe secret keys (that our software will load, I think, but Stripe will reject):: + + >>> import base64, os + >>> print((b"sk_test_" + base64.b64encode(os.urandom(25)).strip(b"=")).decode("ascii")) + sk_test_Dr+XLVjkC0oO3Zw8Ws0yWtDLqR1sM+/fmw + +Public keys are the same but "pk_test" instead of "sk_test" ("test" is for "test mode" key that can only process pretend txns; for real txns there are keys with "live" embedded). + +The ZKAPIssuer.service needs a working TLS certificate and expects it in the certbot directory for the domain you configured, in my case:: + + openssl req -x509 -newkey rsa:4096 -nodes -keyout privkey.pem -out cert.pem -days 3650 + touch chain.pem + +Move the three .pem files into the payment's server ``/var/lib/letsencrypt/live/payments.localdev/`` directory and issue a ``sudo systemctl restart zkapissuer.service``. + +Create Wireguard VPN key pairs in ``PrivateStorageSecrets/monitoringvpn/`` or where you have them:: + + for i in "172.23.23.11" "172.23.23.12" "172.23.23.13" "server"; do + wg genkey | tee ${i}.key | wg pubkey > ${i}.pub + done + +And a shared VPN key for "post-quantum resistance":: + + wg genpsk > preshared.key + + diff --git a/morph/README.rst b/morph/README.rst index 1f48d5e0ad30b1f44a1a2cee8c5aa6f0669bcc75..12472518ad8e061764d6812694c306e87553c843 100644 --- a/morph/README.rst +++ b/morph/README.rst @@ -55,6 +55,10 @@ This path is **ignored** by git. The intended workflow is that the secrets will be maintained on secure storage and a symlink to the correct location created here. This keeps the secrets themselves out of the git working tree as an extra protection against unintentionally committing them. +An exception is the ``secrets`` directory in the ``local`` morph grid: +That directory is fully populated, provided as an example, and mostly: not very secret. +Do not deploy these keys to machines reachable via the internet. + config.json ~~~~~~~~~~~ diff --git a/morph/grid/local/.gitignore b/morph/grid/local/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8000dd9db47c0b9dd34046ec17880dcbb27e5eb9 --- /dev/null +++ b/morph/grid/local/.gitignore @@ -0,0 +1 @@ +.vagrant diff --git a/morph/grid/local/README.rst b/morph/grid/local/README.rst index 8887c297bc0e2aa300e27f86ff7a0f08535028a5..73bfbbdd2a11922fe696161fe8346d7e10157313 100644 --- a/morph/grid/local/README.rst +++ b/morph/grid/local/README.rst @@ -1,111 +1,51 @@ Set up and use a network of local development VMs ------------------------------------------------- -... using `Vagrant <https://www.vagrantup.com/>`_ to manage VirtualBox VMs [#]_. -To get started, first install Vagrant and make sure it works. -One possible way to do it in NixOS: +... using `Vagrant <https://www.vagrantup.com/>`_ to manage VirtualBox VMs. +(The author of this documentation wasted a lot of time trying to get Vagrant to work with KVM/libvirt. +Issues with networking that looked like guest misconfigurations vanished after changing to the better-tested combination of Vagrant and VirtualBox.) -1. Install Vagrant, by adding the packages: - - ``vagrant`` (orchestrating virtual machines on the command line) - - Only use when version >= 2.2.16 has become available. Else see below. - - Optional: ``packer`` (for creating your own VM images) - -2. Add configuration to install and enable VirtualBox: - - - ``virtualisation.virtualbox.host.enable = true;`` - -3. Add your user to the ``vboxusers`` group, for example: - - - ``users.extraGroups.vboxusers.members = [ "flo" "jp" ];`` - - -.. [#] The author of this documentation wasted a lot of time trying to get Vagrant to work with KVM/libvirt. Issues with networking that looked like guest misconfigurations vanished after changing to the better-tested combination of Vagrant and VirtualBox. - - -Pre-Vagrant 2.2.16: Get Vagrant with the required fixes for NixOS guests -```````````````````````````````````````````````````````````````````````` - -The Vagrant nixos-guest template `received a critical update on 2021-03-08 <https://github.com/hashicorp/vagrant/commit/990d94ed9d0b3092e855bc1bb9deeeb7aa7792cf>`_ which came out with Vagrant version 2.2.16. - -If you run an older Nixpkgs, retrieve and use the latest Vagrant development version like so:: - - NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs/archive/refs/heads/master.tar.gz nix-shell -p vagrant - - -Generating and deploying keys -````````````````````````````` - -``config.json`` has the paths for the Ristretto and the Stripe secret key files. - -Here is a Ristretto key you can use, randomly generated just now:: - - SILOWzbnkBjxC1hGde9d5Q3Ir/4yLosCLEnEQGAxEQE= - -Generate your own like this:: - - [flo@la:~/PrivateStorageio]$ nix-shell - [nix-shell:~/PrivateStorageio]$ nix-shell -p zkapissuer.components.exes.PaymentServer-generate-key - [nix-shell:~/PrivateStorageio]$ PaymentServer-generate-key - SILOWzbnkBjxC1hGde9d5Q3Ir/4yLosCLEnEQGAxEQE= - -Make sure you write it into the key file `without any leading or trailing white space, also without newlines <https://github.com/LeastAuthority/python-challenge-bypass-ristretto/issues/37>`_. -For example:: - - echo -n "SILOWzbnkBjxC1hGde9d5Q3Ir/4yLosCLEnEQGAxEQE=" > ristretto.signing-key - -For the Stripe key any random bytes with a little light formatting "work" - at least to make our software happy - but if you want to be able to interact with Stripe and have payments (even pretend payments) move all the way through the system you should get a Stripe account and generate a key w/ them. -Lauri can get you added to our "dev" Stripe account, too, though I forget how important that is for ad hoc dev/testing. - -I think this will work for generating random Stripe secret keys (that our software will load, I think, but Stripe will reject):: - - >>> import base64, os - >>> print((b"sk_test_" + base64.b64encode(os.urandom(25)).strip(b"=")).decode("ascii")) - sk_test_Dr+XLVjkC0oO3Zw8Ws0yWtDLqR1sM+/fmw +Use the local development environment +````````````````````````````````````` -Public keys are the same but "pk_test" instead of "sk_test" ("test" is for "test mode" key that can only process pretend txns; for real txns there are keys with "live" embedded). +1. Enter the morph local grid directory:: -The ZKAPIssuer.service needs a working TLS certificate and expects it in the certbot directory for the domain you configured, in my case:: + cd morph/grid/local - openssl req -x509 -newkey rsa:4096 -nodes -keyout privkey.pem -out cert.pem -days 3650 - touch chain.pem +2. Enter the project's nix-shell:: -Move the three .pem files into the payment's server ``/var/lib/letsencrypt/live/payments.localdev/`` directory and issue a ``sudo systemctl restart zkapissuer.service``. + nix-shell ../../../shell.nix - -Use the local development environment -````````````````````````````````````` - -1. Build and start the VMs:: +3. Build and start the VMs:: VAGRANT_DEFAULT_PROVIDER=virtualbox vagrant up -2. Then, once:: +4. Then, add the Vagrant SSH configuration to your user's ``~/.ssh/config`` file:: - vagrant ssh-config > ./vagrant-ssh-config + install -d ~/.ssh ; vagrant ssh-config >> ~/.ssh/config -3. Edit the output: Add the IPs from ``grid.nix`` to the ``vagrant-ssh-config`` **Host match blocks** so the config reads like:: +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 payments1 192.168.67.21 - HostName 192.168.67.21 + HostName 127.0.0.1 User vagrant - Port 22 [...] -4. Then, make morph use this ssh config either - with newer morph [#]_ - by pointing it to it:: - - export SSH_CONFIG_FILE=./vagrant-ssh-config + 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. - Or, with older morph, adding the config to your user's ``~/.ssh/config`` file. +6. Add your SSH key to ``users.nix`` so you'll be able to log in after deploying the new configuration:: - .. [#] 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>`_. + $EDITOR secrets/users.nix -5. Then, build and deploy our software to the Vagrant VMs:: +7. Then, build and deploy our software to the Vagrant VMs:: morph build grid.nix morph push grid.nix + morph deploy grid.nix boot + vagrant halt + vagrant up morph upload-secrets grid.nix - morph deploy grid.nix switch - You will now be able to log in with the users and keys you set in your ``localdev-users.nix`` file. + 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 81dec21ee701d761b4347f11df43398d78d4b528..82bbef1063b108829261670fdceb2e27af8d6764 100644 --- a/morph/grid/local/Vagrantfile +++ b/morph/grid/local/Vagrantfile @@ -14,6 +14,10 @@ Vagrant.configure("2") do |config| config.vm.box_version = "20.09" config.vm.box_check_update = false config.vm.network "private_network", ip: "192.168.67.21" + # Add self signed SSL key for zkap-issuer: + config.vm.provision "file", source: "secrets/payments-localdev-ssl", destination: "/tmp/payments-localdev-ssl" + config.vm.provision "shell", inline: "sudo mkdir -p /var/lib/letsencrypt/live/payments.localdev/" + config.vm.provision "shell", inline: "sudo mv /tmp/payments-localdev-ssl/* /var/lib/letsencrypt/live/payments.localdev/" end config.vm.define "storage1" do |config| @@ -32,6 +36,14 @@ Vagrant.configure("2") do |config| config.vm.network "private_network", ip: "192.168.67.23" end + config.vm.define "monitoring1" do |config| + config.vm.hostname = "monitoring1" + config.vm.box = "esselius/nixos" + config.vm.box_version = "20.09" + config.vm.box_check_update = false + config.vm.network "private_network", ip: "192.168.67.24" + end + # To make the VMs assign the static IPs to the network interfaces we need a rebuild: config.vm.provision "shell", inline: "echo '{nix.trustedUsers = [ \"@wheel\" \"root\" \"vagrant\" ];}' > /etc/nixos/custom-configuration.nix" config.vm.provision "shell", inline: "nixos-rebuild switch" diff --git a/morph/grid/local/config.json b/morph/grid/local/config.json index e970c3c6c29498497e5fad19d04ed56a56471ec1..38f00367bf2fa36ad7663c89f7849146783b8515 100644 --- a/morph/grid/local/config.json +++ b/morph/grid/local/config.json @@ -1,6 +1,8 @@ { "publicStoragePort": 8898 -, "ristrettoSigningKeyPath": "../../PrivateStorageSecrets/ristretto.signing-key" -, "stripeSecretKeyPath": "../../PrivateStorageSecrets/privatestorageio-testing-stripe.secret" +, "ristrettoSigningKeyPath": "./secrets/ristretto.signing-key" +, "stripeSecretKeyPath": "./secrets/stripe.secret" +, "monitoringvpnKeyDir": "./secrets/monitoringvpn" +, "monitoringvpnEndpoint": "192.168.67.24:51820" , "passValue": 1000000 , "issuerDomains": ["payments.localdev"] , "letsEncryptAdminEmail": "florian@privatestorage.io" diff --git a/morph/grid/local/grid.nix b/morph/grid/local/grid.nix index fdda12e4537cd281a8d0768f0a95aa0608eca36b..a762186d3aaad642fe24aaf7666853fde79986b3 100644 --- a/morph/grid/local/grid.nix +++ b/morph/grid/local/grid.nix @@ -6,27 +6,46 @@ import ../../lib/make-grid.nix { config = ./config.json; nodes = cfg: let - sshUsers = import ../../../../PrivateStorageSecrets/localdev-users.nix; + sshUsers = import ./secrets/users.nix; + vpnClientIPs = [ "172.23.23.11" "172.23.23.12" "172.23.23.13" ]; # TBD: derive automatically + # Get absolute vpn key directory path, as a string: + monitoringvpnKeyDir = toString ./. + "/${cfg.monitoringvpnKeyDir}"; in { - "payments1" = import ../../lib/make-issuer.nix (rec { + "payments1" = import ../../lib/make-issuer.nix (cfg // rec { publicIPv4 = "192.168.67.21"; + monitoringvpnIPv4 = "172.23.23.11"; + inherit monitoringvpnKeyDir; inherit sshUsers; hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; }); stateVersion = "19.03"; - } // cfg); + }); - "storage1" = import ../../lib/make-testing.nix (rec { + "storage1" = import ../../lib/make-testing.nix (cfg // rec { publicIPv4 = "192.168.67.22"; + monitoringvpnIPv4 = "172.23.23.12"; + inherit monitoringvpnKeyDir; inherit sshUsers; hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; }); stateVersion = "19.09"; - } // cfg); + }); - "storage2" = import ../../lib/make-testing.nix (rec { + "storage2" = import ../../lib/make-testing.nix (cfg // rec { publicIPv4 = "192.168.67.23"; + monitoringvpnIPv4 = "172.23.23.13"; + inherit monitoringvpnKeyDir; inherit sshUsers; hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; }); stateVersion = "19.09"; - } // cfg); + }); + + "monitoring1" = import ../../lib/make-monitoring.nix (cfg // rec { + publicIPv4 = "192.168.67.24"; + monitoringvpnIPv4 = "172.23.23.1"; + inherit vpnClientIPs; + inherit sshUsers; + inherit monitoringvpnKeyDir; + hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; }); + stateVersion = "19.09"; + }); }; } diff --git a/morph/grid/local/secrets/monitoringvpn/172.23.23.11.key b/morph/grid/local/secrets/monitoringvpn/172.23.23.11.key new file mode 100644 index 0000000000000000000000000000000000000000..22f11b7bc230a1a1b08d68850caa375171cc386d --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/172.23.23.11.key @@ -0,0 +1 @@ +cLP62YAYoA7FY+OhSLR64DIHekOjGGQlfJAWp5cYP00= diff --git a/morph/grid/local/secrets/monitoringvpn/172.23.23.11.pub b/morph/grid/local/secrets/monitoringvpn/172.23.23.11.pub new file mode 100644 index 0000000000000000000000000000000000000000..44c0d84b7ad9c50c75c379fd7589dd33370b3e58 --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/172.23.23.11.pub @@ -0,0 +1 @@ +GYNjLkoyQ1d3OMymYbgq40WAHIUzrSEGBWXvxqceF00= diff --git a/morph/grid/local/secrets/monitoringvpn/172.23.23.12.key b/morph/grid/local/secrets/monitoringvpn/172.23.23.12.key new file mode 100644 index 0000000000000000000000000000000000000000..e717bf7ec42129926ceae6c7a44372738162378e --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/172.23.23.12.key @@ -0,0 +1 @@ +qFjBtvJKBchzl2HwFvEDoe3zFzyc10osiRlP8HOk2n0= diff --git a/morph/grid/local/secrets/monitoringvpn/172.23.23.12.pub b/morph/grid/local/secrets/monitoringvpn/172.23.23.12.pub new file mode 100644 index 0000000000000000000000000000000000000000..18110f20c3bb734fd229f1bd7f87f37050130b6a --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/172.23.23.12.pub @@ -0,0 +1 @@ +veio/0E0sJYOjwp3E8EccCyME1pqjkZr4R6whFMdrhs= diff --git a/morph/grid/local/secrets/monitoringvpn/172.23.23.13.key b/morph/grid/local/secrets/monitoringvpn/172.23.23.13.key new file mode 100644 index 0000000000000000000000000000000000000000..6dd5087e19e8e9e97f3b459a30563555d10de155 --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/172.23.23.13.key @@ -0,0 +1 @@ +8HlKTvxZBAZeww6JaNk9kBPjSfT0pVMbDJbzV67yUGE= diff --git a/morph/grid/local/secrets/monitoringvpn/172.23.23.13.pub b/morph/grid/local/secrets/monitoringvpn/172.23.23.13.pub new file mode 100644 index 0000000000000000000000000000000000000000..d80b7abbfa20982e69772e6cd66f20dea946582d --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/172.23.23.13.pub @@ -0,0 +1 @@ +4VlUMl9FubrLWaN0pRvfdNjjRBQzfCVLMA2lU7OwPzA= diff --git a/morph/grid/local/secrets/monitoringvpn/preshared.key b/morph/grid/local/secrets/monitoringvpn/preshared.key new file mode 100644 index 0000000000000000000000000000000000000000..4389e80504f524ecb9b8ee2e8248882da55a7097 --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/preshared.key @@ -0,0 +1 @@ +E7KTLVnWMmP/mIEkU8WX2DBZJaeMS2+sYArRZuGT1o4= diff --git a/morph/grid/local/secrets/monitoringvpn/server.key b/morph/grid/local/secrets/monitoringvpn/server.key new file mode 100644 index 0000000000000000000000000000000000000000..01058684fdb2438b4bff23f0370939628c3ef18c --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/server.key @@ -0,0 +1 @@ +iOp2pk2HWyNgRnke7nJgFwodkTWMyHRIKwe8pk+bN3M= diff --git a/morph/grid/local/secrets/monitoringvpn/server.pub b/morph/grid/local/secrets/monitoringvpn/server.pub new file mode 100644 index 0000000000000000000000000000000000000000..188c4b4cdea11ca02add26cba104ce61af0ee4c1 --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/server.pub @@ -0,0 +1 @@ +ojo+p9ZE03GN66ewoIlrHmyV7ICt+2LV32Prs66JsA4= diff --git a/morph/grid/local/secrets/payments-localdev-ssl/cert.pem b/morph/grid/local/secrets/payments-localdev-ssl/cert.pem new file mode 100644 index 0000000000000000000000000000000000000000..5300ed591899cb802f2ceff49ac5aa195bb87d12 --- /dev/null +++ b/morph/grid/local/secrets/payments-localdev-ssl/cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDGTCCAgGgAwIBAgIUM9YnOMe2yYQuCLpYiI2TpZg21AMwDQYJKoZIhvcNAQEL +BQAwHDEaMBgGA1UEAwwRcGF5bWVudHMubG9jYWxkZXYwHhcNMjEwNjA5MTQzNzU4 +WhcNMzEwNjA3MTQzNzU4WjAcMRowGAYDVQQDDBFwYXltZW50cy5sb2NhbGRldjCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOBCvkMprdRjD8ECeweMVTFT +pILu5VA8HC8XK15Y4iE8G48cSYE3m/e6w5g4JvfXgED9eY+1/ZazQXVI6sojnfHL +Vj9XqsUww3IVtq2Zn+0B8YTrbNxcDH77mUx0mUziAm1bglmoNbd4+q0Fe8FhK/EN +Jj7UppRjD2ziV9Mw7UT1JjMbfSo7/7ZOV2cWk+hezOywsE+3BM6mju1aHbbYryAd +EzRwfQKcI/9PC84Bck9e+tEiWQImBf8DguQ+ChuSOmGtP1rI+hq5HfCimH0NCCNS +iUfNVcubz920FRBeAx9oM0G/u4feeS8T5a1PThZrdhjIycEmU5wsM7F34RzkuEkC +AwEAAaNTMFEwHQYDVR0OBBYEFAbBfAFOlx4c53CNgsRlobFwUIBbMB8GA1UdIwQY +MBaAFAbBfAFOlx4c53CNgsRlobFwUIBbMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBACD+47l30gGaZBPvuCMc/CENLmuqZqj7WGGmWcmUAzsdEgHt +Q1zhj4un4u4qQ78jeT+cjqNK9qartQIjxzYTpn6lKDBpM9sS2G7RdLxOWWRVAXQj +Cv6l0tEQArIqqMnzmECe0VDCc97kTg6tnMLFeyQL29XSSNIpS0DiQ+NC69fyrF2E +vt2bAi+QTlN1U1ZGDJqWlwqkpI3xTRDJnmRPuVNrt07gkMWeSJHEI98Qcve7Ujf3 +hFcAnbshJ8iXxbNjTFIQcCJzHq1UF+eZo8BF1ixYmrk/jmaLNBOSy93tOk1XeJfS +XtV6X9jmAE20V0XV8uCli6cDxQQYthll/1q5JYQ= +-----END CERTIFICATE----- diff --git a/morph/grid/local/secrets/payments-localdev-ssl/chain.pem b/morph/grid/local/secrets/payments-localdev-ssl/chain.pem new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/morph/grid/local/secrets/payments-localdev-ssl/privkey.pem b/morph/grid/local/secrets/payments-localdev-ssl/privkey.pem new file mode 100644 index 0000000000000000000000000000000000000000..36b699fab9e7dac880daf89ae3f9a7ea9ce732ef --- /dev/null +++ b/morph/grid/local/secrets/payments-localdev-ssl/privkey.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDgQr5DKa3UYw/B +AnsHjFUxU6SC7uVQPBwvFyteWOIhPBuPHEmBN5v3usOYOCb314BA/XmPtf2Ws0F1 +SOrKI53xy1Y/V6rFMMNyFbatmZ/tAfGE62zcXAx++5lMdJlM4gJtW4JZqDW3ePqt +BXvBYSvxDSY+1KaUYw9s4lfTMO1E9SYzG30qO/+2TldnFpPoXszssLBPtwTOpo7t +Wh222K8gHRM0cH0CnCP/TwvOAXJPXvrRIlkCJgX/A4LkPgobkjphrT9ayPoauR3w +oph9DQgjUolHzVXLm8/dtBUQXgMfaDNBv7uH3nkvE+WtT04Wa3YYyMnBJlOcLDOx +d+Ec5LhJAgMBAAECggEARI3in6FkFCLcNAJQHbSWbmfFSIlC7E4Tx4lrpoHBTquT +OSJKjgez0/zxwdyYfPcRq8xQls/pX2IYxoOt0nEk3T9tdBuWhoUrmfptR5BIxSjs +7dcSBiLVZxP+ftK98jS8zTVGGaZEFXwUFUQx2qGbzypX4Kkc6wuFMaHXeyXfwk4j +v3lOTpT7kX/3iVXzQU9Y5m45W1bbt3lSV4yCndOt/4Xg5d4ue6UcUsyg/r8m5wsU +nCc14L0HsY/VCCRISmDwa4UoqHGfQv6+XXxLT8gJM7H8PkZK8TRV/ZG2Yug63wDS +xkhMZBodGoYuQpB19Y+NxjwG8Se7RxcCAyS7zcYcCQKBgQD/VWesc2/TplikifQf +LJl+utiQ9G/o3wAquAKInxQOcUxOm1fsvjgsLfrjpAVj0D3qD0Sf3lSp7z3tpUMf +MSi9MgNunSU7pKST7jex6BJNU0TTRcFnoqcIlUYiDoLLbkkVlf8Nome88gkwJRKZ +RjI+6ES9hGaM85QEgjdtRNGXIwKBgQDg2JPfVXYyrOIITus/DHHv8em1RuGCIe6X +T3M0+GgJ27hOEeneAyzk4aWvVzE3/3lxx55ePGRAz43jPrUxn0kfy/Jx4UMKsEW+ +XzR7CfxTxamUx/mq2bbqk+bbnXZZQedAip4eQ23GbWdrE4/v83JXzWj355yUQCQk +uuIcda7fowKBgEY20CmmHOxQ5DNrFEy2UQd+jitebJ/XIw6cR2YWiMdn9JnxMf6S +WJQdmM6cvjayfzQsOqzT0OhiN99wAMNFG3TbmgIDCMgcAH4Flh9AODg3W8fVeNfs +7I35rq2S2/jhPQvIkbjIHkrhLBGnQDQSD6Mo8C5FiIXePaf3vxI3SIONAoGAZdOv +pEUf8nM5KmoTP8pzDyePn/kpx7V2SDBDDIozE8PeA/043MKzYjSOxInIUIPyjATL +RAI1pORabb/Ib2CjzTKf6dMKeZy6+SxEqDQtggLSef7WovlWTYYN1wfIwUOHZ0Nf +uHTxEhwZ6fRCC3lFH153W04ZK0qhE8FPBXSGbeECgYBcY0QmOd3ao3v0xscKmPlM +E9MICgwgEJ6pAsaOI30OHqUAtlqrlw5ph3skxlLUpHWW6OUczUUV6nwguk4piuee +1J9uuA02FlIvvUy5Bsrgqlu0Lj5vJ8Im2Go9dJ8k/m9J5BUgDdPuNwnmjiyNQurd +Fl50FWx/3WeJB2qK981vmw== +-----END PRIVATE KEY----- diff --git a/morph/grid/local/secrets/ristretto.signing-key b/morph/grid/local/secrets/ristretto.signing-key new file mode 100644 index 0000000000000000000000000000000000000000..8726b7060694499f61cc15ba826f3933b88795a5 --- /dev/null +++ b/morph/grid/local/secrets/ristretto.signing-key @@ -0,0 +1 @@ +NAQBkEEUKPDtq8af5anlHvWMjeSVoH56RnpCTy70QwA= \ No newline at end of file diff --git a/morph/grid/local/secrets/stripe.secret b/morph/grid/local/secrets/stripe.secret new file mode 100644 index 0000000000000000000000000000000000000000..ebf3fdabcd222af9ca7ed46bf0b45a2fd18a603e --- /dev/null +++ b/morph/grid/local/secrets/stripe.secret @@ -0,0 +1 @@ +sk_test_Dr+XLVjkC0oO3Zw8Ws0yWtDLqR1sM+/fmw diff --git a/morph/grid/local/secrets/users.nix b/morph/grid/local/secrets/users.nix new file mode 100644 index 0000000000000000000000000000000000000000..93a8b660c78fa12b1e20c6d560f78efb1b5684c7 --- /dev/null +++ b/morph/grid/local/secrets/users.nix @@ -0,0 +1,4 @@ +# Add your public key. Example: +# let key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHx7wJQNqKn8jOC4AxySRL2UxidNp7uIK9ad3pMb1ifF flo@fs-la"; +let key = undefined; +in { "root" = key; "vagrant" = key; } diff --git a/morph/grid/local/vagrant-guest.nix b/morph/grid/local/vagrant-guest.nix index 8505b2f34dba067bf2c39a1645145bc626d30cf8..9e8e6d8ccab25d98d11738ff7df4a574c5cfd724 100644 --- a/morph/grid/local/vagrant-guest.nix +++ b/morph/grid/local/vagrant-guest.nix @@ -22,6 +22,9 @@ in # Enable the OpenSSH daemon. services.openssh.enable = true; + # Wireguard kernel module + boot.extraModulePackages = [ config.boot.kernelPackages.wireguard ]; + # Enable DBus services.dbus.enable = true; diff --git a/morph/grid/production/grid.nix b/morph/grid/production/grid.nix index 69a17602f0499acaa8b45adca5e45c8acc637110..f5735d259dbff27f1d9cabbbca512af81d4550bb 100644 --- a/morph/grid/production/grid.nix +++ b/morph/grid/production/grid.nix @@ -6,7 +6,7 @@ import ../../lib/make-grid.nix { config = ./config.json; nodes = cfg: let - sshUsers = import ./users.nix; + sshUsers = import ./secrets/users.nix; 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 diff --git a/morph/grid/production/users.nix b/morph/grid/production/users.nix deleted file mode 100644 index d3520076636b56c0b07055a135becaf6a77b798f..0000000000000000000000000000000000000000 --- a/morph/grid/production/users.nix +++ /dev/null @@ -1,2 +0,0 @@ -let key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGN4VQm3BIQKEFTw6aPrEwNuShf640N+Py2LOKznFCRT exarkun@bottom"; -in { "root" = key; jcalderone = key; } diff --git a/morph/grid/testing/grid.nix b/morph/grid/testing/grid.nix index 90acab60b7bf6a12f2c5ff3ff93cb93e479491aa..065cd5faa5a5e90a657d1fd1a38e79266e6b6475 100644 --- a/morph/grid/testing/grid.nix +++ b/morph/grid/testing/grid.nix @@ -6,7 +6,7 @@ import ../../lib/make-grid.nix { config = ./config.json; nodes = cfg: let - sshUsers = import ./users.nix; + sshUsers = import ./secrets/users.nix; in { "payments" = import ../../lib/make-issuer.nix ({ publicIPv4 = "18.194.183.13"; diff --git a/morph/grid/testing/users.nix b/morph/grid/testing/users.nix deleted file mode 100644 index d3520076636b56c0b07055a135becaf6a77b798f..0000000000000000000000000000000000000000 --- a/morph/grid/testing/users.nix +++ /dev/null @@ -1,2 +0,0 @@ -let key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGN4VQm3BIQKEFTw6aPrEwNuShf640N+Py2LOKznFCRT exarkun@bottom"; -in { "root" = key; jcalderone = key; } diff --git a/morph/lib/make-issuer.nix b/morph/lib/make-issuer.nix index 5625b565c452d1fc9c8bf84eb1720cecd197f124..58b8a4f20496472409c2063a2923bc29f161d68a 100644 --- a/morph/lib/make-issuer.nix +++ b/morph/lib/make-issuer.nix @@ -7,10 +7,37 @@ , sshUsers , stateVersion , publicIPv4 +, monitoringvpnKeyDir ? null +, monitoringvpnIPv4 ? null +, monitoringvpnEndpoint ? null , ... -}: rec { +}: 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 = { - targetUser = "root"; targetHost = publicIPv4; secrets = { @@ -30,12 +57,13 @@ permissions = "0400"; action = ["sudo" "systemctl" "restart" "zkapissuer.service"]; }; - }; + } // vpnSecrets; }; imports = [ hardware ../../nixos/modules/issuer.nix + ../../nixos/modules/monitoring/vpn/client.nix ]; services.private-storage.sshUsers = sshUsers; @@ -52,4 +80,11 @@ }; 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 new file mode 100644 index 0000000000000000000000000000000000000000..c37ea2297088fafba1b97e8d037c378505c3d84c --- /dev/null +++ b/morph/lib/make-monitoring.nix @@ -0,0 +1,55 @@ +{ publicIPv4 +, hardware +, publicStoragePort +, ristrettoSigningKeyPath +, passValue +, sshUsers +, stateVersion +, monitoringvpnIPv4 ? null +, monitoringvpnKeyDir ? null +, vpnClientIPs ? null +, ... }: 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 + ]; + + services.private-storage.monitoring.vpn.server = if !enableVpn then {} else { + enable = true; + ip = monitoringvpnIPv4; + inherit vpnClientIPs; + pubKeysPath = monitoringvpnKeyDir; + }; + + system.stateVersion = stateVersion; +} diff --git a/morph/lib/make-storage.nix b/morph/lib/make-storage.nix index 25f3a95bfb5e66a4b42c5f2f82b4fdacbaed4b41..af0867c8b8342e31393f19a76a7cbfc4c95f86c9 100644 --- a/morph/lib/make-storage.nix +++ b/morph/lib/make-storage.nix @@ -14,7 +14,6 @@ , ... }: rec { deployment = { - targetUser = "root"; targetHost = cfg.publicIPv4; secrets = { diff --git a/morph/lib/make-testing.nix b/morph/lib/make-testing.nix index ed6ba27e70726cb08c38850cd09f08b37897fcfa..f1c1b56fc5444322a8f3a1191fe296fe23528a3e 100644 --- a/morph/lib/make-testing.nix +++ b/morph/lib/make-testing.nix @@ -1,7 +1,41 @@ -{ publicIPv4, hardware, publicStoragePort, ristrettoSigningKeyPath, passValue, sshUsers, stateVersion, ... }: rec { +{ 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 = { - targetUser = "root"; targetHost = publicIPv4; secrets = { @@ -16,12 +50,13 @@ # 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 ]; services.private-storage = @@ -34,4 +69,11 @@ }; 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/nixos/modules/monitoring/vpn/client.nix b/nixos/modules/monitoring/vpn/client.nix new file mode 100644 index 0000000000000000000000000000000000000000..dbd50b82ef5b09495e332e6fbb7ac5676f5ac322 --- /dev/null +++ b/nixos/modules/monitoring/vpn/client.nix @@ -0,0 +1,74 @@ +# Client section of our Monitoring VPN config + +{ lib, config, ... }: let + cfg = config.services.private-storage.monitoring.vpn; + +in { + options.services.private-storage.monitoring.vpn.client = { + enable = lib.mkEnableOption "PrivateStorageio Monitoring VPN client service"; + privateKeyFile = lib.mkOption { + type = lib.types.path; + example = lib.literalExample /run/keys/monitoringvpn/host.key; + default = /run/keys/monitoringvpn/client.key; + description = '' + File with base64 private key generated by <command>wg genkey</command>. + Shorthand to create private and public key: + <command>wg genkey | tee peer_A.key | wg pubkey > peer_A.pub</command> + ''; + }; + presharedKeyFile = lib.mkOption { + type = lib.types.path; + example = lib.literalExample /run/keys/monitoringvpn/preshared.key; + default = /run/keys/monitoringvpn/preshared.key; + description = '' + File with base64 preshared key generated by <command>wg genpsk</command>. + ''; + }; + allowedIPs = lib.mkOption { + type = lib.types.listOf lib.types.str; + example = lib.literalExample [ "172.23.23.1/32" ]; + default = [ "172.23.23.1/32" ]; + description = '' + Limits which IPs this client receives data from. + ''; + }; + ip = lib.mkOption { + type = lib.types.str; + example = lib.literalExample "172.23.23.11"; + description = '' + The IP addresses of the interface. + ''; + }; + endpoint = lib.mkOption { + type = lib.types.str; + example = lib.literalExample "vpn.monitoring.private.storage:54321"; + description = '' + The address and port number of the server to establish the VPN with. + ''; + }; + endpointPublicKeyFile = lib.mkOption { + type = lib.types.path; + example = lib.literalExample ../PrivateStorageSecrets/monitoringvpn/server.pub; + description = '' + File with base64 public key generated by <command>cat private.key | wg pubkey > pubkey.pub</command>. + ''; + }; + }; + + config = lib.mkIf cfg.client.enable { + networking.wireguard.interfaces.monitoringvpn = { + ips = [ "${cfg.client.ip}/24" ]; + privateKeyFile = toString cfg.client.privateKeyFile; + peers = [ + { + allowedIPs = cfg.client.allowedIPs; + endpoint = cfg.client.endpoint; # meaning: the server. + publicKey = lib.fileContents(cfg.client.endpointPublicKeyFile); + presharedKeyFile = toString cfg.client.presharedKeyFile; + persistentKeepalive = 25; + } + ]; + }; + }; +} + diff --git a/nixos/modules/monitoring/vpn/server.nix b/nixos/modules/monitoring/vpn/server.nix new file mode 100644 index 0000000000000000000000000000000000000000..2374ddc8657fb299fb83155cbabe328cd54c1aaf --- /dev/null +++ b/nixos/modules/monitoring/vpn/server.nix @@ -0,0 +1,72 @@ +# Server section of our Monitoring VPN config + +{ lib, config, ... }: let + cfg = config.services.private-storage.monitoring.vpn; + clients = map (x: { + allowedIPs = [ "${x}/32" ]; + publicKey = lib.fileContents(cfg.server.pubKeysPath + "/${x}.pub"); + presharedKeyFile = toString cfg.server.presharedKeyFile; + }) cfg.server.vpnClientIPs; + +in { + options.services.private-storage.monitoring.vpn.server = { + enable = lib.mkEnableOption "PrivateStorageio Monitoring VPN server service"; + privateKeyFile = lib.mkOption { + type = lib.types.path; + example = lib.literalExample /run/keys/monitoringvpn/server.key; + default = /run/keys/monitoringvpn/server.key; + description = '' + File with base64 private key generated by <command>wg genkey</command>. + ''; + }; + presharedKeyFile = lib.mkOption { + type = lib.types.path; + example = lib.literalExample /run/keys/monitoringvpn/preshared.key; + default = /run/keys/monitoringvpn/preshared.key; + description = '' + File with base64 preshared key generated by <command>wg genpsk</command>. + ''; + }; + ip = lib.mkOption { + type = lib.types.str; + example = lib.literalExample [ "172.23.23.23" ]; + description = '' + The IP address of the interface. + ''; + }; + port = lib.mkOption { + type = lib.types.port; + example = lib.literalExample 54321; + default = 51820; + description = '' + The UDP port to listen on. + ''; + }; + vpnClientIPs = lib.mkOption { + type = lib.types.listOf lib.types.str; + example = lib.literalExample [ "172.23.23.23" "172.23.23.42" ]; + description = '' + The IP addresses to allow connections from. + ''; + }; + pubKeysPath = lib.mkOption { + type = lib.types.path; + example = lib.literalExample ../PrivateStorageSecrets/monitoringvpn; + description = '' + The path to the directory that holds the public keys. + ''; + }; + }; + + config = lib.mkIf cfg.server.enable { + networking.firewall.allowedUDPPorts = [ cfg.server.port ]; + + networking.wireguard.interfaces.monitoringvpn = { + ips = [ "${cfg.server.ip}/24" ]; + listenPort = cfg.server.port; + privateKeyFile = toString cfg.server.privateKeyFile; + peers = clients; + }; + }; +} + diff --git a/nixos/modules/ssh.nix b/nixos/modules/ssh.nix index 59ee2fec949be247143041379626f35b7d8bf657..667bdd26215b4e0978781244741dd4c5313cefbd 100644 --- a/nixos/modules/ssh.nix +++ b/nixos/modules/ssh.nix @@ -37,6 +37,10 @@ # password-based authentication at all. PermitEmptyPasswords no + # Agent forwarding is fraught. It can be used by an attacker to + # leverage one compromised system into more. Discourage its use. + AllowAgentForwarding no + # Only allow authentication as one of the configured users, not random # other (often system-managed) users. Possibly this is also # superfluous! NixOS system users have nologin as their shell ... so they diff --git a/nixos/modules/tests/get-passes.py b/nixos/modules/tests/get-passes.py index 691a3d26f37125379df85c85481cfdac67741d07..63b59e5700e0fa0c659f04df8fa889a0501f125f 100755 --- a/nixos/modules/tests/get-passes.py +++ b/nixos/modules/tests/get-passes.py @@ -95,7 +95,7 @@ def charge_json(voucher): return { "token": "tok_abcdef", "voucher": voucher, - "amount": "100", + "amount": "650", "currency": "USD", } diff --git a/nixpkgs-2105.json b/nixpkgs-2105.json new file mode 100644 index 0000000000000000000000000000000000000000..d441d00995a78a20cc8677a85ced2a675a9502ae --- /dev/null +++ b/nixpkgs-2105.json @@ -0,0 +1,4 @@ +{ "name": "stable2105" +, "url": "https://releases.nixos.org/nixos/21.05/nixos-21.05.804.5de44c15758/nixexprs.tar.xz" +, "sha256": "002zvc16hyrbs0icx1qj255c9dqjpdxx4bhhfjndlj3kwn40by0m" +} diff --git a/nixpkgs.json b/nixpkgs.json index a13edba683061306533106d1f2d1e5c6eacaadba..33b343ef3498ae226218f59be257e808e9a88c7e 100644 --- a/nixpkgs.json +++ b/nixpkgs.json @@ -1,4 +1,4 @@ { "name": "nixpkgs" -, "url": "https://github.com/PrivateStorageio/nixpkgs/archive/d7c46f46c3e6acfcde44bb05877fd5c9f07dfe1b.tar.gz" -, "sha256": "1vddxhp3ljaq9qqzbpjp2kx34ps7nzbsn4zy31x0748a52rlsh0q" +, "url": "https://github.com/PrivateStorageio/nixpkgs/archive/8c7a61c658e32eaccf666e5fe818a996c36a988f.tar.gz" +, "sha256": "1ln0a8c20qykm57wl901lixny1fcfmzgbavd7pbjk6jbnfij59bl" } diff --git a/shell.nix b/shell.nix index b15b7c66b110a785480142c3b1d34b3d365004f6..6e46c9ca0feaa3ab6fbd22c1228ec786a49e79b6 100644 --- a/shell.nix +++ b/shell.nix @@ -1,12 +1,12 @@ let - nixpkgs-pin = builtins.fromJSON (builtins.readFile ./nixpkgs.json); - nixpkgs-src = builtins.fetchTarball nixpkgs-pin; - nixpkgs = import nixpkgs-src { }; + nixpkgs = import (builtins.fetchTarball (builtins.fromJSON (builtins.readFile ./nixpkgs.json))) { }; + stable2105 = import (builtins.fetchTarball (builtins.fromJSON (builtins.readFile ./nixpkgs-2105.json))) { }; in { pkgs ? nixpkgs }: pkgs.mkShell { NIX_PATH = "nixpkgs=${nixpkgs.path}"; buildInputs = [ pkgs.morph + stable2105.vagrant ]; }