Overriding a module

Hey!

I am trying to change the MIME types definition in NixOS nginx module. It is using pkgs.mailcap, so as a first option, I have added the following overlay:

self: super:
{
  mailcap = super.mailcap.override {
    fetchzip = { ... } @ args:
      super.fetchzip ({
        sha256 = "1ah9jz80md2w4livm4qnc08haym6aib82mi9dy2hacs9ng2j2mqd";
        postFetch = ''
          ${args.postFetch}
          sed -i -e "/^application\/javascript /d" \
                 -e "1a text/javascript js;" \
                 -e "1a text/vtt        vtt;" \
              $out/etc/nginx/mime.types
        '';
      } // removeAttrs args [ "postFetch" "sha256" ]);
  };
}

It works, but nginx module is not the only user of mailcap and my system is trying to recompile Go. I don’t want that. Ideally, I would like to override pkgs in NixOS nginx module definition.

Is there a possibility to use .override or the overlay system with NixOS modules?

Thanks.

1 Like

To solve your problem at hand, you can simply override the mailcap that nginx depends on, with an overlay like

self: super: {
nginx.override {
  mailcap = super.mailcap.override {
    fetchzip = { ... } @ args:
      super.fetchzip ({
        sha256 = "1ah9jz80md2w4livm4qnc08haym6aib82mi9dy2hacs9ng2j2mqd";
        postFetch = ''
          ${args.postFetch}
          sed -i -e "/^application\/javascript /d" \
                 -e "1a text/javascript js;" \
                 -e "1a text/vtt        vtt;" \
              $out/etc/nginx/mime.types
        '';
      } // removeAttrs args [ "postFetch" "sha256" ]);
  };
};
}

You can probably also put that sed in postPatch, preFixup or something like that, instead of overriding fetchzip.

If you can also use disabledModules and import a modified copy, see this section of this manual.

1 Like

nginx package does not use mailcap. Only the module uses mailcap. That’s why I am looking to have an overlay for the module. Also, mailcap is just a call to fetchzip not a derivation calling fetchzip, but I’ll try your suggestion later nonetheless.

Following your second suggestion, I have added this:

disabledModules = [ "services/web-servers/nginx/default.nix" ];
imports = [ ./modules/nginx.nix ]

and

rest@{ config, lib, pkgs, ... }:

let
  pkgsWithModifiedMailcap = pkgs.overrideAttrs(oldAttrs: {
    mailcap = oldAttrs.mailcap.override {
      fetchzip = { ... } @ args:
        lib.fetchzip ({
          sha256 = "1ah9jz80md2w4livm4qnc08haym6aib82mi9dy2hacs9ng2j2";
          postFetch = ''
                      ${args.postFetch}
                      sed -i -e "/^application\/javascript /d" \
                             -e "1a text/javascript js;" \
                             -e "1a text/vtt        vtt;" \
                          $out/etc/nginx/mime.types
                      '';
        } // removeAttrs args [ "postFetch" "sha256" ]);
    };
  });
in
(import <nixpkgs/nixos/modules/services/web-servers/nginx/default.nix> (
  { inherit config lib;
    pkgs = pkgsWithModifiedMailcap;
  } // rest))

But my way of overriding packages doesn’t seem to work as expected (overridden mailcap is not evaluated).

2 Likes

I was able to make the latest solution work with:

args@{ config, lib, pkgs, ... }:

let
  pkgsWithModifiedMailcap = {
    # Update mailcap to replace application/javascript (IANA) with text/javascript (HTML WHATWG).
    # Also add text/vtt (IANA).
    mailcap = pkgs.mailcap.override {
      fetchzip = { ... } @ args:
        pkgs.fetchzip ({
          sha256 = "06yzyk8gxa12z0dbxsi8fphspi9mwmccy37n2kgxhf3p94rjyds6";
          postFetch = ''
                      ${args.postFetch}
                      sed -i -e "/^application\/javascript[ \t]/d" \
                             -e "1a text/javascript js;" \
                             -e "1a text/vtt        vtt;" \
                          $out/etc/nginx/mime.types
                      '';
        } // removeAttrs args [ "postFetch" "sha256" ]);
    };
  } // (removeAttrs pkgs ["mailcap"]);
in
(import <nixpkgs/nixos/modules/services/web-servers/nginx/default.nix> (
  {
    pkgs = pkgsWithModifiedMailcap;
  } // (removeAttrs args ["pkgs"])))

I was fooled because the wiki said args@ would collect the remaining arguments (I have fixed it) while it collect all arguments.

I don’t think I can use preFixup to simplify the override as mailcap is using directly fetchzip.

1 Like

I’ll preface this by saying I don’t use nginx.

Ideally, there should be a way to configure this. Importing from mailcap may be desirable in most cases. But it still seems weird to have to go through these hoops.

Something like services.nginx.useMailcapMIMETypes = true; as a default, then make the offending lines:

  commonHttpConfig = ''
      # The mime type definitions included with nginx are very incomplete, so
      # we use a list of mime types from the mailcap package, which is also
      # used by most other Linux distributions by default.
      ${lib.optionalString cfg.useMailcapMIMETypes "include ${pkgs.mailcap}/etc/nginx/mime.types;"}
      include ${cfg.package}/conf/fastcgi.conf;
      include ${cfg.package}/conf/uwsgi_params;
  '';

also, I feel like it would makes sense to have an option for extraMIMETypes

      include ${cfg.package}/conf/uwsgi_params;
      ${cfg.extraMIMETypes}
  '';
1 Like

In most cases, you need to include some MIME types. The choice is more
between the builtin list from nginx (which is easier to override since
it’s part of nginx package) and the list from mailcap (which is more
complete).

I think the most sensible change would be to have something like that:

  commonHttpConfig = ''
      include ${cfg.package}/conf/mime.types;
      include ${cfg.package}/conf/fastcgi.conf;
      include ${cfg.package}/conf/uwsgi_params;
  '';

By default, content of mime.types would be from pkgs.mailcap, but
you could have extraMIMETypes to add at the end of the file or ability
to override its content entirely.

hi,
are there better ways to add MIME types to Nginx now?

I tried the following but it doesn’t seem to work.

 services.nginx.commonHttpConfig = ''

        types {
            application/javascript mjs;
            application/wasm wasm;
        }

      '';