From 2cd880b5607b3d6dea598288fa5760b2a08d1a9b Mon Sep 17 00:00:00 2001 From: Jake Hillion Date: Sun, 11 Jun 2023 17:09:10 +0100 Subject: [PATCH] storj: create module --- .../default.nix | 23 ++++ modules/default.nix | 1 + modules/storj.nix | 130 ++++++++++++++++++ secrets/secrets.nix | 3 + secrets/storj/tywin/zfs_auth.age | 22 +++ 5 files changed, 179 insertions(+) create mode 100644 modules/storj.nix create mode 100644 secrets/storj/tywin/zfs_auth.age diff --git a/hosts/tywin.storage.ts.hillion.co.uk/default.nix b/hosts/tywin.storage.ts.hillion.co.uk/default.nix index dcfcb57..688eed6 100644 --- a/hosts/tywin.storage.ts.hillion.co.uk/default.nix +++ b/hosts/tywin.storage.ts.hillion.co.uk/default.nix @@ -71,5 +71,28 @@ targetAddress = "xch1tl87mjd9zpugs7qy2ysc3j4qlftqlyjn037jywq6v2y4kp22g74qahn6sw"; plotDirectories = [ ]; }; + + ## Storj + age.secrets."storj/zfs_auth" = { + file = ../../secrets/storj/tywin/zfs_auth.age; + owner = "storj"; + group = "storj"; + }; + custom.storj = { + enable = true; + openFirewall = true; + email = "jake+storj@hillion.co.uk"; + wallet = "0x03cebe2608945D51f0bcE6c5ef70b4948fCEcfEe"; + }; + custom.storj.instances.zfs = { + configDir = "/data/storj/config"; + identityDir = "/data/storj/identity"; + storage = "500GB"; + consoleAddress = "100.115.31.91:14002"; + serverPort = 28967; + externalAddress = "zfs.tywin.storj.hillion.co.uk:28967"; + authorizationTokenFile = config.age.secrets."storj/zfs_auth".path; + }; + networking.firewall.interfaces."tailscale0".allowedTCPPorts = [ 14002 ]; }; } diff --git a/modules/default.nix b/modules/default.nix index 63aed6a..5bede50 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -9,6 +9,7 @@ ./resilio.nix ./services/mastodon/default.nix ./services/matrix.nix + ./storj.nix ./tailscale.nix ./www/global.nix ./www/www-repo.nix diff --git a/modules/storj.nix b/modules/storj.nix new file mode 100644 index 0000000..61f55b1 --- /dev/null +++ b/modules/storj.nix @@ -0,0 +1,130 @@ +{ config, pkgs, lib, ... }: + +let + cfg = config.custom.storj; +in +{ + options.custom.storj = { + enable = lib.mkEnableOption "storj"; + + instances = lib.mkOption { + type = with lib.types; attrsOf + (submodule { + options = { + configDir = lib.mkOption { + type = str; + }; + identityDir = lib.mkOption { + type = str; + }; + storage = lib.mkOption { + type = str; + }; + consoleAddress = lib.mkOption { + type = str; + default = "127.0.0.1:14002"; + }; + serverPort = lib.mkOption { + type = port; + default = 28967; + }; + externalAddress = lib.mkOption { + type = nullOr str; + default = null; + }; + authorizationTokenFile = lib.mkOption { + type = nullOr str; + default = null; + }; + }; + }); + default = { }; + }; + + wallet = lib.mkOption { + type = lib.types.str; + }; + email = lib.mkOption { + type = lib.types.str; + }; + openFirewall = lib.mkOption { + type = lib.types.bool; + default = false; + }; + }; + + config = lib.mkIf cfg.enable { + users.groups.storj = { }; + users.users.storj = { + isSystemUser = true; + createHome = false; + group = "storj"; + }; + + systemd.services = + let + mkService = name: value: { + name = "storj-${name}"; + value = { + description = "Storj storagenode ${name}"; + wantedBy = [ "multi-user.target" ]; + + script = + let + args = lib.concatStringsSep "\\\n " ([ + "--config-dir '${value.configDir}'" + "--identity-dir '${value.identityDir}'" + "--operator.email '${cfg.email}'" + "--operator.wallet '${cfg.wallet}'" + "--console.address '${value.consoleAddress}'" + "--server.address ':${toString value.serverPort}'" + "--storage.allocated-disk-space '${value.storage}'" + ] ++ (if value.externalAddress == null then [ ] else [ + "--contact.external-address '${value.externalAddress}'" + ])); + in + with pkgs; + if value.authorizationTokenFile == null then "" else with pkgs; '' + if ! grep -c BEGIN ${value.identityDir}/ca.cert; then + rm -rf ${value.identityDir}/storagenode + ${storj}/bin/identity create storagenode \ + --identity-dir '${value.identityDir}' + ${storj}/bin/identity authorize storagenode \ + $(cat ${value.authorizationTokenFile}) \ + --identity-dir '${value.identityDir}' \ + --signer.tls.revocation-dburl 'bolt://${value.identityDir}/revocations.db' + mv ${value.identityDir}/storagenode/* ${value.identityDir} + rm -d ${value.identityDir}/storagenode + fi + '' + '' + if ! test -d ${value.configDir}/storage/blobs; then + ${storj}/bin/storagenode setup ${args} + fi + ${storj}/bin/storagenode run ${args} + ''; + + serviceConfig = { + User = "storj"; + Group = "storj"; + + Restart = "always"; + RestartSec = 10; + }; + + unitConfig = { + RequiresMountsFor = lib.concatStringsSep " " [ value.configDir value.identityDir ]; + }; + }; + }; + in + builtins.listToAttrs (lib.attrsets.mapAttrsToList mkService cfg.instances); + + networking.firewall = lib.mkIf cfg.openFirewall { + allowedTCPPorts = lib.attrsets.mapAttrsToList (name: value: value.serverPort) cfg.instances; + allowedUDPPorts = lib.attrsets.mapAttrsToList (name: value: value.serverPort) cfg.instances; + }; + }; +} + + + diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 031073f..9fce915 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -80,4 +80,7 @@ in # Chia Secrets "chia/farmer.key.age".publicKeys = jake_users ++ [ ts.storage.tywin ]; + + # Storj Secrets + "storj/tywin/zfs_auth.age".publicKeys = jake_users ++ [ ts.storage.tywin ]; } diff --git a/secrets/storj/tywin/zfs_auth.age b/secrets/storj/tywin/zfs_auth.age new file mode 100644 index 0000000..eae1123 --- /dev/null +++ b/secrets/storj/tywin/zfs_auth.age @@ -0,0 +1,22 @@ +age-encryption.org/v1 +-> ssh-rsa GxPFJQ +H8DuH/VcW6DNBt64Ci5XWzmfxHNBZS0THUWhM/CmvW8IL3kCHuwNSTr2CsYPRBpQ +bSrAM2fmwuwPsTAeukkIwF6Umt2/xUDi4rbf/+q7nP36a5mPkNyVCOJ1GANwU0Gr +AtTfU+V8WDT1gB6qD8Ldw9eIomFS9SNr7nPRQ6O4ISCGrkKQF/XzFL4vXkjYlsFv +96UbvOEFpV9GzK+5STNOZ4WpuqQGozXP+JXHkXL5FjBURhClUKxtEtcyr+QYup/e +X+RAuloUvh1wKqXRr59BTEtqntJ3kKUX/S97CMYzS0r17AC6IFLtTSpcWLNuzFzI +tzUxJA1401z3cC1dwhoYvA +-> ssh-rsa K9mW1w +xfcFazRdW6kIqmPDKzDmlpDkx0grzmsvvTOo1rA/cTUVJzqPIY5spz5f51iFm8CX +0KxslTWBzD2jGQ+mcgf/7a4Dx7RZiVWncgEZTeufiCBKfYTvj2iABwcz5rg7fT5P +iU2kDhHB37OkaEiJqG/qJRCdH7/jXUqx/zCQtU1sTP4KX3KAz9jeV75UysFMQG5w +q27WUZDzgI6r/ceHsiWEKqODzHiBqEvYpbOg4ArHycBYgNG8NfTet4pVQsC9H1PL +yXn7SLlwfD4rZaSRfvxDExI5r/URl5ycxRhUczp+8ak96J/Fyt2qa6n4YEgnx67m +tNEiz53xZQluDPUDJLPGFA +-> ssh-ed25519 nWv9MA 58EVNX9E+ZVog6RZiXLxJcxBocfblq3TVWKXHSXsaTI +PElhg1xHV+AwP6YxU99KwQIl+rWVDjOaV3gaCC+IrwM +-> 2-grease bZ?fb]c + +5lZWHejAOCn74H2Xu922YMTJO8tnY3tYjcUiMLT1GuKjxIRFtpKGVkLDa9ubIoRR +psPl/0vDY7qdk+HPvxjAUlmBnQ +--- dWrPZo+vQ7qEjmG+wr3/74+c4oCVqekxZLw3s3t0eUo +zÉo} HjåÝŸ¯²cPÆ<¦˜Ÿ Æ|D£`¶SØ'6¬|…ˆç\³¬:gý›»4öP{ZÅp <ûÕH!óê0€25FVý÷uÆSŠÓqÈ6½Éå_g™sÖ–ÆÑk¤¢³:†l}ÌÑ6öO"…g¾9 ^b¿ãb8>X.jˆàCn%)†Ù­ÊÎÇaè≧ê \ No newline at end of file