How to import a service module from GitLab in my NixOS configuration.nix?

I’m trying to deploy a one-shot Python script to my NixOS server. I have the application set up and working with Nix locally on my Mac. The script needs to be activated by a systemd timer, so I’ve written a service.nix file in the repository that the package is in.

I’m attempting to include the package in /etc/nixos/configuration.nix like so:

{ config, pkgs, ... }:

let
  superficial = pkgs.fetchFromGitLab {
    owner = "slice";
    repo = "superficial";
    rev = "...";
    sha256 = "...";
  };
in
{
  imports = [
    ./hardware-configuration.nix
    "${superficial}/service.nix"
  ];

  services.superficial = {
    enable = true;
    ...
  };

  ...
}

From my understanding, the fetchFromGitLab downloads the source code tarball from GitLab, and I can just use the package by referencing it in imports because the service.nix module contains a pkgs.callPackage ./derivation.nix {} call, which means that the package should be built as well.

I’m running into infinite recursion errors, though:

error: infinite recursion encountered, at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:305:28
(use '--show-trace' to show detailed location information)
building Nix...
error: infinite recursion encountered, at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:305:28
(use '--show-trace' to show detailed location information)
building the system configuration...
error: infinite recursion encountered, at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:305:28
(use '--show-trace' to show detailed location information)

This happens if I reference the superficial package in the imports declaration at all. Nix doesn’t even bother to fetch the tarball. So… how do I import my service properly?

nix-info -m:

 - system: `"x86_64-linux"`
 - host os: `Linux 5.10.52, NixOS, 21.05.1666.537678cb1ea (Okapi)`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.3.14`
 - channels(root): `"nixos-21.05.1666.537678cb1ea, nixos-unstable-21.11pre301044.87807e64a5e"`
 - channels(slice): `""`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`

Okay, a friend helped me solve this.

You have to use builtins.fetchGit or alternatively builtins.fetchTarball instead of pkgs.fetchFromGitLab. This is because importing a module that itself comes from an evaluation depending on pkgs (such as pkgs.fetchFromGitLab) can trigger the reevaluation of pkgs, causing the infinite recursion.

Hypothetically one could also do (import <nixpkgs> {}).fetchFromGitLab to avoid depending on the module argument and also sidestepping the error, but I haven’t tested that.