diff options
Diffstat (limited to 'nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix')
-rw-r--r-- | nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix | 189 |
1 files changed, 102 insertions, 87 deletions
diff --git a/nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix b/nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix index 1f5c14d777d..f298f831fa7 100644 --- a/nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix +++ b/nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix @@ -1,69 +1,39 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, options, ... }: with lib; let - inherit (pkgs) ipfs runCommand makeWrapper; - cfg = config.services.ipfs; + opt = options.services.ipfs; ipfsFlags = toString ([ (optionalString cfg.autoMount "--mount") - #(optionalString cfg.autoMigrate "--migrate") (optionalString cfg.enableGC "--enable-gc") (optionalString (cfg.serviceFdlimit != null) "--manage-fdlimit=false") (optionalString (cfg.defaultMode == "offline") "--offline") (optionalString (cfg.defaultMode == "norouting") "--routing=none") ] ++ cfg.extraFlags); - defaultDataDir = if versionAtLeast config.system.stateVersion "17.09" then - "/var/lib/ipfs" else - "/var/lib/ipfs/.ipfs"; - - # Wrapping the ipfs binary with the environment variable IPFS_PATH set to dataDir because we can't set it in the user environment - wrapped = runCommand "ipfs" { buildInputs = [ makeWrapper ]; preferLocalBuild = true; } '' - mkdir -p "$out/bin" - makeWrapper "${ipfs}/bin/ipfs" "$out/bin/ipfs" \ - --set IPFS_PATH ${cfg.dataDir} \ - --prefix PATH : /run/wrappers/bin - ''; + splitMulitaddr = addrRaw: lib.tail (lib.splitString "/" addrRaw); + + multiaddrToListenStream = addrRaw: let + addr = splitMulitaddr addrRaw; + s = builtins.elemAt addr; + in if s 0 == "ip4" && s 2 == "tcp" + then "${s 1}:${s 3}" + else if s 0 == "ip6" && s 2 == "tcp" + then "[${s 1}]:${s 3}" + else if s 0 == "unix" + then "/${lib.concatStringsSep "/" (lib.tail addr)}" + else null; # not valid for listen stream, skip + + multiaddrToListenDatagram = addrRaw: let + addr = splitMulitaddr addrRaw; + s = builtins.elemAt addr; + in if s 0 == "ip4" && s 2 == "udp" + then "${s 1}:${s 3}" + else if s 0 == "ip6" && s 2 == "udp" + then "[${s 1}]:${s 3}" + else null; # not valid for listen datagram, skip - - commonEnv = { - environment.IPFS_PATH = cfg.dataDir; - path = [ wrapped ]; - serviceConfig.User = cfg.user; - serviceConfig.Group = cfg.group; - }; - - baseService = recursiveUpdate commonEnv { - wants = [ "ipfs-init.service" ]; - # NB: migration must be performed prior to pre-start, else we get the failure message! - preStart = optionalString cfg.autoMount '' - ipfs --local config Mounts.FuseAllowOther --json true - ipfs --local config Mounts.IPFS ${cfg.ipfsMountDir} - ipfs --local config Mounts.IPNS ${cfg.ipnsMountDir} - '' + concatStringsSep "\n" (collect - isString - (mapAttrsRecursive - (path: value: - # Using heredoc below so that the value is never improperly quoted - '' - read value <<EOF - ${builtins.toJSON value} - EOF - ipfs --local config --json "${concatStringsSep "." path}" "$value" - '') - ({ Addresses.API = cfg.apiAddress; - Addresses.Gateway = cfg.gatewayAddress; - Addresses.Swarm = cfg.swarmAddress; - } // - cfg.extraConfig)) - ); - serviceConfig = { - ExecStart = "${wrapped}/bin/ipfs daemon ${ipfsFlags}"; - Restart = "on-failure"; - RestartSec = 1; - } // optionalAttrs (cfg.serviceFdlimit != null) { LimitNOFILE = cfg.serviceFdlimit; }; - }; in { ###### interface @@ -88,7 +58,9 @@ in { dataDir = mkOption { type = types.str; - default = defaultDataDir; + default = if versionAtLeast config.system.stateVersion "17.09" + then "/var/lib/ipfs" + else "/var/lib/ipfs/.ipfs"; description = "The data dir for IPFS"; }; @@ -98,18 +70,6 @@ in { description = "systemd service that is enabled by default"; }; - /* - autoMigrate = mkOption { - type = types.bool; - default = false; - description = '' - Whether IPFS should try to migrate the file system automatically. - - The daemon will need to be able to download a binary from https://ipfs.io to perform the migration. - ''; - }; - */ - autoMount = mkOption { type = types.bool; default = false; @@ -142,7 +102,12 @@ in { swarmAddress = mkOption { type = types.listOf types.str; - default = [ "/ip4/0.0.0.0/tcp/4001" "/ip6/::/tcp/4001" ]; + default = [ + "/ip4/0.0.0.0/tcp/4001" + "/ip6/::/tcp/4001" + "/ip4/0.0.0.0/udp/4001/quic" + "/ip6/::/udp/4001/quic" + ]; description = "Where IPFS listens for incoming p2p connections"; }; @@ -199,13 +164,21 @@ in { example = 64*1024; }; + startWhenNeeded = mkOption { + type = types.bool; + default = false; + description = "Whether to use socket activation to start IPFS when needed."; + }; + }; }; ###### implementation config = mkIf cfg.enable { - environment.systemPackages = [ wrapped ]; + environment.systemPackages = [ pkgs.ipfs ]; + environment.variables.IPFS_PATH = cfg.dataDir; + programs.fuse = mkIf cfg.autoMount { userAllowOther = true; }; @@ -234,10 +207,14 @@ in { "d '${cfg.ipnsMountDir}' - ${cfg.user} ${cfg.group} - -" ]; - systemd.services.ipfs-init = recursiveUpdate commonEnv { + systemd.packages = [ pkgs.ipfs ]; + + systemd.services.ipfs-init = { description = "IPFS Initializer"; - before = [ "ipfs.service" "ipfs-offline.service" "ipfs-norouting.service" ]; + environment.IPFS_PATH = cfg.dataDir; + + path = [ pkgs.ipfs ]; script = '' if [[ ! -f ${cfg.dataDir}/config ]]; then @@ -251,34 +228,72 @@ in { fi ''; + wantedBy = [ "default.target" ]; + serviceConfig = { Type = "oneshot"; RemainAfterExit = true; + User = cfg.user; + Group = cfg.group; }; }; - # TODO These 3 definitions possibly be further abstracted through use of a function - # like: mutexServices "ipfs" [ "", "offline", "norouting" ] { ... shared conf here ... } + systemd.services.ipfs = { + path = [ "/run/wrappers" pkgs.ipfs ]; + environment.IPFS_PATH = cfg.dataDir; + + wants = [ "ipfs-init.service" ]; + after = [ "ipfs-init.service" ]; - systemd.services.ipfs = recursiveUpdate baseService { - description = "IPFS Daemon"; - wantedBy = mkIf (cfg.defaultMode == "online") [ "multi-user.target" ]; - after = [ "network.target" "ipfs-init.service" ]; - conflicts = [ "ipfs-offline.service" "ipfs-norouting.service"]; + preStart = optionalString cfg.autoMount '' + ipfs --local config Mounts.FuseAllowOther --json true + ipfs --local config Mounts.IPFS ${cfg.ipfsMountDir} + ipfs --local config Mounts.IPNS ${cfg.ipnsMountDir} + '' + concatStringsSep "\n" (collect + isString + (mapAttrsRecursive + (path: value: + # Using heredoc below so that the value is never improperly quoted + '' + read value <<EOF + ${builtins.toJSON value} + EOF + ipfs --local config --json "${concatStringsSep "." path}" "$value" + '') + ({ Addresses.API = cfg.apiAddress; + Addresses.Gateway = cfg.gatewayAddress; + Addresses.Swarm = cfg.swarmAddress; + } // + cfg.extraConfig)) + ); + serviceConfig = { + ExecStart = ["" "${pkgs.ipfs}/bin/ipfs daemon ${ipfsFlags}"]; + User = cfg.user; + Group = cfg.group; + } // optionalAttrs (cfg.serviceFdlimit != null) { LimitNOFILE = cfg.serviceFdlimit; }; + } // optionalAttrs (!cfg.startWhenNeeded) { + wantedBy = [ "default.target" ]; }; - systemd.services.ipfs-offline = recursiveUpdate baseService { - description = "IPFS Daemon (offline mode)"; - wantedBy = mkIf (cfg.defaultMode == "offline") [ "multi-user.target" ]; - after = [ "ipfs-init.service" ]; - conflicts = [ "ipfs.service" "ipfs-norouting.service"]; + systemd.sockets.ipfs-gateway = { + wantedBy = [ "sockets.target" ]; + socketConfig = { + ListenStream = let + fromCfg = multiaddrToListenStream cfg.gatewayAddress; + in [ "" ] ++ lib.optional (fromCfg != null) fromCfg; + ListenDatagram = let + fromCfg = multiaddrToListenDatagram cfg.gatewayAddress; + in [ "" ] ++ lib.optional (fromCfg != null) fromCfg; + }; }; - systemd.services.ipfs-norouting = recursiveUpdate baseService { - description = "IPFS Daemon (no routing mode)"; - wantedBy = mkIf (cfg.defaultMode == "norouting") [ "multi-user.target" ]; - after = [ "ipfs-init.service" ]; - conflicts = [ "ipfs.service" "ipfs-offline.service"]; + systemd.sockets.ipfs-api = { + wantedBy = [ "sockets.target" ]; + # We also include "%t/ipfs.sock" because tere is no way to put the "%t" + # in the multiaddr. + socketConfig.ListenStream = let + fromCfg = multiaddrToListenStream cfg.apiAddress; + in [ "" "%t/ipfs.sock" ] ++ lib.optional (fromCfg != null) fromCfg; }; }; |