diff --git a/.sops.yaml b/.sops.yaml index 5ae16b1..fccf6a6 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -1,9 +1,17 @@ keys: - &walkah age16yv7atd8n880ja98pksqqvunu2yw00660lkh4n0sg39j5vt3dujshyu95j - &plato age12m47c7xvqttncps0e79pwamzqa4nmnxekwumtwcv5ju6q74fufaqp9d0xh + - &agent age1vc8svd5277rjkgzg7frf04uaa45w3crhfvg628rqyrqmxul3q9nsjz6yxk + - &form age1ulmzprdmcd8r0w47a0nrrlg8melkjk6evl2rc54yh6lxkcfas36q6wrsv9 + - &matter age1lfjkch3pqaq3uwmjxyucpm2tws6llxqqjglj4yn49jkwkf50xvmqrl974e + - &purpose age1jnf94uq5ap96vk7nfk3qkr38ylhletc6pskj0ypc470d7gmt0qeqskdy5z creation_rules: - path_regex: secrets/[^/]+\.yaml$ key_groups: - age: - *walkah - - *plato \ No newline at end of file + - *plato + - *agent + - *form + - *matter + - *purpose \ No newline at end of file diff --git a/hosts/aristotle/configuration.nix b/hosts/aristotle/configuration.nix index 7eef02c..8a7d3a7 100644 --- a/hosts/aristotle/configuration.nix +++ b/hosts/aristotle/configuration.nix @@ -6,6 +6,7 @@ ./rpi-poe.nix ../../modules/ipfs/cluster.nix + ../../modules/sops ]; # Use the extlinux boot loader. (NixOS wants to enable GRUB by default) diff --git a/modules/ipfs/cluster.nix b/modules/ipfs/cluster.nix index 7c53b18..94bc140 100644 --- a/modules/ipfs/cluster.nix +++ b/modules/ipfs/cluster.nix @@ -1,7 +1,11 @@ { config, lib, pkgs, ... }: { - imports = [ ./default.nix ]; + imports = [ + ./default.nix + ../../services/ipfs-cluster.nix + ]; + services = { ipfs = { enable = true; @@ -17,5 +21,15 @@ }; }; }; + + ipfs-cluster = { + enable = true; + consensus = "crdt"; + secretFile = config.sops.secrets.ipfs-cluster-secret.path; + }; + }; + + sops.secrets.ipfs-cluster-secret = { + owner = "ipfs"; }; } diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml index 985e33a..3098f49 100644 --- a/secrets/secrets.yaml +++ b/secrets/secrets.yaml @@ -1,4 +1,5 @@ -matrix-registration-secret: ENC[AES256_GCM,data:w/rq68h8VU7oivm9in8CuMPWipX76LqJwq4A2lWANZgAxK3KwOdRAmH81O0W9v5xNTFYf/JJmfLXrBf8mLyLT6Ng8tcJwkZmNrwpEf91gO6jK0bwKz9RBKmwBeg=,iv:W2zqyrsQb2XHcPZZ5W4evmbSex4v3RRiP+fF0AU2EB0=,tag:OJDk1DbAYY8ucH1JIoA6ew==,type:str] +matrix-registration-secret: ENC[AES256_GCM,data:Sn3pGBq4U3Tgw0pYaetnBLRiNdFGnMxAxyfrxhF9kFDMFijKSy9XBj71M5XxV4shYQyPvu2WDnPR1YvyoQVlv8cEoXhX7++JlYsp/2ZfKIzp4iMxh24z57Cw8vg=,iv:/zxlIeI9gWWCHbejYgz8pjjOrukKome0/bmcXuG3/yE=,tag:3fc3c96H3pO1FUO7p3T4gw==,type:str] +ipfs-cluster-secret: ENC[AES256_GCM,data:Z9i7ZLhlXw4m8myNUSiY5ej2/6UIwCwIe0bvbCttVLdv8cAHwzR2f22poKD6KnPBe9yaym+X3YtrHTCM4pVIbiSzMsHwYZ00vRQi35ZmYg==,iv:9PBz/olzA4X7JEL1xG8ACUaH1WDHSzApzlG5q0ZqSYk=,tag:9I4PGf91MHAKNeG4fVKIow==,type:str] sops: kms: [] gcp_kms: [] @@ -8,23 +9,59 @@ sops: - recipient: age16yv7atd8n880ja98pksqqvunu2yw00660lkh4n0sg39j5vt3dujshyu95j enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzMW9GbTVQWjdOaUVJNjJH - VUhsSGxLb1NlU2NXTjRqYklLUlYxRnpkbm44CjRZU2lNTTlERmFHYTRoL0dRWjRq - QUhkYjBsK2NyWDMzL004aDZBMGJrNjgKLS0tIFNHbEl2ejZJK0tGeEcyRTk3TU9S - MmFZc29kdEFlL202emU3cUhwMytUeXMK429JtnxnZfDl8Op2NSz40xUXKO2XWICY - I0Z2xOATxOq9N1MvNbD6HheT8ngUtu/LQJXcsDIHk0MkzBJRe8u79A== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXNkhRdXhFTVkxVTNVTlhK + d0xiQ3VmcURreWFzVGxVb0RPK2RNMGVob2g0CnBkZzF4U0FrWVVVbW03Umliby9P + djNUKzFWbW0xR1QyOUh3d2g5SjNsUW8KLS0tIGRhamZvOERxUmxDdDNHM1ZUbzdZ + UjJUQS9vL2ZkQ3NCd1VwLzRMQS9Xc0EKKcGxURwN3ejTk41W/q5VVrhalPO4GOdr + JvdxH7OIn+u/8KNNXgKOPV8Iss35Mu4geSh1zJXPVf+YhTZNq8C2jQ== -----END AGE ENCRYPTED FILE----- - recipient: age12m47c7xvqttncps0e79pwamzqa4nmnxekwumtwcv5ju6q74fufaqp9d0xh enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZNklPdm52OHVzL0cxOHRI - cVdFcW0zL0RuYXJJbzlTZjI0dkxoQThjVG5zCldCLzE3cGF0ZGJTZ0dBajFaMktr - ZDA3WHFaQzJONmlUSXBrNzY5MHJTT1EKLS0tIHczU2JVc2RhVmc1Y01NOWZHclly - QXJkUkFMS1ZCcXl1ZCsvUmdqeVVvc0EK9xP+VkSN61gLwMwwlOFCpLsfL6Jzk7CB - 5LfW5lsyWCMqnw00W52h177kHZdf/nLmnoLDz2jZ7hPXiDpS7G9MrA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCTkxOWEo0Nk9iMy8zUGFP + endwS2NQQWJnVmo3RTNyYiszMndtSGNZUjFJCmZzUTZidmNWVGxVWDduUldMaXV4 + SnZTMTZaU3FUNFpwbjBTQk94azhRZ2sKLS0tIDU1R1cwZDJQZW5qcXkyLzZIQitV + ZUptMXcvcXhkNUdRZDc2WmF3c2tLeXMKnicAN5U1KO/vhJxGgv/oHGPJ4mEoVogL + Gv5RTCKMwfHgdEHOUPbq/kPz0eTc9R57XsfhA7DHpgZAxo86gZNqOg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2021-11-15T03:21:59Z" - mac: ENC[AES256_GCM,data:XpHNSRFlPz/6IhAZ+GDiGinLFRNxrxoBQEXesJX2qnhD0qYE03429zt0MUpH+/0SCXQ3zEd+nbUYSP3+ZMW1K3qb4QcWgnyQUelZFZ7INjz0ljGSplphA+/eLbgh/PnwgsWhoGsbcLLIUv6FGkQNDLL0Y+wFBCr9mDfz5vbjbTs=,iv:3qUeFgrbdhHWu4/S0Z6uutvEtvVYYBI2/yjDo/YJ4Kw=,tag:2joVAJE/QV+xaRArL7G1EA==,type:str] + - recipient: age1vc8svd5277rjkgzg7frf04uaa45w3crhfvg628rqyrqmxul3q9nsjz6yxk + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNcjdmckwyVVJkQXpScTU2 + WWt1MHFhTExxbCtwT1ZGWlZRZ3orRmZpYUZjCmNySmRVWkV4TEIyU09SUXNLdGFZ + VjN5RFhwelFvVW1PR04rQ3NyU0trVHcKLS0tIDVZZGt5TnZNU21PbE9PZVVtTUdI + eXhsWlkwa3l2Zk9KTkc0dzZpajFxVmcKTmhGMdS0Uq32P5I+X+8h4ve/KHvHWA/a + Juu+VjGRe7hm0pWOutDQPbL6o8l+wij2ugDsNy3LKHbWs4lM5VZEHg== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ulmzprdmcd8r0w47a0nrrlg8melkjk6evl2rc54yh6lxkcfas36q6wrsv9 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5MFRGVllUM0R2VXB0bmtj + dXV2bDFvbmpjTktZRlpKUXRPMXdwdmRxL3o4Cmg2WjRFdTgydkd5OHp2dS9TRlhG + Y29NOUVEeXptYWhzMGVJOENrTjdpdUEKLS0tIEZzOGlsWGJPMitkTVpwTC82Uzdh + NDhRVGQweXhEdFk4bHQxOWFOSmxNYVkKlb9KvHfUnM7uApzed5zvFPh7X8QMbdE/ + VSlmccOG1zlbstbr4mU/Xu+52FMBsp8UEkK29y07uhZQEh/txI9Wwg== + -----END AGE ENCRYPTED FILE----- + - recipient: age1lfjkch3pqaq3uwmjxyucpm2tws6llxqqjglj4yn49jkwkf50xvmqrl974e + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiSWRSdGUvRnFuZUtPcG9T + N3FsWldiOTBLUXQ0SHd1UTk2T3ArNkpaN3l3CnBtN1o0SGY5S1Z3WnVhcVYrRUYr + S0htZUh3RlQvYkV4Rmg2b3NPOFdCQkkKLS0tIEVUdVNxRnFZVlFKd3R4d1dCZk9N + cHo2empQdDd4TTZJckczdzU3YVJZeW8K0tFG5fMFiVqAw0HqEV3F8yV6tLV/XY2e + R8Rp2kAcPvBNdHZ52oKyGZNgblg5uia4mBjbvB8iXkX/z8Bddo/vCQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age1jnf94uq5ap96vk7nfk3qkr38ylhletc6pskj0ypc470d7gmt0qeqskdy5z + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwYk5PazQ2U2ZiYU03K28v + elhtQjllbThwOE5Ockd4S1B6Z1AvNmNjcXlrCmZyTzMyUWFmcEZGazRWTG40bmJI + TXkvOXpWVW1TYkcxckRtT3N6Y1BuZEUKLS0tIDBPRkJ0M3Y2T1NxN0RtbW1aNUhL + alB4LzZGSTJmUEt0TFBkUTdzR1pOOTQKG8T65JhLKx602YnEmG/Gqi/rY8X/9XgF + 61ejhZ1DucTrM3sfUKjTFwaNVJLJgGEoPRioZW0SJkckjm5NNlutLw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2021-11-16T01:39:44Z" + mac: ENC[AES256_GCM,data:fDm9ReOiKh0QpKXxL+1BBj8Ewa0rGNeeacRr2L2IWeb51i6KhE+9q/9s6/x3m1z9NcR3BFrdw/yhOakYjcfrMiBtgZMwkJ+17KieKrgPz95lKD/udZeiemlimUQZn6E2HuTj8lGRw1mJLGdlSgZrAtTKYzuUezcvqtX/zmMahmw=,iv:ju81TbXRZRhGI6oGn2NSpXCMnK7PtcaHH8RmDAOjP8k=,tag:z8pt/6a1WXVOB3hndZPGJw==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.7.1 diff --git a/services/ipfs-cluster.nix b/services/ipfs-cluster.nix new file mode 100644 index 0000000..28c28e2 --- /dev/null +++ b/services/ipfs-cluster.nix @@ -0,0 +1,122 @@ +## From https://github.com/NixOS/nixpkgs/pull/100871 +{ config, lib, pkgs, options, ... }: +with lib; +let + cfg = config.services.ipfs-cluster; + opt = options.services.ipfs-cluster; + + # secret is by envvar, not flag + initFlags = toString [ + (optionalString (cfg.initPeers != [ ]) "--peers") + (lib.strings.concatStringsSep "," cfg.initPeers) + ]; +in { + + ###### interface + + options = { + + services.ipfs-cluster = { + + enable = mkEnableOption + "Pinset orchestration for IPFS - requires ipfs daemon to be useful"; + + user = mkOption { + type = types.str; + default = "ipfs"; + description = "User under which the ipfs-cluster daemon runs."; + }; + + group = mkOption { + type = types.str; + default = "ipfs"; + description = "Group under which the ipfs-cluster daemon runs."; + }; + + consensus = mkOption { + type = types.enum [ "raft" "crdt" ]; + description = "Consensus protocol - 'raft' or 'crdt'. https://cluster.ipfs.io/documentation/guides/consensus/"; + }; + + dataDir = mkOption { + type = types.str; + default = "/var/lib/ipfs-cluster"; + description = "The data dir for ipfs-cluster."; + }; + + initPeers = mkOption { + type = types.listOf types.str; + default = [ ]; + description = "Peer addresses to initialize with on first run."; + }; + + openSwarmPort = mkOption { + type = types.bool; + description = "Open swarm port, secured by the cluster secret. This does not expose the API or proxy. https://cluster.ipfs.io/documentation/guides/security/"; + }; + + secretFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + File containing the cluster secret in the format of EnvironmentFile as described by + systemd.exec + 5. For example: + + CLUSTER_SECRET=... + + + if null, a new secret will be generated on first run. + A secret in the correct format can also be generated by: openssl rand -hex 32 + ''; + }; + }; + }; + + ###### implementation + + config = mkIf cfg.enable { + environment.systemPackages = [ pkgs.ipfs-cluster ]; + + + systemd.tmpfiles.rules = + [ "d '${cfg.dataDir}' - ${cfg.user} ${cfg.group} - -" ]; + + systemd.services.ipfs-cluster-init = { + path = [ "/run/wrappers" pkgs.ipfs-cluster ]; + environment.IPFS_CLUSTER_PATH = cfg.dataDir; + wantedBy = [ "default.target" ]; + + serviceConfig = { + # "" clears exec list (man systemd.service -> execStart) + ExecStart = [ + "" + "${pkgs.ipfs-cluster}/bin/ipfs-cluster-service init --consensus ${cfg.consensus} ${initFlags}" + ]; + Type = "oneshot"; + RemainAfterExit = true; + User = cfg.user; + Group = cfg.group; + } // optionalAttrs (cfg.secretFile != null) { + EnvironmentFile = cfg.secretFile; + }; + unitConfig.ConditionDirectoryNotEmpty = "!${cfg.dataDir}"; + }; + + systemd.services.ipfs-cluster = { + environment.IPFS_CLUSTER_PATH = cfg.dataDir; + wantedBy = [ "multi-user.target" ]; + + wants = [ "ipfs-cluster-init.service" ]; + after = [ "ipfs-cluster-init.service" ]; + + serviceConfig = { + ExecStart = + [ "" "${pkgs.ipfs-cluster}/bin/ipfs-cluster-service daemon" ]; + User = cfg.user; + Group = cfg.group; + }; + }; + networking.firewall.allowedTCPPorts = mkIf cfg.openSwarmPort [ 9096 ]; + }; +}