NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
16.54k stars 13.03k forks source link

Documentation: services.netbox.plugins #261522

Open brotherdust opened 8 months ago

brotherdust commented 8 months ago

Problem

The documentation for this attribute is inadequate. Here's the definition:

 plugins = lib.mkOption {
      type = with lib.types; functionTo (listOf package);
      default = _: [];
      defaultText = lib.literalExpression ''
        python3Packages: with python3Packages; [];
      '';
      description = lib.mdDoc ''
        List of plugin packages to install.
      '';
    };

Okay... what should this actually look like, then? Does it require that the python package must be present in nixpkgs? What if it's not? Can examples be provided to make those plugins available?

Proposal

  1. Enhance the documentation to include an example of what this option will accept. The current value of defaultText is too obtuse. How would a newcomer know how to interpret this?
  2. If the Python package is not available in nixpkgs, provide a link to or in-line example of how to make the package available. I.E. netbox-bgp

Thank you kindly!

Checklist

felbinger commented 6 months ago

@brotherdust Did you find a solution to install a plugin? I'm trying to setup peering-manager with oidc which requires mozilla-django-oidc - it's the same schema there, because it's also a django app.

felbinger commented 6 months ago

@brotherdust Did you find a solution to install a plugin? I'm trying to setup peering-manager with oidc which requires mozilla-django-oidc - it's the same schema there, because it's also a django app.

I found a solution to my problem, in case someone else needs an example:

{ config
, lib
, pkgs
, ...
}: let 
  mozilla-django-oidc = ps: ps.buildPythonPackage rec {
    pname = "mozilla-django-oidc";
    version = "2.0.0";
    format = "pyproject";
    src = ps.fetchPypi {
      inherit pname version;
      hash = "sha256-qLLyfGnBItL02AHDdZdh0z3r8Grp2ruriu2CiHu6O7g";
    };
    nativeBuildInputs = with ps; [
      setuptools
    ];
    propagatedBuildInputs = with ps; [
      django
      josepy
      requests
      cryptography
    ];
    meta = with lib; {
      description = "A django OpenID Connect library";
      homepage = "https://github.com/mozilla/mozilla-django-oidc";
      license = licenses.mpl20;
      platforms = platforms.linux;
    };
  };
in  {
  sops.secrets = {
    "peering-manager/secretKey".owner = "peering-manager";
    "peering-manager/oidcSecret".owner = "peering-manager";
  };

  services = {
    peering-manager = {
      enable = true;
      secretKeyFile = config.sops.secrets."peering-manager/secretKey".path;
      port = 8000;
      listenAddress = "127.0.0.1";
      plugins = (ps: [ (mozilla-django-oidc ps) ]);
      settings = {
        # CLIENT_ID and SECRET are required to authenticate against the provider
        OIDC_RP_CLIENT_ID = "pm.domain.de";

        # The following two may be required depending on your provider,
        # check the configuration endpoint for JWKS information
        OIDC_RP_SIGN_ALGO = "RS256";
        OIDC_OP_JWKS_ENDPOINT = "https://id.domain.de/realms/main/protocol/openid-connect/certs";

        # Refer to the configuration endpoint of your provider
        OIDC_OP_AUTHORIZATION_ENDPOINT = "https://id.domain.de/realms/main/protocol/openid-connect/auth";
        OIDC_OP_TOKEN_ENDPOINT = "https://id.domain.de/realms/main/protocol/openid-connect/token";
        OIDC_OP_USER_ENDPOINT = "https://id.domain.de/realms/main/protocol/openid-connect/userinfo";

        # Set these to the base path of your Peering Manager installation
        LOGIN_REDIRECT_URL = "https://pm.domain.de";
        LOGOUT_REDIRECT_URL = "https://pm.domain.de";

        # If this is True, new users will be created if not yet existing.
        OIDC_CREATE_USER = true;

        LOGIN_REQUIRED = true;
        TIME_ZONE = "Europe/Berlin";
        ALLOWED_HOSTS = [
          "pm.domain.de"
        ];
      };
      extraConfig = ''
        with open("${config.sops.secrets."peering-manager/oauthSecret".path}", "r") as file:
          OIDC_RP_CLIENT_SECRET = file.readline()
      '';
    };
  };
}
minijackson commented 5 months ago

Hello! You're right that the documentation is lacking in that aspect. Currently, I don't think any NetBox plugins are packaged in nixpkgs, so this option is not really usable from a new user perspective. I might be interested in packaging the interface-sync and ipcalculator plugin when I have time, so this might change.

To answer your question, to add a plugin you'd have to:

services.netbox = {
  # ...
  plugins = ps: with ps; [ netbox-plugin-interface-sync ];
  settings.PLUGINS = ["netbox_interface_sync"];
};

I think it's weird to have to specify both, so we might change it in the future.

If you want to package a NetBox plugin yourself, it should be the same as making a Python package. You can look at the buildPythonPackage documentation.

Xyz00777 commented 2 months ago

hi i would really like to use some plugins for my netbox instance. @minijackson any status update on your site? sadly i dont know how to package them myself....

minijackson commented 2 months ago

There's currently two PRs in progress:

Plugins seems to be quite similar, packaging wise. I have a bunch of them currently on my working tree, but I'm discussing with my colleagues to see which one we want, so which one I'd be willing to maintain. But so far, packaging each NetBox plugin has been pretty much copying pasting.

Another I think I'll propose, is to rename services.netbox.plugins -> services.netbox.extraPackages, so that it's clearer on what it does. It may be more obvious that settings.PLUGINS needs to be set.