Build GoLang code provided not as Go module

I’m trying to build binary and provision it as a NixOS package, but official NixPkgs documentation only includes way of building Go modules, which means that Go code has to have go.mod inside, and vendoring set up. But in my case, I have just regular repository, which, imperatively I would have built, like this:

go build -o $BIN_PATH

Is there’s a way to build GoLang source code in NixOS, without it being a Go module?

There is a section about legacy projects.

Though they require indeed that dependencies are either vendored or specified manually in the list assigned to goDeps.

How do I now use it? I designed my config, the way it described in the manual, and it was able to build it successfully:

{ stdenv, fetchFromGitHub, buildGoPackage, ... }:
  buildGoPackage rec {
    version = "1.0.1";
    name = "nginx-mail-auth-http";

    goPackagePath = "github.com/dcmediahosting/nginx-mail-auth-http";
    subPackages = [ "types" ];

    src = fetchFromGitHub {
      owner = "dcmediahosting";
      repo = "nginx-mail-auth-http";
      rev = "${version}";
      sha256 = "18r4var9s1rdxymf1k3shcw4bfyscy8899786ipa4bl1f1jfghci";
    };

    buildFlags = [ "--tags" "release" ];
}

But, now, when I’m trying to use it in NixOS confifg:

{ pkgs, ... }:
{
  systemd.services.nginxAuth = {
    serviceConfig = {
      ExecStart = "${pkgs.nginx-mail-auth-http}/bin/nginx-mail-auth-http";
    };
  };
}

Nix interpreter returns error error: attribute 'nginx-mail-auth-http' missing
How do I make it appear in the NixOS environment. I’ve already did simillar thing with scripts, created with writeScriptBin function, but I think, overlays are not suitable there. Or, am I wrong?

How do you include your derivation into your configuration?

Basically it seems as if it is pretty much the same question as in Infinite recursion at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix while building Rust crate - #10 by anon22412468?

Yeah, sorry. Forgot about that question. I’m using server on NixOS, in production environment, but I rather new to it, that’s why I have to ask many questions to handle server administration :slight_smile:

Yes, I need to get this package into ${pkgs}. I was able to get scripts, I write, into ${pkgs} using:

nixpkgs.overlays = [(self: super: {
    helloWorld = pkgs.writeScriptBin "helloWorld" ''
      #!${pkgs.stdenv.shell}
      echo Hello World
    '';
  })];

If there’s a way to do so for packages, I built from source, that’s would be a great solution

It works exactly the same, you can even use the same overlay.

Though you shouldn’t use pkgs within the overlay, as the overlay modifies it. That’s prone to infinite recursion.

As a rule of thumb, refer to packages from super and functions from self. As self is roughly to describe as the package set after all modifications and at the same time what will become pkgs eventually, and that is actually why your snippet does not infinitely recurse.

To get your attributes into pkgs eventually, adding the following attribute should suffice:

nginx-mail-auth-http = self.callPackage ./the-file.nix {};
1 Like

Sorry for bothering, again, but could you please give a hint, about, what I did wrong here:

{ pkgs, stdenv, fetchFromGitHub, buildGoPackage, ... }:
{
  nixpkgs.overlays = [(self: super: {
    nginxAuth = buildGoPackage rec {
      version = "1.0.1";
      name = "nginx-mail-auth-http";

      goPackagePath = "github.com/dcmediahosting/nginx-mail-auth-http";
      subPackages = [ "types" ];

      src = fetchFromGitHub {
        owner = "dcmediahosting";
        repo = "nginx-mail-auth-http";
        rev = "${version}";
        sha256 = "18r4var9s1rdxymf1k3shcw4bfyscy8899786ipa4bl1f1jfghci";
      };
      buildFlags = [ "--tags" "release" ];
    };
  })];
  systemd.services.nginxAuth = {
    serviceConfig = {
      ExecStart = "${pkgs.nginxAuth}/bin/nginx-mail-auth-http";
    };
  };
  environment.etc."nginx-mail-auth-http/config.json" = ''
{
    "default": {
        "imap": {
            "ip": "127.0.0.1",
            "port": 143
        },
        "smtp": {
            "ip": "127.0.0.1",
            "port": 587
        }
    }
}
  '';
}

It fails with an error:

error: attribute 'buildGoPackage' missing, at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:217:28

Do you want this to be a module or a package?

The argumentset at the top looks like for a package, while the returned attribute set looks like beeing for a module.

I want it to be package

Then keep the argument set and the buildGoPackage call in that file, such that it looks roughly like this:

{ pkgs, stdenv, fetchFromGitHub, buildGoPackage, ... }:

buildGoPackage rec {
      version = "1.0.1";
      name = "nginx-mail-auth-http";

      goPackagePath = "github.com/dcmediahosting/nginx-mail-auth-http";
      subPackages = [ "types" ];

      src = fetchFromGitHub {
        owner = "dcmediahosting";
        repo = "nginx-mail-auth-http";
        rev = "${version}";
        sha256 = "18r4var9s1rdxymf1k3shcw4bfyscy8899786ipa4bl1f1jfghci";
      };
      buildFlags = [ "--tags" "release" ];
    }

From your modules where you define the overlay, add a line as suggested earlier.