Two output folders for one Golang derivation?

I’m trying to build this package (it’s an IRC server) but am having a strange issue. The package definition first, my first Go package but based on other Go packages so it seems to work:

{ stdenv, buildGoPackage, fetchFromGitHub }:

buildGoPackage rec {
  name = "oragono-${version}";
  version = "1.0.0";

  goPackagePath = "github.com/oragono/oragono";

  src = fetchFromGitHub {
    owner = "oragono";
    repo = "oragono";
    rev = "v${version}";
    sha256 = "0fyj3d9bibw4jfxwi1gywjlq5h0myl0mky0kla02b40hsfj9vydp";
  };

  goDeps = ./deps.nix;

  postInstall = ''
    mkdir -p $out/{bin,share}
    cp ${src}/oragono.{motd,yaml} $out/share
    cp -r ${src}/languages/ $out/share
  '';

  meta = with stdenv.lib; {
    homepage = https://oragono.io/;
    description = "A modern IRC server (daemon/ircd) written in Go.";
    maintainers = with maintainers; [ eelco bachp ];
    platforms = platforms.unix;
    license = licenses.mit;
  };
}

It builds fine (deps.nix just contains the dependencies), but it seems that two folders are created for oragono?!

# ll $(which oragono)
lrwxrwxrwx 1 root root 73 Jan  1  1970 /run/current-system/sw/bin/oragono -> /nix/store/azg5bxfcsz7m6qrpignkpj60aymlzf4y-oragono-1.0.0-bin/bin/oragono

# ls /nix/store/azg5bxfcsz7m6qrpignkpj60aymlzf4y-oragono-1.0.0-bin/
bin

…yet, if I list all folders without the suffix -bin this is what I can see:

# ll /nix/store/*oragono-1.0.0/
/nix/store/ks7v9i91przigzmm0gj57s4c7znx0705-oragono-1.0.0/:
total 12
dr-xr-xr-x 2 root root 4096 Jan  1  1970 bin
dr-xr-xr-x 2 root root 4096 Jan  1  1970 nix-support
dr-xr-xr-x 3 root root 4096 Jan  1  1970 share

# ll /nix/store/*oragono-1.0.0/share
/nix/store/ks7v9i91przigzmm0gj57s4c7znx0705-oragono-1.0.0/share:
total 36
dr-xr-xr-x 3 root root 12288 Jan  1  1970 languages
-r--r--r-- 1 root root  2052 Jan  1  1970 oragono.motd
-r--r--r-- 1 root root 17360 Jan  1  1970 oragono.yaml

When I try to setup a service for this, it seems that the $out variable points to the binary only folder:

    systemd.services.oragono = {
      description = "oragono server";
      wantedBy = [ "multi-user.target" ];
      after = [ "network.target" ];
      path = [ pkgs.coreutils pkgs.procps pkgs.oragono ];

      preStart = ''
        cp ${pkgs.oragono}/share/* ${cfg.workingDir}/
        chown -R ${cfg.user}:${cfg.group} ${cfg.workingDir}
      '';

      serviceConfig = {
        ExecStart = ''${pkgs.oragono}/bin/oragono run --conf ${cfg.configFile}'';
        ExecReload = ''${pkgs.procps}/bin/pkill -HUP oragono'';
        User = cfg.user;
        Group = cfg.group;
      };
    };

…but the service wont start:

● oragono.service - oragono server
   Loaded: loaded (/nix/store/7b1lzx6760m5l3a5grq8wnxwhhs3nlqy-unit-oragono.service/oragono.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Wed 2019-04-10 16:00:04 CEST; 1h 1min ago
  Process: 16120 ExecStartPre=/nix/store/jgldj2s06v1ddgzjgjn6g0x2alrl419p-unit-script-oragono-pre-start (code=exited, status=1/FAILURE)

Apr 10 16:00:04 pacioli systemd[1]: Starting oragono server...
Apr 10 16:00:04 pacioli jgldj2s06v1ddgzjgjn6g0x2alrl419p-unit-script-oragono-pre-start[16120]: cp: cannot stat '/nix/store/azg5bxfcsz7m6qrpignkpj60aymlzf4y-oragono-1.0.0-bin/share/*': No such file or directory
Apr 10 16:00:04 pacioli systemd[1]: oragono.service: Control process exited, code=exited status=1
Apr 10 16:00:04 pacioli systemd[1]: oragono.service: Failed with result 'exit-code'.
Apr 10 16:00:04 pacioli systemd[1]: Failed to start oragono server.

…so what am I missing here? :slight_smile:

This is because buildGoPackage is using multiple outputs (see the Nix/nixpkgs manual).

I suspect oragono is simply looking for share relative to it’s binary which will clearly not work.

I suggest one of the following:

  • Install the share directory in $bin (low effort, should “just work”)

  • Patch upstream (preferable but more work)

  • Make a single output derivation and install everything in $out

1 Like

Thank you for the reply!

The files I was trying to refer to are translation files and similar, and the plan was to copy these from the output directory to a folder from which the program could reliably read them (/var/run/oragono as configured in the service), all of this to avoid understanding how to have nix handle generating the configuration files :smiley:

But, after reading the multiple output section in the manual, is it safe to assume that I could use something like ${pkgs.oragono.lib}/share/ and that would point to the folder I copied my translations to? Or should it be ${pkgs.oragono.out}/share? The manual is not entirely clear, at least not for me today. :slight_smile:

Edit: figured it out, used ${pkgs.oragono.out}!

Also with the new buildGoModule we switched to a single ouput again.
buildGoPackage used to have multiple outputs because $out would also contain the source code.
Later we dropped this but for compatibility will still have both $out and $bin.

1 Like