Change:
Describe the bug IPFS module should use upstream systemd files for socket-based activation. Right now we have a custom service file that is different from the one in ipfs-go 0.5.0. This is something quickly I can do. /cc

Discussion:
<del> { config, lib, pkgs, ... }: </del> <ins> { config, lib, pkgs, options, ... }: </ins> with lib; let <del> inherit (pkgs) ipfs runCommand makeWrapper; </del> cfg = config.services.ipfs; <ins> opt = options.services.ipfs; </ins> ipfsFlags = toString ([ (optionalString  cfg.autoMount                   "--mount") <del> #(optionalString  cfg.autoMigrate                 "--migrate") </del> (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); <del> 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 ''; 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; }; }; </del> in { ###### interface

dataDir = mkOption { type = types.str; <del> default = defaultDataDir; </del> <ins> default = if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/ipfs" else "/var/lib/ipfs/.ipfs"; </ins> description = "The data dir for IPFS"; };

description = "systemd service that is enabled by default"; }; <del> /* 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. ''; }; */ </del> autoMount = mkOption { type = types.bool; default = false;

example = 64*1024; }; <ins> startWhenNeeded = mkOption { type = types.bool; default = false; description = "Whether to use socket activation to start IPFS when needed."; }; </ins> }; }; ###### implementation config = mkIf cfg.enable { <del> environment.systemPackages = [ wrapped ]; </del> <ins> environment.systemPackages = [ pkgs.ipfs ]; environment.variables.IPFS_PATH = cfg.dataDir; </ins> programs.fuse = mkIf cfg.autoMount { userAllowOther = true; };

"d '${cfg.ipnsMountDir}' - ${cfg.user} ${cfg.group} - -" ]; <del> systemd.services.ipfs-init = recursiveUpdate commonEnv { </del> <ins> systemd.packages = [ pkgs.ipfs ]; systemd.services.ipfs-init = { </ins> description = "IPFS Initializer"; <del> before = [ "ipfs.service" "ipfs-offline.service" "ipfs-norouting.service" ]; </del> <ins> environment.IPFS_PATH = cfg.dataDir; path = [ pkgs.ipfs ]; </ins> script = '' if [[ ! -f ${cfg.dataDir}/config ]]; then

fi ''; <ins> wantedBy = [ "default.target" ]; </ins> serviceConfig = { Type = "oneshot"; RemainAfterExit = true; <ins> User = cfg.user; Group = cfg.group; </ins> }; }; <del> # TODO These 3 definitions possibly be further abstracted through use of a function # like: mutexServices "ipfs" [ "", "offline", "norouting" ] { ... shared conf here ... } </del> <ins> systemd.services.ipfs = { path = [ "/run/wrappers" pkgs.ipfs ]; environment.IPFS_PATH = cfg.dataDir; wants = [ "ipfs-init.service" ]; after = [ "ipfs-init.service" ]; </ins> <del> 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"]; </del> <ins> 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" ]; </ins> }; <del> 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"]; </del> <ins> systemd.sockets.ipfs-gateway = { wantedBy = [ "sockets.target" ]; socketConfig.ListenStream = [ "" ] ++ lib.optional (cfg.gatewayAddress == opt.gatewayAddress.default) [ "127.0.0.1:8080" "[::1]:8080" ]; </ins> }; <del> 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"]; </del> <ins> systemd.sockets.ipfs-api = { wantedBy = [ "sockets.target" ]; socketConfig.ListenStream = [ "" "%t/ipfs.sock" ] ++ lib.optional (cfg.apiAddress == opt.apiAddress.default) [ "127.0.0.1:5001" "[::1]:5001" ]; </ins> }; };

) machine.succeed(f"ipfs cat /ipfs/{ipfs_hash.strip()} | grep fnord") <ins> ipfs_hash = machine.succeed( "echo fnord2 | ipfs --api /unix/run/ipfs.sock add | awk '{ print $2 }'" ) machine.succeed( f"ipfs --api /unix/run/ipfs.sock cat /ipfs/{ipfs_hash.strip()} | grep fnord2" ) </ins> ''; })

vendorSha256 = null; <ins> postInstall = '' install -D misc/systemd/ipfs.service $out/etc/systemd/system/ipfs.service install -D misc/systemd/ipfs-api.socket $out/etc/systemd/system/ipfs-api.socket install -D misc/systemd/ipfs-gateway.socket $out/etc/systemd/system/ipfs-gateway.socket substituteInPlace $out/etc/systemd/system/ipfs.service  --replace /usr/bin/ipfs $out/bin/ipfs ''; </ins> meta = with stdenv.lib; { description = "A global, versioned, peer-to-peer filesystem"; homepage = "https://ipfs.io/";