Combining override and overrideAttrs

Recently, I had to recompile Nginx web server to include GeoIP module into the server package. For this, I’ve used overrideAttrs function:

services.nginx.package = pkgs.nginx.overrideAttrs (oldAttrs: rec {
      configureFlags = oldAttrs.configureFlags ++ [ "--add-module=${ngx_http_geoip2_module}" ];
      buildInputs = oldAttrs.buildInputs ++ [ pkgs.libmaxminddb ];
    });

But now, when I need to add ipscrub module, I’m struggling how to combine those code, I’m already using and code to include ipscrub module:

services.nginx.package = pkgs.nginx.override {
    modules = with pkgs.nginxModules; [ ipscrub ];
  };

Can someone please advice correct way of including both GeoIP and ipscrub module?

1 Like

Simple, you just need to set some parens like so

(pkgs.nginx.overrideAttrs (oldAttrs: rec {
    configureFlags = oldAttrs.configureFlags ++ [ "--add-module=${ngx_http_geoip2_module}" ];
    buildInputs = oldAttrs.buildInputs ++ [ pkgs.libmaxminddb ];
  })
).override{ modules = with pkgs.nginxModules; [ ipscrub ]; };
2 Likes

It causes this syntax error:

error: syntax error, unexpected '(', at /etc/nixos/geoip.nix:47:3
(use '--show-trace' to show detailed location information)
building Nix...
error: syntax error, unexpected '(', at /etc/nixos/geoip.nix:47:3
(use '--show-trace' to show detailed location information)
building the system configuration...
error: syntax error, unexpected '(', at /etc/nixos/geoip.nix:47:3

By unexpected ( it means those () that are placed around pkgs.nginx.overrideAttrs snippet

Can you please share the complete snippet as you have it?

That it marks column 3 looks really suspicious to me…

Here it is. I stripped the let part. I hope that it won’t be an obstacle. Let me know if you need something else.

{ config, pkgs, lib, ... }:
let
  ...
in
{
  (services.nginx.package = pkgs.nginx.overrideAttrs (oldAttrs: rec {
      configureFlags = oldAttrs.configureFlags ++ [ "--add-module=${ngx_http_geoip2_module}" ];
      buildInputs = oldAttrs.buildInputs ++ [ pkgs.libmaxminddb ];
  })).override{ modules = with pkgs.nginxModules; [ipscrub]; };
  users.groups.srv = {};
  users.users.geoip = {
    isSystemUser = true;
    group = "srv";
    description = "GeoIP database updater";
  };
  systemd.timers.geoip-updater =
    { description = "GeoIP Updater Timer";
      partOf = [ "geoip-updater.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = geolite2UpdaterConfig.interval;
      timerConfig.Persistent = "true";
      timerConfig.RandomizedDelaySec = "3600";
    };

  systemd.services.geoip-updater = {
    description = "GeoIP Updater";
    after = [ "network-online.target" "nss-lookup.target" ];
    wants = [ "network-online.target" ];
    preStart = with geolite2UpdaterConfig; ''
      mkdir -p "${databaseDir}"
      chmod 755 "${databaseDir}"
      chown geoip:srv "${databaseDir}"
    '';
    serviceConfig = {
      ExecStart = "${geolite2UpdaterConfig.geoip-updater}/bin/geoip-updater";
      User = "geoip";
      PermissionsStartOnly = true;
    };
  };

  systemd.services.geoip-updater-setup = {
    description = "GeoIP Updater Setup";
    after = [ "network-online.target" "nss-lookup.target" ];
    wants = [ "network-online.target" ];
    wantedBy = [ "multi-user.target" ];
    conflicts = [ "geoip-updater.service" ];
    preStart = with geolite2UpdaterConfig; ''
      mkdir -p "${databaseDir}"
      chmod 755 "${databaseDir}"
      chown geoip:srv "${databaseDir}"
    '';
    serviceConfig = {
      ExecStart = "${geolite2UpdaterConfig.geoip-updater}/bin/geoip-updater --skip-existing";
      User = "geoip";
      PermissionsStartOnly = true;
      # So it won't be (needlessly) restarted:
      RemainAfterExit = true;
    };
  };
}

You got the parens a bit wrong, services.nginx.package needs to be out of the poarens

Just tried doing it this way:

services.nginx.package = (services.nginx.package = pkgs.nginx.overrideAttrs (oldAttrs: rec {
      configureFlags = oldAttrs.configureFlags ++ [ "--add-module=${ngx_http_geoip2_module}" ];
      buildInputs = oldAttrs.buildInputs ++ [ pkgs.libmaxminddb ];
  })).override{ modules = with pkgs.nginxModules; [ipscrub]; };

Got:

error: syntax error, unexpected '=', expecting ')', at /etc/nixos/geoip.nix:47:52
(use '--show-trace' to show detailed location information)
building Nix...
error: syntax error, unexpected '=', expecting ')', at /etc/nixos/geoip.nix:47:52
(use '--show-trace' to show detailed location information)
building the system configuration...
error: syntax error, unexpected '=', expecting ')', at /etc/nixos/geoip.nix:47:52
(use '--show-trace' to show detailed location information)

Yes. Because you still have services.nginx.pacakge = within the parens.

You mean that I should pull it out from the in{} scope?

Sorry, I do not understand.

You want to set the services.nginx.pacakge option. That is what you put on the left hand side of the =.

You want to give it the value (pkgs.nginx.overrideAttrs (oldAttrs: rec { configureFlags = oldAttrs.configureFlags ++ [ "--add-module=${ngx_http_geoip2_module}" ]; buildInputs = oldAttrs.buildInputs ++ [ pkgs.libmaxminddb ]; })).override{ modules = with pkgs.nginxModules; [ipscrub]; }, that is what you put on the right hand side of the =.

Yes, that’s correct. Then it seems that I misunderstood, what do you mean by saying that my services.nginx.package option is between the parenthesis

You literally had foo = (foo = …), that additional foo = within the parens was your problem.

1 Like

Oh, I got it. Now it works :slight_smile: Sorry for misunderstanding

1 Like