~aasg/nixexprs

83f5417517270006384c02d0a75dd5e4b81e5ffa — Aluísio Augusto Silva Gonçalves 5 months ago 279d1c6
bird-lg: init at 2020-05-20-unstable
M modules/default.nix => modules/default.nix +1 -0
@@ 1,4 1,5 @@
{
  bird-lg = ./services/networking/monitoring/bird-lg.nix;
  dma = ./programs/dma.nix;
  dyndnsc = ./services/networking/dyndnsc.nix;
  ipfs-cluster = ./services/cluster/ipfs-cluster.nix;

A modules/services/networking/monitoring/bird-lg.nix => modules/services/networking/monitoring/bird-lg.nix +141 -0
@@ 0,0 1,141 @@
{ config, lib, pkgs, ... }:
let
  inherit (lib) mkDefault mkEnableOption mkIf mkOption types;

  jsonFormat = pkgs.formats.json { };
  pyJSONFormat =
    {
      type = jsonFormat.type;
      generate = name: value: pkgs.runCommandNoCC
        name
        {
          passAsFile = [ "script" "value" ];
          value = builtins.toJSON value;
          script = ''
            import json
            import sys
            value = json.load(sys.stdin)
            print("globals().update({!r})".format(value), file=sys.stdout)
          '';
        }
        ''
          ${pkgs.python3}/bin/python $scriptPath <$valuePath >$out
        '';
    };

  cfg = config.services.bird-lg;
  serverGunicornConfigFile = pyJSONFormat.generate "bird-lg-gunicorn.py" cfg.server.gunicornSettings;
  clientGunicornConfigFile = pyJSONFormat.generate "bird-lgproxy-gunicorn.py" cfg.client.gunicornSettings;
in
{

  options = {
    services.bird-lg.server = {
      enable = mkEnableOption "BIRD looking glass server";

      appSettings = mkOption {
        description = "Configuration for bird-lg's server.";
        type = jsonFormat.type;
        default = { };
      };

      gunicornSettings = mkOption {
        description = "Configuration for the Gunicorn instance running bird-lg's server.";
        type = pyJSONFormat.type;
        default = { };
      };
    };

    services.bird-lg.client = {
      enable = mkEnableOption "BIRD looking glass client proxy";

      appSettings = mkOption {
        description = "Configuration for bird-lg's client proxy.";
        type = jsonFormat.type;
        default = { };
      };

      gunicornSettings = mkOption {
        description = "Configuration for the Gunicorn instance running bird-lg's client proxy.";
        type = pyJSONFormat.type;
        default = { };
      };
    };
  };

  config = {

    ################
    # Server setup #
    ################

    environment.etc."bird-lg/lg.json" = mkIf cfg.server.enable {
      source = jsonFormat.generate "bird-lg.json" cfg.server.appSettings;
    };

    systemd.services.bird-lg-server = mkIf cfg.server.enable {
      description = "BIRD looking glass web server";
      requires = [ "network-online.target" ];
      after = [ "bird.service" "bird6.service" "bird2.service" "network-online.target" ];
      wantedBy = [ "multi-user.target" ];
      serviceConfig = {
        Type = "simple";
        ExecStart = "${pkgs.bird-lg}/bin/bird-lg-webservice --config=${serverGunicornConfigFile}";
        Restart = "on-failure";

        WorkingDirectory = "/etc/bird-lg";
        ConfigurationDirectory = "/etc/bird-lg";

        DynamicUser = true;
        NoNewPrivileges = true;
        ProtectSystem = "strict";
        ProtectHome = true;
        ProtectKernelLogs = true;
        ProtectKernelModules = true;
        ProtectKernelTunables = true;
        ProtectControlGroups = true;
        PrivateDevices = true;
        PrivateTmp = true;
        DevicePolicy = "closed";
        MemoryDenyWriteExecute = true;
      };
    };

    ######################
    # Client proxy setup #
    ######################

    environment.etc."bird-lg/lgproxy.json" = mkIf cfg.client.enable {
      source = jsonFormat.generate "bird-lgproxy.json" cfg.client.appSettings;
    };

    systemd.services.bird-lg-client = mkIf cfg.client.enable {
      description = "BIRD looking glass client proxy";
      requires = [ "network-online.target" ];
      after = [ "bird.service" "bird6.service" "bird2.service" "network-online.target" ];
      wantedBy = [ "multi-user.target" ];
      serviceConfig = {
        Type = "simple";
        ExecStart = "${pkgs.bird-lg}/bin/bird-lg-proxy --config=${clientGunicornConfigFile}";
        Restart = "on-failure";

        WorkingDirectory = "/etc/bird-lg";
        ConfigurationDirectory = "/etc/bird-lg";

        DynamicUser = true;
        NoNewPrivileges = true;
        ProtectSystem = "strict";
        ProtectHome = true;
        ProtectKernelLogs = true;
        ProtectKernelModules = true;
        ProtectKernelTunables = true;
        ProtectControlGroups = true;
        PrivateDevices = true;
        PrivateTmp = true;
        DevicePolicy = "closed";
      };
    };

  };

}

M pkgs/manifest.nix => pkgs/manifest.nix +1 -0
@@ 1,4 1,5 @@
[
  [ "bird-lg" ]
  [ "dma" ]
  [ "drep" ]
  [ "dyndnsc" ]

M pkgs/overlay.nix => pkgs/overlay.nix +2 -0
@@ 2,6 2,8 @@ final: prev:

{

  bird-lg = final.callPackage ./servers/monitoring/bird-lg { };

  dma = final.callPackage ./tools/networking/dma { };

  drep = final.callPackage ./tools/text/drep {

A pkgs/servers/monitoring/bird-lg/default.nix => pkgs/servers/monitoring/bird-lg/default.nix +67 -0
@@ 0,0 1,67 @@
{ stdenv, fetchFromGitHub, graphviz, python3, traceroute, whois }:
let
  runtimeDeps = [
    (python3.withPackages (ps: with ps; [
      flask
      dnspython
      gunicorn
      pydot
      memcached
    ]))
    graphviz
    whois
    traceroute
  ];
in
stdenv.mkDerivation rec {
  pname = "bird-lg-burble";
  version = "2020-05-20-unstable";

  src = fetchFromGitHub {
    owner = "sesa-me";
    repo = "bird-lg";
    rev = "f3699a3b61f2d9f77cb17fb163bcf3c3ad722835"; # refs/head/burble-clean
    sha256 = "0gisi6mbfclw36kms3qy3b0wzcwdkd50p2a6xdwggln4fi5y6bh1";
  };

  postPatch = ''
    # Don't configure a log file; let systemd handle it.
    sed -i '/file_handler/d' lg.py lgproxy.py

    # Support loading config from a JSON file so we don't have to learn
    # how to escape strings in Python code.
    sed -i '/app\.config\.from_pyfile/a app.config.from_json("lg.json")' lg.py
    sed -i '/app\.config\.from_pyfile/a app.config.from_json("lgproxy.json")' lgproxy.py
  '';

  WRAPPER_PATH = stdenv.lib.makeBinPath runtimeDeps;
  WRAPPER_PYTHONPATH = placeholder "out";

  installPhase = ''
    function wrapWSGI {
      set -e
      substitute ${./run-wsgi.sh} "$2" \
        --subst-var shell \
        --subst-var WRAPPER_PATH \
        --subst-var WRAPPER_PYTHONPATH \
        --subst-var-by SCRIPT "$1"
      chmod +x "$2"
    }

    runHook preInstall
    mkdir -p $out $out/bin
    cp -r * $out
    touch $out/__init__.py
    wrapWSGI lg:app $out/bin/bird-lg-webservice
    wrapWSGI lgproxy:app $out/bin/bird-lg-proxy
    runHook postInstall
  '';

  meta = with stdenv.lib; {
    description = "Looking glass for the BIRD Internet Routing Daemon";
    homepage = "https://github.com/sesa-me/bird-lg";
    license = licenses.gpl3Only;
    platforms = platforms.unix;
    maintainers = with maintainers; [ AluisioASG ];
  };
}

A pkgs/servers/monitoring/bird-lg/run-wsgi.sh => pkgs/servers/monitoring/bird-lg/run-wsgi.sh +5 -0
@@ 0,0 1,5 @@
#!@shell@
PATH=@WRAPPER_PATH@
PYTHONPATH=@WRAPPER_PYTHONPATH@
export PATH PYTHONPATH
exec python -m gunicorn.app.wsgiapp @SCRIPT@ "$@"